summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-10-12 17:42:15 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-10-12 17:42:15 +0200
commita2e4ab2e4e3570cd313e8d5422b276625f87e0d7 (patch)
treeceb4d096b6774bfe7fc5982c64d4eaaa10d56e44 /compiler
parentd6c401acfbb738d0e91df18cc89c40dc1b28525c (diff)
downloadNim-a2e4ab2e4e3570cd313e8d5422b276625f87e0d7.tar.gz
simple programs now work with the new destroyer pass
Diffstat (limited to 'compiler')
-rw-r--r--compiler/destroyer.nim86
-rw-r--r--compiler/semexprs.nim7
-rw-r--r--compiler/semstmts.nim21
-rw-r--r--compiler/transf.nim2
4 files changed, 60 insertions, 56 deletions
diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim
index db26c5366..a650df7dd 100644
--- a/compiler/destroyer.nim
+++ b/compiler/destroyer.nim
@@ -179,28 +179,34 @@ proc genDestroy(t: PType; dest: PNode): PNode =
   assert t.destructor != nil
   result = newTree(nkCall, newSymNode(t.destructor), newTree(nkHiddenAddr, dest))
 
+proc addTopVar(c: var Con; v: PNode) =
+  c.topLevelVars.add newTree(nkIdentDefs, v, emptyNode, emptyNode)
+
+proc p(n: PNode; c: var Con): PNode
+
+template recurse(n, dest) =
+  for i in 0..<n.len:
+    dest.add p(n[i], c)
+
 proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
   if ri.kind in nkCallKinds:
     result = genSink(ri.typ, dest)
+    # watch out and no not transform 'ri' twice if it's a call:
+    let ri2 = copyNode(ri)
+    recurse(ri, ri2)
+    result.add ri2
   elif ri.kind == nkSym and isHarmlessVar(ri.sym, c):
     result = genSink(ri.typ, dest)
+    result.add p(ri, c)
   else:
     result = genCopy(ri.typ, dest)
+    result.add p(ri, c)
 
-proc addTopVar(c: var Con; v: PNode) =
-  c.topLevelVars.add newTree(nkIdentDefs, v, emptyNode)
-
-proc p(n, parent: PNode; c: var Con) =
-  template recurse(n, dest) =
-    let x = dest
-    for i in 0..<n.safeLen:
-      p(n[i], x, c)
-    parent.add x
-
+proc p(n: PNode; c: var Con): PNode =
   case n.kind
   of nkVarSection, nkLetSection:
     discard "transform; var x = y to  var x; x op y  where op is a move or copy"
-    var stmtList = newNodeI(nkStmtList, n.info)
+    result = newNodeI(nkStmtList, n.info)
 
     for i in 0..<n.len:
       let it = n[i]
@@ -208,10 +214,9 @@ proc p(n, parent: PNode; c: var Con) =
       let ri = it[L]
       if it.kind == nkVarTuple and hasDestructor(ri.typ):
         let x = lowerTupleUnpacking(it, c.owner)
-        p(x, stmtList, c)
+        result.add p(x, c)
       elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
-        it.sons[L] = emptyNode
-        for j in 0..L-1:
+        for j in 0..L-2:
           let v = it[j]
           doAssert v.kind == nkSym
           # move the variable declaration to the top of the frame:
@@ -220,48 +225,45 @@ proc p(n, parent: PNode; c: var Con) =
           c.destroys.add genDestroy(v.typ, v)
           if ri.kind != nkEmpty:
             let r = moveOrCopy(v, ri, c)
-            recurse(ri, r)
-            stmtList.add r
+            result.add r
       else:
         # keep it, but transform 'ri':
         var varSection = copyNode(n)
         var itCopy = copyNode(it)
         for j in 0..L-1:
           itCopy.add it[j]
-        p(ri, itCopy, c)
+        itCopy.add p(ri, c)
         varSection.add itCopy
-        stmtList.add varSection
-    parent.add stmtList
+        result.add varSection
   of nkCallKinds:
     if n.typ != nil and hasDestructor(n.typ):
       discard "produce temp creation"
-      let stmtList = newNodeIT(nkStmtListExpr, n.info, n.typ)
+      result = newNodeIT(nkStmtListExpr, n.info, n.typ)
       let f = newSym(skField, getIdent(":d" & $c.tmpObj.n.len), c.owner, n.info)
+      f.typ = n.typ
       rawAddField c.tmpObj, f
       var m = genSink(n.typ, rawDirectAccess(c.tmp, f))
-      recurse(n, m)
-      stmtList.add m
-      stmtList.add rawDirectAccess(c.tmp, f)
-      parent.add stmtList
+      var call = copyNode(n)
+      recurse(n, call)
+      m.add call
+      result.add m
+      result.add rawDirectAccess(c.tmp, f)
       c.destroys.add genDestroy(n.typ, rawDirectAccess(c.tmp, f))
     else:
-      recurse(n, copyNode(n))
+      result = copyNode(n)
+      recurse(n, result)
   of nkAsgn, nkFastAsgn:
     if n[0].kind == nkSym and interestingSym(n[0].sym):
-      discard "use move or assignment"
-      let ri = n[1]
-      let r = moveOrCopy(n[0], ri, c)
-      # fortunately this skips the nkCall which we do not want to transform
-      # to a temp here!
-      recurse(ri, r)
-      parent.add r
+      result = moveOrCopy(n[0], n[1], c)
     else:
-      recurse(n, copyNode(n))
-  of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
-      nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
-    parent.add n
+      result = copyNode(n)
+      recurse(n, result)
+  of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
+      nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
+    result = n
   else:
-    recurse(n, copyNode(n))
+    result = copyNode(n)
+    recurse(n, result)
 
 proc injectDestructorCalls*(owner: PSym; n: PNode): PNode =
   var c: Con
@@ -277,15 +279,15 @@ proc injectDestructorCalls*(owner: PSym; n: PNode): PNode =
   for i in 0..<c.g.len:
     if c.g[i].kind in {goto, fork}:
       c.jumpTargets.incl(i+c.g[i].dest)
-  var stmtList = newNodeI(nkStmtList, n.info)
-  for i in 0..<n.len:
-    p(n[i], stmtList, c)
+  let body = p(n, c)
   if c.tmp.typ.n.len > 0:
     c.addTopVar(newSymNode c.tmp)
   result = newNodeI(nkStmtList, n.info)
   if c.topLevelVars.len > 0:
     result.add c.topLevelVars
   if c.destroys.len > 0:
-    result.add newTryFinally(stmtList, c.destroys)
+    result.add newTryFinally(body, c.destroys)
   else:
-    result.add stmtList
+    result.add body
+
+  echo "transformed into: ", result
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index c336afc89..e8989f832 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1383,9 +1383,10 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
           typeMismatch(n.info, lhs.typ, rhs.typ)
 
     n.sons[1] = fitNode(c, le, rhs, n.info)
-    if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
-        mode != noOverloadedAsgn:
-      return overloadedAsgn(c, lhs, n.sons[1])
+    when not newDestructors:
+      if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
+          mode != noOverloadedAsgn:
+        return overloadedAsgn(c, lhs, n.sons[1])
 
     fixAbstractType(c, n)
     asgnToResultVar(c, n, n.sons[0], n.sons[1])
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index ccf332d3a..c8eda9d94 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -100,15 +100,16 @@ proc semProc(c: PContext, n: PNode): PNode
 include semdestruct
 
 proc semDestructorCheck(c: PContext, n: PNode, flags: TExprFlags) {.inline.} =
-  if efAllowDestructor notin flags and
-      n.kind in nkCallKinds+{nkObjConstr,nkBracket}:
-    if instantiateDestructor(c, n.typ) != nil:
-      localError(n.info, warnDestructor)
-  # This still breaks too many things:
-  when false:
-    if efDetermineType notin flags and n.typ.kind == tyTypeDesc and
-        c.p.owner.kind notin {skTemplate, skMacro}:
-      localError(n.info, errGenerated, "value expected, but got a type")
+  when not newDestructors:
+    if efAllowDestructor notin flags and
+        n.kind in nkCallKinds+{nkObjConstr,nkBracket}:
+      if instantiateDestructor(c, n.typ) != nil:
+        localError(n.info, warnDestructor)
+    # This still breaks too many things:
+    when false:
+      if efDetermineType notin flags and n.typ.kind == tyTypeDesc and
+          c.p.owner.kind notin {skTemplate, skMacro}:
+        localError(n.info, errGenerated, "value expected, but got a type")
 
 proc semExprBranch(c: PContext, n: PNode): PNode =
   result = semExpr(c, n)
@@ -116,7 +117,7 @@ proc semExprBranch(c: PContext, n: PNode): PNode =
     # XXX tyGenericInst here?
     semProcvarCheck(c, result)
     if result.typ.kind == tyVar: result = newDeref(result)
-    when not newDestructors: semDestructorCheck(c, result, {})
+    semDestructorCheck(c, result, {})
 
 proc semExprBranchScope(c: PContext, n: PNode): PNode =
   openScope(c)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index f5ea8feb9..2a33c60a6 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -973,7 +973,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
     incl(result.flags, nfTransf)
     when useEffectSystem: trackProc(prc, result)
     if prc.kind == skFunc:
-      result = injectDestructorCalls(prc, n)
+      result = injectDestructorCalls(prc, result)
     #if prc.name.s == "testbody":
     #  echo renderTree(result)