summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-03-22 11:50:42 +0100
committerAraq <rumpf_a@web.de>2014-03-22 11:50:42 +0100
commit5f478e5aa125289efa232cd57043b8ee31aad562 (patch)
treea7dd3cfbca3c69451909a798ed5f8f747423a54b /compiler
parent5aac789e0e183a1a2193bd7615de0b4a29f4708c (diff)
downloadNim-5f478e5aa125289efa232cd57043b8ee31aad562.tar.gz
fixes #1010
Diffstat (limited to 'compiler')
-rw-r--r--compiler/msgs.nim2
-rw-r--r--compiler/vm.nim47
-rw-r--r--compiler/vmgen.nim8
3 files changed, 30 insertions, 27 deletions
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index cdafc997b..a63fbca7f 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -202,7 +202,7 @@ const
     errXExpectsArrayType: "\'$1\' expects an array type", 
     errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet", 
     errExprXAmbiguous: "expression '$1' ambiguous in this context", 
-    errConstantDivisionByZero: "constant division by zero", 
+    errConstantDivisionByZero: "division by zero", 
     errOrdinalTypeExpected: "ordinal type expected", 
     errOrdinalOrFloatTypeExpected: "ordinal or float type expected", 
     errOverOrUnderflow: "over- or underflow", 
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 06f0e8886..f093527f8 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -10,6 +10,8 @@
 ## This file implements the new evaluation engine for Nimrod code.
 ## An instruction is 1-3 int32s in memory, it is a register based VM.
 
+const debugEchoCode = false
+
 import ast except getstr
 
 import
@@ -328,6 +330,7 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
 
 proc compile(c: PCtx, s: PSym): int = 
   result = vmgen.genProc(c, s)
+  when debugEchoCode: c.echoCode result
   #c.echoCode
 
 proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
@@ -381,18 +384,23 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNodeToReg:
       let ra = instr.regA
       let rb = instr.regB
-      assert regs[rb].kind == rkNode
-      let nb = regs[rb].node
-      case nb.kind
-      of nkCharLit..nkInt64Lit:
-        ensureKind(rkInt)
-        regs[ra].intVal = nb.intVal
-      of nkFloatLit..nkFloat64Lit:
-        ensureKind(rkFloat)
-        regs[ra].floatVal = nb.floatVal
+      # opcDeref might already have loaded it into a register. XXX Let's hope
+      # this is still correct this way:
+      if regs[rb].kind != rkNode:
+        regs[ra] = regs[rb]
       else:
-        ensureKind(rkNode)
-        regs[ra].node = nb
+        assert regs[rb].kind == rkNode
+        let nb = regs[rb].node
+        case nb.kind
+        of nkCharLit..nkInt64Lit:
+          ensureKind(rkInt)
+          regs[ra].intVal = nb.intVal
+        of nkFloatLit..nkFloat64Lit:
+          ensureKind(rkFloat)
+          regs[ra].floatVal = nb.floatVal
+        else:
+          ensureKind(rkNode)
+          regs[ra].node = nb
     of opcLdArr:
       # a = b[c]
       decodeBC(rkNode)
@@ -520,10 +528,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       regs[ra].intVal = regs[rb].intVal * regs[rc].intVal
     of opcDivInt:
       decodeBC(rkInt)
-      regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
+      if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
+      else: regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
     of opcModInt:
       decodeBC(rkInt)
-      regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
+      if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
+      else: regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
     of opcAddFloat:
       decodeBC(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal + regs[rc].floatVal
@@ -1174,12 +1184,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       regs[ra].node.strVal = typ.typeToString(preferExported)
     inc pc
 
-proc fixType(result, n: PNode) {.inline.} =
-  # XXX do it deeply for complex values; there seems to be no simple
-  # solution except to check it deeply here.
-  #if result.typ.isNil: result.typ = n.typ
-  discard
-
 proc execute(c: PCtx, start: int): PNode =
   var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
   newSeq(tos.slots, c.prc.maxSlots)
@@ -1198,8 +1202,6 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
   let start = genExpr(c, n)
   assert c.code[start].opcode != opcEof
   result = execute(c, start)
-  if not result.isNil:
-    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
@@ -1243,11 +1245,11 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
   let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
   if c.code[start].opcode == opcEof: return emptyNode
   assert c.code[start].opcode != opcEof
+  when debugEchoCode: c.echoCode start
   var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
   newSeq(tos.slots, c.prc.maxSlots)
   #for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
-  fixType(result, n)
 
 proc evalConstExpr*(module: PSym, e: PNode): PNode = 
   result = evalConstExprAux(module, nil, e, emConst)
@@ -1264,6 +1266,7 @@ proc setupCompileTimeVar*(module: PSym, n: PNode) =
 proc setupMacroParam(x: PNode): PNode =
   result = x
   if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
+  result = canonValue(result)
   result.flags.incl nfIsRef
   result.typ = x.typ
 
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 89845c198..0a0fcaebb 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -308,20 +308,20 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
   c.gen(n.sons[2], dest)
   c.patch(L1)
 
-proc canonConst(n: PNode): PNode =
+proc canonValue*(n: PNode): PNode =
   if n.kind == nkExprColonExpr:
     result = n.sons[1]
   elif n.hasSubnodeWith(nkExprColonExpr):
     result = n.copyNode
     newSeq(result.sons, n.len)
     for i in 0.. <n.len:
-      result.sons[i] = canonConst(n.sons[i])
+      result.sons[i] = canonValue(n.sons[i])
   else:
     result = n
 
 proc rawGenLiteral(c: PCtx; n: PNode): int =
   result = c.constants.len
-  c.constants.add n.canonConst
+  c.constants.add n.canonValue
   internalAssert result < 0x7fff
 
 proc sameConstant*(a, b: PNode): bool =
@@ -1227,7 +1227,7 @@ proc genVarSection(c: PCtx; n: PNode) =
           if sfImportc in s.flags: c.importcSym(a.info, s)
           else:
             let sa = if s.ast.isNil: getNullValue(s.typ, a.info) 
-                     else: canonConst(s.ast)
+                     else: canonValue(s.ast)
             c.globals.add(sa)
             s.position = c.globals.len
         if a.sons[2].kind == nkEmpty: