computed goto now works; some progress on the new VM

This commit is contained in:
Araq
2013-10-25 13:30:34 +02:00
parent ca12bf76f5
commit 6ea538cec3
5 changed files with 53 additions and 23 deletions

View File

@@ -322,8 +322,20 @@ proc genComputedGoto(p: BProc; n: PNode) =
gotoArray.appf("&&TMP$#, ", (id+i).toRope)
gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope)
line(p, cpsLocals, gotoArray)
let topBlock = p.blocks.len-1
let oldBody = p.blocks[topBlock].sections[cpsStmts]
p.blocks[topBlock].sections[cpsStmts] = nil
for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
let tailB = p.blocks[topBlock].sections[cpsStmts]
p.blocks[topBlock].sections[cpsStmts] = nil
for j in 0 .. casePos-1: genStmts(p, n.sons[j])
let tailA = p.blocks[topBlock].sections[cpsStmts]
p.blocks[topBlock].sections[cpsStmts] = oldBody.con(tailA)
let caseStmt = n.sons[casePos]
var a: TLoc
initLocExpr(p, caseStmt.sons[0], a)
@@ -340,8 +352,11 @@ proc genComputedGoto(p: BProc; n: PNode) =
let val = getOrdValue(it.sons[j])
lineF(p, cpsStmts, "TMP$#:$n", intLiteral(val+id+1))
genStmts(p, it.lastSon)
for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
for j in 0 .. casePos-1: genStmts(p, n.sons[j])
#for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB
#for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA
app(p.s(cpsStmts), tailB)
app(p.s(cpsStmts), tailA)
var a: TLoc
initLocExpr(p, caseStmt.sons[0], a)
lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc)

View File

@@ -10,8 +10,10 @@
## This file implements the new evaluation engine for Nimrod code.
## An instruction is 1-2 int32s in memory, it is a register based VM.
import ast except getstr
import
strutils, ast, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
parser, vmdeps, idents, trees, renderer
from semfold import leValueConv, ordinalValToString
@@ -131,7 +133,7 @@ proc asgnComplex(x, y: PNode) =
for i in countup(0, sonsLen(y) - 1): addSon(x, y.sons[i])
template getstr(a: expr): expr =
(if a.kind == nkStrLit: a.strVal else: $chr(int(a.intVal)))
(if a.kind in {nkStrLit..nkTripleStrLit}: a.strVal else: $chr(int(a.intVal)))
proc pushSafePoint(f: PStackFrame; pc: int) =
if f.safePoints.isNil: f.safePoints = @[]
@@ -669,8 +671,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcSetLenStr:
decodeB(nkStrLit)
regs[ra].strVal.setLen(regs[rb].getOrdValue.int)
of opcOf:
decodeBC(nkIntLit)
regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, regs[rc].typ) >= 0)
of opcSetLenSeq,
opcSwap, opcIsNil, opcOf,
opcSwap, opcIsNil,
opcCast, opcReset:
internalError(c.debug[pc], "too implement")
of opcNBindSym:
@@ -868,6 +873,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
regs[ra].strVal = typ.typeToString(preferExported)
inc pc
proc fixType(result, n: PNode) {.inline.} =
# XXX do it deeply for complex values
if result.typ.isNil: result.typ = n.typ
proc execute(c: PCtx, start: int): PNode =
var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
newSeq(tos.slots, c.prc.maxSlots)
@@ -885,6 +894,7 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
let start = genExpr(c, n)
assert c.code[start].opcode != opcEof
result = execute(c, start)
fixType(result, n)
# for now we share the 'globals' environment. XXX Coming soon: An API for
# storing&loading the 'globals' environment to get what a component system
@@ -928,6 +938,7 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
newSeq(tos.slots, c.prc.maxSlots)
for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
result = rawExecute(c, start, tos)
fixType(result, n)
proc evalConstExpr*(module: PSym, e: PNode): PNode =
result = evalConstExprAux(module, nil, e, emConst)

View File

@@ -32,8 +32,8 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
appendToModule(module, newNode(nkIncludeStmt, info, @[
newStrNode(nkStrLit, filename)]))
except EIO:
result = ""
LocalError(info, errCannotOpenFile, file)
result = ""
when false:
proc opExpandToAst*(c: PEvalContext, original: PNode): PNode =

View File

@@ -1,16 +1,16 @@
discard """
output: '''yeah A
yeah A
yeah CD
yeah CD
yeah A
yeah CD
yeah CD
yeah A
yeah B
yeah A
yeah A
yeah A'''
output: '''yeah A enumB
yeah A enumB
yeah CD enumD
yeah CD enumE
yeah A enumB
yeah CD enumE
yeah CD enumD
yeah A enumB
yeah B enumC
yeah A enumB
yeah A enumB
yeah A enumB'''
"""
type
@@ -32,13 +32,14 @@ proc vm() =
while true:
{.computedGoto.}
let instr = instructions[pc]
let ra = instr.succ # instr.regA
case instr
of enumA:
echo "yeah A"
echo "yeah A ", ra
of enumC, enumD:
echo "yeah CD"
echo "yeah CD ", ra
of enumB:
echo "yeah B"
echo "yeah B ", ra
of enumE:
break
inc(pc)

View File

@@ -2,11 +2,12 @@ version 0.9.4
=============
- new VM:
- get rid of nkIntLit..nkUInt64Lit,
nkFloatLit..nkFloat128Lit, nkStrLit..nkTripleStrLit?
- new VM requires lambda lifting
- codegen for computed goto still wrong
- test and activate the jump optimizer
- implement overflow checking
- implement the FFI
- test and activate the jump optimizer
- make 'bind' default for templates and introduce 'mixin'
- special rule for ``[]=``
@@ -20,6 +21,8 @@ version 0.9.4
Bugs
====
- bug: 'type T = ref T' not recognized as illegal recursion
- bug: type conversions concerning proc types are weird
- compilation of niminst takes way too long. looks like a regression
- simple closure iterator doesn't work
- docgen: sometimes effects are listed twice