summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-06-27 16:03:11 +0200
committerAraq <rumpf_a@web.de>2014-06-27 16:03:11 +0200
commit7014d0c5c82b942c7e3e299c5b29d28ac70831fe (patch)
tree4672c6cda3515810a39eb41bbe8b4ef8c8495311 /compiler
parent85a1d896c2ccb69d81003673b00ac21b53133b06 (diff)
downloadNim-7014d0c5c82b942c7e3e299c5b29d28ac70831fe.tar.gz
some progress for jester+async
Diffstat (limited to 'compiler')
-rw-r--r--compiler/lambdalifting.nim77
-rw-r--r--compiler/lowerings.nim17
-rw-r--r--compiler/magicsys.nim2
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