diff options
author | Araq <rumpf_a@web.de> | 2014-06-27 16:03:11 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-06-27 16:03:11 +0200 |
commit | 7014d0c5c82b942c7e3e299c5b29d28ac70831fe (patch) | |
tree | 4672c6cda3515810a39eb41bbe8b4ef8c8495311 /compiler | |
parent | 85a1d896c2ccb69d81003673b00ac21b53133b06 (diff) | |
download | Nim-7014d0c5c82b942c7e3e299c5b29d28ac70831fe.tar.gz |
some progress for jester+async
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/lambdalifting.nim | 77 | ||||
-rw-r--r-- | compiler/lowerings.nim | 17 | ||||
-rw-r--r-- | compiler/magicsys.nim | 2 |
3 files changed, 68 insertions, 28 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index f3398187a..402ad7d3d 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -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 = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 4a2f6a12b..e7b5cd987 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -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) diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index b4f6e043d..475326161 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -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 |