mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 10:24:44 +00:00
bugfix: type alias to generic; generic type not stripped away from for loop variable
This commit is contained in:
@@ -32,6 +32,9 @@ proc isDefined*(symbol: PIdent): bool =
|
||||
var sym = StrTableGet(gSymbols, symbol)
|
||||
result = sym != nil and sym.position == 1
|
||||
|
||||
proc isDefined*(symbol: string): bool =
|
||||
result = isDefined(getIdent(symbol))
|
||||
|
||||
proc ListSymbols*() =
|
||||
var it: TTabIter
|
||||
var s = InitTabIter(it, gSymbols)
|
||||
|
||||
@@ -116,9 +116,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
# type parameters:
|
||||
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
||||
result.add(explicitGenericSym(c, n, candidate))
|
||||
# get rid of nkSymChoice if not ambigious:
|
||||
# get rid of nkSymChoice if not ambiguous:
|
||||
if result.len == 1: result = result[0]
|
||||
# candidateCount != 1: return explicitGenericInstError(n)
|
||||
else:
|
||||
assert false
|
||||
result = explicitGenericInstError(n)
|
||||
|
||||
|
||||
@@ -417,7 +417,10 @@ proc semFor(c: PContext, n: PNode): PNode =
|
||||
if iter.kind != tyTuple or length == 3:
|
||||
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
|
||||
var v = newSymS(skForVar, n.sons[0], c)
|
||||
v.typ = iter
|
||||
# BUGFIX: don't use `iter` here as that would strip away
|
||||
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
|
||||
# for an example:
|
||||
v.typ = n.sons[length-2].typ
|
||||
n.sons[0] = newSymNode(v)
|
||||
addDecl(c, v)
|
||||
else:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
|
||||
magicsys
|
||||
magicsys, condsyms, idents
|
||||
|
||||
type
|
||||
TCandidateState* = enum
|
||||
@@ -27,7 +27,7 @@ type
|
||||
callee*: PType # may not be nil!
|
||||
calleeSym*: PSym # may be nil
|
||||
call*: PNode # modified call
|
||||
bindings*: TIdTable # maps sym-ids to types
|
||||
bindings*: TIdTable # maps types to types
|
||||
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||
# for example
|
||||
|
||||
@@ -52,6 +52,12 @@ proc initCandidate*(c: var TCandidate, callee: PType) =
|
||||
c.calleeSym = nil
|
||||
initIdTable(c.bindings)
|
||||
|
||||
proc put(t: var TIdTable, key, val: PType) {.inline.} =
|
||||
IdTablePut(t, key, val)
|
||||
if val.kind == tyObject and isDefined"testme" and
|
||||
IdentEq(val.sym.name, "TTable"):
|
||||
assert false
|
||||
|
||||
proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode) =
|
||||
initCandidateAux(c, callee.typ)
|
||||
c.calleeSym = callee
|
||||
@@ -61,7 +67,7 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode) =
|
||||
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
||||
var formalTypeParam = typeParams.sons[i-1].typ
|
||||
#debug(formalTypeParam)
|
||||
IdTablePut(c.bindings, formalTypeParam, binding[i].typ)
|
||||
put(c.bindings, formalTypeParam, binding[i].typ)
|
||||
|
||||
proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||
a.exactMatches = b.exactMatches
|
||||
@@ -100,7 +106,7 @@ proc getNotFoundError*(c: PContext, n: PNode): string =
|
||||
# in case of an error).
|
||||
result = msgKindToString(errTypeMismatch)
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
#debug(n.sons[i].typ);
|
||||
#debug(n.sons[i].typ)
|
||||
if n.sons[i].kind == nkExprEqExpr:
|
||||
add(result, renderTree(n.sons[i].sons[0]))
|
||||
add(result, ": ")
|
||||
@@ -225,7 +231,7 @@ proc procTypeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
|
||||
result = isNone
|
||||
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
|
||||
# noSideEffect implies ``tfThread``!
|
||||
# noSideEffect implies ``tfThread``! XXX really?
|
||||
result = isNone
|
||||
else: nil
|
||||
|
||||
@@ -236,7 +242,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
assert(a != nil)
|
||||
if a.kind == tyGenericInst and
|
||||
skipTypes(f, {tyVar}).kind notin {
|
||||
tyGenericBody, tyGenericInvokation, tyGenericParam}:
|
||||
tyGenericBody, tyGenericInvokation, tyGenericParam}:
|
||||
return typeRel(mapping, f, lastSon(a))
|
||||
if a.kind == tyVar and f.kind != tyVar:
|
||||
return typeRel(mapping, f, a.sons[0])
|
||||
@@ -413,7 +419,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
|
||||
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
|
||||
InternalError("wrong instantiated type!")
|
||||
idTablePut(mapping, f.sons[i], x)
|
||||
put(mapping, f.sons[i], x)
|
||||
of tyGenericParam:
|
||||
var x = PType(idTableGet(mapping, f))
|
||||
if x == nil:
|
||||
@@ -421,7 +427,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
# no constraints
|
||||
var concrete = concreteType(mapping, a)
|
||||
if concrete != nil:
|
||||
idTablePut(mapping, f, concrete)
|
||||
put(mapping, f, concrete)
|
||||
result = isGeneric
|
||||
else:
|
||||
# check constraints:
|
||||
@@ -429,7 +435,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
if typeRel(mapping, f.sons[i], a) >= isSubtype:
|
||||
var concrete = concreteType(mapping, a)
|
||||
if concrete != nil:
|
||||
idTablePut(mapping, f, concrete)
|
||||
put(mapping, f, concrete)
|
||||
result = isGeneric
|
||||
break
|
||||
elif a.kind == tyEmpty:
|
||||
|
||||
117
koch.nim
117
koch.nim
@@ -36,7 +36,7 @@ Possible Commands:
|
||||
zip builds the installation ZIP package
|
||||
inno [options] builds the Inno Setup installer (for Windows)
|
||||
tests run the testsuite
|
||||
update updates nimrod to the latest version from the repo
|
||||
update updates nimrod to the latest version from github
|
||||
Boot options:
|
||||
-d:release produce a release version of the compiler
|
||||
-d:tinyc include the Tiny C backend (not supported on Windows)
|
||||
@@ -83,62 +83,6 @@ proc web(args: string) =
|
||||
exec("nimrod cc -r tools/nimweb.nim web/nimrod --putenv:nimrodversion=$#" %
|
||||
NimrodVersion)
|
||||
|
||||
proc update(args: string) =
|
||||
when defined(windows):
|
||||
echo("Windows users: Make sure to be running this in Bash. ",
|
||||
"If you aren't, press CTRL+C now.")
|
||||
|
||||
var thisDir = getAppDir()
|
||||
var git = findExe("git")
|
||||
echo("Checking for git repo and git executable...")
|
||||
if existsDir(thisDir & "/.git") and git != "":
|
||||
echo("Git repo found!")
|
||||
# use git to download latest source
|
||||
echo("Checking for updates...")
|
||||
discard startCmd(git & " fetch origin master")
|
||||
var procs = startCmd(git & " diff origin/master master")
|
||||
var errcode = procs.waitForExit()
|
||||
var output = readLine(procs.outputStream)
|
||||
echo(output)
|
||||
if errcode == 0:
|
||||
if output == "":
|
||||
# No changes
|
||||
echo("No update. Exiting..")
|
||||
return
|
||||
else:
|
||||
echo("Fetching updates from repo...")
|
||||
var pullout = execCmdEx(git & " pull origin master")
|
||||
if pullout[1] != 0:
|
||||
quit("An error has occured.")
|
||||
else:
|
||||
if pullout[0].startsWith("Already up-to-date."):
|
||||
quit("No new changes fetched from the repo. " &
|
||||
"Local branch must be ahead of it. Exiting...")
|
||||
else:
|
||||
quit("An error has occured.")
|
||||
|
||||
else:
|
||||
echo("No repo or executable found!")
|
||||
when defined(haveZipLib):
|
||||
echo("Falling back.. Downloading source code from repo...")
|
||||
# use dom96's httpclient to download zip
|
||||
downloadFile("https://github.com/Araq/Nimrod/zipball/master",
|
||||
thisDir / "update.zip")
|
||||
try:
|
||||
echo("Extracting source code from archive...")
|
||||
var zip: TZipArchive
|
||||
discard open(zip, thisDir & "/update.zip", fmRead)
|
||||
extractAll(zip, thisDir & "/")
|
||||
except:
|
||||
quit("Error reading archive.")
|
||||
else:
|
||||
quit("No failback available. Exiting...")
|
||||
|
||||
echo("Starting update...")
|
||||
boot(args)
|
||||
echo("Update complete!")
|
||||
|
||||
|
||||
# -------------- boot ---------------------------------------------------------
|
||||
|
||||
const
|
||||
@@ -237,6 +181,65 @@ proc clean(args: string) =
|
||||
echo "removing dir: ", path
|
||||
RemoveDir(path)
|
||||
|
||||
# -------------- update -------------------------------------------------------
|
||||
|
||||
proc update(args: string) =
|
||||
when defined(windows):
|
||||
echo("Windows users: Make sure to be running this in Bash. ",
|
||||
"If you aren't, press CTRL+C now.")
|
||||
|
||||
var thisDir = getAppDir()
|
||||
var git = findExe("git")
|
||||
echo("Checking for git repo and git executable...")
|
||||
if existsDir(thisDir & "/.git") and git != "":
|
||||
echo("Git repo found!")
|
||||
# use git to download latest source
|
||||
echo("Checking for updates...")
|
||||
discard startCmd(git & " fetch origin master")
|
||||
var procs = startCmd(git & " diff origin/master master")
|
||||
var errcode = procs.waitForExit()
|
||||
var output = readLine(procs.outputStream)
|
||||
echo(output)
|
||||
if errcode == 0:
|
||||
if output == "":
|
||||
# No changes
|
||||
echo("No update. Exiting..")
|
||||
return
|
||||
else:
|
||||
echo("Fetching updates from repo...")
|
||||
var pullout = execCmdEx(git & " pull origin master")
|
||||
if pullout[1] != 0:
|
||||
quit("An error has occured.")
|
||||
else:
|
||||
if pullout[0].startsWith("Already up-to-date."):
|
||||
quit("No new changes fetched from the repo. " &
|
||||
"Local branch must be ahead of it. Exiting...")
|
||||
else:
|
||||
quit("An error has occured.")
|
||||
|
||||
else:
|
||||
echo("No repo or executable found!")
|
||||
when defined(haveZipLib):
|
||||
echo("Falling back.. Downloading source code from repo...")
|
||||
# use dom96's httpclient to download zip
|
||||
downloadFile("https://github.com/Araq/Nimrod/zipball/master",
|
||||
thisDir / "update.zip")
|
||||
try:
|
||||
echo("Extracting source code from archive...")
|
||||
var zip: TZipArchive
|
||||
discard open(zip, thisDir & "/update.zip", fmRead)
|
||||
extractAll(zip, thisDir & "/")
|
||||
except:
|
||||
quit("Error reading archive.")
|
||||
else:
|
||||
quit("No failback available. Exiting...")
|
||||
|
||||
echo("Starting update...")
|
||||
boot(args)
|
||||
echo("Update complete!")
|
||||
|
||||
# -------------- tests --------------------------------------------------------
|
||||
|
||||
proc tests(args: string) =
|
||||
# we compile the tester with taintMode:on to have a basic
|
||||
# taint mode test :-)
|
||||
|
||||
11
tests/compile/tgeneric.nim
Normal file
11
tests/compile/tgeneric.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
import tables
|
||||
|
||||
type
|
||||
TX = TTable[string, int]
|
||||
|
||||
proc foo(models: seq[TTable[string, float]]): seq[float] =
|
||||
result = @[]
|
||||
for model in models.items:
|
||||
result.add model["foobar"]
|
||||
|
||||
|
||||
11
tests/compile/tgeneric2.nim
Normal file
11
tests/compile/tgeneric2.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
import tables
|
||||
|
||||
type
|
||||
TX = TTable[string, int]
|
||||
|
||||
proc foo(models: seq[TX]): seq[int] =
|
||||
result = @[]
|
||||
for model in models.items:
|
||||
result.add model["foobar"]
|
||||
|
||||
|
||||
12
tests/compile/tgenericprop.nim
Normal file
12
tests/compile/tgenericprop.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
type
|
||||
TProperty[T] = object of TObject
|
||||
getProc: proc(property: TProperty[T]): T
|
||||
setProc: proc(property: TProperty[T], value: T)
|
||||
value: T
|
||||
|
||||
proc newProperty[T](value: TObject): TProperty[T] =
|
||||
result.getProc = proc (property: TProperty[T]) =
|
||||
return property.value
|
||||
|
||||
|
||||
Reference in New Issue
Block a user