[refactoring] liftdestructors.nim is callable from lambdalifting; refs #11217
This commit is contained in:
parent
e4d0f4fee0
commit
b056d32a79
3 changed files with 120 additions and 104 deletions
|
|
@ -12,7 +12,7 @@
|
||||||
import
|
import
|
||||||
intsets, strutils, options, ast, astalgo, trees, treetab, msgs,
|
intsets, strutils, options, ast, astalgo, trees, treetab, msgs,
|
||||||
idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos,
|
idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos,
|
||||||
transf
|
transf, liftdestructors
|
||||||
|
|
||||||
discard """
|
discard """
|
||||||
The basic approach is that captured vars need to be put on the heap and
|
The basic approach is that captured vars need to be put on the heap and
|
||||||
|
|
@ -583,6 +583,11 @@ proc rawClosureCreation(owner: PSym;
|
||||||
# oldenv, env.info))
|
# oldenv, env.info))
|
||||||
else:
|
else:
|
||||||
localError(d.graph.config, env.info, "internal error: cannot create up reference")
|
localError(d.graph.config, env.info, "internal error: cannot create up reference")
|
||||||
|
# we are not in the sem'check phase anymore! so pass 'nil' for the PContext
|
||||||
|
# and hope for the best:
|
||||||
|
when false:
|
||||||
|
if optNimV2 in d.graph.config.globalOptions:
|
||||||
|
createTypeBoundOps(d.graph, nil, env.typ, owner.info)
|
||||||
|
|
||||||
proc closureCreationForIter(iter: PNode;
|
proc closureCreationForIter(iter: PNode;
|
||||||
d: DetectionPass; c: var LiftingPass): PNode =
|
d: DetectionPass; c: var LiftingPass): PNode =
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,19 @@ import modulegraphs, lineinfos, idents, ast, astalgo, renderer, semdata,
|
||||||
|
|
||||||
type
|
type
|
||||||
TLiftCtx = object
|
TLiftCtx = object
|
||||||
graph: ModuleGraph
|
g: ModuleGraph
|
||||||
info: TLineInfo # for construction
|
info: TLineInfo # for construction
|
||||||
kind: TTypeAttachedOp
|
kind: TTypeAttachedOp
|
||||||
fn: PSym
|
fn: PSym
|
||||||
asgnForType: PType
|
asgnForType: PType
|
||||||
recurse: bool
|
recurse: bool
|
||||||
c: PContext
|
c: PContext # c can be nil, then we are called from lambdalifting!
|
||||||
|
|
||||||
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
|
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
|
||||||
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
info: TLineInfo): PSym
|
info: TLineInfo): PSym
|
||||||
|
|
||||||
proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo)
|
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo)
|
||||||
|
|
||||||
proc at(a, i: PNode, elemType: PType): PNode =
|
proc at(a, i: PNode, elemType: PType): PNode =
|
||||||
result = newNodeI(nkBracketExpr, a.info, 2)
|
result = newNodeI(nkBracketExpr, a.info, 2)
|
||||||
|
|
@ -40,7 +40,7 @@ proc at(a, i: PNode, elemType: PType): PNode =
|
||||||
|
|
||||||
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
for i in 0 ..< t.len:
|
for i in 0 ..< t.len:
|
||||||
let lit = lowerings.newIntLit(c.graph, x.info, i)
|
let lit = lowerings.newIntLit(c.g, x.info, i)
|
||||||
fillBody(c, t.sons[i], body, x.at(lit, t.sons[i]), y.at(lit, t.sons[i]))
|
fillBody(c, t.sons[i], body, x.at(lit, t.sons[i]), y.at(lit, t.sons[i]))
|
||||||
|
|
||||||
proc dotField(x: PNode, f: PSym): PNode =
|
proc dotField(x: PNode, f: PSym): PNode =
|
||||||
|
|
@ -87,7 +87,7 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for t in items(n): fillBodyObj(c, t, body, x, y)
|
for t in items(n): fillBodyObj(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
illFormedAstLocal(n, c.graph.config)
|
illFormedAstLocal(n, c.g.config)
|
||||||
|
|
||||||
proc genAddr(g: ModuleGraph; x: PNode): PNode =
|
proc genAddr(g: ModuleGraph; x: PNode): PNode =
|
||||||
if x.kind == nkHiddenDeref:
|
if x.kind == nkHiddenDeref:
|
||||||
|
|
@ -124,20 +124,28 @@ proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
|
||||||
result = newAsgnStmt(x, newOpCall(op, y))
|
result = newAsgnStmt(x, newOpCall(op, y))
|
||||||
|
|
||||||
proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} =
|
proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} =
|
||||||
result = optNimV2 in c.graph.config.globalOptions and
|
result = optNimV2 in c.g.config.globalOptions and
|
||||||
({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem)
|
({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem)
|
||||||
|
|
||||||
|
proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
|
||||||
|
if c.c != nil and typeInst != nil:
|
||||||
|
result = c.c.instTypeBoundOp(c.c, op, typeInst, c.info, attachedAsgn, 1)
|
||||||
|
else:
|
||||||
|
localError(c.g.config, c.info,
|
||||||
|
"cannot generate destructor for generic type: " & typeToString(t))
|
||||||
|
result = nil
|
||||||
|
|
||||||
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||||
field: var PSym): bool =
|
field: var PSym): bool =
|
||||||
if optNimV2 in c.graph.config.globalOptions:
|
if optNimV2 in c.g.config.globalOptions:
|
||||||
let op = field
|
let op = field
|
||||||
if field != nil and sfOverriden in field.flags:
|
if field != nil and sfOverriden in field.flags:
|
||||||
if sfError in op.flags:
|
if sfError in op.flags:
|
||||||
incl c.fn.flags, sfError
|
incl c.fn.flags, sfError
|
||||||
#else:
|
#else:
|
||||||
# markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
# markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
body.add newAsgnCall(c.graph, op, x, y)
|
body.add newAsgnCall(c.g, op, x, y)
|
||||||
result = true
|
result = true
|
||||||
elif tfHasAsgn in t.flags:
|
elif tfHasAsgn in t.flags:
|
||||||
var op: PSym
|
var op: PSym
|
||||||
|
|
@ -151,38 +159,37 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||||
else:
|
else:
|
||||||
op = field
|
op = field
|
||||||
if op == nil:
|
if op == nil:
|
||||||
op = produceSym(c.c, t, c.kind, c.info)
|
op = produceSym(c.g, c.c, t, c.kind, c.info)
|
||||||
if sfError in op.flags:
|
if sfError in op.flags:
|
||||||
incl c.fn.flags, sfError
|
incl c.fn.flags, sfError
|
||||||
#else:
|
#else:
|
||||||
# markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
# markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
# We also now do generic instantiations in the destructor lifting pass:
|
# We also now do generic instantiations in the destructor lifting pass:
|
||||||
if op.ast[genericParamsPos].kind != nkEmpty:
|
if op.ast[genericParamsPos].kind != nkEmpty:
|
||||||
assert t.typeInst != nil
|
op = instantiateGeneric(c, op, t, t.typeInst)
|
||||||
op = c.c.instTypeBoundOp(c.c, op, t.typeInst, c.info, attachedAsgn, 1)
|
|
||||||
field = op
|
field = op
|
||||||
#echo "trying to use ", op.ast
|
#echo "trying to use ", op.ast
|
||||||
#echo "for ", op.name.s, " "
|
#echo "for ", op.name.s, " "
|
||||||
#debug(t)
|
#debug(t)
|
||||||
#return false
|
#return false
|
||||||
assert op.ast[genericParamsPos].kind == nkEmpty
|
assert op.ast[genericParamsPos].kind == nkEmpty
|
||||||
body.add newAsgnCall(c.graph, op, x, y)
|
body.add newAsgnCall(c.g, op, x, y)
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode) =
|
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode) =
|
||||||
var op = t.destructor
|
var op = t.destructor
|
||||||
if op == nil and useNoGc(c, t):
|
if op == nil and useNoGc(c, t):
|
||||||
op = produceSym(c.c, t, attachedDestructor, c.info)
|
op = produceSym(c.g, c.c, t, attachedDestructor, c.info)
|
||||||
doAssert op != nil
|
doAssert op != nil
|
||||||
doAssert op == t.destructor
|
doAssert op == t.destructor
|
||||||
|
|
||||||
if op != nil:
|
if op != nil:
|
||||||
#markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
#markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
body.add destructorCall(c.graph, op, x)
|
body.add destructorCall(c.g, op, x)
|
||||||
elif useNoGc(c, t):
|
elif useNoGc(c, t):
|
||||||
internalError(c.graph.config, c.info,
|
internalError(c.g.config, c.info,
|
||||||
"type-bound operator could not be resolved")
|
"type-bound operator could not be resolved")
|
||||||
|
|
||||||
proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
|
|
@ -192,14 +199,13 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
if op != nil and sfOverriden in op.flags:
|
if op != nil and sfOverriden in op.flags:
|
||||||
|
|
||||||
if op.ast[genericParamsPos].kind != nkEmpty:
|
if op.ast[genericParamsPos].kind != nkEmpty:
|
||||||
assert t.typeInst != nil
|
|
||||||
# patch generic destructor:
|
# patch generic destructor:
|
||||||
op = c.c.instTypeBoundOp(c.c, op, t.typeInst, c.info, attachedAsgn, 1)
|
op = instantiateGeneric(c, op, t, t.typeInst)
|
||||||
t.attachedOps[attachedDestructor] = op
|
t.attachedOps[attachedDestructor] = op
|
||||||
|
|
||||||
#markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
#markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
body.add destructorCall(c.graph, op, x)
|
body.add destructorCall(c.g, op, x)
|
||||||
result = true
|
result = true
|
||||||
#result = addDestructorCall(c, t, body, x)
|
#result = addDestructorCall(c, t, body, x)
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
|
|
@ -209,7 +215,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
of attachedDeepCopy:
|
of attachedDeepCopy:
|
||||||
let op = t.attachedOps[attachedDeepCopy]
|
let op = t.attachedOps[attachedDeepCopy]
|
||||||
if op != nil:
|
if op != nil:
|
||||||
#markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
#markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
body.add newDeepCopyCall(op, x, y)
|
body.add newDeepCopyCall(op, x, y)
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -226,13 +232,13 @@ proc addVar(father, v, value: PNode) =
|
||||||
addSon(father, vpart)
|
addSon(father, vpart)
|
||||||
|
|
||||||
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||||
var temp = newSym(skTemp, getIdent(c.graph.cache, lowerings.genPrefix), c.fn, c.info)
|
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
|
||||||
temp.typ = getSysType(c.graph, body.info, tyInt)
|
temp.typ = getSysType(c.g, body.info, tyInt)
|
||||||
incl(temp.flags, sfFromGeneric)
|
incl(temp.flags, sfFromGeneric)
|
||||||
|
|
||||||
var v = newNodeI(nkVarSection, c.info)
|
var v = newNodeI(nkVarSection, c.info)
|
||||||
result = newSymNode(temp)
|
result = newSymNode(temp)
|
||||||
v.addVar(result, lowerings.newIntLit(c.graph, body.info, first))
|
v.addVar(result, lowerings.newIntLit(c.g, body.info, first))
|
||||||
body.add v
|
body.add v
|
||||||
|
|
||||||
proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
|
proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
|
||||||
|
|
@ -242,9 +248,9 @@ proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
|
||||||
|
|
||||||
proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
|
proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
|
||||||
result = newNodeI(nkWhileStmt, c.info, 2)
|
result = newNodeI(nkWhileStmt, c.info, 2)
|
||||||
let cmp = genBuiltin(c.graph, mLtI, "<", i)
|
let cmp = genBuiltin(c.g, mLtI, "<", i)
|
||||||
cmp.add genLen(c.graph, dest)
|
cmp.add genLen(c.g, dest)
|
||||||
cmp.typ = getSysType(c.graph, c.info, tyBool)
|
cmp.typ = getSysType(c.g, c.info, tyBool)
|
||||||
result.sons[0] = cmp
|
result.sons[0] = cmp
|
||||||
result.sons[1] = newNodeI(nkStmtList, c.info)
|
result.sons[1] = newNodeI(nkStmtList, c.info)
|
||||||
|
|
||||||
|
|
@ -252,8 +258,8 @@ proc genIf(c: var TLiftCtx; cond, action: PNode): PNode =
|
||||||
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action))
|
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action))
|
||||||
|
|
||||||
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
|
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
|
||||||
let incCall = genBuiltin(c.graph, mInc, "inc", i)
|
let incCall = genBuiltin(c.g, mInc, "inc", i)
|
||||||
incCall.add lowerings.newIntLit(c.graph, c.info, 1)
|
incCall.add lowerings.newIntLit(c.g, c.info, 1)
|
||||||
body.add incCall
|
body.add incCall
|
||||||
|
|
||||||
proc newSeqCall(g: ModuleGraph; x, y: PNode): PNode =
|
proc newSeqCall(g: ModuleGraph; x, y: PNode): PNode =
|
||||||
|
|
@ -270,14 +276,14 @@ proc setLenStrCall(g: ModuleGraph; x, y: PNode): PNode =
|
||||||
result.add lenCall
|
result.add lenCall
|
||||||
|
|
||||||
proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
||||||
let lenCall = genBuiltin(c.graph, mLengthSeq, "len", y)
|
let lenCall = genBuiltin(c.g, mLengthSeq, "len", y)
|
||||||
lenCall.typ = getSysType(c.graph, x.info, tyInt)
|
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||||
var op = getSysMagic(c.graph, x.info, "setLen", mSetLengthSeq)
|
var op = getSysMagic(c.g, x.info, "setLen", mSetLengthSeq)
|
||||||
op = c.c.instTypeBoundOp(c.c, op, t, c.info, attachedAsgn, 1)
|
op = instantiateGeneric(c, op, t, t)
|
||||||
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
||||||
|
|
||||||
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
let i = declareCounter(c, body, firstOrd(c.graph.config, t))
|
let i = declareCounter(c, body, firstOrd(c.g.config, t))
|
||||||
let whileLoop = genWhileLoop(c, i, x)
|
let whileLoop = genWhileLoop(c, i, x)
|
||||||
let elemType = t.lastSon
|
let elemType = t.lastSon
|
||||||
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
|
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
|
||||||
|
|
@ -296,63 +302,63 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
body.add setLenSeqCall(c, t, x, y)
|
body.add setLenSeqCall(c, t, x, y)
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
let moveCall = genBuiltin(c.graph, mMove, "move", x)
|
let moveCall = genBuiltin(c.g, mMove, "move", x)
|
||||||
moveCall.add y
|
moveCall.add y
|
||||||
doAssert t.destructor != nil
|
doAssert t.destructor != nil
|
||||||
moveCall.add destructorCall(c.graph, t.destructor, x)
|
moveCall.add destructorCall(c.g, t.destructor, x)
|
||||||
body.add moveCall
|
body.add moveCall
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
# destroy all elements:
|
# destroy all elements:
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
body.add genBuiltin(c.graph, mDestroy, "destroy", x)
|
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
||||||
|
|
||||||
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
createTypeBoundOps(c.c, t, body.info)
|
createTypeBoundOps(c.g, c.c, t, body.info)
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedAsgn, attachedDeepCopy:
|
of attachedAsgn, attachedDeepCopy:
|
||||||
doAssert t.assignment != nil
|
doAssert t.assignment != nil
|
||||||
body.add newAsgnCall(c.graph, t.assignment, x, y)
|
body.add newAsgnCall(c.g, t.assignment, x, y)
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
# we always inline the move for better performance:
|
# we always inline the move for better performance:
|
||||||
let moveCall = genBuiltin(c.graph, mMove, "move", x)
|
let moveCall = genBuiltin(c.g, mMove, "move", x)
|
||||||
moveCall.add y
|
moveCall.add y
|
||||||
doAssert t.destructor != nil
|
doAssert t.destructor != nil
|
||||||
moveCall.add destructorCall(c.graph, t.destructor, x)
|
moveCall.add destructorCall(c.g, t.destructor, x)
|
||||||
body.add moveCall
|
body.add moveCall
|
||||||
# alternatively we could do this:
|
# alternatively we could do this:
|
||||||
when false:
|
when false:
|
||||||
doAssert t.asink != nil
|
doAssert t.asink != nil
|
||||||
body.add newAsgnCall(c.graph, t.asink, x, y)
|
body.add newAsgnCall(c.g, t.asink, x, y)
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
doAssert t.destructor != nil
|
doAssert t.destructor != nil
|
||||||
body.add destructorCall(c.graph, t.destructor, x)
|
body.add destructorCall(c.g, t.destructor, x)
|
||||||
|
|
||||||
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedAsgn, attachedDeepCopy:
|
of attachedAsgn, attachedDeepCopy:
|
||||||
body.add callCodegenProc(c.graph, "nimAsgnStrV2", c.info, genAddr(c.graph, x), y)
|
body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c.g, x), y)
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
let moveCall = genBuiltin(c.graph, mMove, "move", x)
|
let moveCall = genBuiltin(c.g, mMove, "move", x)
|
||||||
moveCall.add y
|
moveCall.add y
|
||||||
doAssert t.destructor != nil
|
doAssert t.destructor != nil
|
||||||
moveCall.add destructorCall(c.graph, t.destructor, x)
|
moveCall.add destructorCall(c.g, t.destructor, x)
|
||||||
body.add moveCall
|
body.add moveCall
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
body.add genBuiltin(c.graph, mDestroy, "destroy", x)
|
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
||||||
|
|
||||||
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
# we 'nil' y out afterwards so we *need* to take over its reference
|
# we 'nil' y out afterwards so we *need* to take over its reference
|
||||||
# count value:
|
# count value:
|
||||||
body.add genIf(c, x, callCodegenProc(c.graph, "nimDecWeakRef", c.info, x))
|
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
body.add genIf(c, y, callCodegenProc(c.graph, "nimIncWeakRef", c.info, y))
|
body.add genIf(c, y, callCodegenProc(c.g, "nimIncWeakRef", c.info, y))
|
||||||
body.add genIf(c, x, callCodegenProc(c.graph, "nimDecWeakRef", c.info, x))
|
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
body.add genIf(c, x, callCodegenProc(c.graph, "nimDecWeakRef", c.info, x))
|
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
||||||
of attachedDeepCopy: assert(false, "cannot happen")
|
of attachedDeepCopy: assert(false, "cannot happen")
|
||||||
|
|
||||||
proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
|
@ -360,14 +366,14 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
|
||||||
let elemType = t.lastSon
|
let elemType = t.lastSon
|
||||||
#fillBody(c, elemType, actions, genDeref(x), genDeref(y))
|
#fillBody(c, elemType, actions, genDeref(x), genDeref(y))
|
||||||
#var disposeCall = genBuiltin(c.graph, mDispose, "dispose", x)
|
#var disposeCall = genBuiltin(c.g, mDispose, "dispose", x)
|
||||||
|
|
||||||
if isFinal(elemType):
|
if isFinal(elemType):
|
||||||
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
||||||
actions.add callCodegenProc(c.graph, "nimRawDispose", c.info, x)
|
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
|
||||||
else:
|
else:
|
||||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||||
actions.add callCodegenProc(c.graph, "nimDestroyAndDispose", c.info, x)
|
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
|
||||||
|
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedSink, attachedAsgn:
|
of attachedSink, attachedAsgn:
|
||||||
|
|
@ -383,35 +389,35 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
# have to go through some indirection; we delegate this to the codegen:
|
# have to go through some indirection; we delegate this to the codegen:
|
||||||
let call = newNodeI(nkCall, c.info, 2)
|
let call = newNodeI(nkCall, c.info, 2)
|
||||||
call.typ = t
|
call.typ = t
|
||||||
call.sons[0] = newSymNode(createMagic(c.graph, "deepCopy", mDeepCopy))
|
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
|
||||||
call.sons[1] = y
|
call.sons[1] = y
|
||||||
body.add newAsgnStmt(x, call)
|
body.add newAsgnStmt(x, call)
|
||||||
elif optNimV2 in c.graph.config.globalOptions:
|
elif optNimV2 in c.g.config.globalOptions:
|
||||||
let xx = genBuiltin(c.graph, mAccessEnv, "accessEnv", x)
|
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||||
xx.typ = getSysType(c.graph, c.info, tyPointer)
|
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
# we 'nil' y out afterwards so we *need* to take over its reference
|
# we 'nil' y out afterwards so we *need* to take over its reference
|
||||||
# count value:
|
# count value:
|
||||||
body.add genIf(c, xx, callCodegenProc(c.graph, "nimDecWeakRef", c.info, xx))
|
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
let yy = genBuiltin(c.graph, mAccessEnv, "accessEnv", y)
|
let yy = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
|
||||||
yy.typ = getSysType(c.graph, c.info, tyPointer)
|
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
body.add genIf(c, yy, callCodegenProc(c.graph, "nimIncWeakRef", c.info, yy))
|
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncWeakRef", c.info, yy))
|
||||||
body.add genIf(c, xx, callCodegenProc(c.graph, "nimDecWeakRef", c.info, xx))
|
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
body.add genIf(c, xx, callCodegenProc(c.graph, "nimDecWeakRef", c.info, xx))
|
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||||
of attachedDeepCopy: assert(false, "cannot happen")
|
of attachedDeepCopy: assert(false, "cannot happen")
|
||||||
|
|
||||||
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
let xx = genBuiltin(c.graph, mAccessEnv, "accessEnv", x)
|
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||||
xx.typ = getSysType(c.graph, c.info, tyPointer)
|
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
var actions = newNodeI(nkStmtList, c.info)
|
var actions = newNodeI(nkStmtList, c.info)
|
||||||
let elemType = t.lastSon
|
let elemType = t.lastSon
|
||||||
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
|
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
|
||||||
actions.add callCodegenProc(c.graph, "nimDestroyAndDispose", c.info, xx)
|
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedSink, attachedAsgn:
|
of attachedSink, attachedAsgn:
|
||||||
body.add genIf(c, xx, actions)
|
body.add genIf(c, xx, actions)
|
||||||
|
|
@ -427,7 +433,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
tyPtr, tyOpt, tyUncheckedArray:
|
tyPtr, tyOpt, tyUncheckedArray:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyRef:
|
of tyRef:
|
||||||
if optNimV2 in c.graph.config.globalOptions:
|
if optNimV2 in c.g.config.globalOptions:
|
||||||
weakrefOp(c, t, body, x, y)
|
weakrefOp(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
|
|
@ -438,7 +444,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyOwned:
|
of tyOwned:
|
||||||
let base = t.skipTypes(abstractInstOwned)
|
let base = t.skipTypes(abstractInstOwned)
|
||||||
if optNimV2 in c.graph.config.globalOptions:
|
if optNimV2 in c.g.config.globalOptions:
|
||||||
case base.kind
|
case base.kind
|
||||||
of tyRef:
|
of tyRef:
|
||||||
ownedRefOp(c, base, body, x, y)
|
ownedRefOp(c, base, body, x, y)
|
||||||
|
|
@ -457,13 +463,13 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if useNoGc(c, t):
|
if useNoGc(c, t):
|
||||||
useSeqOrStrOp(c, t, body, x, y)
|
useSeqOrStrOp(c, t, body, x, y)
|
||||||
elif c.graph.config.selectedGC == gcDestructors:
|
elif c.g.config.selectedGC == gcDestructors:
|
||||||
# note that tfHasAsgn is propagated so we need the check on
|
# note that tfHasAsgn is propagated so we need the check on
|
||||||
# 'selectedGC' here to determine if we have the new runtime.
|
# 'selectedGC' here to determine if we have the new runtime.
|
||||||
discard considerUserDefinedOp(c, t, body, x, y)
|
discard considerUserDefinedOp(c, t, body, x, y)
|
||||||
elif tfHasAsgn in t.flags:
|
elif tfHasAsgn in t.flags:
|
||||||
if c.kind != attachedDestructor:
|
if c.kind != attachedDestructor:
|
||||||
body.add newSeqCall(c.graph, x, y)
|
body.add newSeqCall(c.g, x, y)
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
|
|
@ -483,12 +489,12 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
fillBodyTup(c, t, body, x, y)
|
fillBodyTup(c, t, body, x, y)
|
||||||
of tyVarargs, tyOpenArray:
|
of tyVarargs, tyOpenArray:
|
||||||
localError(c.graph.config, c.info, "cannot copy openArray")
|
localError(c.g.config, c.info, "cannot copy openArray")
|
||||||
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
||||||
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
|
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
|
||||||
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
|
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
|
||||||
tyTypeDesc, tyGenericInvocation, tyForward:
|
tyTypeDesc, tyGenericInvocation, tyForward:
|
||||||
#internalError(c.graph.config, c.info, "assignment requested for type: " & typeToString(t))
|
#internalError(c.g.config, c.info, "assignment requested for type: " & typeToString(t))
|
||||||
discard
|
discard
|
||||||
of tyVar, tyLent:
|
of tyVar, tyLent:
|
||||||
if c.kind != attachedDestructor:
|
if c.kind != attachedDestructor:
|
||||||
|
|
@ -497,25 +503,24 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
tyGenericInst, tyStatic, tyAlias, tySink:
|
tyGenericInst, tyStatic, tyAlias, tySink:
|
||||||
fillBody(c, lastSon(t), body, x, y)
|
fillBody(c, lastSon(t), body, x, y)
|
||||||
|
|
||||||
proc produceSymDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
||||||
assert typ.kind == tyDistinct
|
assert typ.kind == tyDistinct
|
||||||
let baseType = typ[0]
|
let baseType = typ[0]
|
||||||
if baseType.attachedOps[kind] == nil:
|
if baseType.attachedOps[kind] == nil:
|
||||||
discard produceSym(c, baseType, kind, info)
|
discard produceSym(g, c, baseType, kind, info)
|
||||||
typ.attachedOps[kind] = baseType.attachedOps[kind]
|
typ.attachedOps[kind] = baseType.attachedOps[kind]
|
||||||
result = typ.attachedOps[kind]
|
result = typ.attachedOps[kind]
|
||||||
|
|
||||||
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
if typ.kind == tyDistinct:
|
if typ.kind == tyDistinct:
|
||||||
return produceSymDistinctType(c, typ, kind, info)
|
return produceSymDistinctType(g, c, typ, kind, info)
|
||||||
|
|
||||||
var a: TLiftCtx
|
var a: TLiftCtx
|
||||||
a.info = info
|
a.info = info
|
||||||
a.graph = c.graph
|
a.g = g
|
||||||
a.kind = kind
|
a.kind = kind
|
||||||
a.c = c
|
a.c = c
|
||||||
let g = c.graph
|
|
||||||
let body = newNodeI(nkStmtList, info)
|
let body = newNodeI(nkStmtList, info)
|
||||||
let procname = getIdent(g.cache, AttachedOpToStr[kind])
|
let procname = getIdent(g.cache, AttachedOpToStr[kind])
|
||||||
|
|
||||||
|
|
@ -537,7 +542,7 @@ proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
typ.attachedOps[kind] = result
|
typ.attachedOps[kind] = result
|
||||||
|
|
||||||
var tk: TTypeKind
|
var tk: TTypeKind
|
||||||
if optNimV2 in c.graph.config.globalOptions:
|
if optNimV2 in g.config.globalOptions:
|
||||||
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
||||||
else:
|
else:
|
||||||
tk = tyNone # no special casing for strings and seqs
|
tk = tyNone # no special casing for strings and seqs
|
||||||
|
|
@ -561,33 +566,39 @@ proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
||||||
discard "now a nop"
|
discard "now a nop"
|
||||||
|
|
||||||
proc patchBody(c: PContext; n: PNode; info: TLineInfo) =
|
proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) =
|
||||||
if n.kind in nkCallKinds:
|
if n.kind in nkCallKinds:
|
||||||
if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
|
if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
|
||||||
let t = n[1].typ.skipTypes(abstractVar)
|
let t = n[1].typ.skipTypes(abstractVar)
|
||||||
if t.destructor == nil:
|
if t.destructor == nil:
|
||||||
discard produceSym(c, t, attachedDestructor, info)
|
discard produceSym(g, c, t, attachedDestructor, info)
|
||||||
|
|
||||||
if t.destructor != nil:
|
if t.destructor != nil:
|
||||||
if t.destructor.ast[genericParamsPos].kind != nkEmpty:
|
if t.destructor.ast[genericParamsPos].kind != nkEmpty:
|
||||||
internalError(c.graph.config, info, "resolved destructor is generic")
|
internalError(g.config, info, "resolved destructor is generic")
|
||||||
if t.destructor.magic == mDestroy:
|
if t.destructor.magic == mDestroy:
|
||||||
internalError(c.graph.config, info, "patching mDestroy with mDestroy?")
|
internalError(g.config, info, "patching mDestroy with mDestroy?")
|
||||||
n.sons[0] = newSymNode(t.destructor)
|
n.sons[0] = newSymNode(t.destructor)
|
||||||
for x in n: patchBody(c, x, info)
|
for x in n: patchBody(g, c, x, info)
|
||||||
|
|
||||||
template inst(field, t) =
|
template inst(field, t) =
|
||||||
if field.ast != nil and field.ast[genericParamsPos].kind != nkEmpty:
|
if field.ast != nil and field.ast[genericParamsPos].kind != nkEmpty:
|
||||||
if t.typeInst != nil:
|
if t.typeInst != nil:
|
||||||
field = c.instTypeBoundOp(c, field, t.typeInst, info, attachedAsgn, 1)
|
var a: TLiftCtx
|
||||||
|
a.info = info
|
||||||
|
a.g = g
|
||||||
|
a.kind = k
|
||||||
|
a.c = c
|
||||||
|
|
||||||
|
field = instantiateGeneric(a, field, t, t.typeInst)
|
||||||
if field.ast != nil:
|
if field.ast != nil:
|
||||||
patchBody(c, field.ast, info)
|
patchBody(g, c, field.ast, info)
|
||||||
else:
|
else:
|
||||||
localError(c.graph.config, info, "unresolved generic parameter")
|
localError(g.config, info, "unresolved generic parameter")
|
||||||
|
|
||||||
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
|
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
|
||||||
|
|
||||||
proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
|
||||||
## In the semantic pass this is called in strategic places
|
## In the semantic pass this is called in strategic places
|
||||||
## to ensure we lift assignment, destructors and moves properly.
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
## The later 'injectdestructors' pass depends on it.
|
## The later 'injectdestructors' pass depends on it.
|
||||||
|
|
@ -595,11 +606,11 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
incl orig.flags, tfCheckedForDestructor
|
incl orig.flags, tfCheckedForDestructor
|
||||||
|
|
||||||
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned, CoDistinct})
|
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned, CoDistinct})
|
||||||
var canon = c.graph.canonTypes.getOrDefault(h)
|
var canon = g.canonTypes.getOrDefault(h)
|
||||||
var overwrite = false
|
var overwrite = false
|
||||||
if canon == nil:
|
if canon == nil:
|
||||||
let typ = orig.skipTypes({tyGenericInst, tyAlias})
|
let typ = orig.skipTypes({tyGenericInst, tyAlias})
|
||||||
c.graph.canonTypes[h] = typ
|
g.canonTypes[h] = typ
|
||||||
canon = typ
|
canon = typ
|
||||||
elif canon != orig:
|
elif canon != orig:
|
||||||
overwrite = true
|
overwrite = true
|
||||||
|
|
@ -614,7 +625,7 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
# we generate the destructor first so that other operators can depend on it:
|
# we generate the destructor first so that other operators can depend on it:
|
||||||
for k in attachedDestructor..attachedSink:
|
for k in attachedDestructor..attachedSink:
|
||||||
if canon.attachedOps[k] == nil:
|
if canon.attachedOps[k] == nil:
|
||||||
discard produceSym(c, canon, k, info)
|
discard produceSym(g, c, canon, k, info)
|
||||||
else:
|
else:
|
||||||
inst(canon.attachedOps[k], canon)
|
inst(canon.attachedOps[k], canon)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -709,7 +709,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
return
|
return
|
||||||
if n.typ != nil:
|
if n.typ != nil:
|
||||||
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||||
createTypeBoundOps(tracked.c, n.typ, n.info)
|
createTypeBoundOps(tracked.graph, tracked.c, n.typ, n.info)
|
||||||
if a.kind == nkCast and a[1].typ.kind == tyProc:
|
if a.kind == nkCast and a[1].typ.kind == tyProc:
|
||||||
a = a[1]
|
a = a[1]
|
||||||
# XXX: in rare situations, templates and macros will reach here after
|
# XXX: in rare situations, templates and macros will reach here after
|
||||||
|
|
@ -770,18 +770,18 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
notNilCheck(tracked, n.sons[1], n.sons[0].typ)
|
notNilCheck(tracked, n.sons[1], n.sons[0].typ)
|
||||||
when false: cstringCheck(tracked, n)
|
when false: cstringCheck(tracked, n)
|
||||||
if tracked.owner.kind != skMacro:
|
if tracked.owner.kind != skMacro:
|
||||||
createTypeBoundOps(tracked.c, n[0].typ, n.info)
|
createTypeBoundOps(tracked.graph, tracked.c, n[0].typ, n.info)
|
||||||
of nkVarSection, nkLetSection:
|
of nkVarSection, nkLetSection:
|
||||||
for child in n:
|
for child in n:
|
||||||
let last = lastSon(child)
|
let last = lastSon(child)
|
||||||
if last.kind != nkEmpty: track(tracked, last)
|
if last.kind != nkEmpty: track(tracked, last)
|
||||||
if tracked.owner.kind != skMacro:
|
if tracked.owner.kind != skMacro:
|
||||||
if child.kind == nkVarTuple:
|
if child.kind == nkVarTuple:
|
||||||
createTypeBoundOps(tracked.c, child[^1].typ, child.info)
|
createTypeBoundOps(tracked.graph, tracked.c, child[^1].typ, child.info)
|
||||||
for i in 0..child.len-3:
|
for i in 0..child.len-3:
|
||||||
createTypeBoundOps(tracked.c, child[i].typ, child.info)
|
createTypeBoundOps(tracked.graph, tracked.c, child[i].typ, child.info)
|
||||||
else:
|
else:
|
||||||
createTypeBoundOps(tracked.c, child[0].typ, child.info)
|
createTypeBoundOps(tracked.graph, tracked.c, child[0].typ, child.info)
|
||||||
if child.kind == nkIdentDefs and last.kind != nkEmpty:
|
if child.kind == nkIdentDefs and last.kind != nkEmpty:
|
||||||
for i in 0 .. child.len-3:
|
for i in 0 .. child.len-3:
|
||||||
initVar(tracked, child.sons[i], volatileCheck=false)
|
initVar(tracked, child.sons[i], volatileCheck=false)
|
||||||
|
|
@ -827,15 +827,15 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
if tracked.owner.kind != skMacro:
|
if tracked.owner.kind != skMacro:
|
||||||
if it.kind == nkVarTuple:
|
if it.kind == nkVarTuple:
|
||||||
for x in it:
|
for x in it:
|
||||||
createTypeBoundOps(tracked.c, x.typ, x.info)
|
createTypeBoundOps(tracked.graph, tracked.c, x.typ, x.info)
|
||||||
else:
|
else:
|
||||||
createTypeBoundOps(tracked.c, it.typ, it.info)
|
createTypeBoundOps(tracked.graph, tracked.c, it.typ, it.info)
|
||||||
let iterCall = n[n.len-2]
|
let iterCall = n[n.len-2]
|
||||||
let loopBody = n[n.len-1]
|
let loopBody = n[n.len-1]
|
||||||
if tracked.owner.kind != skMacro and iterCall.safelen > 1:
|
if tracked.owner.kind != skMacro and iterCall.safelen > 1:
|
||||||
# XXX this is a bit hacky:
|
# XXX this is a bit hacky:
|
||||||
if iterCall[1].typ != nil and iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}:
|
if iterCall[1].typ != nil and iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}:
|
||||||
createTypeBoundOps(tracked.c, iterCall[1].typ, iterCall[1].info)
|
createTypeBoundOps(tracked.graph, tracked.c, iterCall[1].typ, iterCall[1].info)
|
||||||
track(tracked, iterCall)
|
track(tracked, iterCall)
|
||||||
track(tracked, loopBody)
|
track(tracked, loopBody)
|
||||||
setLen(tracked.init, oldState)
|
setLen(tracked.init, oldState)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue