further progress on closure iterators; tforum still failing
This commit is contained in:
parent
1ad69be988
commit
813f98fb34
3 changed files with 34 additions and 18 deletions
|
|
@ -238,8 +238,6 @@ proc liftIterSym*(n: PNode; owner: PSym): PNode =
|
||||||
var v = newNodeI(nkVarSection, n.info)
|
var v = newNodeI(nkVarSection, n.info)
|
||||||
addVar(v, newSymNode(env))
|
addVar(v, newSymNode(env))
|
||||||
result.add(v)
|
result.add(v)
|
||||||
# leave room for optional up reference setup:
|
|
||||||
result.add(ast.emptyNode)
|
|
||||||
# add 'new' statement:
|
# add 'new' statement:
|
||||||
let envAsNode = env.newSymNode
|
let envAsNode = env.newSymNode
|
||||||
result.add newCall(getSysSym"internalNew", envAsNode)
|
result.add newCall(getSysSym"internalNew", envAsNode)
|
||||||
|
|
@ -289,7 +287,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym) =
|
||||||
let obj = refObj.lastSon
|
let obj = refObj.lastSon
|
||||||
let fieldType = c.getEnvTypeForOwner(dep) #getHiddenParam(dep).typ
|
let fieldType = c.getEnvTypeForOwner(dep) #getHiddenParam(dep).typ
|
||||||
if refObj == fieldType:
|
if refObj == fieldType:
|
||||||
localError(dep.info, "internal error: invald up reference computed")
|
localError(dep.info, "internal error: invalid up reference computed")
|
||||||
|
|
||||||
let upIdent = getIdent(upName)
|
let upIdent = getIdent(upName)
|
||||||
let upField = lookupInRecord(obj.n, upIdent)
|
let upField = lookupInRecord(obj.n, upIdent)
|
||||||
|
|
@ -338,7 +336,7 @@ proc addClosureParam(c: var DetectionPass; fn: PSym) =
|
||||||
addHiddenParam(fn, cp)
|
addHiddenParam(fn, cp)
|
||||||
elif cp.typ != t:
|
elif cp.typ != t:
|
||||||
localError(fn.info, "internal error: inconsistent environment type")
|
localError(fn.info, "internal error: inconsistent environment type")
|
||||||
echo "adding closure to ", fn.name.s
|
#echo "adding closure to ", fn.name.s
|
||||||
|
|
||||||
proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -382,6 +380,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||||
c.somethingToDo = true
|
c.somethingToDo = true
|
||||||
markAsClosure(owner, n)
|
markAsClosure(owner, n)
|
||||||
addClosureParam(c, owner)
|
addClosureParam(c, owner)
|
||||||
|
#echo "captureing ", 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).lastSon
|
||||||
|
|
@ -403,7 +402,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||||
# give it the same env type that outer's env var gets:
|
# give it the same env type that outer's env var gets:
|
||||||
"""
|
"""
|
||||||
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) # , ow
|
||||||
createUpField(c, w, up)
|
createUpField(c, w, up)
|
||||||
|
|
@ -469,10 +468,19 @@ proc setupEnvVar(owner: PSym; d: DetectionPass;
|
||||||
result = newEnvVar(owner, envVarType)
|
result = newEnvVar(owner, envVarType)
|
||||||
c.envVars[owner.id] = result
|
c.envVars[owner.id] = result
|
||||||
|
|
||||||
|
proc getUpViaParam(owner: PSym): PNode =
|
||||||
|
let p = getHiddenParam(owner)
|
||||||
|
result = p.newSymNode
|
||||||
|
if owner.isIterator:
|
||||||
|
let upField = lookupInRecord(p.typ.lastSon.n, getIdent(upName))
|
||||||
|
if upField == nil:
|
||||||
|
localError(owner.info, "could not find up reference for closure iter")
|
||||||
|
else:
|
||||||
|
result = rawIndirectAccess(result, upField, p.info)
|
||||||
|
|
||||||
proc rawClosureCreation(owner: PSym;
|
proc rawClosureCreation(owner: PSym;
|
||||||
d: DetectionPass; c: var LiftingPass): PNode =
|
d: DetectionPass; c: var LiftingPass): PNode =
|
||||||
result = newNodeI(nkStmtList, owner.info)
|
result = newNodeI(nkStmtList, owner.info)
|
||||||
#if owner.isIterator: return result
|
|
||||||
|
|
||||||
let env = setupEnvVar(owner, d, c)
|
let env = setupEnvVar(owner, d, c)
|
||||||
if env.kind == nkSym:
|
if env.kind == nkSym:
|
||||||
|
|
@ -491,20 +499,19 @@ proc rawClosureCreation(owner: PSym;
|
||||||
|
|
||||||
let upField = lookupInRecord(env.typ.lastSon.n, getIdent(upName))
|
let upField = lookupInRecord(env.typ.lastSon.n, getIdent(upName))
|
||||||
if upField != nil:
|
if upField != nil:
|
||||||
let param = getEnvParam(owner)
|
let up = getUpViaParam(owner)
|
||||||
if param != nil and upField.typ == param.typ:
|
if up != nil and upField.typ == up.typ:
|
||||||
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
||||||
newSymNode(param), env.info))
|
up, env.info))
|
||||||
#elif oldenv != nil and oldenv.typ == upField.typ:
|
#elif oldenv != nil and oldenv.typ == upField.typ:
|
||||||
# result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
# result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
||||||
# oldenv, env.info))
|
# oldenv, env.info))
|
||||||
else:
|
else:
|
||||||
echo owner.name.s
|
|
||||||
localError(env.info, "internal error: cannot create up reference")
|
localError(env.info, "internal error: cannot create up reference")
|
||||||
|
|
||||||
proc closureCreationForIter(iter: PNode;
|
proc closureCreationForIter(iter: PNode;
|
||||||
d: DetectionPass; c: var LiftingPass): PNode =
|
d: DetectionPass; c: var LiftingPass): PNode =
|
||||||
result = newNodeI(nkStmtListExpr, iter.info)
|
result = newNodeIT(nkStmtListExpr, iter.info, iter.sym.typ)
|
||||||
let owner = iter.sym.skipGenericOwner
|
let owner = iter.sym.skipGenericOwner
|
||||||
var v = newSym(skVar, getIdent(envName), owner, iter.info)
|
var v = newSym(skVar, getIdent(envName), owner, iter.info)
|
||||||
incl(v.flags, sfShadowed)
|
incl(v.flags, sfShadowed)
|
||||||
|
|
@ -788,9 +795,10 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
|
||||||
|
|
||||||
# static binding?
|
# static binding?
|
||||||
var env: PSym
|
var env: PSym
|
||||||
if call[0].kind == nkSym and call[0].sym.isIterator:
|
let op = call[0]
|
||||||
|
if op.kind == nkSym and op.sym.isIterator:
|
||||||
# createClosure()
|
# createClosure()
|
||||||
let iter = call[0].sym
|
let iter = op.sym
|
||||||
|
|
||||||
let hp = getHiddenParam(iter)
|
let hp = getHiddenParam(iter)
|
||||||
env = newSym(skLet, iter.name, owner, body.info)
|
env = newSym(skLet, iter.name, owner, body.info)
|
||||||
|
|
@ -802,6 +810,12 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
|
||||||
result.add(v)
|
result.add(v)
|
||||||
# add 'new' statement:
|
# add 'new' statement:
|
||||||
result.add(newCall(getSysSym"internalNew", env.newSymNode))
|
result.add(newCall(getSysSym"internalNew", env.newSymNode))
|
||||||
|
elif op.kind == nkStmtListExpr:
|
||||||
|
let closure = op.lastSon
|
||||||
|
if closure.kind == nkClosure:
|
||||||
|
call.sons[0] = closure
|
||||||
|
for i in 0 .. op.len-2:
|
||||||
|
result.add op[i]
|
||||||
|
|
||||||
var loopBody = newNodeI(nkStmtList, body.info, 3)
|
var loopBody = newNodeI(nkStmtList, body.info, 3)
|
||||||
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
|
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
|
||||||
|
|
@ -814,7 +828,7 @@ proc liftForLoop*(body: PNode; owner: PSym): PNode =
|
||||||
var v2 = newNodeI(nkLetSection, body.info)
|
var v2 = newNodeI(nkLetSection, body.info)
|
||||||
var vpart = newNodeI(if L == 3: nkIdentDefs else: nkVarTuple, body.info)
|
var vpart = newNodeI(if L == 3: nkIdentDefs else: nkVarTuple, body.info)
|
||||||
for i in 0 .. L-3:
|
for i in 0 .. L-3:
|
||||||
assert body[i].kind == nkSym
|
if body[i].kind == nkSym:
|
||||||
body[i].sym.kind = skLet
|
body[i].sym.kind = skLet
|
||||||
addSon(vpart, body[i])
|
addSon(vpart, body[i])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -500,6 +500,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
|
||||||
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
|
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
|
||||||
call.sons[0].typ.callConv == ccClosure:
|
call.sons[0].typ.callConv == ccClosure:
|
||||||
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
|
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
|
||||||
|
if not c.tooEarly:
|
||||||
|
n.sons[length-2] = transform(c, n.sons[length-2]).PNode
|
||||||
result[1] = lambdalifting.liftForLoop(n, getCurrOwner(c)).PTransNode
|
result[1] = lambdalifting.liftForLoop(n, getCurrOwner(c)).PTransNode
|
||||||
discard c.breakSyms.pop
|
discard c.breakSyms.pop
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
discard """
|
discard """
|
||||||
line: 12
|
line: 12
|
||||||
errormsg: "type mismatch: got (proc (x: int){.closure, gcsafe, locks: 0.})"
|
errormsg: "type mismatch: got (proc (x: int){.gcsafe, locks: 0.})"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc ugh[T](x: T) {.closure.} =
|
proc ugh[T](x: T) {.nimcall.} =
|
||||||
echo "ugha"
|
echo "ugha"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue