diff options
Diffstat (limited to 'compiler/lambdalifting.nim')
-rw-r--r-- | compiler/lambdalifting.nim | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 180c5531b..6f0f8e0a5 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -261,7 +261,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = let envParam = getHiddenParam(g, owner) - let obj = envParam.typ.lastSon + let obj = envParam.typ.skipTypes({tyOwned, tyRef}) addField(obj, s, g.cache) var access = newSymNode(envParam) @@ -320,15 +320,23 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym; rawAddSon(result, obj) c.ownerToType[owner.id] = result +proc asOwnedRef(c: DetectionPass; t: PType): PType = + if optNimV2 in c.graph.config.globalOptions: + assert t.kind == tyRef + result = newType(tyOwned, t.owner) + result.rawAddSon t + else: + result = t + proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym; info: TLineInfo): PType = var r = c.getEnvTypeForOwner(owner, info) result = newType(tyPtr, owner) - rawAddSon(result, r.base) + rawAddSon(result, r.skipTypes({tyOwned, tyRef})) proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ - let obj = refObj.lastSon + let obj = refObj.skipTypes({tyOwned, tyRef}) # The assumption here is that gcDestructors means we cannot deal # with cycles properly, so it's better to produce a weak ref (=ptr) here. # This seems to be generally correct but since it's a bit risky it's only @@ -343,7 +351,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = let upIdent = getIdent(c.graph.cache, upName) let upField = lookupInRecord(obj.n, upIdent) if upField != nil: - if upField.typ.base != fieldType.base: + if upField.typ.skipTypes({tyOwned, tyRef}) != fieldType.skipTypes({tyOwned, tyRef}): localError(c.graph.config, dep.info, "internal error: up references do not agree") else: let result = newSym(skField, upIdent, obj.owner, obj.owner.info) @@ -414,8 +422,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = addClosureParam(c, owner, n.info) if interestingIterVar(s): if not c.capturedVars.containsOrIncl(s.id): - let obj = getHiddenParam(c.graph, owner).typ.lastSon - #let obj = c.getEnvTypeForOwner(s.owner).lastSon + let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef}) + #let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef}) if s.name.id == getIdent(c.graph.cache, ":state").id: obj.n[0].sym.id = -s.id @@ -440,8 +448,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = #echo "capturing ", n.info # variable 's' is actually captured: if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id): - let obj = c.getEnvTypeForOwner(ow, n.info).lastSon - #getHiddenParam(owner).typ.lastSon + let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef}) + #getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef}) addField(obj, s, c.graph.cache) # create required upFields: var w = owner.skipGenericOwner @@ -530,14 +538,14 @@ proc setupEnvVar(owner: PSym; d: DetectionPass; let envVarType = d.ownerToType.getOrDefault(owner.id) if envVarType.isNil: localError d.graph.config, owner.info, "internal error: could not determine closure type" - result = newEnvVar(d.graph.cache, owner, envVarType) + result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType)) c.envVars[owner.id] = result proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode = let p = getHiddenParam(g, owner) result = p.newSymNode if owner.isIterator: - let upField = lookupInRecord(p.typ.lastSon.n, getIdent(g.cache, upName)) + let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef}).n, getIdent(g.cache, upName)) if upField == nil: localError(g.config, owner.info, "could not find up reference for closure iter") else: @@ -566,10 +574,10 @@ proc rawClosureCreation(owner: PSym; # add ``env.param = param`` result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) - let upField = lookupInRecord(env.typ.lastSon.n, getIdent(d.graph.cache, upName)) + let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName)) if upField != nil: let up = getUpViaParam(d.graph, owner) - if up != nil and upField.typ.base == up.typ.base: + if up != nil and upField.typ.skipTypes({tyOwned, tyRef}) == up.typ.skipTypes({tyOwned, tyRef}): result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info), up, env.info)) #elif oldenv != nil and oldenv.typ == upField.typ: @@ -584,11 +592,11 @@ proc closureCreationForIter(iter: PNode; let owner = iter.sym.skipGenericOwner var v = newSym(skVar, getIdent(d.graph.cache, envName), owner, iter.info) incl(v.flags, sfShadowed) - v.typ = getHiddenParam(d.graph, iter.sym).typ + v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ) var vnode: PNode if owner.isIterator: let it = getHiddenParam(d.graph, owner) - addUniqueField(it.typ.sons[0], v, d.graph.cache) + addUniqueField(it.typ.skipTypes({tyOwned, tyRef}), v, d.graph.cache) vnode = indirectAccess(newSymNode(it), v, v.info) else: vnode = v.newSymNode @@ -597,10 +605,10 @@ proc closureCreationForIter(iter: PNode; result.add(vs) result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode)) - let upField = lookupInRecord(v.typ.lastSon.n, getIdent(d.graph.cache, upName)) + let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName)) if upField != nil: let u = setupEnvVar(owner, d, c) - if u.typ.base == upField.typ.base: + if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}): result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info), u, iter.info)) else: @@ -610,7 +618,7 @@ proc closureCreationForIter(iter: PNode; proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass; c: var LiftingPass): PNode = let access = setupEnvVar(owner, d, c) - let obj = access.typ.sons[0] + let obj = access.typ.skipTypes({tyOwned, tyRef}) let field = getFieldFromObj(obj, n.sym) if field != nil: result = rawIndirectAccess(access, field, n.info) @@ -619,7 +627,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass; result = n proc getStateField*(g: ModuleGraph; owner: PSym): PSym = - getHiddenParam(g, owner).typ.sons[0].n.sons[0].sym + getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef}).n.sons[0].sym proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; c: var LiftingPass): PNode @@ -644,7 +652,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass; while true: if access.typ == wanted: return makeClosure(d.graph, s, access, n.info) - let obj = access.typ.sons[0] + let obj = access.typ.skipTypes({tyOwned, tyRef}) let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName)) if upField == nil: localError(d.graph.config, n.info, "internal error: no environment found") |