summary refs log tree commit diff stats
path: root/compiler/vm.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/vm.nim')
-rw-r--r--compiler/vm.nim37
1 files changed, 27 insertions, 10 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index e40acca6c..e5b357a11 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -133,6 +133,8 @@ proc createStrKeepNode(x: var TFullReg) =
     # cause of bugs like these is that the VM does not properly distinguish
     # between variable defintions (var foo = e) and variable updates (foo = e).
 
+include vmhooks
+
 template createStr(x) =
   x.node = newNode(nkStrLit)
 
@@ -256,8 +258,16 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
         c.currentExceptionB = c.currentExceptionA
         c.currentExceptionA = nil
         # execute the corresponding handler:
+        while c.code[pc2].opcode == opcExcept: inc pc2
         return (pc2, f)
       inc pc2
+      if c.code[pc2].opcode != opcExcept and nextExceptOrFinally >= 0:
+        # we're at the end of the *except list*, but maybe there is another
+        # *except branch*?
+        pc2 = nextExceptOrFinally+1
+        if c.code[pc2].opcode == opcExcept:
+          nextExceptOrFinally = pc2 + c.code[pc2].regBx - wordExcess
+
     if nextExceptOrFinally >= 0:
       pc2 = nextExceptOrFinally
     if c.code[pc2].opcode == opcFinally:
@@ -801,7 +811,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       let bb = regs[rb].node
       let isClosure = bb.kind == nkPar
       let prc = if not isClosure: bb.sym else: bb.sons[0].sym
-      if sfImportc in prc.flags:
+      if prc.offset < -1:
+        # it's a callback:
+        c.callbacks[-prc.offset-2].value(
+          VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs)))
+      elif sfImportc in prc.flags:
         if allowFFI notin c.features:
           globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI")
         # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
@@ -832,9 +846,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         if isClosure:
           newFrame.slots[rc].kind = rkNode
           newFrame.slots[rc].node = regs[rb].node.sons[1]
-        # allocate the temporaries:
-        #for i in rc+ord(isClosure) .. <prc.offset:
-        #  newFrame.slots[i] = newNode(nkEmpty)
         tos = newFrame
         move(regs, newFrame.slots)
         # -1 for the following 'inc pc'
@@ -888,10 +899,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcTry:
       let rbx = instr.regBx - wordExcess
       tos.pushSafePoint(pc + rbx)
+      assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
     of opcExcept:
       # just skip it; it's followed by a jump;
       # we'll execute in the 'raise' handler
-      discard
+      let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
+      inc pc, rbx
+      assert c.code[pc+1].opcode in {opcExcept, opcFinally}
     of opcFinally:
       # just skip it; it's followed by the code we need to execute anyway
       tos.popSafePoint()
@@ -1033,8 +1047,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       internalError(c.debug[pc], "too implement")
     of opcNarrowS:
       decodeB(rkInt)
-      let min = -(1 shl (rb-1))
-      let max = (1 shl (rb-1))-1
+      let min = -(1.BiggestInt shl (rb-1))
+      let max = (1.BiggestInt shl (rb-1))-1
       if regs[ra].intVal < min or regs[ra].intVal > max:
         stackTrace(c, tos, pc, errGenerated,
           msgKindToString(errUnhandledExceptionX) % "value out of range")
@@ -1132,14 +1146,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcParseExprToAst:
       decodeB(rkNode)
       # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
-      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
                             c.debug[pc].line.int)
       if sonsLen(ast) != 1:
         globalError(c.debug[pc], errExprExpected, "multiple statements")
       regs[ra].node = ast.sons[0]
     of opcParseStmtToAst:
       decodeB(rkNode)
-      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
+      let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
                             c.debug[pc].line.int)
       regs[ra].node = ast
     of opcCallSite:
@@ -1316,6 +1330,8 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
   assert c.code[start].opcode != opcEof
   result = execute(c, start)
 
+include vmops
+
 # for now we share the 'globals' environment. XXX Coming soon: An API for
 # storing&loading the 'globals' environment to get what a component system
 # requires.
@@ -1325,6 +1341,7 @@ var
 proc setupGlobalCtx(module: PSym) =
   if globalCtx.isNil: globalCtx = newCtx(module)
   else: refresh(globalCtx, module)
+  registerAdditionalOps(globalCtx)
 
 proc myOpen(module: PSym): PPassContext =
   #var c = newEvalContext(module, emRepl)