summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-10-25 13:30:34 +0200
committerAraq <rumpf_a@web.de>2013-10-25 13:30:34 +0200
commit6ea538cec3f2da832873252d0ec3810b9dbfede4 (patch)
treea5d6e6abd506dbbfca91485137e36c48cd3fba85
parentca12bf76f595027076a437f8bf98a1928f1504d4 (diff)
downloadNim-6ea538cec3f2da832873252d0ec3810b9dbfede4.tar.gz
computed goto now works; some progress on the new VM
-rw-r--r--compiler/ccgstmts.nim19
-rw-r--r--compiler/vm.nim17
-rw-r--r--compiler/vmdeps.nim2
-rw-r--r--tests/compile/tcomputedgoto.nim31
-rw-r--r--todo.txt7
5 files changed, 53 insertions, 23 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 75cabf414..d71d65ceb 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -322,8 +322,20 @@ proc genComputedGoto(p: BProc; n: PNode) =
     gotoArray.appf("&&TMP$#, ", (id+i).toRope)
   gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope)
   line(p, cpsLocals, gotoArray)
+
+  let topBlock = p.blocks.len-1
+  let oldBody = p.blocks[topBlock].sections[cpsStmts]
+  p.blocks[topBlock].sections[cpsStmts] = nil
   
+  for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
+  let tailB = p.blocks[topBlock].sections[cpsStmts]
+
+  p.blocks[topBlock].sections[cpsStmts] = nil
   for j in 0 .. casePos-1: genStmts(p, n.sons[j])
+  let tailA = p.blocks[topBlock].sections[cpsStmts]
+
+  p.blocks[topBlock].sections[cpsStmts] = oldBody.con(tailA)
+
   let caseStmt = n.sons[casePos]
   var a: TLoc
   initLocExpr(p, caseStmt.sons[0], a)
@@ -340,8 +352,11 @@ proc genComputedGoto(p: BProc; n: PNode) =
       let val = getOrdValue(it.sons[j])
       lineF(p, cpsStmts, "TMP$#:$n", intLiteral(val+id+1))
     genStmts(p, it.lastSon)
-    for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
-    for j in 0 .. casePos-1: genStmts(p, n.sons[j])
+    #for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB
+    #for j in 0 .. casePos-1: genStmts(p, n.sons[j])  # tailA
+    app(p.s(cpsStmts), tailB)
+    app(p.s(cpsStmts), tailA)
+
     var a: TLoc
     initLocExpr(p, caseStmt.sons[0], a)
     lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc)
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 943324de1..ad390e53c 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -10,8 +10,10 @@
 ## This file implements the new evaluation engine for Nimrod code.
 ## An instruction is 1-2 int32s in memory, it is a register based VM.
 
+import ast except getstr
+
 import
-  strutils, ast, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
+  strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
   parser, vmdeps, idents, trees, renderer
 
 from semfold import leValueConv, ordinalValToString
@@ -131,7 +133,7 @@ proc asgnComplex(x, y: PNode) =
       for i in countup(0, sonsLen(y) - 1): addSon(x, y.sons[i])
 
 template getstr(a: expr): expr =
-  (if a.kind == nkStrLit: a.strVal else: $chr(int(a.intVal)))
+  (if a.kind in {nkStrLit..nkTripleStrLit}: a.strVal else: $chr(int(a.intVal)))
 
 proc pushSafePoint(f: PStackFrame; pc: int) =
   if f.safePoints.isNil: f.safePoints = @[]
@@ -669,8 +671,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
     of opcSetLenStr:
       decodeB(nkStrLit)
       regs[ra].strVal.setLen(regs[rb].getOrdValue.int)
+    of opcOf:
+      decodeBC(nkIntLit)
+      regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, regs[rc].typ) >= 0)
     of opcSetLenSeq,
-        opcSwap, opcIsNil, opcOf,
+        opcSwap, opcIsNil,
         opcCast, opcReset:
       internalError(c.debug[pc], "too implement")
     of opcNBindSym:
@@ -868,6 +873,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       regs[ra].strVal = typ.typeToString(preferExported)
     inc pc
 
+proc fixType(result, n: PNode) {.inline.} =
+  # XXX do it deeply for complex values
+  if result.typ.isNil: result.typ = n.typ
+
 proc execute(c: PCtx, start: int): PNode =
   var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
   newSeq(tos.slots, c.prc.maxSlots)
@@ -885,6 +894,7 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
   let start = genExpr(c, n)
   assert c.code[start].opcode != opcEof
   result = execute(c, start)
+  fixType(result, n)
 
 # for now we share the 'globals' environment. XXX Coming soon: An API for
 # storing&loading the 'globals' environment to get what a component system
@@ -928,6 +938,7 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
   newSeq(tos.slots, c.prc.maxSlots)
   for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos)
+  fixType(result, n)
 
 proc evalConstExpr*(module: PSym, e: PNode): PNode = 
   result = evalConstExprAux(module, nil, e, emConst)
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 2a40276d1..5b1a028b1 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -32,8 +32,8 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
     appendToModule(module, newNode(nkIncludeStmt, info, @[
       newStrNode(nkStrLit, filename)]))
   except EIO:
-    result = ""
     LocalError(info, errCannotOpenFile, file)
+    result = ""
 
 when false:
   proc opExpandToAst*(c: PEvalContext, original: PNode): PNode =
diff --git a/tests/compile/tcomputedgoto.nim b/tests/compile/tcomputedgoto.nim
index 2c3b4bbd4..b21fc07a3 100644
--- a/tests/compile/tcomputedgoto.nim
+++ b/tests/compile/tcomputedgoto.nim
@@ -1,16 +1,16 @@
 discard """
-  output: '''yeah A
-yeah A
-yeah CD
-yeah CD
-yeah A
-yeah CD
-yeah CD
-yeah A
-yeah B
-yeah A
-yeah A
-yeah A'''
+  output: '''yeah A enumB
+yeah A enumB
+yeah CD enumD
+yeah CD enumE
+yeah A enumB
+yeah CD enumE
+yeah CD enumD
+yeah A enumB
+yeah B enumC
+yeah A enumB
+yeah A enumB
+yeah A enumB'''
 """
 
 type
@@ -32,13 +32,14 @@ proc vm() =
   while true:
     {.computedGoto.}
     let instr = instructions[pc]
+    let ra = instr.succ # instr.regA
     case instr
     of enumA:
-      echo "yeah A"
+      echo "yeah A ", ra
     of enumC, enumD:
-      echo "yeah CD"
+      echo "yeah CD ", ra
     of enumB:
-      echo "yeah B"
+      echo "yeah B ", ra
     of enumE:
       break
     inc(pc)
diff --git a/todo.txt b/todo.txt
index 647f5e2c1..1dcaa8ff6 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,11 +2,12 @@ version 0.9.4
 =============
 
 - new VM:
+  - get rid of nkIntLit..nkUInt64Lit, 
+    nkFloatLit..nkFloat128Lit, nkStrLit..nkTripleStrLit?
   - new VM requires lambda lifting
-  - codegen for computed goto still wrong
-  - test and activate the jump optimizer
   - implement overflow checking
   - implement the FFI
+  - test and activate the jump optimizer
 
 - make 'bind' default for templates and introduce 'mixin'
 - special rule for ``[]=``
@@ -20,6 +21,8 @@ version 0.9.4
 Bugs
 ====
 
+- bug: 'type T = ref T' not recognized as illegal recursion
+- bug: type conversions concerning proc types are weird
 - compilation of niminst takes way too long. looks like a regression
 - simple closure iterator doesn't work
 - docgen: sometimes effects are listed twice