From 8324b7a86de1aeb3c7bcf872c70591e5be1efb3c Mon Sep 17 00:00:00 2001 From: narimiran Date: Wed, 6 Nov 2019 09:44:26 +0100 Subject: [PATCH] port the whole 'lambdalifting.nim' from devel --- compiler/lambdalifting.nim | 61 +++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index e25aaa4e2c..ebd8843246 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -233,6 +233,10 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} = let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro result = conf.cmd == cmdCompileToJS and not isCompileTime +proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo) = + createTypeBoundOps(g, nil, refType.lastSon, info) + createTypeBoundOps(g, nil, refType, info) + proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = # transforms (iter) to (let env = newClosure[iter](); (iter, env)) if liftingHarmful(g.config, owner): return n @@ -245,7 +249,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = var env: PNode if owner.isIterator: let it = getHiddenParam(g, owner) - addUniqueField(it.typ.sons[0], hp, g.cache) + addUniqueField(it.typ.skipTypes({tyOwned}).sons[0], hp, g.cache) env = indirectAccess(newSymNode(it), hp, hp.info) else: let e = newSym(skLet, iter.name, owner, n.info) @@ -262,7 +266,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.skipTypes({tyOwned, tyRef}) + let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr}) addField(obj, s, g.cache) var access = newSymNode(envParam) @@ -322,7 +326,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym; c.ownerToType[owner.id] = result proc asOwnedRef(c: DetectionPass; t: PType): PType = - if optNimV2 in c.graph.config.globalOptions: + if optOwnedRefs in c.graph.config.globalOptions: assert t.kind == tyRef result = newType(tyOwned, t.owner) result.flags.incl tfHasOwned @@ -334,16 +338,17 @@ proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym; info: TLineInfo): PType = var r = c.getEnvTypeForOwner(owner, info) result = newType(tyPtr, owner) - rawAddSon(result, r.skipTypes({tyOwned, tyRef})) + rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr})) proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ - let obj = refObj.skipTypes({tyOwned, tyRef}) + let obj = refObj.skipTypes({tyOwned, tyRef, tyPtr}) # 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 - # enabled for gcDestructors. - let fieldType = if false: # c.graph.config.selectedGC == gcDestructors: + # This seems to be generally correct but since it's a bit risky it's disabled + # for now. + let fieldType = if isDefined(c.graph.config, "nimCycleBreaker") or + c.graph.config.selectedGC == gcDestructors: c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ else: c.getEnvTypeForOwner(dep, info) @@ -353,7 +358,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.skipTypes({tyOwned, tyRef}) != fieldType.skipTypes({tyOwned, tyRef}): + if upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) != fieldType.skipTypes({tyOwned, tyRef, tyPtr}): localError(c.graph.config, dep.info, "internal error: up references do not agree") else: let result = newSym(skField, upIdent, obj.owner, obj.owner.info) @@ -424,8 +429,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.skipTypes({tyOwned, tyRef}) - #let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef}) + let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}) + #let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr}) if s.name.id == getIdent(c.graph.cache, ":state").id: obj.n[0].sym.id = -s.id @@ -450,8 +455,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).skipTypes({tyOwned, tyRef}) - #getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef}) + let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr}) + #getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr}) addField(obj, s, c.graph.cache) # create required upFields: var w = owner.skipGenericOwner @@ -541,7 +546,7 @@ proc setupEnvVar(owner: PSym; d: DetectionPass; localError d.graph.config, owner.info, "internal error: could not determine closure type" result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info) c.envVars[owner.id] = result - if optNimV2 in d.graph.config.globalOptions: + if optOwnedRefs in d.graph.config.globalOptions: var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), owner, info) v.flags = {sfShadowed, sfGeneratedOp} v.typ = envVarType @@ -551,7 +556,7 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode = let p = getHiddenParam(g, owner) result = p.newSymNode if owner.isIterator: - let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef}).n, getIdent(g.cache, upName)) + let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(g.cache, upName)) if upField == nil: localError(g.config, owner.info, "could not find up reference for closure iter") else: @@ -571,20 +576,20 @@ proc rawClosureCreation(owner: PSym; var v = newNodeI(nkVarSection, env.info) addVar(v, env) result.add(v) - if optNimV2 in d.graph.config.globalOptions: + if optOwnedRefs in d.graph.config.globalOptions: let unowned = c.unownedEnvVars[owner.id] assert unowned != nil addVar(v, unowned) # add 'new' statement: result.add(newCall(getSysSym(d.graph, env.info, "internalNew"), env)) - if optNimV2 in d.graph.config.globalOptions: + if optOwnedRefs in d.graph.config.globalOptions: let unowned = c.unownedEnvVars[owner.id] assert unowned != nil let env2 = copyTree(env) env2.typ = unowned.typ result.add newAsgnStmt(unowned, env2, env.info) - createTypeBoundOps(d.graph, nil, unowned.typ, env.info) + createTypeBoundOpsLL(d.graph, unowned.typ, env.info) # add assignment statements for captured parameters: for i in 1..