fixes nested gensym'ed parameters; fixes #9476

This commit is contained in:
Araq
2018-12-08 13:30:06 +01:00
parent 7a0191ac7e
commit e874705971
9 changed files with 82 additions and 23 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)