new VM is getting stable

This commit is contained in:
Araq 2013-10-29 01:07:59 +01:00
commit b4e25a6372
8 changed files with 206 additions and 124 deletions

View file

@ -216,7 +216,7 @@ proc makeYamlString*(s: string): PRope =
const MaxLineLength = 64 const MaxLineLength = 64
result = nil result = nil
var res = "\"" var res = "\""
for i in countup(0, len(s) - 1): for i in countup(0, if s.isNil: -1 else: (len(s)-1)):
if (i + 1) mod MaxLineLength == 0: if (i + 1) mod MaxLineLength == 0:
add(res, '\"') add(res, '\"')
add(res, "\n") add(res, "\n")

View file

@ -68,6 +68,19 @@ proc myreset(n: PNode) =
reset(n[]) reset(n[])
n.info = oldInfo n.info = oldInfo
proc skipMeta(n: PNode): PNode = (if n.kind != nkMetaNode: n else: n.sons[0])
proc setMeta(n, child: PNode) =
assert n.kind == nkMetaNode
let child = child.skipMeta
if n.sons.isNil: n.sons = @[child]
else: n.sons[0] = child
proc uast(n: PNode): PNode {.inline.} =
# "underlying ast"
assert n.kind == nkMetaNode
n.sons[0]
template ensureKind(k: expr) {.immediate, dirty.} = template ensureKind(k: expr) {.immediate, dirty.} =
if regs[ra].kind != k: if regs[ra].kind != k:
myreset(regs[ra]) myreset(regs[ra])
@ -98,26 +111,30 @@ template decodeBx(k: expr) {.immediate, dirty.} =
template move(a, b: expr) = system.shallowCopy(a, b) template move(a, b: expr) = system.shallowCopy(a, b)
# XXX fix minor 'shallowCopy' overloading bug in compiler # XXX fix minor 'shallowCopy' overloading bug in compiler
when false: proc moveConst(x, y: PNode) =
proc asgnRef(x, y: PNode) = if x.kind != y.kind:
myreset(x) myreset(x)
x.kind = y.kind x.kind = y.kind
x.typ = y.typ x.typ = y.typ
case x.kind case x.kind
of nkCharLit..nkInt64Lit: x.intVal = y.intVal of nkCharLit..nkInt64Lit: x.intVal = y.intVal
of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
of nkStrLit..nkTripleStrLit: x.strVal = y.strVal of nkStrLit..nkTripleStrLit: move(x.strVal, y.strVal)
of nkIdent: x.ident = y.ident of nkIdent: x.ident = y.ident
of nkSym: x.sym = y.sym of nkSym: x.sym = y.sym
of nkMetaNode:
if x.sons.isNil: x.sons = @[y.sons[0]]
else: x.sons[0] = y.sons[0]
else: else:
if x.kind notin {nkEmpty..nkNilLit}: if x.kind notin {nkEmpty..nkNilLit}:
move(x.sons, y.sons) move(x.sons, y.sons)
else:
# this seems to be the best way to model the reference semantics # this seems to be the best way to model the reference semantics
# of PNimrodNode: # of PNimrodNode:
template asgnRef(x, y: expr) = x = y template asgnRef(x, y: expr) = moveConst(x, y)
proc asgnComplex(x, y: PNode) = proc asgnComplex(x, y: PNode) =
if x.kind != y.kind:
myreset(x) myreset(x)
x.kind = y.kind x.kind = y.kind
x.typ = y.typ x.typ = y.typ
@ -127,6 +144,9 @@ proc asgnComplex(x, y: PNode) =
of nkStrLit..nkTripleStrLit: x.strVal = y.strVal of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
of nkIdent: x.ident = y.ident of nkIdent: x.ident = y.ident
of nkSym: x.sym = y.sym of nkSym: x.sym = y.sym
of nkMetaNode:
if x.sons.isNil: x.sons = @[y.sons[0]]
else: x.sons[0] = y.sons[0]
else: else:
if x.kind notin {nkEmpty..nkNilLit}: if x.kind notin {nkEmpty..nkNilLit}:
let y = y.copyTree let y = y.copyTree
@ -286,16 +306,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcAsgnRef: of opcAsgnRef:
asgnRef(regs[ra], regs[instr.regB]) asgnRef(regs[ra], regs[instr.regB])
of opcWrGlobalRef: of opcWrGlobalRef:
asgnRef(c.globals.sons[instr.regBx-wordExcess-1], regs[ra]) asgnRef(c.globals.sons[instr.regBx-wordExcess-1], regs[ra].skipMeta)
of opcWrGlobal: of opcWrGlobal:
asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra]) asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra].skipMeta)
of opcLdArr: of opcLdArr:
# a = b[c] # a = b[c]
let rb = instr.regB let rb = instr.regB
let rc = instr.regC let rc = instr.regC
let idx = regs[rc].intVal let idx = regs[rc].intVal
# XXX what if the array is not 0-based? -> codegen should insert a sub # XXX what if the array is not 0-based? -> codegen should insert a sub
regs[ra] = regs[rb].sons[idx.int] assert regs[rb].kind != nkMetaNode
asgnComplex(regs[ra], regs[rb].sons[idx.int])
of opcLdStrIdx: of opcLdStrIdx:
decodeBC(nkIntLit) decodeBC(nkIntLit)
let idx = regs[rc].intVal let idx = regs[rc].intVal
@ -305,12 +326,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
let rb = instr.regB let rb = instr.regB
let rc = instr.regC let rc = instr.regC
let idx = regs[rb].intVal let idx = regs[rb].intVal
asgnComplex(regs[ra].sons[idx.int], regs[rc]) asgnComplex(regs[ra].sons[idx.int], regs[rc].skipMeta)
of opcWrArrRef: of opcWrArrRef:
let rb = instr.regB let rb = instr.regB
let rc = instr.regC let rc = instr.regC
let idx = regs[rb].intVal let idx = regs[rb].intVal
asgnRef(regs[ra].sons[idx.int], regs[rc]) asgnRef(regs[ra].sons[idx.int], regs[rc].skipMeta)
of opcLdObj: of opcLdObj:
# a = b.c # a = b.c
let rb = instr.regB let rb = instr.regB
@ -322,11 +343,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
# a.b = c # a.b = c
let rb = instr.regB let rb = instr.regB
let rc = instr.regC let rc = instr.regC
asgnComplex(regs[ra].sons[rb], regs[rc]) asgnComplex(regs[ra].sons[rb], regs[rc].skipMeta)
of opcWrObjRef: of opcWrObjRef:
let rb = instr.regB let rb = instr.regB
let rc = instr.regC let rc = instr.regC
asgnRef(regs[ra].sons[rb], regs[rc]) asgnRef(regs[ra].sons[rb], regs[rc].skipMeta)
of opcWrStrIdx: of opcWrStrIdx:
decodeBC(nkStrLit) decodeBC(nkStrLit)
let idx = regs[rb].intVal.int let idx = regs[rb].intVal.int
@ -341,6 +362,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
if regs[rb].kind == nkNilLit: if regs[rb].kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess) stackTrace(c, tos, pc, errNilAccess)
assert regs[rb].kind == nkRefTy assert regs[rb].kind == nkRefTy
# XXX this is not correct
regs[ra] = regs[rb].sons[0] regs[ra] = regs[rb].sons[0]
of opcAddInt: of opcAddInt:
decodeBC(nkIntLit) decodeBC(nkIntLit)
@ -357,8 +379,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcLenSeq: of opcLenSeq:
decodeBImm(nkIntLit) decodeBImm(nkIntLit)
#assert regs[rb].kind == nkBracket #assert regs[rb].kind == nkBracket
# also used by mNLen # also used by mNLen:
regs[ra].intVal = regs[rb].len - imm regs[ra].intVal = regs[rb].skipMeta.len - imm
of opcLenStr: of opcLenStr:
decodeBImm(nkIntLit) decodeBImm(nkIntLit)
assert regs[rb].kind == nkStrLit assert regs[rb].kind == nkStrLit
@ -366,6 +388,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcIncl: of opcIncl:
decodeB(nkCurly) decodeB(nkCurly)
if not inSet(regs[ra], regs[rb]): addSon(regs[ra], copyTree(regs[rb])) if not inSet(regs[ra], regs[rb]): addSon(regs[ra], copyTree(regs[rb]))
of opcInclRange:
decodeBC(nkCurly)
var r = newNode(nkRange)
r.add regs[rb]
r.add regs[rc]
addSon(regs[ra], r.copyTree)
of opcExcl: of opcExcl:
decodeB(nkCurly) decodeB(nkCurly)
var b = newNodeIT(nkCurly, regs[rb].info, regs[rb].typ) var b = newNodeIT(nkCurly, regs[rb].info, regs[rb].typ)
@ -456,6 +484,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
regs[ra].intVal = ord((regs[rb].kind == nkNilLit and regs[ra].intVal = ord((regs[rb].kind == nkNilLit and
regs[rc].kind == nkNilLit) or regs[rc].kind == nkNilLit) or
regs[rb].sons == regs[rc].sons) regs[rb].sons == regs[rc].sons)
of opcEqNimrodNode:
decodeBC(nkIntLit)
regs[ra].intVal = ord(regs[rb].uast == regs[rc].uast)
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)
@ -529,7 +560,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
writeln(stdout, "") writeln(stdout, "")
of opcContainsSet: of opcContainsSet:
decodeBC(nkIntLit) decodeBC(nkIntLit)
regs[ra].intVal = Ord(inSet(regs[rb], regs[rc])) regs[ra].intVal = ord(inSet(regs[rb], regs[rc]))
of opcSubStr: of opcSubStr:
decodeBC(nkStrLit) decodeBC(nkStrLit)
inc pc inc pc
@ -581,18 +612,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc' let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
inc pc, rbx inc pc, rbx
of opcBranch: of opcBranch:
# we know the next instruction is a 'jmp': # we know the next instruction is a 'fjmp':
let branch = c.constants[instr.regBx-wordExcess] let branch = c.constants[instr.regBx-wordExcess]
var cond = false var cond = false
for j in countup(0, sonsLen(branch) - 2): for j in countup(0, sonsLen(branch) - 2):
if overlap(regs[ra], branch.sons[j]): if overlap(regs[ra], branch.sons[j]):
cond = true cond = true
break break
assert c.code[pc+1].opcode == opcJmp assert c.code[pc+1].opcode == opcFJmp
inc pc inc pc
# we skip this instruction so that the final 'inc(pc)' skips # we skip this instruction so that the final 'inc(pc)' skips
# the following jump # the following jump
if cond: if not cond:
let instr2 = c.code[pc] let instr2 = c.code[pc]
let rbx = instr2.regBx - wordExcess - 1 # -1 for the following 'inc pc' let rbx = instr2.regBx - wordExcess - 1 # -1 for the following 'inc pc'
inc pc, rbx inc pc, rbx
@ -646,7 +677,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
let typ = c.types[instr.regBx - wordExcess] let typ = c.types[instr.regBx - wordExcess]
regs[ra] = getNullValue(typ, c.debug[pc]) regs[ra] = getNullValue(typ, c.debug[pc])
of opcLdConst: of opcLdConst:
regs[ra] = c.constants.sons[instr.regBx - wordExcess] let rb = instr.regBx - wordExcess
if regs[ra].isNil:
regs[ra] = copyTree(c.constants.sons[rb])
else:
moveConst(regs[ra], c.constants.sons[rb])
of opcAsgnConst: of opcAsgnConst:
let rb = instr.regBx - wordExcess let rb = instr.regBx - wordExcess
if regs[ra].isNil: if regs[ra].isNil:
@ -661,7 +696,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
asgnComplex(regs[ra], c.globals.sons[rb]) asgnComplex(regs[ra], c.globals.sons[rb])
of opcRepr: of opcRepr:
decodeB(nkStrLit) decodeB(nkStrLit)
regs[ra].strVal = renderTree(regs[rb], {renderNoComments}) regs[ra].strVal = renderTree(regs[rb].skipMeta, {renderNoComments})
of opcQuit: of opcQuit:
if c.mode in {emRepl, emStatic}: if c.mode in {emRepl, emStatic}:
Message(c.debug[pc], hintQuitCalled) Message(c.debug[pc], hintQuitCalled)
@ -674,62 +709,71 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcOf: of opcOf:
decodeBC(nkIntLit) decodeBC(nkIntLit)
regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, regs[rc].typ) >= 0) regs[ra].intVal = ord(inheritanceDiff(regs[rb].typ, regs[rc].typ) >= 0)
of opcSetLenSeq, of opcSetLenSeq:
opcSwap, opcIsNil, decodeB(nkBracket)
opcCast, opcReset: let newLen = regs[rb].getOrdValue.int
setLen(regs[ra].sons, newLen)
of opcSwap, opcCast, opcReset:
internalError(c.debug[pc], "too implement") internalError(c.debug[pc], "too implement")
of opcIsNil:
decodeB(nkIntLit)
regs[ra].intVal = ord(regs[rb].skipMeta.kind == nkNilLit)
of opcNBindSym: of opcNBindSym:
# trivial implementation: # trivial implementation:
let rb = instr.regB decodeB(nkMetaNode)
regs[ra] = regs[rb].sons[1] setMeta(regs[ra], regs[rb].skipMeta.sons[1])
of opcNChild: of opcNChild:
let rb = instr.regB decodeBC(nkMetaNode)
let rc = instr.regC setMeta(regs[ra], regs[rb].uast.sons[regs[rc].intVal.int])
regs[ra] = regs[rb].sons[regs[rc].intVal.int]
of opcNSetChild: of opcNSetChild:
let rb = instr.regB decodeBC(nkMetaNode)
let rc = instr.regC regs[ra].uast.sons[regs[rb].intVal.int] = regs[rc].uast
regs[ra].sons[regs[rb].intVal.int] = regs[rc]
of opcNAdd: of opcNAdd:
declBC() decodeBC(nkMetaNode)
regs[rb].add(regs[rc]) var u = regs[rb].uast
regs[ra] = regs[rb] u.add(regs[rc].uast)
setMeta(regs[ra], u)
of opcNAddMultiple: of opcNAddMultiple:
declBC() decodeBC(nkMetaNode)
let x = regs[rc] let x = regs[rc]
var u = regs[rb].uast
# XXX can be optimized: # XXX can be optimized:
for i in 0.. <x.len: regs[rb].add(x.sons[i]) for i in 0.. <x.len: u.add(x.sons[i].skipMeta)
regs[ra] = regs[rb] setMeta(regs[ra], u)
of opcNKind: of opcNKind:
decodeB(nkIntLit) decodeB(nkIntLit)
regs[ra].intVal = ord(regs[rb].kind) regs[ra].intVal = ord(regs[rb].uast.kind)
of opcNIntVal: of opcNIntVal:
decodeB(nkIntLit) decodeB(nkIntLit)
let a = regs[rb] let a = regs[rb].uast
case a.kind case a.kind
of nkCharLit..nkInt64Lit: regs[ra].intVal = a.intVal of nkCharLit..nkInt64Lit: regs[ra].intVal = a.intVal
else: stackTrace(c, tos, pc, errFieldXNotFound, "intVal") else: stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
of opcNFloatVal: of opcNFloatVal:
decodeB(nkFloatLit) decodeB(nkFloatLit)
let a = regs[rb] let a = regs[rb].uast
case a.kind case a.kind
of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
else: stackTrace(c, tos, pc, errFieldXNotFound, "floatVal") else: stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
of opcNSymbol: of opcNSymbol:
let rb = instr.regB decodeB(nkSym)
if regs[rb].kind != nkSym: let a = regs[rb].uast
if a.kind == nkSym:
regs[ra].sym = a.sym
else:
stackTrace(c, tos, pc, errFieldXNotFound, "symbol") stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
regs[ra] = regs[rb]
of opcNIdent: of opcNIdent:
let rb = instr.regB decodeB(nkIdent)
if regs[rb].kind != nkIdent: let a = regs[rb].uast
if a.kind == nkIdent:
regs[ra].ident = a.ident
else:
stackTrace(c, tos, pc, errFieldXNotFound, "ident") stackTrace(c, tos, pc, errFieldXNotFound, "ident")
regs[ra] = regs[rb]
of opcNGetType: of opcNGetType:
InternalError(c.debug[pc], "unknown opcode " & $instr.opcode) InternalError(c.debug[pc], "unknown opcode " & $instr.opcode)
of opcNStrVal: of opcNStrVal:
decodeB(nkStrLit) decodeB(nkStrLit)
let a = regs[rb] let a = regs[rb].uast
case a.kind case a.kind
of nkStrLit..nkTripleStrLit: regs[ra].strVal = a.strVal of nkStrLit..nkTripleStrLit: regs[ra].strVal = a.strVal
else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal") else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
@ -746,25 +790,26 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
of opcNHint: of opcNHint:
Message(c.debug[pc], hintUser, regs[ra].strVal) Message(c.debug[pc], hintUser, regs[ra].strVal)
of opcParseExprToAst: of opcParseExprToAst:
let rb = instr.regB decodeB(nkMetaNode)
# c.debug[pc].line.int - countLines(regs[rb].strVal) ? # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
let ast = parseString(regs[rb].strVal, c.debug[pc].toFilename, let ast = parseString(regs[rb].strVal, c.debug[pc].toFilename,
c.debug[pc].line.int) c.debug[pc].line.int)
if sonsLen(ast) != 1: if sonsLen(ast) != 1:
GlobalError(c.debug[pc], errExprExpected, "multiple statements") GlobalError(c.debug[pc], errExprExpected, "multiple statements")
regs[ra] = ast.sons[0] setMeta(regs[ra], ast.sons[0])
of opcParseStmtToAst: of opcParseStmtToAst:
let rb = instr.regB decodeB(nkMetaNode)
let ast = parseString(regs[rb].strVal, c.debug[pc].toFilename, let ast = parseString(regs[rb].strVal, c.debug[pc].toFilename,
c.debug[pc].line.int) c.debug[pc].line.int)
regs[ra] = ast setMeta(regs[ra], ast)
of opcCallSite: of opcCallSite:
if c.callsite != nil: regs[ra] = c.callsite ensureKind(nkMetaNode)
if c.callsite != nil: setMeta(regs[ra], c.callsite)
else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite") else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite")
of opcNLineInfo: of opcNLineInfo:
let rb = instr.regB decodeB(nkStrLit)
let n = regs[rb] let n = regs[rb]
regs[ra] = newStrNode(nkStrLit, n.info.toFileLineCol) regs[ra].strVal = n.info.toFileLineCol
regs[ra].info = c.debug[pc] regs[ra].info = c.debug[pc]
of opcEqIdent: of opcEqIdent:
decodeBC(nkIntLit) decodeBC(nkIntLit)
@ -773,16 +818,16 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
else: else:
regs[ra].intVal = 0 regs[ra].intVal = 0
of opcStrToIdent: of opcStrToIdent:
let rb = instr.regB decodeB(nkIdent)
if regs[rb].kind notin {nkStrLit..nkTripleStrLit}: if regs[rb].kind notin {nkStrLit..nkTripleStrLit}:
stackTrace(c, tos, pc, errFieldXNotFound, "strVal") stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
else: else:
regs[ra] = newNodeI(nkIdent, c.debug[pc]) regs[ra].info = c.debug[pc]
regs[ra].ident = getIdent(regs[rb].strVal) regs[ra].ident = getIdent(regs[rb].strVal)
of opcIdentToStr: of opcIdentToStr:
let rb = instr.regB decodeB(nkStrLit)
let a = regs[rb] let a = regs[rb]
regs[ra] = newNodeI(nkStrLit, c.debug[pc]) regs[ra].info = c.debug[pc]
if a.kind == nkSym: if a.kind == nkSym:
regs[ra].strVal = a.sym.name.s regs[ra].strVal = a.sym.name.s
elif a.kind == nkIdent: elif a.kind == nkIdent:
@ -800,71 +845,80 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
msgKindToString(errIllegalConvFromXtoY) % [ msgKindToString(errIllegalConvFromXtoY) % [
"unknown type" , "unknown type"]) "unknown type" , "unknown type"])
of opcNSetIntVal: of opcNSetIntVal:
let rb = instr.regB decodeB(nkMetaNode)
if regs[ra].kind in {nkCharLit..nkInt64Lit} and var dest = regs[ra].uast
if dest.kind in {nkCharLit..nkInt64Lit} and
regs[rb].kind in {nkCharLit..nkInt64Lit}: regs[rb].kind in {nkCharLit..nkInt64Lit}:
regs[ra].intVal = regs[rb].intVal dest.intVal = regs[rb].intVal
else: else:
stackTrace(c, tos, pc, errFieldXNotFound, "intVal") stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
of opcNSetFloatVal: of opcNSetFloatVal:
let rb = instr.regB decodeB(nkMetaNode)
if regs[ra].kind in {nkFloatLit..nkFloat64Lit} and var dest = regs[ra].uast
if dest.kind in {nkFloatLit..nkFloat64Lit} and
regs[rb].kind in {nkFloatLit..nkFloat64Lit}: regs[rb].kind in {nkFloatLit..nkFloat64Lit}:
regs[ra].floatVal = regs[rb].floatVal dest.floatVal = regs[rb].floatVal
else: else:
stackTrace(c, tos, pc, errFieldXNotFound, "floatVal") stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
of opcNSetSymbol: of opcNSetSymbol:
let rb = instr.regB decodeB(nkMetaNode)
if regs[ra].kind == nkSym and regs[rb].kind == nkSym: var dest = regs[ra].uast
regs[ra].sym = regs[rb].sym if dest.kind == nkSym and regs[rb].kind == nkSym:
dest.sym = regs[rb].sym
else: else:
stackTrace(c, tos, pc, errFieldXNotFound, "symbol") stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
of opcNSetIdent: of opcNSetIdent:
let rb = instr.regB decodeB(nkMetaNode)
if regs[ra].kind == nkIdent and regs[rb].kind == nkIdent: var dest = regs[ra].uast
regs[ra].ident = regs[rb].ident if dest.kind == nkIdent and regs[rb].kind == nkIdent:
dest.ident = regs[rb].ident
else: else:
stackTrace(c, tos, pc, errFieldXNotFound, "ident") stackTrace(c, tos, pc, errFieldXNotFound, "ident")
of opcNSetType: of opcNSetType:
let b = regs[instr.regB] decodeB(nkMetaNode)
let b = regs[rb].skipMeta
InternalAssert b.kind == nkSym and b.sym.kind == skType InternalAssert b.kind == nkSym and b.sym.kind == skType
regs[ra].typ = b.sym.typ regs[ra].uast.typ = b.sym.typ
of opcNSetStrVal: of opcNSetStrVal:
let rb = instr.regB decodeB(nkMetaNode)
if regs[ra].kind in {nkStrLit..nkTripleStrLit} and var dest = regs[ra].uast
if dest.kind in {nkStrLit..nkTripleStrLit} and
regs[rb].kind in {nkStrLit..nkTripleStrLit}: regs[rb].kind in {nkStrLit..nkTripleStrLit}:
regs[ra].strVal = regs[rb].strVal dest.strVal = regs[rb].strVal
else: else:
#c.echoCode
#debug regs[ra]
#debug regs[rb]
stackTrace(c, tos, pc, errFieldXNotFound, "strVal") stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
of opcNNewNimNode: of opcNNewNimNode:
let rb = instr.regB decodeBC(nkMetaNode)
let rc = instr.regC
var k = regs[rb].intVal var k = regs[rb].intVal
if k < 0 or k > ord(high(TNodeKind)): if k < 0 or k > ord(high(TNodeKind)):
internalError(c.debug[pc], internalError(c.debug[pc],
"request to create a NimNode with invalid kind") "request to create a NimNode of invalid kind")
regs[ra] = newNodeI(TNodeKind(int(k)), let cc = regs[rc].skipMeta
if regs[rc].kind == nkNilLit: c.debug[pc] else: regs[rc].info) setMeta(regs[ra], newNodeI(TNodeKind(int(k)),
if cc.kind == nkNilLit: c.debug[pc] else: cc.info))
of opcNCopyNimNode: of opcNCopyNimNode:
let rb = instr.regB decodeB(nkMetaNode)
regs[ra] = copyNode(regs[rb]) setMeta(regs[ra], copyNode(regs[rb]))
of opcNCopyNimTree: of opcNCopyNimTree:
let rb = instr.regB decodeB(nkMetaNode)
regs[ra] = copyTree(regs[rb]) setMeta(regs[ra], copyTree(regs[rb]))
of opcNDel: of opcNDel:
let rb = instr.regB decodeBC(nkMetaNode)
let rc = instr.regC let bb = regs[rb].intVal.int
for i in countup(0, regs[rc].intVal.int-1): for i in countup(0, regs[rc].intVal.int-1):
delSon(regs[ra], regs[rb].intVal.int) delSon(regs[ra].uast, bb)
of opcGenSym: of opcGenSym:
let k = regs[instr.regB].intVal decodeBC(nkMetaNode)
let b = regs[instr.regC] let k = regs[rb].intVal
let name = if b.strVal.len == 0: ":tmp" else: b.strVal let name = if regs[rc].strVal.len == 0: ":tmp" else: regs[rc].strVal
if k < 0 or k > ord(high(TSymKind)): if k < 0 or k > ord(high(TSymKind)):
internalError(c.debug[pc], "request to create symbol of invalid kind") internalError(c.debug[pc], "request to create symbol of invalid kind")
regs[ra] = newSymNode(newSym(k.TSymKind, name.getIdent, c.module, var sym = newSym(k.TSymKind, name.getIdent, c.module, c.debug[pc])
c.debug[pc])) incl(sym.flags, sfGenSym)
incl(regs[ra].sym.flags, sfGenSym) setMeta(regs[ra], newSymNode(sym))
of opcTypeTrait: of opcTypeTrait:
# XXX only supports 'name' for now; we can use regC to encode the # XXX only supports 'name' for now; we can use regC to encode the
# type trait operation # type trait operation
@ -894,6 +948,8 @@ 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:
result = result.skipMeta
fixType(result, n) 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
@ -949,6 +1005,9 @@ proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): 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]
let y = result
result = newNode(nkMetaNode)
result.add y
var evalMacroCounter: int var evalMacroCounter: int
@ -979,4 +1038,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
result = rawExecute(c, start, tos) result = rawExecute(c, start, tos)
if cyclicTree(result): GlobalError(n.info, errCyclicTree) if cyclicTree(result): GlobalError(n.info, errCyclicTree)
dec(evalMacroCounter) dec(evalMacroCounter)
if result != nil:
internalAssert result.kind == nkMetaNode
result = result.sons[0]
c.callsite = nil c.callsite = nil

View file

@ -51,11 +51,11 @@ type
opcLenSeq, opcLenSeq,
opcLenStr, opcLenStr,
opcIncl, opcExcl, opcCard, opcMulInt, opcDivInt, opcModInt, opcIncl, opcInclRange, opcExcl, opcCard, opcMulInt, opcDivInt, opcModInt,
opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, opcShrInt, opcShlInt, opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, opcShrInt, opcShlInt,
opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu, opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu,
opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat, opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat,
opcLeFloat, opcLtFloat, opcLeu, opcLtu, opcEqRef, opcXor, opcLeFloat, opcLtFloat, opcLeu, opcLtu, opcEqRef, opcEqNimrodNode, opcXor,
opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt,
opcEqStr, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet, opcEqStr, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr, opcMulSet, opcPlusSet, opcMinusSet, opcSymdiffSet, opcConcatStr,

View file

@ -277,9 +277,9 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
# asgn dest, b # asgn dest, b
# L1: # L1:
if dest < 0: dest = getTemp(c, n.typ) if dest < 0: dest = getTemp(c, n.typ)
c.gen(n.sons[0], dest)
let L1 = c.xjmp(n, opc)
c.gen(n.sons[1], dest) c.gen(n.sons[1], dest)
let L1 = c.xjmp(n, opc, dest)
c.gen(n.sons[2], dest)
c.patch(L1) c.patch(L1)
proc rawGenLiteral(c: PCtx; n: PNode): int = proc rawGenLiteral(c: PCtx; n: PNode): int =
@ -758,7 +758,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent) of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
of mIdentToStr: genUnaryABC(c, n, dest, opcIdentToStr) of mIdentToStr: genUnaryABC(c, n, dest, opcIdentToStr)
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent) of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqRef) of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo) of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo)
of mNHint: of mNHint:
unused(n, dest) unused(n, dest)
@ -1040,6 +1040,13 @@ proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
if dest < 0: dest = c.getTemp(n.typ) if dest < 0: dest = c.getTemp(n.typ)
c.gABx(n, opcLdNull, dest, c.genType(n.typ)) c.gABx(n, opcLdNull, dest, c.genType(n.typ))
for x in n: for x in n:
if x.kind == nkRange:
let a = c.genx(x.sons[0])
let b = c.genx(x.sons[1])
c.gABC(n, opcInclRange, dest, a, b)
c.freeTemp(b)
c.freeTemp(a)
else:
let a = c.genx(x) let a = c.genx(x)
c.gABC(n, opcIncl, dest, a) c.gABC(n, opcIncl, dest, a)
c.freeTemp(a) c.freeTemp(a)
@ -1297,8 +1304,6 @@ proc genProc(c: PCtx; s: PSym): int =
c.gABC(body, opcEof, eofInstr.regA) c.gABC(body, opcEof, eofInstr.regA)
s.position = c.prc.maxSlots s.position = c.prc.maxSlots
c.prc = oldPrc c.prc = oldPrc
#if s.name.s == "xmlConstructor":
# echoCode(c)
else: else:
c.prc.maxSlots = s.position c.prc.maxSlots = s.position
result = x.intVal.int result = x.intVal.int

View file

@ -45,6 +45,7 @@ Possible Commands:
tests run the testsuite tests run the testsuite
update updates nimrod to the latest version from github update updates nimrod to the latest version from github
(compile koch with -d:withUpdate to enable) (compile koch with -d:withUpdate to enable)
temp options creates a temporary compiler for testing
Boot options: Boot options:
-d:release produce a release version of the compiler -d:release produce a release version of the compiler
-d:tinyc include the Tiny C backend (not supported on Windows) -d:tinyc include the Tiny C backend (not supported on Windows)
@ -268,6 +269,13 @@ proc tests(args: string) =
exec(getCurrentDir() / "tests/tester".exe & " run") exec(getCurrentDir() / "tests/tester".exe & " run")
exec(getCurrentDir() / "tests/tester".exe & " merge") exec(getCurrentDir() / "tests/tester".exe & " merge")
proc temp(args: string) =
var output = "compiler" / "nimrod".exe
var finalDest = "bin" / "nimrod".exe
exec("nimrod c compiler" / "nimrod")
copyExe(output, finalDest)
if args.len > 0: exec(finalDest & " " & args)
proc showHelp() = proc showHelp() =
quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)), quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)),
CompileDate, CompileTime]) CompileDate, CompileTime])
@ -291,6 +299,7 @@ of cmdArgument:
update(op.cmdLineRest) update(op.cmdLineRest)
else: else:
quit "this Koch has not been compiled with -d:withUpdate" quit "this Koch has not been compiled with -d:withUpdate"
of "temp": temp(op.cmdLineRest)
else: showHelp() else: showHelp()
of cmdEnd: showHelp() of cmdEnd: showHelp()

View file

@ -158,7 +158,13 @@ proc `intVal=`*(n: PNimrodNode, val: biggestInt) {.magic: "NSetIntVal".}
proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".} proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".}
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".} proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".} proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".} #proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
# can easily do:
# let bracket = semCheck([1, 2])
# let fake = semCheck(2.0)
# bracket[0] = fake # constructs a mixed array with ints and floats!
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".} proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
proc newNimNode*(kind: TNimrodNodeKind, proc newNimNode*(kind: TNimrodNodeKind,

View file

@ -93,7 +93,7 @@ proc normalize*(s: string): string {.noSideEffect, procvar,
var j = 0 var j = 0
for i in 0..len(s) - 1: for i in 0..len(s) - 1:
if s[i] in {'A'..'Z'}: if s[i] in {'A'..'Z'}:
result[j] = Chr(Ord(s[i]) + (Ord('a') - Ord('A'))) result[j] = chr(ord(s[i]) + (ord('a') - ord('A')))
inc j inc j
elif s[i] != '_': elif s[i] != '_':
result[j] = s[i] result[j] = s[i]

View file

@ -2,8 +2,8 @@ version 0.9.4
============= =============
- new VM: - new VM:
- get rid of nkIntLit..nkUInt64Lit, compiling htmlgen (txmlgen) makes the compiler go into an infinite loop
nkFloatLit..nkFloat128Lit, nkStrLit..nkTripleStrLit? tcntseq
- new VM requires lambda lifting - new VM requires lambda lifting
- implement overflow checking - implement overflow checking
- implement the FFI - implement the FFI