new VM: passes more tests

This commit is contained in:
Araq 2013-12-06 01:48:02 +01:00
commit 4ffe6a8282
6 changed files with 45 additions and 26 deletions

View file

@ -700,11 +700,9 @@ type
proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) = proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
template maybeTrace = template maybeTrace =
if defined(debug) or gVerbosity >= 3: if defined(debug) or gVerbosity >= 3 or msg == errInternal:
writeStackTrace() writeStackTrace()
if msg == errInternal:
writeStackTrace() # we always want a stack trace here
if msg >= fatalMin and msg <= fatalMax: if msg >= fatalMin and msg <= fatalMax:
maybeTrace() maybeTrace()
quit(1) quit(1)

View file

@ -1168,13 +1168,18 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
proc semStaticStmt(c: PContext, n: PNode): PNode = proc semStaticStmt(c: PContext, n: PNode): PNode =
let a = semStmt(c, n.sons[0]) let a = semStmt(c, n.sons[0])
result = evalStaticExpr(c.module, a, c.p.owner) n.sons[0] = a
if result.isNil: evalStaticStmt(c.module, a, c.p.owner)
LocalError(n.info, errCannotInterpretNodeX, renderTree(n)) result = newNodeI(nkDiscardStmt, n.info, 1)
result = emptyNode result.sons[0] = emptyNode
elif result.kind == nkEmpty: when false:
result = newNodeI(nkDiscardStmt, n.info, 1) result = evalStaticStmt(c.module, a, c.p.owner)
result.sons[0] = emptyNode if result.isNil:
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
result = emptyNode
elif result.kind == nkEmpty:
result = newNodeI(nkDiscardStmt, n.info, 1)
result.sons[0] = emptyNode
proc usesResult(n: PNode): bool = proc usesResult(n: PNode): bool =
# nkStmtList(expr) properly propagates the void context, # nkStmtList(expr) properly propagates the void context,

View file

@ -515,7 +515,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
regs[rb].sons == regs[rc].sons) regs[rb].sons == regs[rc].sons)
of opcEqNimrodNode: of opcEqNimrodNode:
decodeBC(nkIntLit) decodeBC(nkIntLit)
regs[ra].intVal = ord(regs[rb].uast == regs[rc].uast) regs[ra].intVal = ord(regs[rb].skipMeta == regs[rc].skipMeta)
of opcXor: of opcXor:
decodeBC(nkIntLit) decodeBC(nkIntLit)
regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal) regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
@ -746,7 +746,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
decodeB(nkStrLit) decodeB(nkStrLit)
regs[ra].strVal = renderTree(regs[rb].skipMeta, {renderNoComments}) regs[ra].strVal = renderTree(regs[rb].skipMeta, {renderNoComments})
of opcQuit: of opcQuit:
if c.mode in {emRepl, emStatic}: if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
Message(c.debug[pc], hintQuitCalled) Message(c.debug[pc], hintQuitCalled)
quit(int(getOrdValue(regs[ra]))) quit(int(getOrdValue(regs[ra])))
else: else:
@ -1036,7 +1036,7 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
setupGlobalCtx(module) setupGlobalCtx(module)
var c = globalCtx var c = globalCtx
c.mode = mode c.mode = mode
let start = genExpr(c, n) let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
assert c.code[start].opcode != opcEof assert c.code[start].opcode != opcEof
var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil) var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
newSeq(tos.slots, c.prc.maxSlots) newSeq(tos.slots, c.prc.maxSlots)
@ -1047,8 +1047,11 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
proc evalConstExpr*(module: PSym, e: PNode): PNode = proc evalConstExpr*(module: PSym, e: PNode): PNode =
result = evalConstExprAux(module, nil, e, emConst) result = evalConstExprAux(module, nil, e, emConst)
proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode = proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
result = evalConstExprAux(module, prc, e, emStatic) result = evalConstExprAux(module, prc, e, emStaticExpr)
proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
discard evalConstExprAux(module, prc, e, emStaticStmt)
proc setupMacroParam(x: PNode): PNode = proc setupMacroParam(x: PNode): PNode =
result = x result = x

View file

@ -134,8 +134,9 @@ type
emConst, ## evaluate for 'const' according to spec emConst, ## evaluate for 'const' according to spec
emOptimize, ## evaluate for optimization purposes (same as emOptimize, ## evaluate for optimization purposes (same as
## emConst?) ## emConst?)
emStatic ## evaluate for enforced compile time eval emStaticExpr, ## evaluate for enforced compile time eval
## ('static' context) ## ('static' context)
emStaticStmt ## 'static' as an expression
TSandboxFlag* = enum ## what the evaluation engine should allow TSandboxFlag* = enum ## what the evaluation engine should allow
allowCast, ## allow unsafe language feature: 'cast' allowCast, ## allow unsafe language feature: 'cast'

View file

@ -314,6 +314,11 @@ proc genLiteral(c: PCtx; n: PNode): int =
if sameConstant(c.constants[i], n): return i if sameConstant(c.constants[i], n): return i
result = rawGenLiteral(c, n) result = rawGenLiteral(c, n)
proc unused(n: PNode; x: TDest) {.inline.} =
if x >= 0:
#debug(n)
InternalError(n.info, "not unused")
proc genCase(c: PCtx; n: PNode; dest: var TDest) = proc genCase(c: PCtx; n: PNode; dest: var TDest) =
# if (!expr1) goto L1; # if (!expr1) goto L1;
# thenPart # thenPart
@ -325,7 +330,10 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
# L2: # L2:
# elsePart # elsePart
# Lend: # Lend:
if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ) if not isEmptyType(n.typ):
if dest < 0: dest = getTemp(c, n.typ)
else:
unused(n, dest)
var endings: seq[TPosition] = @[] var endings: seq[TPosition] = @[]
withTemp(tmp, n.sons[0].typ): withTemp(tmp, n.sons[0].typ):
c.gen(n.sons[0], tmp) c.gen(n.sons[0], tmp)
@ -503,11 +511,6 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
else: else:
genBinaryABC(c, n, dest, opc) genBinaryABC(c, n, dest, opc)
proc unused(n: PNode; x: TDest) {.inline.} =
if x >= 0:
#debug(n)
InternalError(n.info, "not unused")
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) = proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
let tmp = c.genx(arg) let tmp = c.genx(arg)
c.gABx(n, opcSetType, tmp, genType(c, arg.typ)) c.gABx(n, opcSetType, tmp, genType(c, arg.typ))
@ -1168,7 +1171,10 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
c.gABx(n, opcLdImmInt, dest, n.intVal.int) c.gABx(n, opcLdImmInt, dest, n.intVal.int)
else: else:
genLit(c, n, dest) genLit(c, n, dest)
of nkUIntLit..nkNilLit: genLit(c, n, dest) of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
of nkNilLit:
if not n.typ.isEmptyType: genLit(c, n, dest)
else: unused(n, dest)
of nkAsgn, nkFastAsgn: of nkAsgn, nkFastAsgn:
unused(n, dest) unused(n, dest)
genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn) genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
@ -1253,14 +1259,16 @@ proc genStmt*(c: PCtx; n: PNode): int =
var d: TDest = -1 var d: TDest = -1
c.gen(n, d) c.gen(n, d)
c.gABC(n, opcEof) c.gABC(n, opcEof)
InternalAssert d < 0 if d >= 0: internalError(n.info, "some destination set")
proc genExpr*(c: PCtx; n: PNode): int = proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
c.removeLastEof c.removeLastEof
result = c.code.len result = c.code.len
var d: TDest = -1 var d: TDest = -1
c.gen(n, d) c.gen(n, d)
InternalAssert d >= 0 if d < 0:
if requiresValue: internalError(n.info, "no destination set")
d = 0
c.gABC(n, opcEof, d) c.gABC(n, opcEof, d)
proc genParams(c: PCtx; params: PNode) = proc genParams(c: PCtx; params: PNode) =

View file

@ -44,6 +44,10 @@ good(genericParamOnce(TFoo, TFoo))
bad(genericParamOnce(string, int)) bad(genericParamOnce(string, int))
bad(genericParamOnce(TFoo, float)) bad(genericParamOnce(TFoo, float))
type
type1 = typedesc
type2 = typedesc
proc typePairs(A, B: type1; C, D: type2) = nil proc typePairs(A, B: type1; C, D: type2) = nil
good(typePairs(int, int, TFoo, TFOO)) good(typePairs(int, int, TFoo, TFOO))