fixes nested gensym'ed parameters; fixes #9476
This commit is contained in:
parent
7a0191ac7e
commit
e874705971
9 changed files with 82 additions and 23 deletions
|
|
@ -1087,9 +1087,6 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
when debugIds:
|
when debugIds:
|
||||||
registerId(result)
|
registerId(result)
|
||||||
#if result.id == 77131:
|
|
||||||
# writeStacktrace()
|
|
||||||
# echo name.s
|
|
||||||
|
|
||||||
proc isMetaType*(t: PType): bool =
|
proc isMetaType*(t: PType): bool =
|
||||||
return t.kind in tyMetaTypes or
|
return t.kind in tyMetaTypes or
|
||||||
|
|
@ -1261,6 +1258,9 @@ proc `$`*(x: TLockLevel): string =
|
||||||
elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
|
elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
|
||||||
else: result = $int16(x)
|
else: result = $int16(x)
|
||||||
|
|
||||||
|
proc `$`*(s: PSym): string =
|
||||||
|
result = s.name.s & "@" & $s.id
|
||||||
|
|
||||||
proc newType*(kind: TTypeKind, owner: PSym): PType =
|
proc newType*(kind: TTypeKind, owner: PSym): PType =
|
||||||
new(result)
|
new(result)
|
||||||
result.kind = kind
|
result.kind = kind
|
||||||
|
|
|
||||||
|
|
@ -37,18 +37,21 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||||
case templ.kind
|
case templ.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var s = templ.sym
|
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:
|
if s.kind == skParam and sfGenSym notin s.flags:
|
||||||
handleParam actual.sons[s.position]
|
handleParam actual.sons[s.position]
|
||||||
elif s.kind == skGenericParam or
|
elif (s.owner != nil) and (s.kind == skGenericParam or
|
||||||
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam:
|
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
|
||||||
handleParam actual.sons[s.owner.typ.len + s.position - 1]
|
handleParam actual.sons[s.owner.typ.len + s.position - 1]
|
||||||
else:
|
else:
|
||||||
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
|
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
|
||||||
var x = PSym(idTableGet(c.mapping, s))
|
var x = PSym(idTableGet(c.mapping, s))
|
||||||
if x == nil:
|
if x == nil:
|
||||||
x = copySym(s)
|
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)
|
idTablePut(c.mapping, s, x)
|
||||||
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
|
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
|
||||||
else:
|
else:
|
||||||
|
|
@ -173,6 +176,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||||
initIdTable(ctx.mapping)
|
initIdTable(ctx.mapping)
|
||||||
|
|
||||||
let body = tmpl.getBody
|
let body = tmpl.getBody
|
||||||
|
#echo "instantion of ", renderTree(body, {renderIds})
|
||||||
if isAtom(body):
|
if isAtom(body):
|
||||||
result = newNodeI(nkPar, body.info)
|
result = newNodeI(nkPar, body.info)
|
||||||
evalTemplateAux(body, args, ctx, result)
|
evalTemplateAux(body, args, ctx, result)
|
||||||
|
|
@ -189,5 +193,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||||
evalTemplateAux(body.sons[i], args, ctx, result)
|
evalTemplateAux(body.sons[i], args, ctx, result)
|
||||||
result.flags.incl nfFromTemplate
|
result.flags.incl nfFromTemplate
|
||||||
result = wrapInComesFrom(n.info, tmpl, result)
|
result = wrapInComesFrom(n.info, tmpl, result)
|
||||||
|
#if ctx.debugActive:
|
||||||
|
# echo "instantion of ", renderTree(result, {renderIds})
|
||||||
dec(conf.evalTemplateCounter)
|
dec(conf.evalTemplateCounter)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -407,11 +407,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||||
obj.n[0].sym.id = -s.id
|
obj.n[0].sym.id = -s.id
|
||||||
else:
|
else:
|
||||||
addField(obj, s, c.graph.cache)
|
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:
|
# 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 """
|
discard """
|
||||||
proc outer() =
|
proc outer() =
|
||||||
var x: int
|
var x: int
|
||||||
|
|
|
||||||
|
|
@ -207,11 +207,12 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||||
if result.kind notin {kind, skTemp}:
|
if result.kind notin {kind, skTemp}:
|
||||||
localError(c.config, n.info, "cannot use symbol of kind '" &
|
localError(c.config, n.info, "cannot use symbol of kind '" &
|
||||||
$result.kind & "' as a '" & $kind & "'")
|
$result.kind & "' as a '" & $kind & "'")
|
||||||
if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
|
when false:
|
||||||
# declarative context, so produce a fresh gensym:
|
if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
|
||||||
result = copySym(result)
|
# declarative context, so produce a fresh gensym:
|
||||||
result.ast = n.sym.ast
|
result = copySym(result)
|
||||||
put(c.p, n.sym, result)
|
result.ast = n.sym.ast
|
||||||
|
put(c.p, n.sym, result)
|
||||||
# when there is a nested proc inside a template, semtmpl
|
# when there is a nested proc inside a template, semtmpl
|
||||||
# will assign a wrong owner during the first pass over the
|
# will assign a wrong owner during the first pass over the
|
||||||
# template; we must fix it here: see #909
|
# 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 ...
|
# XXX see the hack in sigmatch.nim ...
|
||||||
return s.typ.n
|
return s.typ.n
|
||||||
elif sfGenSym in s.flags:
|
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:
|
if c.p.wasForwarded:
|
||||||
# gensym'ed parameters that nevertheless have been forward declared
|
# gensym'ed parameters that nevertheless have been forward declared
|
||||||
# need a special fixup:
|
# 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)
|
var labl = newSymG(skLabel, n.sons[0], c)
|
||||||
if sfGenSym notin labl.flags:
|
if sfGenSym notin labl.flags:
|
||||||
addDecl(c, labl)
|
addDecl(c, labl)
|
||||||
|
elif labl.owner == nil:
|
||||||
|
labl.owner = c.p.owner
|
||||||
n.sons[0] = newSymNode(labl, n.sons[0].info)
|
n.sons[0] = newSymNode(labl, n.sons[0].info)
|
||||||
suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym)
|
suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym)
|
||||||
styleCheckDef(c.config, labl)
|
styleCheckDef(c.config, labl)
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
|
||||||
var x = PSym(idTableGet(symMap, s))
|
var x = PSym(idTableGet(symMap, s))
|
||||||
if x != nil:
|
if x != nil:
|
||||||
n.sym = x
|
n.sym = x
|
||||||
elif s.owner.kind == skPackage:
|
elif s.owner == nil or s.owner.kind == skPackage:
|
||||||
#echo "copied this ", s.name.s
|
#echo "copied this ", s.name.s
|
||||||
x = copySym(s)
|
x = copySym(s)
|
||||||
x.owner = owner
|
x.owner = owner
|
||||||
|
|
|
||||||
|
|
@ -497,8 +497,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
var v = semIdentDef(c, a.sons[j], symkind)
|
var v = semIdentDef(c, a.sons[j], symkind)
|
||||||
styleCheckDef(c.config, v)
|
styleCheckDef(c.config, v)
|
||||||
onDef(a[j].info, v)
|
onDef(a[j].info, v)
|
||||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v):
|
if sfGenSym notin v.flags:
|
||||||
addInterfaceDecl(c, v)
|
if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
|
||||||
|
else:
|
||||||
|
if v.owner == nil: v.owner = c.p.owner
|
||||||
when oKeepVariableNames:
|
when oKeepVariableNames:
|
||||||
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
|
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
|
||||||
else:
|
else:
|
||||||
|
|
@ -573,6 +575,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||||
setVarType(c, v, typ)
|
setVarType(c, v, typ)
|
||||||
v.ast = def # no need to copy
|
v.ast = def # no need to copy
|
||||||
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
||||||
|
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||||
var b = newNodeI(nkConstDef, a.info)
|
var b = newNodeI(nkConstDef, a.info)
|
||||||
if importantComments(c.config): b.comment = a.comment
|
if importantComments(c.config): b.comment = a.comment
|
||||||
addSon(b, newSymNode(v))
|
addSon(b, newSymNode(v))
|
||||||
|
|
@ -616,6 +619,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||||
v.typ = iterBase
|
v.typ = iterBase
|
||||||
n.sons[0] = newSymNode(v)
|
n.sons[0] = newSymNode(v)
|
||||||
if sfGenSym notin v.flags: addForVarDecl(c, v)
|
if sfGenSym notin v.flags: addForVarDecl(c, v)
|
||||||
|
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||||
else:
|
else:
|
||||||
localError(c.config, n.info, errWrongNumberOfVariables)
|
localError(c.config, n.info, errWrongNumberOfVariables)
|
||||||
elif length-2 != sonsLen(iter):
|
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)
|
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||||
v.typ = iter.sons[i]
|
v.typ = iter.sons[i]
|
||||||
n.sons[i] = newSymNode(v)
|
n.sons[i] = newSymNode(v)
|
||||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v):
|
if sfGenSym notin v.flags:
|
||||||
addForVarDecl(c, v)
|
if not isDiscardUnderscore(v): addForVarDecl(c, v)
|
||||||
|
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||||
inc(c.p.nestedLoopCounter)
|
inc(c.p.nestedLoopCounter)
|
||||||
openScope(c)
|
openScope(c)
|
||||||
n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
|
n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
|
||||||
|
|
@ -922,6 +927,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
||||||
s = typsym
|
s = typsym
|
||||||
# add it here, so that recursive types are possible:
|
# add it here, so that recursive types are possible:
|
||||||
if sfGenSym notin s.flags: addInterfaceDecl(c, s)
|
if sfGenSym notin s.flags: addInterfaceDecl(c, s)
|
||||||
|
elif s.owner == nil: s.owner = getCurrOwner(c)
|
||||||
|
|
||||||
if name.kind == nkPragmaExpr:
|
if name.kind == nkPragmaExpr:
|
||||||
a.sons[0].sons[0] = newSymNode(s)
|
a.sons[0].sons[0] = newSymNode(s)
|
||||||
|
|
@ -1620,7 +1626,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
else:
|
else:
|
||||||
s.typ.callConv = lastOptionEntry(c).defaultCC
|
s.typ.callConv = lastOptionEntry(c).defaultCC
|
||||||
# add it here, so that recursive procs are possible:
|
# 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:
|
elif kind in OverloadableSyms:
|
||||||
if not typeIsDetermined:
|
if not typeIsDetermined:
|
||||||
addInterfaceOverloadableSymAt(c, oldScope, s)
|
addInterfaceOverloadableSymAt(c, oldScope, s)
|
||||||
|
|
|
||||||
|
|
@ -821,7 +821,11 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||||
a.typ = nn.typ
|
a.typ = nn.typ
|
||||||
addDecl(c, a)
|
addDecl(c, a)
|
||||||
else:
|
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) =
|
template shouldHaveMeta(t) =
|
||||||
internalAssert c.config, tfHasMeta in t.flags
|
internalAssert c.config, tfHasMeta in t.flags
|
||||||
|
|
|
||||||
|
|
@ -70,3 +70,43 @@ proc genericProc(x: any) =
|
||||||
|
|
||||||
concreteProc(7) # This works
|
concreteProc(7) # This works
|
||||||
genericProc(7) # This doesn't compile
|
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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue