Skip to content
Permalink
Browse files

fixes nested gensym'ed parameters; fixes #9476

  • Loading branch information...
Araq committed Dec 8, 2018
1 parent 7a0191a commit e8747059710370819800bdc0742fa86761c6737b
@@ -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
@@ -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)

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

0 comments on commit e874705

Please sign in to comment.
You can’t perform that action at this time.