mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-01 03:24:41 +00:00
fixes nested gensym'ed parameters; fixes #9476
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user