closure types get names; refs #4332
This commit is contained in:
parent
c5a336741c
commit
c743b2969f
2 changed files with 21 additions and 16 deletions
|
|
@ -139,10 +139,10 @@ proc createStateField(iter: PSym): PSym =
|
||||||
result = newSym(skField, getIdent(":state"), iter, iter.info)
|
result = newSym(skField, getIdent(":state"), iter, iter.info)
|
||||||
result.typ = createStateType(iter)
|
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
|
# 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:
|
# hard to figure out if it comes from a closure iterator:
|
||||||
result = createObj(owner, owner.info)
|
result = createObj(owner, info)
|
||||||
rawAddField(result, createStateField(owner))
|
rawAddField(result, createStateField(owner))
|
||||||
|
|
||||||
proc getIterResult(iter: PSym): PSym =
|
proc getIterResult(iter: PSym): PSym =
|
||||||
|
|
@ -296,18 +296,19 @@ This is why need to store the 'ownerToType' table and use it
|
||||||
during .closure'fication.
|
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)
|
result = c.ownerToType.getOrDefault(owner.id)
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
result = newType(tyRef, owner)
|
result = newType(tyRef, owner)
|
||||||
let obj = createEnvObj(owner)
|
let obj = createEnvObj(owner, info)
|
||||||
rawAddSon(result, obj)
|
rawAddSon(result, obj)
|
||||||
c.ownerToType[owner.id] = result
|
c.ownerToType[owner.id] = result
|
||||||
|
|
||||||
proc createUpField(c: var DetectionPass; dest, dep: PSym) =
|
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||||
let refObj = c.getEnvTypeForOwner(dest) # getHiddenParam(dest).typ
|
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
|
||||||
let obj = refObj.lastSon
|
let obj = refObj.lastSon
|
||||||
let fieldType = c.getEnvTypeForOwner(dep) #getHiddenParam(dep).typ
|
let fieldType = c.getEnvTypeForOwner(dep, info) #getHiddenParam(dep).typ
|
||||||
if refObj == fieldType:
|
if refObj == fieldType:
|
||||||
localError(dep.info, "internal error: invalid up reference computed")
|
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)
|
var cp = getEnvParam(fn)
|
||||||
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
|
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
|
||||||
let t = c.getEnvTypeForOwner(owner)
|
let t = c.getEnvTypeForOwner(owner, info)
|
||||||
if cp == nil:
|
if cp == nil:
|
||||||
cp = newSym(skParam, getIdent(paramName), fn, fn.info)
|
cp = newSym(skParam, getIdent(paramName), fn, fn.info)
|
||||||
incl(cp.flags, sfFromGeneric)
|
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:
|
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
|
# this handles the case that the inner proc was declared as
|
||||||
# .closure but does not actually capture anything:
|
# .closure but does not actually capture anything:
|
||||||
addClosureParam(c, s)
|
addClosureParam(c, s, n.info)
|
||||||
c.somethingToDo = true
|
c.somethingToDo = true
|
||||||
|
|
||||||
let innerProc = isInnerProc(s)
|
let innerProc = isInnerProc(s)
|
||||||
|
|
@ -379,7 +380,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||||
if ow == owner:
|
if ow == owner:
|
||||||
if owner.isIterator:
|
if owner.isIterator:
|
||||||
c.somethingToDo = true
|
c.somethingToDo = true
|
||||||
addClosureParam(c, owner)
|
addClosureParam(c, owner, n.info)
|
||||||
if interestingIterVar(s):
|
if interestingIterVar(s):
|
||||||
if not c.capturedVars.containsOrIncl(s.id):
|
if not c.capturedVars.containsOrIncl(s.id):
|
||||||
let obj = getHiddenParam(owner).typ.lastSon
|
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:
|
# mark 'owner' as taking a closure:
|
||||||
c.somethingToDo = true
|
c.somethingToDo = true
|
||||||
markAsClosure(owner, n)
|
markAsClosure(owner, n)
|
||||||
addClosureParam(c, owner)
|
addClosureParam(c, owner, n.info)
|
||||||
#echo "capturing ", n.info
|
#echo "capturing ", n.info
|
||||||
# variable 's' is actually captured:
|
# variable 's' is actually captured:
|
||||||
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
|
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
|
#getHiddenParam(owner).typ.lastSon
|
||||||
addField(obj, s)
|
addField(obj, s)
|
||||||
# create required upFields:
|
# create required upFields:
|
||||||
|
|
@ -428,8 +429,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||||
let up = w.skipGenericOwner
|
let up = w.skipGenericOwner
|
||||||
#echo "up for ", w.name.s, " up ", up.name.s
|
#echo "up for ", w.name.s, " up ", up.name.s
|
||||||
markAsClosure(w, n)
|
markAsClosure(w, n)
|
||||||
addClosureParam(c, w) # , ow
|
addClosureParam(c, w, n.info) # , ow
|
||||||
createUpField(c, w, up)
|
createUpField(c, w, up, n.info)
|
||||||
w = up
|
w = up
|
||||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
|
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||||
nkTemplateDef, nkTypeSection:
|
nkTemplateDef, nkTypeSection:
|
||||||
|
|
@ -793,7 +794,7 @@ proc liftLambdas*(fn: PSym, body: PNode; tooEarly: var bool): PNode =
|
||||||
var d = initDetectionPass(fn)
|
var d = initDetectionPass(fn)
|
||||||
detectCapturedVars(body, fn, d)
|
detectCapturedVars(body, fn, d)
|
||||||
if not d.somethingToDo and fn.isIterator:
|
if not d.somethingToDo and fn.isIterator:
|
||||||
addClosureParam(d, fn)
|
addClosureParam(d, fn, body.info)
|
||||||
d.somethingToDo = true
|
d.somethingToDo = true
|
||||||
if d.somethingToDo:
|
if d.somethingToDo:
|
||||||
var c = initLiftingPass(fn)
|
var c = initLiftingPass(fn)
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,10 @@ proc createObj*(owner: PSym, info: TLineInfo): PType =
|
||||||
rawAddSon(result, nil)
|
rawAddSon(result, nil)
|
||||||
incl result.flags, tfFinal
|
incl result.flags, tfFinal
|
||||||
result.n = newNodeI(nkRecList, info)
|
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) =
|
proc rawAddField*(obj: PType; field: PSym) =
|
||||||
assert field.kind == skField
|
assert field.kind == skField
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue