mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-27 17:53:58 +00:00
closure types get names; refs #4332
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -114,6 +114,10 @@ proc createObj*(owner: PSym, info: TLineInfo): PType =
|
||||
rawAddSon(result, nil)
|
||||
incl result.flags, tfFinal
|
||||
result.n = newNodeI(nkRecList, info)
|
||||
let s = newSym(skType, getIdent("Env_" & info.toFilename & "_" & $info.line),
|
||||
owner, info)
|
||||
s.typ = result
|
||||
result.sym = s
|
||||
|
||||
proc rawAddField*(obj: PType; field: PSym) =
|
||||
assert field.kind == skField
|
||||
|
||||
Reference in New Issue
Block a user