some progress for jester+async
This commit is contained in:
parent
85a1d896c2
commit
7014d0c5c8
12 changed files with 7587 additions and 29 deletions
|
|
@ -154,12 +154,20 @@ proc getStateType(iter: PSym): PType =
|
|||
addSon(n, newIntNode(nkIntLit, 0))
|
||||
result = newType(tyRange, iter)
|
||||
result.n = n
|
||||
rawAddSon(result, getSysType(tyInt))
|
||||
var intType = nilOrSysInt()
|
||||
if intType.isNil: intType = newType(tyInt, iter)
|
||||
rawAddSon(result, intType)
|
||||
|
||||
proc createStateField(iter: PSym): PSym =
|
||||
result = newSym(skField, getIdent(":state"), iter, iter.info)
|
||||
result.typ = getStateType(iter)
|
||||
|
||||
proc createEnvObj(owner: PSym): 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)
|
||||
rawAddField(result, createStateField(owner))
|
||||
|
||||
proc newIterResult(iter: PSym): PSym =
|
||||
if resultPos < iter.ast.len:
|
||||
result = iter.ast.sons[resultPos].sym
|
||||
|
|
@ -197,24 +205,18 @@ proc initIter(iter: PSym): TIter =
|
|||
if iter.kind == skClosureIterator:
|
||||
var cp = getEnvParam(iter)
|
||||
if cp == nil:
|
||||
result.obj = createObj(iter, iter.info)
|
||||
result.obj = createEnvObj(iter)
|
||||
|
||||
cp = newSym(skParam, getIdent(paramName), iter, iter.info)
|
||||
incl(cp.flags, sfFromGeneric)
|
||||
cp.typ = newType(tyRef, iter)
|
||||
rawAddSon(cp.typ, result.obj)
|
||||
addHiddenParam(iter, cp)
|
||||
|
||||
result.state = createStateField(iter)
|
||||
rawAddField(result.obj, result.state)
|
||||
else:
|
||||
result.obj = cp.typ.sons[0]
|
||||
assert result.obj.kind == tyObject
|
||||
if result.obj.n.len > 0:
|
||||
result.state = result.obj.n[0].sym
|
||||
else:
|
||||
result.state = createStateField(iter)
|
||||
rawAddField(result.obj, result.state)
|
||||
internalAssert result.obj.n.len > 0
|
||||
result.state = result.obj.n[0].sym
|
||||
result.closureParam = cp
|
||||
if iter.typ.sons[0] != nil:
|
||||
result.resultSym = newIterResult(iter)
|
||||
|
|
@ -231,20 +233,26 @@ proc newOuterContext(fn: PSym): POuterContext =
|
|||
proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv =
|
||||
new(result)
|
||||
result.capturedVars = @[]
|
||||
result.obj = createObj(owner, owner.info)
|
||||
result.up = up
|
||||
result.attachedNode = n
|
||||
result.fn = owner
|
||||
result.vars = initIntSet()
|
||||
result.next = o.head
|
||||
o.head = result
|
||||
if owner.kind != skModule and (up == nil or up.fn != owner):
|
||||
if owner.ast == nil:
|
||||
debug owner
|
||||
echo owner.name.s
|
||||
let param = getEnvParam(owner)
|
||||
if param != nil:
|
||||
result.obj = param.typ.sons[0]
|
||||
assert result.obj.kind == tyObject
|
||||
if result.obj.isNil:
|
||||
result.obj = createEnvObj(owner)
|
||||
|
||||
proc addCapturedVar(e: PEnv, v: PSym) =
|
||||
for x in e.capturedVars:
|
||||
if x == v: return
|
||||
# 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:
|
||||
if e.obj.n.len == 0: addField(e.obj, createStateField(v.owner))
|
||||
e.capturedVars.add(v)
|
||||
addField(e.obj, v)
|
||||
|
||||
|
|
@ -262,7 +270,7 @@ proc isInnerProc(s, outerProc: PSym): bool =
|
|||
owner = owner.owner
|
||||
#s.typ.callConv == ccClosure
|
||||
|
||||
proc addClosureParam(fn: PSym; e: PEnv): PSym =
|
||||
proc addClosureParam(fn: PSym; e: PEnv) =
|
||||
var cp = getEnvParam(fn)
|
||||
if cp == nil:
|
||||
cp = newSym(skParam, getIdent(paramName), fn, fn.info)
|
||||
|
|
@ -270,11 +278,9 @@ proc addClosureParam(fn: PSym; e: PEnv): PSym =
|
|||
cp.typ = newType(tyRef, fn)
|
||||
rawAddSon(cp.typ, e.obj)
|
||||
addHiddenParam(fn, cp)
|
||||
else:
|
||||
#assert e.obj == nil or e.obj == cp.typ.sons[0]
|
||||
e.obj = cp.typ.sons[0]
|
||||
assert e.obj.kind == tyObject
|
||||
result = cp
|
||||
#else:
|
||||
#cp.typ.sons[0] = e.obj
|
||||
#assert e.obj.kind == tyObject
|
||||
|
||||
proc illegalCapture(s: PSym): bool {.inline.} =
|
||||
result = skipTypes(s.typ, abstractInst).kind in
|
||||
|
|
@ -296,7 +302,7 @@ proc nestedAccess(top: PEnv; local: PSym): PNode =
|
|||
# echo [:paramI.up.]foo
|
||||
# inner([:envO])
|
||||
# outer([:env])
|
||||
if not (interestingVar(local) and top.fn != local.owner):
|
||||
if not interestingVar(local) or top.fn == local.owner:
|
||||
return nil
|
||||
# check it's in fact a captured variable:
|
||||
var it = top
|
||||
|
|
@ -307,7 +313,6 @@ proc nestedAccess(top: PEnv; local: PSym): PNode =
|
|||
let envParam = top.fn.getEnvParam
|
||||
internalAssert(not envParam.isNil)
|
||||
var access = newSymNode(envParam)
|
||||
# we could also simply check the tuple type for the field here, I think.
|
||||
it = top.up
|
||||
while it != nil:
|
||||
if it.vars.contains(local.id):
|
||||
|
|
@ -316,6 +321,17 @@ proc nestedAccess(top: PEnv; local: PSym): PNode =
|
|||
internalAssert it.upField != nil
|
||||
access = indirectAccess(access, it.upField, local.info)
|
||||
it = it.up
|
||||
when false:
|
||||
# Type based expression construction works too, but turned out to hide
|
||||
# other bugs:
|
||||
while true:
|
||||
let obj = access.typ.sons[0]
|
||||
let field = getFieldFromObj(obj, local)
|
||||
if field != nil:
|
||||
return rawIndirectAccess(access, field, local.info)
|
||||
let upField = lookupInRecord(obj.n, getIdent(upName))
|
||||
if upField == nil: break
|
||||
access = rawIndirectAccess(access, upField, local.info)
|
||||
return nil
|
||||
|
||||
proc createUpField(obj, fieldType: PType): PSym =
|
||||
|
|
@ -324,6 +340,7 @@ proc createUpField(obj, fieldType: PType): PSym =
|
|||
result.typ = newType(tyRef, obj.owner)
|
||||
result.position = pos
|
||||
rawAddSon(result.typ, fieldType)
|
||||
#rawAddField(obj, result)
|
||||
addField(obj, result)
|
||||
|
||||
proc captureVar(o: POuterContext; top: PEnv; local: PSym;
|
||||
|
|
@ -348,10 +365,13 @@ proc captureVar(o: POuterContext; top: PEnv; local: PSym;
|
|||
if it.fn != local.owner:
|
||||
it.fn.typ.callConv = ccClosure
|
||||
incl(it.fn.typ.flags, tfCapturesEnv)
|
||||
discard addClosureParam(it.fn, it.up)
|
||||
|
||||
var u = it.up
|
||||
while u != nil and u.fn == it.fn: u = u.up
|
||||
addClosureParam(it.fn, u)
|
||||
|
||||
if idTableGet(o.lambdasToEnv, it.fn) == nil:
|
||||
idTablePut(o.lambdasToEnv, it.fn, it.up)
|
||||
if u != nil: idTablePut(o.lambdasToEnv, it.fn, u)
|
||||
|
||||
it = it.up
|
||||
# don't do this: 'top' might not require a closure:
|
||||
|
|
@ -521,7 +541,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode, env: PEnv) =
|
|||
#assert tfCapturesEnv notin n.sym.typ.flags
|
||||
if idTableGet(o.lambdasToEnv, fn) == nil:
|
||||
idTablePut(o.lambdasToEnv, fn, env)
|
||||
discard addClosureParam(fn, env)
|
||||
addClosureParam(fn, env)
|
||||
|
||||
elif fn.getEnvParam != nil:
|
||||
# only transform if it really needs a closure:
|
||||
|
|
@ -616,7 +636,7 @@ proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode =
|
|||
else:
|
||||
result.add(newAsgnStmt(indirectAccess(env, scope.upField, env.info),
|
||||
newSymNode(getClosureVar(scope.up)), env.info))
|
||||
|
||||
|
||||
proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
|
||||
var env = getClosureVar(scope)
|
||||
result = rawClosureCreation(o, scope, env)
|
||||
|
|
@ -643,6 +663,9 @@ proc interestingIterVar(s: PSym): bool {.inline.} =
|
|||
proc transformOuterProc(o: POuterContext, n: PNode, it: TIter): PNode
|
||||
|
||||
proc transformYield(c: POuterContext, n: PNode, it: TIter): PNode =
|
||||
assert it.state != nil
|
||||
assert it.state.typ != nil
|
||||
assert it.state.typ.n != nil
|
||||
inc it.state.typ.n.sons[1].intVal
|
||||
let stateNo = it.state.typ.n.sons[1].intVal
|
||||
|
||||
|
|
@ -867,7 +890,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
|||
discard transformOuterProcBody(o, body, initIter(fn))
|
||||
result = ex
|
||||
finishEnvironments(o)
|
||||
#if fn.name.s == "factory" or fn.name.s == "factory2":
|
||||
#if fn.name.s == "cbOuter" or fn.name.s == "factory2":
|
||||
# echo rendertree(result, {renderIds})
|
||||
|
||||
proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
|
||||
|
|
|
|||
|
|
@ -111,13 +111,28 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
|
|||
t = t.sons[0]
|
||||
if t == nil: break
|
||||
t = t.skipTypes(abstractInst)
|
||||
assert field != nil, b
|
||||
#if field == nil:
|
||||
# debug deref.typ
|
||||
# echo deref.typ.id
|
||||
internalAssert field != nil, b
|
||||
addSon(deref, a)
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
addSon(result, deref)
|
||||
addSon(result, newSymNode(field))
|
||||
result.typ = field.typ
|
||||
|
||||
proc getFieldFromObj*(t: PType; v: PSym): PSym =
|
||||
assert v.kind != skField
|
||||
let fieldName = getIdent(v.name.s & $v.id)
|
||||
var t = t
|
||||
while true:
|
||||
assert t.kind == tyObject
|
||||
result = getSymFromList(t.n, fieldName)
|
||||
if result != nil: break
|
||||
t = t.sons[0]
|
||||
if t == nil: break
|
||||
t = t.skipTypes(abstractInst)
|
||||
|
||||
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
|
||||
# returns a[].b as a node
|
||||
result = indirectAccess(a, b.name.s & $b.id, info)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ var
|
|||
gSysTypes: array[TTypeKind, PType]
|
||||
compilerprocs: TStrTable
|
||||
|
||||
proc nilOrSysInt*: PType = gSysTypes[tyInt]
|
||||
|
||||
proc registerSysType(t: PType) =
|
||||
if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue