summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/vm.nim92
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--compiler/vmgen.nim22
-rw-r--r--todo.txt3
4 files changed, 100 insertions, 19 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index d09d57d89..37f13990f 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -242,14 +242,14 @@ proc execute(c: PCtx, start: int) =
     let ra = instr.regA
     #echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
     case instr.opcode
-    of opcEof: break
+    of opcEof: return regs[ra]
     of opcRet:
       # XXX perform any cleanup actions
       pc = tos.comesFrom
       tos = tos.next
-      if tos.isNil: return
-      
       let retVal = regs[0]
+      if tos.isNil: return retVal
+      
       move(regs, tos.slots)
       assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
       if c.code[pc].opcode == opcIndCallAsgn:
@@ -637,6 +637,16 @@ proc execute(c: PCtx, start: int) =
         regs[ra] = copyTree(c.constants.sons[rb])
       else:
         asgnComplex(regs[ra], c.constants.sons[rb])
+    of opcLdGlobal:
+      let rb = instr.regBx - wordExcess
+      if regs[ra].isNil:
+        regs[ra] = copyTree(c.globals.sons[rb])
+      else:
+        asgnComplex(regs[ra], c.globals.sons[rb])
+    of opcRepr, opcSetLenStr, opcSetLenSeq,
+        opcSwap, opcIsNil, opcOf,
+        opcCast, opcQuit, opcReset:
+      internalError(c.debug[pc], "too implement")
     of opcNBindSym:
       # trivial implementation:
       let rb = instr.regB
@@ -810,19 +820,33 @@ proc execute(c: PCtx, start: int) =
     of opcNCopyNimTree:
       let rb = instr.regB
       regs[ra] = copyTree(regs[rb])
-    else:
-      InternalError(c.debug[pc], "unknown opcode " & $instr.opcode)
+    of opcNDel:
+      let rb = instr.regB
+      let rc = instr.regC
+      for i in countup(0, regs[rc].intVal.int-1):
+        delSon(regs[ra], regs[rb].intVal.int)
+    of opcGenSym:
+      let k = regs[instr.regB].intVal
+      let b = regs[instr.regC]
+      let name = if b.strVal.len == 0: ":tmp" else: b.strVal
+      if k < 0 or k > ord(high(TSymKind)):
+        internalError(c.debug[pc], "request to create symbol of invalid kind")
+      regs[ra] = newSymNode(newSym(k.TSymKind, name.getIdent, c.module,
+                            c.debug[pc]))
+      incl(regs[ra].sym.flags, sfGenSym)
     inc pc
 
-proc eval*(c: PCtx, n: PNode): PNode =
-  ## eval never returns nil! This simplifies the code a lot and
-  ## makes it faster too.
+proc evalStmt*(c: PCtx, n: PNode) =
   let start = genStmt(c, n)
   # execute new instructions; this redundant opcEof check saves us lots
   # of allocations in 'execute':
   if c.code[start].opcode != opcEof:
-    execute(c, start)
-  result = emptyNode
+    discard execute(c, start)
+
+proc evalExpr*(c: PCtx, n: PNode): PNode =
+  let start = genExpr(c, n)
+  assert c.code[start].opcode != opcEof
+  result = execute(c, start)
 
 proc myOpen(module: PSym): PPassContext =
   #var c = newEvalContext(module, emRepl)
@@ -835,10 +859,56 @@ var oldErrorCount: int
 proc myProcess(c: PPassContext, n: PNode): PNode =
   # don't eval errornous code:
   if oldErrorCount == msgs.gErrorCounter:
-    result = eval(PCtx(c), n)
+    evalStmt(PCtx(c), n)
+    result = emptyNode
   else:
     result = n
   oldErrorCount = msgs.gErrorCounter
 
 const vmPass* = makePass(myOpen, nil, myProcess, myProcess)
 
+proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode = 
+  var p = newCtx(module)
+  var s = newStackFrame()
+  s.call = e
+  s.prc = prc
+  pushStackFrame(p, s)
+  result = tryEval(p, e)
+  if result != nil and result.kind == nkExceptBranch: result = nil
+  popStackFrame(p)
+
+proc evalConstExpr*(module: PSym, e: PNode): PNode = 
+  result = evalConstExprAux(module, nil, e, emConst)
+
+proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode = 
+  result = evalConstExprAux(module, prc, e, emStatic)
+
+proc setupMacroParam(x: PNode): PNode =
+  result = x
+  if result.kind == nkHiddenStdConv: result = result.sons[1]
+
+proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
+  # XXX GlobalError() is ugly here, but I don't know a better solution for now
+  inc(evalTemplateCounter)
+  if evalTemplateCounter > 100:
+    GlobalError(n.info, errTemplateInstantiationTooNested)
+
+  c.callsite = nOrig
+  var s = newStackFrame()
+  s.call = n
+  s.prc = sym
+  var L = n.safeLen
+  if L == 0: L = 1
+  setlen(s.slots, L)
+  # return value:
+  s.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
+  # setup parameters:
+  for i in 1 .. < L: s.slots[i] = setupMacroParam(n.sons[i])
+  pushStackFrame(c, s)
+  discard eval(c, optBody(c, sym))
+  result = s.slots[0]
+  popStackFrame(c)
+  if cyclicTree(result): GlobalError(n.info, errCyclicTree)
+  dec(evalTemplateCounter)
+  c.callsite = nil
+
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index a76e035a0..050caa65c 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -80,7 +80,7 @@ type
     
     opcNSetIntVal,
     opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal,
-    opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree,
+    opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree, opcNDel, opcGenSym,
     
     opcSlurp,
     opcGorge,
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 016cfc96c..f7df31c0c 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -674,26 +674,27 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     genUnaryABC(c, n, dest, opcParseStmtToAst)
   of mExpandToAst:
     InternalError(n.info, "cannot generate code for: " & $m)
-  of mTypeTrait: InternalError(n.info, "cannot generate code for: " & $m)
-  of mIs: InternalError(n.info, "cannot generate code for: " & $m)
+  of mTypeTrait: 
+    
+    InternalError(n.info, "cannot generate code for: " & $m)
+  of mIs:
+    InternalError(n.info, "cannot generate code for: " & $m)
   of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
   of mStaticExec: genBinaryABC(c, n, dest, opcGorge)
   of mNLen: genUnaryABI(c, n, dest, opcLenSeq)
   of mNChild: genBinaryABC(c, n, dest, opcNChild)
-  of mNSetChild:
+  of mNSetChild, mNDel:
     unused(n, dest)
     var
       tmp1 = c.genx(n.sons[1])
       tmp2 = c.genx(n.sons[2])
       tmp3 = c.genx(n.sons[3])
-    c.gABC(n, opcNSetChild, tmp1, tmp2, tmp3)
+    c.gABC(n, if m == mNSetChild: opcNSetChild else: opcNDel, tmp1, tmp2, tmp3)
     c.freeTemp(tmp1)
     c.freeTemp(tmp2)
     c.freeTemp(tmp3)
   of mNAdd: genBinaryABC(c, n, dest, opcNAdd)
   of mNAddMultiple: genBinaryABC(c, n, dest, opcNAddMultiple)
-  of mNDel:
-    InternalError(n.info, "cannot generate code for: " & $m)
   of mNKind: genUnaryABC(c, n, dest, opcNKind)
   of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal)
   of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
@@ -740,6 +741,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
   of mNCallSite:
     if dest < 0: dest = c.getTemp(n.typ)
     c.gABC(n, opcCallSite, dest)
+  of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
   of mMinI, mMaxI, mMinI64, mMaxI64, mAbsF64, mMinF64, mMaxF64, mAbsI, mAbsI64:
     c.genCall(n, dest)
   else:
@@ -1166,6 +1168,14 @@ proc genStmt*(c: PCtx; n: PNode): int =
   c.gABC(n, opcEof)
   InternalAssert d < 0
 
+proc genExpr*(c: PCtx; n: PNode): int =
+  c.removeLastEof
+  result = c.code.len
+  var d: TDest = -1
+  c.gen(n, d)
+  InternalAssert d >= 0
+  c.gABC(n, opcEof, d)
+
 proc genParams(c: PCtx; params: PNode) =
   # res.sym.position is already 0
   c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
diff --git a/todo.txt b/todo.txt
index c02534e5a..6fce93290 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,9 +2,10 @@ version 0.9.4
 =============
 
 - new VM:
+  - implement the glue to replace evals.nim
   - implement missing magics
   - implement overflow checking
-  - implement the glue to replace evals.nim
+  - implement the FFI
   - implement on the fly CSE
 
 - make 'bind' default for templates and introduce 'mixin'