diff options
author | Araq <rumpf_a@web.de> | 2018-12-08 13:30:06 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2018-12-08 13:30:06 +0100 |
commit | e8747059710370819800bdc0742fa86761c6737b (patch) | |
tree | 7cba169ecf4990667ff15d4828403b820f222f53 | |
parent | 7a0191ac7ea2c3adfa303cfd6b1d1759a361e5c7 (diff) | |
download | Nim-e8747059710370819800bdc0742fa86761c6737b.tar.gz |
fixes nested gensym'ed parameters; fixes #9476
-rw-r--r-- | compiler/ast.nim | 6 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 14 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 5 | ||||
-rw-r--r-- | compiler/sem.nim | 11 | ||||
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/seminst.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 17 | ||||
-rw-r--r-- | compiler/semtypes.nim | 6 | ||||
-rw-r--r-- | tests/template/tparams_gensymed.nim | 40 |
9 files changed, 82 insertions, 23 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 40a05e6bf..0247acb03 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1087,9 +1087,6 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, result.id = getID() when debugIds: registerId(result) - #if result.id == 77131: - # writeStacktrace() - # echo name.s proc isMetaType*(t: PType): bool = return t.kind in tyMetaTypes or @@ -1261,6 +1258,9 @@ proc `$`*(x: TLockLevel): string = elif x.ord == UnknownLockLevel.ord: result = "<unknown>" else: result = $int16(x) +proc `$`*(s: PSym): string = + result = s.name.s & "@" & $s.id + proc newType*(kind: TTypeKind, owner: PSym): PType = new(result) result.kind = kind diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 09a1cd436..0f9220102 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -37,18 +37,21 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = case templ.kind of nkSym: var s = templ.sym - if s.owner.id == c.owner.id: + if s.owner == nil or s.owner.id == c.owner.id: if s.kind == skParam and sfGenSym notin s.flags: handleParam actual.sons[s.position] - elif s.kind == skGenericParam or - s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam: + elif (s.owner != nil) and (s.kind == skGenericParam or + s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam): handleParam actual.sons[s.owner.typ.len + s.position - 1] else: internalAssert c.config, sfGenSym in s.flags or s.kind == skType var x = PSym(idTableGet(c.mapping, s)) if x == nil: x = copySym(s) - x.owner = c.genSymOwner + # sem'check needs to set the owner properly later, see bug #9476 + x.owner = nil # c.genSymOwner + #if x.kind == skParam and x.owner.kind == skModule: + # internalAssert c.config, false idTablePut(c.mapping, s, x) result.add newSymNode(x, if c.instLines: actual.info else: templ.info) else: @@ -173,6 +176,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; initIdTable(ctx.mapping) let body = tmpl.getBody + #echo "instantion of ", renderTree(body, {renderIds}) if isAtom(body): result = newNodeI(nkPar, body.info) evalTemplateAux(body, args, ctx, result) @@ -189,5 +193,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; evalTemplateAux(body.sons[i], args, ctx, result) result.flags.incl nfFromTemplate result = wrapInComesFrom(n.info, tmpl, result) + #if ctx.debugActive: + # echo "instantion of ", renderTree(result, {renderIds}) dec(conf.evalTemplateCounter) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 874cb4bd0..ddde1be31 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -407,11 +407,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = obj.n[0].sym.id = -s.id else: addField(obj, s, c.graph.cache) - # but always return because the rest of the proc is only relevant when - # ow != owner: - return # direct or indirect dependency: - if (innerProc and s.typ.callConv == ccClosure) or interestingVar(s): + elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s): discard """ proc outer() = var x: int diff --git a/compiler/sem.nim b/compiler/sem.nim index 924e53b66..8332af346 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -207,11 +207,12 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = if result.kind notin {kind, skTemp}: localError(c.config, 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 false: + 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/semexprs.nim b/compiler/semexprs.nim index 08917cb29..ddec457a1 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1083,6 +1083,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = # XXX see the hack in sigmatch.nim ... return s.typ.n elif sfGenSym in s.flags: + # the owner should have been set by now by addParamOrResult + internalAssert c.config, s.owner != nil if c.p.wasForwarded: # gensym'ed parameters that nevertheless have been forward declared # need a special fixup: @@ -2289,6 +2291,8 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode = var labl = newSymG(skLabel, n.sons[0], c) if sfGenSym notin labl.flags: addDecl(c, labl) + elif labl.owner == nil: + labl.owner = c.p.owner n.sons[0] = newSymNode(labl, n.sons[0].info) suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym) styleCheckDef(c.config, labl) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 17f61c7dd..09991048e 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -116,7 +116,7 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = var x = PSym(idTableGet(symMap, s)) if x != nil: n.sym = x - elif s.owner.kind == skPackage: + elif s.owner == nil or s.owner.kind == skPackage: #echo "copied this ", s.name.s x = copySym(s) x.owner = owner diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 48aa75528..2e2a3a20a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -497,8 +497,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var v = semIdentDef(c, a.sons[j], symkind) styleCheckDef(c.config, v) onDef(a[j].info, v) - if sfGenSym notin v.flags and not isDiscardUnderscore(v): - addInterfaceDecl(c, v) + if sfGenSym notin v.flags: + if not isDiscardUnderscore(v): addInterfaceDecl(c, v) + else: + if v.owner == nil: v.owner = c.p.owner when oKeepVariableNames: if c.inUnrolledContext > 0: v.flags.incl(sfShadowed) else: @@ -573,6 +575,7 @@ proc semConst(c: PContext, n: PNode): PNode = setVarType(c, v, typ) v.ast = def # no need to copy if sfGenSym notin v.flags: addInterfaceDecl(c, v) + elif v.owner == nil: v.owner = getCurrOwner(c) var b = newNodeI(nkConstDef, a.info) if importantComments(c.config): b.comment = a.comment addSon(b, newSymNode(v)) @@ -616,6 +619,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = v.typ = iterBase n.sons[0] = newSymNode(v) if sfGenSym notin v.flags: addForVarDecl(c, v) + elif v.owner == nil: v.owner = getCurrOwner(c) else: localError(c.config, n.info, errWrongNumberOfVariables) elif length-2 != sonsLen(iter): @@ -626,8 +630,9 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal) v.typ = iter.sons[i] n.sons[i] = newSymNode(v) - if sfGenSym notin v.flags and not isDiscardUnderscore(v): - addForVarDecl(c, v) + if sfGenSym notin v.flags: + if not isDiscardUnderscore(v): addForVarDecl(c, v) + elif v.owner == nil: v.owner = getCurrOwner(c) inc(c.p.nestedLoopCounter) openScope(c) n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags) @@ -922,6 +927,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = s = typsym # add it here, so that recursive types are possible: if sfGenSym notin s.flags: addInterfaceDecl(c, s) + elif s.owner == nil: s.owner = getCurrOwner(c) if name.kind == nkPragmaExpr: a.sons[0].sons[0] = newSymNode(s) @@ -1620,7 +1626,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, else: s.typ.callConv = lastOptionEntry(c).defaultCC # add it here, so that recursive procs are possible: - if sfGenSym in s.flags: discard + if sfGenSym in s.flags: + if s.owner == nil: s.owner = getCurrOwner(c) elif kind in OverloadableSyms: if not typeIsDetermined: addInterfaceOverloadableSymAt(c, oldScope, s) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a011a8fc8..1e75b563e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -821,7 +821,11 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = a.typ = nn.typ addDecl(c, a) else: - if sfGenSym notin param.flags: addDecl(c, param) + if sfGenSym in param.flags: + # bug #XXX, fix the gensym'ed parameters owner: + if param.owner == nil: + param.owner = getCurrOwner(c) + else: addDecl(c, param) template shouldHaveMeta(t) = internalAssert c.config, tfHasMeta in t.flags diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index da86d63dc..91fa26596 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -70,3 +70,43 @@ proc genericProc(x: any) = concreteProc(7) # This works genericProc(7) # This doesn't compile + +import tables + +# bug #9476 +proc getTypeInfo*(T: typedesc): pointer = + var dummy: T + getTypeInfo(dummy) + + +macro implementUnary(op: untyped): untyped = + result = newStmtList() + + template defineTable(tableSymbol) = + var tableSymbol = initTable[pointer, pointer]() + let tableSymbol = genSym(nskVar, "registeredProcs") + result.add(getAst(defineTable(tableSymbol))) + + template defineRegisterInstantiation(tableSym, regTemplSym, instSym, op) = + template regTemplSym*(T: typedesc) = + let ti = getTypeInfo(T) + + proc instSym(xOrig: int): int {.gensym, cdecl.} = + let x {.inject.} = xOrig + op + + tableSym[ti] = cast[pointer](instSym) + + let regTemplSymbol = ident("registerInstantiation") + let instSymbol = ident("instantiation") + result.add(getAst(defineRegisterInstantiation( + tableSymbol, regTemplSymbol, instSymbol, op + ))) + + echo result.repr + + +implementUnary(): x*x + +registerInstantiation(int) +registerInstantiation(float) |