diff options
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/sem.nim | 15 | ||||
-rw-r--r-- | compiler/semdata.nim | 10 | ||||
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | compiler/seminst.nim | 7 | ||||
-rw-r--r-- | compiler/semstmts.nim | 1 | ||||
-rw-r--r-- | compiler/semtempl.nim | 2 | ||||
-rw-r--r-- | compiler/semtypes.nim | 9 | ||||
-rw-r--r-- | compiler/transf.nim | 5 | ||||
-rw-r--r-- | tests/template/tgensymregression.nim | 13 | ||||
-rw-r--r-- | tests/template/tparams_gensymed.nim | 9 |
11 files changed, 60 insertions, 17 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 8fbec64cf..4ea68dc99 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym = ## Generic instantiations are owned by their originating generic ## symbol. This proc skips such owners and goes straight to the owner ## of the generic itself (the module or the enclosing proc). - result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags == - {sfFromGeneric}: + result = if s.kind in skProcKinds and sfFromGeneric in s.flags: s.owner.owner else: s.owner diff --git a/compiler/sem.nim b/compiler/sem.nim index dbf237635..961d9fa75 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -168,6 +168,16 @@ proc commonType*(x, y: PType): PType = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) +proc getGenSym(c: PContext; s: PSym): PSym = + var it = c.p + while it != nil: + result = get(it, s) + if result != nil: + #echo "got from table ", result.name.s, " ", result.info + return result + it = it.next + result = s + proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii @@ -178,6 +188,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = if result.kind != kind: localError(n.info, "cannot use symbol of kind '" & $result.kind & "' as a '" & $kind & "'") + if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}: + # declarative context, so produce a fresh gensym: + result = copySym(result) + result.ast = n.sym.ast + put(c.p, n.sym, result) # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 20fd1d9be..845efd25a 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -39,6 +39,7 @@ type next*: PProcCon # used for stacking procedure contexts wasForwarded*: bool # whether the current proc has a separate header bracketExpr*: PNode # current bracket expression (for ^ support) + mapping*: TIdTable TInstantiationPair* = object genericSym*: PSym @@ -147,6 +148,15 @@ proc lastOptionEntry*(c: PContext): POptionEntry = proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next +proc put*(p: PProcCon; key, val: PSym) = + if p.mapping.data == nil: initIdTable(p.mapping) + #echo "put into table ", key.info + p.mapping.idTablePut(key, val) + +proc get*(p: PProcCon; key: PSym): PSym = + if p.mapping.data == nil: return nil + result = PSym(p.mapping.idTableGet(key)) + proc newOptionEntry*(): POptionEntry = new(result) result.options = gOptions diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9972585c7..542d7b4e3 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType, return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) #echo "came here: returned nil" -proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = +proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = + let s = getGenSym(c, sym) case s.kind of skConst: markUsed(n.info, s) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 9c57be023..1a96b4bc6 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -106,15 +106,16 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = #if n.kind == nkSym and sfGenSym in n.sym.flags: # if n.sym.owner != orig: # echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner - if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and + if n.kind == nkSym and sfGenSym in n.sym.flags: # and # (n.sym.owner == orig or n.sym.owner.kind in {skPackage}): let s = n.sym var x = PSym(idTableGet(symMap, s)) - if x == nil: + if x != nil: + n.sym = x + when false: x = copySym(s, false) x.owner = owner idTablePut(symMap, s, x) - n.sym = x else: for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, orig, symMap) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 25d4b3c74..e2b0f4b7a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1345,6 +1345,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, proc determineType(c: PContext, s: PSym) = if s.typ != nil: return #if s.magic != mNone: return + #if s.ast.isNil: return discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType) proc semIterator(c: PContext, n: PNode): PNode = diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index a69fe477b..8819f17cc 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -172,7 +172,7 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym = result = newSym(kind, considerQuotedIdent(n), c.owner, n.info) incl(result.flags, sfGenSym) incl(result.flags, sfShadowed) - if c.scopeN == 0: incl(result.flags, sfFromGeneric) + #if c.scopeN == 0: incl(result.flags, sfFromGeneric) proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) = # locals default to 'gensym': diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 17c065b49..440edd226 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -297,7 +297,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = proc semTypeIdent(c: PContext, n: PNode): PSym = if n.kind == nkSym: - result = n.sym + result = getGenSym(c, n.sym) else: when defined(nimfix): result = pickSym(c, n, skType) @@ -1319,8 +1319,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = prev.id = s.typ.id result = prev of nkSym: - if n.sym.kind == skType and n.sym.typ != nil: - var t = n.sym.typ + let s = getGenSym(c, n.sym) + if s.kind == skType and s.typ != nil: + var t = s.typ let alias = maybeAliasType(c, t, prev) if alias != nil: result = alias @@ -1332,7 +1333,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = markUsed(n.info, n.sym) styleCheckUse(n.info, n.sym) else: - if n.sym.kind != skError: localError(n.info, errTypeExpected) + if s.kind != skError: localError(n.info, errTypeExpected) result = newOrPrevType(tyError, prev, c) of nkObjectTy: result = semObjectNode(c, n, prev) of nkTupleTy: result = semTuple(c, n, prev) diff --git a/compiler/transf.nim b/compiler/transf.nim index 13c6dd8fe..cbd1f15e3 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -869,7 +869,10 @@ proc transform(c: PTransf, n: PNode): PTransNode = else: result = transformSons(c, n) of nkIdentDefs, nkConstDef: - result = transformSons(c, n) + result = n.PTransNode + #transformSons(c, n) + let L = n.len-1 + result[L] = transform(c, n.sons[L]) # XXX comment handling really sucks: if importantComments(): PNode(result).comment = n.comment diff --git a/tests/template/tgensymregression.nim b/tests/template/tgensymregression.nim index e73ff258d..e49678fec 100644 --- a/tests/template/tgensymregression.nim +++ b/tests/template/tgensymregression.nim @@ -19,3 +19,16 @@ proc foo(): void = echo repr(v1 *** v2) foo() + +# bug #5383 +import sequtils + +proc zipWithIndex[A](ts: seq[A]): seq[(int, A)] = + toSeq(pairs(ts)) + +proc main = + discard zipWithIndex(@["foo", "bar"]) + discard zipWithIndex(@[1, 2]) + discard zipWithIndex(@[true, false]) + +main() diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index 6c4413866..568725fd4 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -5,8 +5,8 @@ import macros # Test that parameters are properly gensym'ed finally: -template genNodeKind(kind, name: expr): stmt = - proc name*(children: varargs[PNimrodNode]): PNimrodNode {.compiletime.}= +template genNodeKind(kind, name: untyped) = + proc name*(children: varargs[NimNode]): NimNode {.compiletime.}= result = newNimNode(kind) for c in children: result.add(c) @@ -22,7 +22,7 @@ type Something = object proc testA(x: Something) = discard -template def(name: expr) {.immediate.} = +template def(name: untyped) = proc testB[T](reallyUniqueName: T) = `test name`(reallyUniqueName) def A @@ -35,8 +35,7 @@ testB(x) # Test that templates in generics still work (regression to fix the # regression...) -template forStatic(index: expr, slice: Slice[int], predicate: stmt): - stmt {.immediate.} = +template forStatic(index, slice, predicate: untyped) = const a = slice.a const b = slice.b when a <= b: |