diff options
Diffstat (limited to 'compiler/lambdalifting.nim')
-rw-r--r-- | compiler/lambdalifting.nim | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 36ad2e0a6..692d9265b 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -139,10 +139,10 @@ proc createStateField(iter: PSym): PSym = result = newSym(skField, getIdent(":state"), iter, iter.info) result.typ = createStateType(iter) -proc createEnvObj(owner: PSym): PType = +proc createEnvObj(owner: PSym; info: TLineInfo): PType = # YYY meh, just add the state field for every closure for now, it's too # hard to figure out if it comes from a closure iterator: - result = createObj(owner, owner.info) + result = createObj(owner, info) rawAddField(result, createStateField(owner)) proc getIterResult(iter: PSym): PSym = @@ -296,18 +296,19 @@ This is why need to store the 'ownerToType' table and use it during .closure'fication. """ -proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym): PType = +proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym; + info: TLineInfo): PType = result = c.ownerToType.getOrDefault(owner.id) if result.isNil: result = newType(tyRef, owner) - let obj = createEnvObj(owner) + let obj = createEnvObj(owner, info) rawAddSon(result, obj) c.ownerToType[owner.id] = result -proc createUpField(c: var DetectionPass; dest, dep: PSym) = - let refObj = c.getEnvTypeForOwner(dest) # getHiddenParam(dest).typ +proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = + let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ let obj = refObj.lastSon - let fieldType = c.getEnvTypeForOwner(dep) #getHiddenParam(dep).typ + let fieldType = c.getEnvTypeForOwner(dep, info) #getHiddenParam(dep).typ if refObj == fieldType: localError(dep.info, "internal error: invalid up reference computed") @@ -347,10 +348,10 @@ Consider: """ -proc addClosureParam(c: var DetectionPass; fn: PSym) = +proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) = var cp = getEnvParam(fn) let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner - let t = c.getEnvTypeForOwner(owner) + let t = c.getEnvTypeForOwner(owner, info) if cp == nil: cp = newSym(skParam, getIdent(paramName), fn, fn.info) incl(cp.flags, sfFromGeneric) @@ -367,7 +368,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = if s.kind in {skProc, skMethod, skConverter, skIterator} and s.typ != nil and s.typ.callConv == ccClosure: # this handles the case that the inner proc was declared as # .closure but does not actually capture anything: - addClosureParam(c, s) + addClosureParam(c, s, n.info) c.somethingToDo = true let innerProc = isInnerProc(s) @@ -379,7 +380,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = if ow == owner: if owner.isIterator: c.somethingToDo = true - addClosureParam(c, owner) + addClosureParam(c, owner, n.info) if interestingIterVar(s): if not c.capturedVars.containsOrIncl(s.id): let obj = getHiddenParam(owner).typ.lastSon @@ -403,11 +404,11 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = # mark 'owner' as taking a closure: c.somethingToDo = true markAsClosure(owner, n) - addClosureParam(c, owner) + addClosureParam(c, owner, n.info) #echo "capturing ", n.info # variable 's' is actually captured: if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id): - let obj = c.getEnvTypeForOwner(ow).lastSon + let obj = c.getEnvTypeForOwner(ow, n.info).lastSon #getHiddenParam(owner).typ.lastSon addField(obj, s) # create required upFields: @@ -428,8 +429,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = let up = w.skipGenericOwner #echo "up for ", w.name.s, " up ", up.name.s markAsClosure(w, n) - addClosureParam(c, w) # , ow - createUpField(c, w, up) + addClosureParam(c, w, n.info) # , ow + createUpField(c, w, up, n.info) w = up of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkTemplateDef, nkTypeSection: @@ -793,7 +794,7 @@ proc liftLambdas*(fn: PSym, body: PNode; tooEarly: var bool): PNode = var d = initDetectionPass(fn) detectCapturedVars(body, fn, d) if not d.somethingToDo and fn.isIterator: - addClosureParam(d, fn) + addClosureParam(d, fn, body.info) d.somethingToDo = true if d.somethingToDo: var c = initLiftingPass(fn) |