summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-10-16 16:41:24 +0200
committerAraq <rumpf_a@web.de>2013-10-16 16:41:24 +0200
commit3d18053370580916d190c98540a2e3d0ff66f9c3 (patch)
tree262c33dc378a2d812a455bad831e7cfd6bf174f1 /compiler
parent6a9baf3fd7842027a30ee4856d40841610dccc13 (diff)
downloadNim-3d18053370580916d190c98540a2e3d0ff66f9c3.tar.gz
some complex macros work
Diffstat (limited to 'compiler')
-rw-r--r--compiler/vm.nim69
-rw-r--r--compiler/vmdef.nim30
-rw-r--r--compiler/vmgen.nim30
3 files changed, 80 insertions, 49 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index dd8b8d8f2..b2c848287 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -96,19 +96,24 @@ template decodeBx(k: expr) {.immediate, dirty.} =
 template move(a, b: expr) = system.shallowCopy(a, b)
 # XXX fix minor 'shallowCopy' overloading bug in compiler
 
-proc asgnRef(x, y: PNode) =
-  myreset(x)
-  x.kind = y.kind
-  x.typ = y.typ
-  case x.kind
-  of nkCharLit..nkInt64Lit: x.intVal = y.intVal
-  of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
-  of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
-  of nkIdent: x.ident = y.ident
-  of nkSym: x.sym = y.sym
-  else:
-    if x.kind notin {nkEmpty..nkNilLit}:
-      move(x.sons, y.sons)
+when false:
+  proc asgnRef(x, y: PNode) =
+    myreset(x)
+    x.kind = y.kind
+    x.typ = y.typ
+    case x.kind
+    of nkCharLit..nkInt64Lit: x.intVal = y.intVal
+    of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
+    of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
+    of nkIdent: x.ident = y.ident
+    of nkSym: x.sym = y.sym
+    else:
+      if x.kind notin {nkEmpty..nkNilLit}:
+        move(x.sons, y.sons)
+else:
+  # this seems to be the best way to model the reference semantics
+  # of PNimrodNode:
+  template asgnRef(x, y: expr) = x = y
 
 proc asgnComplex(x, y: PNode) =
   myreset(x)
@@ -279,7 +284,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
     of opcAsgnRef:
       asgnRef(regs[ra], regs[instr.regB])
     of opcWrGlobalRef:
-      asgnRef(c.globals[instr.regBx-wordExcess-1], regs[ra])
+      asgnRef(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
     of opcWrGlobal:
       asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
     of opcLdArr:
@@ -470,24 +475,24 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       regs[ra].intVal = not regs[rb].intVal
     of opcEqStr:
       decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(regs[rb].strVal == regs[rc].strVal)
+      regs[ra].intVal = ord(regs[rb].strVal == regs[rc].strVal)
     of opcLeStr:
       decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(regs[rb].strVal <= regs[rc].strVal)
+      regs[ra].intVal = ord(regs[rb].strVal <= regs[rc].strVal)
     of opcLtStr:
       decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(regs[rb].strVal < regs[rc].strVal)
+      regs[ra].intVal = ord(regs[rb].strVal < regs[rc].strVal)
     of opcLeSet:
       decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(containsSets(regs[rb], regs[rc]))
+      regs[ra].intVal = ord(containsSets(regs[rb], regs[rc]))
     of opcEqSet: 
       decodeBC(nkIntLit)
-      regs[ra].intVal = Ord(equalSets(regs[rb], regs[rc]))
+      regs[ra].intVal = ord(equalSets(regs[rb], regs[rc]))
     of opcLtSet:
       decodeBC(nkIntLit)
       let a = regs[rb]
       let b = regs[rc]
-      regs[ra].intVal = Ord(containsSets(a, b) and not equalSets(a, b))
+      regs[ra].intVal = ord(containsSets(a, b) and not equalSets(a, b))
     of opcMulSet:
       decodeBC(nkCurly)
       move(regs[ra].sons, nimsets.intersectSets(regs[rb], regs[rc]).sons)
@@ -652,9 +657,21 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
         regs[ra] = copyTree(c.globals.sons[rb])
       else:
         asgnComplex(regs[ra], c.globals.sons[rb])
-    of opcRepr, opcSetLenStr, opcSetLenSeq,
+    of opcRepr:
+      decodeB(nkStrLit)
+      regs[ra].strVal = renderTree(regs[rb], {renderNoComments})
+    of opcQuit:
+      if c.mode in {emRepl, emStatic}:
+        Message(c.debug[pc], hintQuitCalled)
+        quit(int(getOrdValue(regs[ra])))
+      else:
+        return nil
+    of opcSetLenStr:
+      decodeB(nkStrLit)
+      regs[ra].strVal.setLen(regs[rb].getOrdValue.int)
+    of opcSetLenSeq,
         opcSwap, opcIsNil, opcOf,
-        opcCast, opcQuit, opcReset:
+        opcCast, opcReset:
       internalError(c.debug[pc], "too implement")
     of opcNBindSym:
       # trivial implementation:
@@ -670,7 +687,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       regs[ra].sons[regs[rb].intVal.int] = regs[rc]
     of opcNAdd:
       declBC()
-      regs[rb].add(regs[rb])
+      regs[rb].add(regs[rc])
       regs[ra] = regs[rb]
     of opcNAddMultiple:
       declBC()
@@ -904,6 +921,7 @@ const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
 proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
   setupGlobalCtx(module)
   var c = globalCtx
+  c.mode = mode
   let start = genExpr(c, n)
   assert c.code[start].opcode != opcEof
   var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
@@ -935,7 +953,8 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   let start = genProc(c, sym)
 
   var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
-  newSeq(tos.slots, c.prc.maxSlots)
+  let maxSlots = sym.position
+  newSeq(tos.slots, maxSlots)
   # setup arguments:
   var L = n.safeLen
   if L == 0: L = 1
@@ -945,7 +964,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # setup parameters:
   for i in 1 .. < L: tos.slots[i] = setupMacroParam(n.sons[i])
   # temporary storage:
-  for i in L .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
+  for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos)
   if cyclicTree(result): GlobalError(n.info, errCyclicTree)
   dec(evalMacroCounter)
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index bc6824d3b..fabce58d7 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -129,6 +129,20 @@ type
     label*: PSym
     fixups*: seq[TPosition]
 
+  TEvalMode* = enum           ## reason for evaluation
+    emRepl,                   ## evaluate because in REPL mode
+    emConst,                  ## evaluate for 'const' according to spec
+    emOptimize,               ## evaluate for optimization purposes (same as
+                              ## emConst?)
+    emStatic                  ## evaluate for enforced compile time eval
+                              ## ('static' context)
+
+  TSandboxFlag* = enum        ## what the evaluation engine should allow
+    allowCast,                ## allow unsafe language feature: 'cast'
+    allowFFI,                 ## allow the FFI
+    allowInfiniteLoops        ## allow endless loops
+  TSandboxFlags* = set[TSandboxFlag]
+
   TSlotKind* = enum   # We try to re-use slots in a smart way to
                       # minimize allocations; however the VM supports arbitrary
                       # temporary slot usage. This is required for the parameter
@@ -160,25 +174,11 @@ type
     prc*: PProc
     module*: PSym
     callsite*: PNode
+    mode*: TEvalMode
 
   TPosition* = distinct int
 
   PEvalContext* = PCtx
-
-  TEvalMode* = enum           ## reason for evaluation
-    emRepl,                   ## evaluate because in REPL mode
-    emConst,                  ## evaluate for 'const' according to spec
-    emOptimize,               ## evaluate for optimization purposes (same as
-                              ## emConst?)
-    emStatic                  ## evaluate for enforced compile time eval
-                              ## ('static' context)
-
-  TSandboxFlag* = enum        ## what the evaluation engine should allow
-    allowCast,                ## allow unsafe language feature: 'cast'
-    allowFFI,                 ## allow the FFI
-    allowInfiniteLoops        ## allow endless loops
-  TSandboxFlags* = set[TSandboxFlag]
-
   
 proc newCtx*(module: PSym): PCtx =
   PCtx(code: @[], debug: @[],
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 37807b2d0..4296609cb 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -112,8 +112,10 @@ const
 
 proc getTemp(c: PCtx; typ: PType): TRegister =
   let c = c.prc
-  # we prefer the same slot kind here for efficiency:
-  let k = typ.getSlotKind
+  # we prefer the same slot kind here for efficiency. Unfortunately for
+  # discardable return types we may not know the desired type. This can happen
+  # for e.g. mNAdd[Multiple]:
+  let k = if typ.isNil: slotTempComplex else: typ.getSlotKind
   for i in 0 .. c.maxSlots-1:
     if c.slots[i].kind == k and not c.slots[i].inUse:
       c.slots[i].inUse = true
@@ -179,7 +181,7 @@ proc gen(c: PCtx; n: PNode; dest: TRegister) =
 proc gen(c: PCtx; n: PNode) =
   var tmp: TDest = -1
   gen(c, n, tmp)
-  InternalAssert tmp < 0
+  #if n.typ.isEmptyType: InternalAssert tmp < 0
 
 proc genx(c: PCtx; n: PNode): TRegister =
   var tmp: TDest = -1
@@ -463,7 +465,7 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
   c.freeTemp(tmp)
 
 proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
-  let tmp = c.genx(n.sons[2])
+  let tmp = c.genx(n.sons[1])
   c.gABC(n, opc, tmp, 0, 0)
   c.freeTemp(tmp)
 
@@ -852,11 +854,13 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
     else:
       c.gABC(le, whichAsgnOpc(le, opcWrArr), dest, idx, tmp)
     c.freeTemp(tmp)
-  of nkDotExpr:
-    let dest = c.genx(le.sons[0])
-    let idx = c.genx(le.sons[1])
+  of nkDotExpr, nkCheckedFieldExpr:
+    # XXX field checks here
+    let left = if le.kind == nkDotExpr: le else: le.sons[0]
+    let dest = c.genx(left.sons[0])
+    let idx = c.genx(left.sons[1])
     let tmp = c.genx(ri)
-    c.gABC(le, whichAsgnOpc(le, opcWrObj), dest, idx, tmp)
+    c.gABC(left, whichAsgnOpc(left, opcWrObj), dest, idx, tmp)
     c.freeTemp(tmp)
   of nkSym:
     let s = le.sym
@@ -910,6 +914,10 @@ proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
 proc genObjAccess(c: PCtx; n: PNode; dest: var TDest) =
   genAccess(c, n, dest, opcLdObj)
 
+proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest) =
+  # XXX implement field checks!
+  genAccess(c, n.sons[0], dest, opcLdObj)
+
 proc genArrAccess(c: PCtx; n: PNode; dest: var TDest) =
   if n.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
     genAccess(c, n, dest, opcLdStrIdx)
@@ -1023,7 +1031,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
   c.gABx(n, opcLdNull, tmp, c.genType(intType))
   for x in n:
     let a = c.genx(x)
-    c.gABC(n, opcWrArr, dest, a, tmp)
+    c.gABC(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
     c.gABI(n, opcAddImmInt, tmp, tmp, 1)
     c.freeTemp(a)
   c.freeTemp(tmp)
@@ -1116,6 +1124,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
     unused(n, dest)
     genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
   of nkDotExpr: genObjAccess(c, n, dest)
+  of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest)
   of nkBracketExpr: genArrAccess(c, n, dest)
   of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcDeref)
   of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr)
@@ -1288,5 +1297,8 @@ proc genProc(c: PCtx; s: PSym): int =
     c.gABC(body, opcEof, eofInstr.regA)
     s.position = c.prc.maxSlots
     c.prc = oldPrc
+    #if s.name.s == "xmlConstructor":
+    #  echoCode(c)
   else:
+    c.prc.maxSlots = s.position
     result = x.intVal.int