fixes #1010
This commit is contained in:
parent
5aac789e0e
commit
5f478e5aa1
4 changed files with 51 additions and 28 deletions
|
|
@ -202,7 +202,7 @@ const
|
||||||
errXExpectsArrayType: "\'$1\' expects an array type",
|
errXExpectsArrayType: "\'$1\' expects an array type",
|
||||||
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
|
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
|
||||||
errExprXAmbiguous: "expression '$1' ambiguous in this context",
|
errExprXAmbiguous: "expression '$1' ambiguous in this context",
|
||||||
errConstantDivisionByZero: "constant division by zero",
|
errConstantDivisionByZero: "division by zero",
|
||||||
errOrdinalTypeExpected: "ordinal type expected",
|
errOrdinalTypeExpected: "ordinal type expected",
|
||||||
errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
|
errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
|
||||||
errOverOrUnderflow: "over- or underflow",
|
errOverOrUnderflow: "over- or underflow",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
## This file implements the new evaluation engine for Nimrod code.
|
## This file implements the new evaluation engine for Nimrod code.
|
||||||
## An instruction is 1-3 int32s in memory, it is a register based VM.
|
## An instruction is 1-3 int32s in memory, it is a register based VM.
|
||||||
|
|
||||||
|
const debugEchoCode = false
|
||||||
|
|
||||||
import ast except getstr
|
import ast except getstr
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
@ -328,6 +330,7 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
|
||||||
|
|
||||||
proc compile(c: PCtx, s: PSym): int =
|
proc compile(c: PCtx, s: PSym): int =
|
||||||
result = vmgen.genProc(c, s)
|
result = vmgen.genProc(c, s)
|
||||||
|
when debugEchoCode: c.echoCode result
|
||||||
#c.echoCode
|
#c.echoCode
|
||||||
|
|
||||||
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
|
|
@ -381,18 +384,23 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
of opcNodeToReg:
|
of opcNodeToReg:
|
||||||
let ra = instr.regA
|
let ra = instr.regA
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
assert regs[rb].kind == rkNode
|
# opcDeref might already have loaded it into a register. XXX Let's hope
|
||||||
let nb = regs[rb].node
|
# this is still correct this way:
|
||||||
case nb.kind
|
if regs[rb].kind != rkNode:
|
||||||
of nkCharLit..nkInt64Lit:
|
regs[ra] = regs[rb]
|
||||||
ensureKind(rkInt)
|
|
||||||
regs[ra].intVal = nb.intVal
|
|
||||||
of nkFloatLit..nkFloat64Lit:
|
|
||||||
ensureKind(rkFloat)
|
|
||||||
regs[ra].floatVal = nb.floatVal
|
|
||||||
else:
|
else:
|
||||||
ensureKind(rkNode)
|
assert regs[rb].kind == rkNode
|
||||||
regs[ra].node = nb
|
let nb = regs[rb].node
|
||||||
|
case nb.kind
|
||||||
|
of nkCharLit..nkInt64Lit:
|
||||||
|
ensureKind(rkInt)
|
||||||
|
regs[ra].intVal = nb.intVal
|
||||||
|
of nkFloatLit..nkFloat64Lit:
|
||||||
|
ensureKind(rkFloat)
|
||||||
|
regs[ra].floatVal = nb.floatVal
|
||||||
|
else:
|
||||||
|
ensureKind(rkNode)
|
||||||
|
regs[ra].node = nb
|
||||||
of opcLdArr:
|
of opcLdArr:
|
||||||
# a = b[c]
|
# a = b[c]
|
||||||
decodeBC(rkNode)
|
decodeBC(rkNode)
|
||||||
|
|
@ -520,10 +528,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
regs[ra].intVal = regs[rb].intVal * regs[rc].intVal
|
regs[ra].intVal = regs[rb].intVal * regs[rc].intVal
|
||||||
of opcDivInt:
|
of opcDivInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
|
if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
|
||||||
|
else: regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
|
||||||
of opcModInt:
|
of opcModInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
|
if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
|
||||||
|
else: regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
|
||||||
of opcAddFloat:
|
of opcAddFloat:
|
||||||
decodeBC(rkFloat)
|
decodeBC(rkFloat)
|
||||||
regs[ra].floatVal = regs[rb].floatVal + regs[rc].floatVal
|
regs[ra].floatVal = regs[rb].floatVal + regs[rc].floatVal
|
||||||
|
|
@ -1174,12 +1184,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
regs[ra].node.strVal = typ.typeToString(preferExported)
|
regs[ra].node.strVal = typ.typeToString(preferExported)
|
||||||
inc pc
|
inc pc
|
||||||
|
|
||||||
proc fixType(result, n: PNode) {.inline.} =
|
|
||||||
# XXX do it deeply for complex values; there seems to be no simple
|
|
||||||
# solution except to check it deeply here.
|
|
||||||
#if result.typ.isNil: result.typ = n.typ
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc execute(c: PCtx, start: int): PNode =
|
proc execute(c: PCtx, start: int): PNode =
|
||||||
var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
|
var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
|
||||||
newSeq(tos.slots, c.prc.maxSlots)
|
newSeq(tos.slots, c.prc.maxSlots)
|
||||||
|
|
@ -1198,8 +1202,6 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
|
||||||
let start = genExpr(c, n)
|
let start = genExpr(c, n)
|
||||||
assert c.code[start].opcode != opcEof
|
assert c.code[start].opcode != opcEof
|
||||||
result = execute(c, start)
|
result = execute(c, start)
|
||||||
if not result.isNil:
|
|
||||||
fixType(result, n)
|
|
||||||
|
|
||||||
# for now we share the 'globals' environment. XXX Coming soon: An API for
|
# for now we share the 'globals' environment. XXX Coming soon: An API for
|
||||||
# storing&loading the 'globals' environment to get what a component system
|
# storing&loading the 'globals' environment to get what a component system
|
||||||
|
|
@ -1243,11 +1245,11 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
|
||||||
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
|
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
|
||||||
if c.code[start].opcode == opcEof: return emptyNode
|
if c.code[start].opcode == opcEof: return emptyNode
|
||||||
assert c.code[start].opcode != opcEof
|
assert c.code[start].opcode != opcEof
|
||||||
|
when debugEchoCode: c.echoCode start
|
||||||
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)
|
||||||
#for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
#for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||||
result = rawExecute(c, start, tos).regToNode
|
result = rawExecute(c, start, tos).regToNode
|
||||||
fixType(result, n)
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -1264,6 +1266,7 @@ proc setupCompileTimeVar*(module: PSym, n: PNode) =
|
||||||
proc setupMacroParam(x: PNode): PNode =
|
proc setupMacroParam(x: PNode): PNode =
|
||||||
result = x
|
result = x
|
||||||
if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
|
if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
|
||||||
|
result = canonValue(result)
|
||||||
result.flags.incl nfIsRef
|
result.flags.incl nfIsRef
|
||||||
result.typ = x.typ
|
result.typ = x.typ
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -308,20 +308,20 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
|
||||||
c.gen(n.sons[2], dest)
|
c.gen(n.sons[2], dest)
|
||||||
c.patch(L1)
|
c.patch(L1)
|
||||||
|
|
||||||
proc canonConst(n: PNode): PNode =
|
proc canonValue*(n: PNode): PNode =
|
||||||
if n.kind == nkExprColonExpr:
|
if n.kind == nkExprColonExpr:
|
||||||
result = n.sons[1]
|
result = n.sons[1]
|
||||||
elif n.hasSubnodeWith(nkExprColonExpr):
|
elif n.hasSubnodeWith(nkExprColonExpr):
|
||||||
result = n.copyNode
|
result = n.copyNode
|
||||||
newSeq(result.sons, n.len)
|
newSeq(result.sons, n.len)
|
||||||
for i in 0.. <n.len:
|
for i in 0.. <n.len:
|
||||||
result.sons[i] = canonConst(n.sons[i])
|
result.sons[i] = canonValue(n.sons[i])
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc rawGenLiteral(c: PCtx; n: PNode): int =
|
proc rawGenLiteral(c: PCtx; n: PNode): int =
|
||||||
result = c.constants.len
|
result = c.constants.len
|
||||||
c.constants.add n.canonConst
|
c.constants.add n.canonValue
|
||||||
internalAssert result < 0x7fff
|
internalAssert result < 0x7fff
|
||||||
|
|
||||||
proc sameConstant*(a, b: PNode): bool =
|
proc sameConstant*(a, b: PNode): bool =
|
||||||
|
|
@ -1227,7 +1227,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
if sfImportc in s.flags: c.importcSym(a.info, s)
|
if sfImportc in s.flags: c.importcSym(a.info, s)
|
||||||
else:
|
else:
|
||||||
let sa = if s.ast.isNil: getNullValue(s.typ, a.info)
|
let sa = if s.ast.isNil: getNullValue(s.typ, a.info)
|
||||||
else: canonConst(s.ast)
|
else: canonValue(s.ast)
|
||||||
c.globals.add(sa)
|
c.globals.add(sa)
|
||||||
s.position = c.globals.len
|
s.position = c.globals.len
|
||||||
if a.sons[2].kind == nkEmpty:
|
if a.sons[2].kind == nkEmpty:
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ discard """
|
||||||
aa
|
aa
|
||||||
bb
|
bb
|
||||||
aa
|
aa
|
||||||
bb'''
|
bb
|
||||||
|
24'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
const s = @[1,2,3]
|
const s = @[1,2,3]
|
||||||
|
|
@ -53,3 +54,22 @@ macro ff(d: static[TData]): stmt =
|
||||||
echo x
|
echo x
|
||||||
|
|
||||||
ff(data)
|
ff(data)
|
||||||
|
|
||||||
|
|
||||||
|
# bug #1010
|
||||||
|
|
||||||
|
proc `*==`(x: var int, y: int) {.inline, noSideEffect.} =
|
||||||
|
## Binary `*=` operator for ordinals
|
||||||
|
x = x * y
|
||||||
|
|
||||||
|
proc fac: int =
|
||||||
|
var x = 1;
|
||||||
|
for i in 1..4:
|
||||||
|
x *== i;
|
||||||
|
return x
|
||||||
|
|
||||||
|
const y = fac()
|
||||||
|
|
||||||
|
static:
|
||||||
|
echo y
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue