bugfix: type alias to generic; generic type not stripped away from for loop variable
This commit is contained in:
parent
0e22a51095
commit
7405278138
8 changed files with 118 additions and 69 deletions
|
|
@ -32,6 +32,9 @@ proc isDefined*(symbol: PIdent): bool =
|
||||||
var sym = StrTableGet(gSymbols, symbol)
|
var sym = StrTableGet(gSymbols, symbol)
|
||||||
result = sym != nil and sym.position == 1
|
result = sym != nil and sym.position == 1
|
||||||
|
|
||||||
|
proc isDefined*(symbol: string): bool =
|
||||||
|
result = isDefined(getIdent(symbol))
|
||||||
|
|
||||||
proc ListSymbols*() =
|
proc ListSymbols*() =
|
||||||
var it: TTabIter
|
var it: TTabIter
|
||||||
var s = InitTabIter(it, gSymbols)
|
var s = InitTabIter(it, gSymbols)
|
||||||
|
|
|
||||||
|
|
@ -116,9 +116,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
# type parameters:
|
# type parameters:
|
||||||
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
||||||
result.add(explicitGenericSym(c, n, candidate))
|
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]
|
if result.len == 1: result = result[0]
|
||||||
# candidateCount != 1: return explicitGenericInstError(n)
|
# candidateCount != 1: return explicitGenericInstError(n)
|
||||||
else:
|
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 iter.kind != tyTuple or length == 3:
|
||||||
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
|
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
|
||||||
var v = newSymS(skForVar, n.sons[0], c)
|
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)
|
n.sons[0] = newSymNode(v)
|
||||||
addDecl(c, v)
|
addDecl(c, v)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
|
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
|
||||||
magicsys
|
magicsys, condsyms, idents
|
||||||
|
|
||||||
type
|
type
|
||||||
TCandidateState* = enum
|
TCandidateState* = enum
|
||||||
|
|
@ -27,7 +27,7 @@ type
|
||||||
callee*: PType # may not be nil!
|
callee*: PType # may not be nil!
|
||||||
calleeSym*: PSym # may be nil
|
calleeSym*: PSym # may be nil
|
||||||
call*: PNode # modified call
|
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]
|
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||||
# for example
|
# for example
|
||||||
|
|
||||||
|
|
@ -52,6 +52,12 @@ proc initCandidate*(c: var TCandidate, callee: PType) =
|
||||||
c.calleeSym = nil
|
c.calleeSym = nil
|
||||||
initIdTable(c.bindings)
|
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) =
|
proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode) =
|
||||||
initCandidateAux(c, callee.typ)
|
initCandidateAux(c, callee.typ)
|
||||||
c.calleeSym = callee
|
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):
|
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
||||||
var formalTypeParam = typeParams.sons[i-1].typ
|
var formalTypeParam = typeParams.sons[i-1].typ
|
||||||
#debug(formalTypeParam)
|
#debug(formalTypeParam)
|
||||||
IdTablePut(c.bindings, formalTypeParam, binding[i].typ)
|
put(c.bindings, formalTypeParam, binding[i].typ)
|
||||||
|
|
||||||
proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||||
a.exactMatches = b.exactMatches
|
a.exactMatches = b.exactMatches
|
||||||
|
|
@ -100,7 +106,7 @@ proc getNotFoundError*(c: PContext, n: PNode): string =
|
||||||
# in case of an error).
|
# in case of an error).
|
||||||
result = msgKindToString(errTypeMismatch)
|
result = msgKindToString(errTypeMismatch)
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
#debug(n.sons[i].typ);
|
#debug(n.sons[i].typ)
|
||||||
if n.sons[i].kind == nkExprEqExpr:
|
if n.sons[i].kind == nkExprEqExpr:
|
||||||
add(result, renderTree(n.sons[i].sons[0]))
|
add(result, renderTree(n.sons[i].sons[0]))
|
||||||
add(result, ": ")
|
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:
|
if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
|
||||||
result = isNone
|
result = isNone
|
||||||
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
|
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
|
||||||
# noSideEffect implies ``tfThread``!
|
# noSideEffect implies ``tfThread``! XXX really?
|
||||||
result = isNone
|
result = isNone
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
|
|
@ -413,7 +419,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
|
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
|
||||||
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
|
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
|
||||||
InternalError("wrong instantiated type!")
|
InternalError("wrong instantiated type!")
|
||||||
idTablePut(mapping, f.sons[i], x)
|
put(mapping, f.sons[i], x)
|
||||||
of tyGenericParam:
|
of tyGenericParam:
|
||||||
var x = PType(idTableGet(mapping, f))
|
var x = PType(idTableGet(mapping, f))
|
||||||
if x == nil:
|
if x == nil:
|
||||||
|
|
@ -421,7 +427,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
# no constraints
|
# no constraints
|
||||||
var concrete = concreteType(mapping, a)
|
var concrete = concreteType(mapping, a)
|
||||||
if concrete != nil:
|
if concrete != nil:
|
||||||
idTablePut(mapping, f, concrete)
|
put(mapping, f, concrete)
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
# check constraints:
|
# check constraints:
|
||||||
|
|
@ -429,7 +435,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
if typeRel(mapping, f.sons[i], a) >= isSubtype:
|
if typeRel(mapping, f.sons[i], a) >= isSubtype:
|
||||||
var concrete = concreteType(mapping, a)
|
var concrete = concreteType(mapping, a)
|
||||||
if concrete != nil:
|
if concrete != nil:
|
||||||
idTablePut(mapping, f, concrete)
|
put(mapping, f, concrete)
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
break
|
break
|
||||||
elif a.kind == tyEmpty:
|
elif a.kind == tyEmpty:
|
||||||
|
|
|
||||||
117
koch.nim
117
koch.nim
|
|
@ -36,7 +36,7 @@ Possible Commands:
|
||||||
zip builds the installation ZIP package
|
zip builds the installation ZIP package
|
||||||
inno [options] builds the Inno Setup installer (for Windows)
|
inno [options] builds the Inno Setup installer (for Windows)
|
||||||
tests run the testsuite
|
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:
|
Boot options:
|
||||||
-d:release produce a release version of the compiler
|
-d:release produce a release version of the compiler
|
||||||
-d:tinyc include the Tiny C backend (not supported on Windows)
|
-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=$#" %
|
exec("nimrod cc -r tools/nimweb.nim web/nimrod --putenv:nimrodversion=$#" %
|
||||||
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 ---------------------------------------------------------
|
# -------------- boot ---------------------------------------------------------
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -237,6 +181,65 @@ proc clean(args: string) =
|
||||||
echo "removing dir: ", path
|
echo "removing dir: ", path
|
||||||
RemoveDir(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) =
|
proc tests(args: string) =
|
||||||
# we compile the tester with taintMode:on to have a basic
|
# we compile the tester with taintMode:on to have a basic
|
||||||
# taint mode test :-)
|
# 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
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue