summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/lambdalifting.nim9
-rw-r--r--compiler/lowerings.nim52
-rw-r--r--compiler/transf.nim12
-rw-r--r--compiler/vm.nim2
-rw-r--r--compiler/vmgen.nim31
5 files changed, 73 insertions, 33 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 4bc8eff86..6f6942096 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -11,7 +11,7 @@
 
 import 
   intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
-  idents, renderer, types, magicsys, rodread
+  idents, renderer, types, magicsys, rodread, lowerings
 
 discard """
   The basic approach is that captured vars need to be put on the heap and
@@ -536,13 +536,6 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
   result.sons[0] = le
   result.sons[1] = ri
 
-proc addVar*(father, v: PNode) = 
-  var vpart = newNodeI(nkIdentDefs, v.info)
-  addSon(vpart, v)
-  addSon(vpart, ast.emptyNode)
-  addSon(vpart, ast.emptyNode)
-  addSon(father, vpart)
-
 proc newClosureCreationVar(o: POuterContext; e: PEnv): PSym =
   result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info)
   incl(result.flags, sfShadowed)
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
new file mode 100644
index 000000000..2cf641d93
--- /dev/null
+++ b/compiler/lowerings.nim
@@ -0,0 +1,52 @@
+#
+#
+#           The Nimrod Compiler
+#        (c) Copyright 2014 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements common simple lowerings.
+
+const
+  genPrefix* = ":tmp"         # prefix for generated names
+
+import ast, types, idents, magicsys
+
+proc newTupleAccess*(tup: PNode, i: int): PNode =
+  result = newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(
+                     abstractInst).sons[i])
+  addSon(result, copyTree(tup))
+  var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
+  lit.intVal = i
+  addSon(result, lit)
+
+proc addVar*(father, v: PNode) = 
+  var vpart = newNodeI(nkIdentDefs, v.info, 3)
+  vpart.sons[0] = v
+  vpart.sons[1] = ast.emptyNode
+  vpart.sons[2] = ast.emptyNode
+  addSon(father, vpart)
+
+proc newAsgnStmt(le, ri: PNode): PNode =
+  result = newNodeI(nkAsgn, le.info, 2)
+  result.sons[0] = le
+  result.sons[1] = ri
+
+proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
+  assert n.kind == nkVarTuple
+  let value = n.lastSon
+  result = newNodeI(nkStmtList, n.info)
+
+  var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info)
+  temp.typ = skipTypes(value.typ, abstractInst)
+  incl(temp.flags, sfFromGeneric)
+
+  var v = newNodeI(nkVarSection, value.info)
+  v.addVar(newSymNode(temp))
+  result.add(v)
+  
+  result.add newAsgnStmt(newSymNode(temp), value)
+  for i in 0 .. n.len-3:
+    result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i))
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 9586398c9..7922acbe9 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -20,10 +20,7 @@
 import 
   intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
   idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
-  lambdalifting, sempass2
-
-const 
-  genPrefix* = ":tmp"         # prefix for generated names
+  lambdalifting, sempass2, lowerings
 
 # implementation
 
@@ -240,13 +237,6 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode =
     discard c.contSyms.pop()
   else: 
     result = transform(c, n)
-  
-proc newTupleAccess(tup: PNode, i: int): PNode = 
-  result = newNodeIT(nkBracketExpr, tup.info, tup.typ.sons[i])
-  addSon(result, copyTree(tup))
-  var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
-  lit.intVal = i
-  addSon(result, lit)
 
 proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) = 
   # XXX: BUG: what if `n` is an expression with side-effects?
diff --git a/compiler/vm.nim b/compiler/vm.nim
index f093527f8..70eb6f828 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -486,6 +486,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       regs[ra].intVal = regs[rb].intVal + regs[rc].intVal
     of opcAddImmInt:
       decodeBImm(rkInt)
+      #message(c.debug[pc], warnUser, "came here")
+      #debug regs[rb].node
       regs[ra].intVal = regs[rb].intVal + imm
     of opcSubInt:
       decodeBC(rkInt)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 80c07f39e..82d1e9ab8 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -11,7 +11,7 @@
 
 import
   unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef, 
-  trees, intsets, rodread, magicsys, options
+  trees, intsets, rodread, magicsys, options, lowerings
 
 from os import splitFile
 
@@ -636,11 +636,16 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.genAddSubInt(n, dest, opcAddInt)
   of mInc, mDec:
     unused(n, dest)
-    # XXX generates inefficient code for globals
-    var d = c.genx(n.sons[1]).TDest
-    c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt)
+    let opc = if m == mInc: opcAddInt else: opcSubInt
+    let d = c.genx(n.sons[1])
+    if n.sons[2].isInt8Lit:
+      c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
+    else:
+      let tmp = c.genx(n.sons[2])
+      c.gABC(n, opc, d, d, tmp)
+      c.freeTemp(tmp)
     c.genAsgnPatch(n.sons[1], d)
-    c.freeTemp(d.TRegister)
+    c.freeTemp(d)
   of mOrd, mChr, mArrToSeq: c.gen(n.sons[1], dest)
   of mNew, mNewFinalize:
     unused(n, dest)
@@ -1006,6 +1011,10 @@ proc isOwnedBy(a, b: PSym): bool =
     if a == b: return true
     a = a.owner
 
+proc getOwner(c: PCtx): PSym =
+  result = c.prc.sym
+  if result.isNil: result = c.module
+
 proc checkCanEval(c: PCtx; n: PNode) =
   # we need to ensure that we don't evaluate 'x' here:
   # proc foo() = var x ...
@@ -1148,7 +1157,7 @@ proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
   let a = c.genx(n.sons[0], flags)
   let b = genField(n.sons[1])
   if dest < 0: dest = c.getTemp(n.typ)
-  if gfAddrOf notin flags and fitsRegister(n.typ):
+  if gfAddrOf notin flags and fitsRegister(n.typ.skipTypes({tyVar})):
     var cc = c.getTemp(n.typ)
     c.gABC(n, opcLdObj, cc, a, b)
     c.gABC(n, opcNodeToReg, dest, cc)
@@ -1228,16 +1237,10 @@ proc genVarSection(c: PCtx; n: PNode) =
     if a.kind == nkCommentStmt: continue
     #assert(a.sons[0].kind == nkSym) can happen for transformed vars
     if a.kind == nkVarTuple:
-      let tmp = c.genx(a.lastSon)
       for i in 0 .. a.len-3:
         setSlot(c, a[i].sym)
-        # v = t[i]
-        var v: TDest = -1
         checkCanEval(c, a[i])
-        genRdVar(c, a[i], v, {gfAddrOf})
-        c.gABC(n, opcWrObj, v, tmp, i)
-        # XXX globals?
-      c.freeTemp(tmp)
+      c.gen(lowerTupleUnpacking(a, c.getOwner))
     elif a.sons[0].kind == nkSym:
       let s = a.sons[0].sym
       checkCanEval(c, a.sons[0])
@@ -1581,7 +1584,7 @@ proc genProc(c: PCtx; s: PSym): int =
     c.gABC(body, opcEof, eofInstr.regA)
     c.optimizeJumps(result)
     s.offset = c.prc.maxSlots
-    #if s.name.s == "foo":
+    #if s.name.s == "tupleUnpack":
     #  echo renderTree(body)
     #  c.echoCode(result)
     c.prc = oldPrc