diff options
-rw-r--r-- | compiler/vm.nim | 92 | ||||
-rw-r--r-- | compiler/vmdef.nim | 2 | ||||
-rw-r--r-- | compiler/vmgen.nim | 22 | ||||
-rw-r--r-- | todo.txt | 3 |
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' |