new VM: preparations for evalMacroCall
This commit is contained in:
parent
a294d45fd6
commit
d18c82a9ef
4 changed files with 100 additions and 19 deletions
|
|
@ -242,14 +242,14 @@ proc execute(c: PCtx, start: int) =
|
||||||
let ra = instr.regA
|
let ra = instr.regA
|
||||||
#echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
|
#echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
|
||||||
case instr.opcode
|
case instr.opcode
|
||||||
of opcEof: break
|
of opcEof: return regs[ra]
|
||||||
of opcRet:
|
of opcRet:
|
||||||
# XXX perform any cleanup actions
|
# XXX perform any cleanup actions
|
||||||
pc = tos.comesFrom
|
pc = tos.comesFrom
|
||||||
tos = tos.next
|
tos = tos.next
|
||||||
if tos.isNil: return
|
|
||||||
|
|
||||||
let retVal = regs[0]
|
let retVal = regs[0]
|
||||||
|
if tos.isNil: return retVal
|
||||||
|
|
||||||
move(regs, tos.slots)
|
move(regs, tos.slots)
|
||||||
assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
|
assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
|
||||||
if c.code[pc].opcode == opcIndCallAsgn:
|
if c.code[pc].opcode == opcIndCallAsgn:
|
||||||
|
|
@ -637,6 +637,16 @@ proc execute(c: PCtx, start: int) =
|
||||||
regs[ra] = copyTree(c.constants.sons[rb])
|
regs[ra] = copyTree(c.constants.sons[rb])
|
||||||
else:
|
else:
|
||||||
asgnComplex(regs[ra], c.constants.sons[rb])
|
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:
|
of opcNBindSym:
|
||||||
# trivial implementation:
|
# trivial implementation:
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
|
|
@ -810,19 +820,33 @@ proc execute(c: PCtx, start: int) =
|
||||||
of opcNCopyNimTree:
|
of opcNCopyNimTree:
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
regs[ra] = copyTree(regs[rb])
|
regs[ra] = copyTree(regs[rb])
|
||||||
else:
|
of opcNDel:
|
||||||
InternalError(c.debug[pc], "unknown opcode " & $instr.opcode)
|
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
|
inc pc
|
||||||
|
|
||||||
proc eval*(c: PCtx, n: PNode): PNode =
|
proc evalStmt*(c: PCtx, n: PNode) =
|
||||||
## eval never returns nil! This simplifies the code a lot and
|
|
||||||
## makes it faster too.
|
|
||||||
let start = genStmt(c, n)
|
let start = genStmt(c, n)
|
||||||
# execute new instructions; this redundant opcEof check saves us lots
|
# execute new instructions; this redundant opcEof check saves us lots
|
||||||
# of allocations in 'execute':
|
# of allocations in 'execute':
|
||||||
if c.code[start].opcode != opcEof:
|
if c.code[start].opcode != opcEof:
|
||||||
execute(c, start)
|
discard execute(c, start)
|
||||||
result = emptyNode
|
|
||||||
|
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 =
|
proc myOpen(module: PSym): PPassContext =
|
||||||
#var c = newEvalContext(module, emRepl)
|
#var c = newEvalContext(module, emRepl)
|
||||||
|
|
@ -835,10 +859,56 @@ var oldErrorCount: int
|
||||||
proc myProcess(c: PPassContext, n: PNode): PNode =
|
proc myProcess(c: PPassContext, n: PNode): PNode =
|
||||||
# don't eval errornous code:
|
# don't eval errornous code:
|
||||||
if oldErrorCount == msgs.gErrorCounter:
|
if oldErrorCount == msgs.gErrorCounter:
|
||||||
result = eval(PCtx(c), n)
|
evalStmt(PCtx(c), n)
|
||||||
|
result = emptyNode
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
oldErrorCount = msgs.gErrorCounter
|
oldErrorCount = msgs.gErrorCounter
|
||||||
|
|
||||||
const vmPass* = makePass(myOpen, nil, myProcess, myProcess)
|
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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ type
|
||||||
|
|
||||||
opcNSetIntVal,
|
opcNSetIntVal,
|
||||||
opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal,
|
opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal,
|
||||||
opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree,
|
opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree, opcNDel, opcGenSym,
|
||||||
|
|
||||||
opcSlurp,
|
opcSlurp,
|
||||||
opcGorge,
|
opcGorge,
|
||||||
|
|
|
||||||
|
|
@ -674,26 +674,27 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
genUnaryABC(c, n, dest, opcParseStmtToAst)
|
genUnaryABC(c, n, dest, opcParseStmtToAst)
|
||||||
of mExpandToAst:
|
of mExpandToAst:
|
||||||
InternalError(n.info, "cannot generate code for: " & $m)
|
InternalError(n.info, "cannot generate code for: " & $m)
|
||||||
of mTypeTrait: InternalError(n.info, "cannot generate code for: " & $m)
|
of mTypeTrait:
|
||||||
of mIs: InternalError(n.info, "cannot generate code for: " & $m)
|
|
||||||
|
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 mSlurp: genUnaryABC(c, n, dest, opcSlurp)
|
||||||
of mStaticExec: genBinaryABC(c, n, dest, opcGorge)
|
of mStaticExec: genBinaryABC(c, n, dest, opcGorge)
|
||||||
of mNLen: genUnaryABI(c, n, dest, opcLenSeq)
|
of mNLen: genUnaryABI(c, n, dest, opcLenSeq)
|
||||||
of mNChild: genBinaryABC(c, n, dest, opcNChild)
|
of mNChild: genBinaryABC(c, n, dest, opcNChild)
|
||||||
of mNSetChild:
|
of mNSetChild, mNDel:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
var
|
var
|
||||||
tmp1 = c.genx(n.sons[1])
|
tmp1 = c.genx(n.sons[1])
|
||||||
tmp2 = c.genx(n.sons[2])
|
tmp2 = c.genx(n.sons[2])
|
||||||
tmp3 = c.genx(n.sons[3])
|
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(tmp1)
|
||||||
c.freeTemp(tmp2)
|
c.freeTemp(tmp2)
|
||||||
c.freeTemp(tmp3)
|
c.freeTemp(tmp3)
|
||||||
of mNAdd: genBinaryABC(c, n, dest, opcNAdd)
|
of mNAdd: genBinaryABC(c, n, dest, opcNAdd)
|
||||||
of mNAddMultiple: genBinaryABC(c, n, dest, opcNAddMultiple)
|
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 mNKind: genUnaryABC(c, n, dest, opcNKind)
|
||||||
of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal)
|
of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal)
|
||||||
of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
|
of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
|
||||||
|
|
@ -740,6 +741,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
of mNCallSite:
|
of mNCallSite:
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, opcCallSite, dest)
|
c.gABC(n, opcCallSite, dest)
|
||||||
|
of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
|
||||||
of mMinI, mMaxI, mMinI64, mMaxI64, mAbsF64, mMinF64, mMaxF64, mAbsI, mAbsI64:
|
of mMinI, mMaxI, mMinI64, mMaxI64, mAbsF64, mMinF64, mMaxF64, mAbsI, mAbsI64:
|
||||||
c.genCall(n, dest)
|
c.genCall(n, dest)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1166,6 +1168,14 @@ proc genStmt*(c: PCtx; n: PNode): int =
|
||||||
c.gABC(n, opcEof)
|
c.gABC(n, opcEof)
|
||||||
InternalAssert d < 0
|
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) =
|
proc genParams(c: PCtx; params: PNode) =
|
||||||
# res.sym.position is already 0
|
# res.sym.position is already 0
|
||||||
c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
|
c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -2,9 +2,10 @@ version 0.9.4
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- new VM:
|
- new VM:
|
||||||
|
- implement the glue to replace evals.nim
|
||||||
- implement missing magics
|
- implement missing magics
|
||||||
- implement overflow checking
|
- implement overflow checking
|
||||||
- implement the glue to replace evals.nim
|
- implement the FFI
|
||||||
- implement on the fly CSE
|
- implement on the fly CSE
|
||||||
|
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue