VM: minor fixes to make lexim work

This commit is contained in:
Araq 2015-04-20 11:36:13 +02:00
commit 7be092bba5
4 changed files with 75 additions and 67 deletions

View file

@ -9,40 +9,40 @@
# tree helper routines # tree helper routines
import import
ast, astalgo, lexer, msgs, strutils, wordrecg ast, astalgo, lexer, msgs, strutils, wordrecg
proc hasSon(father, son: PNode): bool = proc hasSon(father, son: PNode): bool =
for i in countup(0, sonsLen(father) - 1): for i in countup(0, sonsLen(father) - 1):
if father.sons[i] == son: if father.sons[i] == son:
return true return true
result = false result = false
proc cyclicTreeAux(n, s: PNode): bool = proc cyclicTreeAux(n, s: PNode): bool =
if n == nil: if n == nil:
return false return false
if hasSon(s, n): if hasSon(s, n):
return true return true
var m = sonsLen(s) var m = sonsLen(s)
addSon(s, n) addSon(s, n)
if not (n.kind in {nkEmpty..nkNilLit}): if not (n.kind in {nkEmpty..nkNilLit}):
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if cyclicTreeAux(n.sons[i], s): if cyclicTreeAux(n.sons[i], s):
return true return true
result = false result = false
delSon(s, m) delSon(s, m)
proc cyclicTree*(n: PNode): bool = proc cyclicTree*(n: PNode): bool =
var s = newNodeI(nkEmpty, n.info) var s = newNodeI(nkEmpty, n.info)
result = cyclicTreeAux(n, s) result = cyclicTreeAux(n, s)
proc exprStructuralEquivalent*(a, b: PNode): bool = proc exprStructuralEquivalent*(a, b: PNode): bool =
result = false result = false
if a == b: if a == b:
result = true result = true
elif (a != nil) and (b != nil) and (a.kind == b.kind): elif (a != nil) and (b != nil) and (a.kind == b.kind):
case a.kind case a.kind
of nkSym: of nkSym:
# don't go nuts here: same symbol as string is enough: # don't go nuts here: same symbol as string is enough:
result = a.sym.name.id == b.sym.name.id result = a.sym.name.id == b.sym.name.id
of nkIdent: result = a.ident.id == b.ident.id of nkIdent: result = a.ident.id == b.ident.id
@ -50,12 +50,12 @@ proc exprStructuralEquivalent*(a, b: PNode): bool =
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkEmpty, nkNilLit, nkType: result = true of nkEmpty, nkNilLit, nkType: result = true
else: else:
if sonsLen(a) == sonsLen(b): if sonsLen(a) == sonsLen(b):
for i in countup(0, sonsLen(a) - 1): for i in countup(0, sonsLen(a) - 1):
if not exprStructuralEquivalent(a.sons[i], b.sons[i]): return if not exprStructuralEquivalent(a.sons[i], b.sons[i]): return
result = true result = true
proc sameTree*(a, b: PNode): bool = proc sameTree*(a, b: PNode): bool =
result = false result = false
if a == b: if a == b:
@ -66,7 +66,7 @@ proc sameTree*(a, b: PNode): bool =
if a.info.col != b.info.col: if a.info.col != b.info.col:
return #if a.info.fileIndex <> b.info.fileIndex then exit; return #if a.info.fileIndex <> b.info.fileIndex then exit;
case a.kind case a.kind
of nkSym: of nkSym:
# don't go nuts here: same symbol as string is enough: # don't go nuts here: same symbol as string is enough:
result = a.sym.name.id == b.sym.name.id result = a.sym.name.id == b.sym.name.id
of nkIdent: result = a.ident.id == b.ident.id of nkIdent: result = a.ident.id == b.ident.id
@ -75,15 +75,15 @@ proc sameTree*(a, b: PNode): bool =
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkEmpty, nkNilLit, nkType: result = true of nkEmpty, nkNilLit, nkType: result = true
else: else:
if sonsLen(a) == sonsLen(b): if sonsLen(a) == sonsLen(b):
for i in countup(0, sonsLen(a) - 1): for i in countup(0, sonsLen(a) - 1):
if not sameTree(a.sons[i], b.sons[i]): return if not sameTree(a.sons[i], b.sons[i]): return
result = true result = true
proc getProcSym*(call: PNode): PSym = proc getProcSym*(call: PNode): PSym =
result = call.sons[0].sym result = call.sons[0].sym
proc getOpSym*(op: PNode): PSym = proc getOpSym*(op: PNode): PSym =
if op.kind notin {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}: if op.kind notin {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}:
result = nil result = nil
else: else:
@ -91,25 +91,25 @@ proc getOpSym*(op: PNode): PSym =
elif op.sons[0].kind == nkSym: result = op.sons[0].sym elif op.sons[0].kind == nkSym: result = op.sons[0].sym
else: result = nil else: result = nil
proc getMagic*(op: PNode): TMagic = proc getMagic*(op: PNode): TMagic =
case op.kind case op.kind
of nkCallKinds: of nkCallKinds:
case op.sons[0].kind case op.sons[0].kind
of nkSym: result = op.sons[0].sym.magic of nkSym: result = op.sons[0].sym.magic
else: result = mNone else: result = mNone
else: result = mNone else: result = mNone
proc treeToSym*(t: PNode): PSym = proc treeToSym*(t: PNode): PSym =
result = t.sym result = t.sym
proc isConstExpr*(n: PNode): bool = proc isConstExpr*(n: PNode): bool =
result = (n.kind in result = (n.kind in
{nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags) nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags)
proc isDeepConstExpr*(n: PNode): bool = proc isDeepConstExpr*(n: PNode): bool =
case n.kind case n.kind
of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
nkFloatLit..nkFloat64Lit, nkNilLit: nkFloatLit..nkFloat64Lit, nkNilLit:
result = true result = true
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
@ -122,33 +122,33 @@ proc isDeepConstExpr*(n: PNode): bool =
result = n.typ.isNil or n.typ.skipTypes({tyGenericInst, tyDistinct}).kind != tyObject result = n.typ.isNil or n.typ.skipTypes({tyGenericInst, tyDistinct}).kind != tyObject
else: discard else: discard
proc flattenTreeAux(d, a: PNode, op: TMagic) = proc flattenTreeAux(d, a: PNode, op: TMagic) =
if (getMagic(a) == op): # a is a "leaf", so add it: if (getMagic(a) == op): # a is a "leaf", so add it:
for i in countup(1, sonsLen(a) - 1): # BUGFIX for i in countup(1, sonsLen(a) - 1): # BUGFIX
flattenTreeAux(d, a.sons[i], op) flattenTreeAux(d, a.sons[i], op)
else: else:
addSon(d, copyTree(a)) addSon(d, copyTree(a))
proc flattenTree*(root: PNode, op: TMagic): PNode = proc flattenTree*(root: PNode, op: TMagic): PNode =
result = copyNode(root) result = copyNode(root)
if getMagic(root) == op: if getMagic(root) == op:
# BUGFIX: forget to copy prc # BUGFIX: forget to copy prc
addSon(result, copyNode(root.sons[0])) addSon(result, copyNode(root.sons[0]))
flattenTreeAux(result, root, op) flattenTreeAux(result, root, op)
proc swapOperands*(op: PNode) = proc swapOperands*(op: PNode) =
var tmp = op.sons[1] var tmp = op.sons[1]
op.sons[1] = op.sons[2] op.sons[1] = op.sons[2]
op.sons[2] = tmp op.sons[2] = tmp
proc isRange*(n: PNode): bool {.inline.} = proc isRange*(n: PNode): bool {.inline.} =
if n.kind == nkInfix: if n.kind in nkCallKinds:
if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or
n[0].kind in {nkClosedSymChoice, nkOpenSymChoice} and n[0].kind in {nkClosedSymChoice, nkOpenSymChoice} and
n[0][1].sym.name.id == ord(wDotDot): n[0][1].sym.name.id == ord(wDotDot):
result = true result = true
proc whichPragma*(n: PNode): TSpecialWord = proc whichPragma*(n: PNode): TSpecialWord =
let key = if n.kind == nkExprColonExpr: n.sons[0] else: n let key = if n.kind == nkExprColonExpr: n.sons[0] else: n
if key.kind == nkIdent: result = whichKeyword(key.ident) if key.kind == nkIdent: result = whichKeyword(key.ident)

View file

@ -1043,7 +1043,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeB(rkNode) decodeB(rkNode)
let newLen = regs[rb].intVal.int let newLen = regs[rb].intVal.int
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess) if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
else: setLen(regs[ra].node.sons, newLen) else:
let oldLen = regs[ra].node.len
setLen(regs[ra].node.sons, newLen)
if oldLen < newLen:
# XXX This is still not entirely correct
# set to default value:
for i in oldLen .. <newLen:
regs[ra].node.sons[i] = newNodeI(nkEmpty, c.debug[pc])
of opcSwap: of opcSwap:
let rb = instr.regB let rb = instr.regB
if regs[ra].kind == regs[rb].kind: if regs[ra].kind == regs[rb].kind:

View file

@ -16,7 +16,7 @@ const
byteExcess* = 128 # we use excess-K for immediates byteExcess* = 128 # we use excess-K for immediates
wordExcess* = 32768 wordExcess* = 32768
MaxLoopIterations* = 500_000 # max iterations of all loops MaxLoopIterations* = 1500_000 # max iterations of all loops
type type
@ -29,7 +29,7 @@ type
opcRet, # return opcRet, # return
opcYldYoid, # yield with no value opcYldYoid, # yield with no value
opcYldVal, # yield with a value opcYldVal, # yield with a value
opcAsgnInt, opcAsgnInt,
opcAsgnStr, opcAsgnStr,
opcAsgnFloat, opcAsgnFloat,
@ -48,8 +48,8 @@ type
opcWrDeref, opcWrDeref,
opcWrStrIdx, opcWrStrIdx,
opcLdStrIdx, # a = b[c] opcLdStrIdx, # a = b[c]
opcAddInt, opcAddInt,
opcAddImmInt, opcAddImmInt,
opcSubInt, opcSubInt,
opcSubImmInt, opcSubImmInt,
@ -58,36 +58,36 @@ type
opcIncl, opcInclRange, 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, opcEqNimrodNode, 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,
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq, opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
opcSwap, opcIsNil, opcOf, opcIs, opcSwap, opcIsNil, opcOf, opcIs,
opcSubStr, opcParseFloat, opcConv, opcCast, opcQuit, opcReset, opcSubStr, opcParseFloat, opcConv, opcCast, opcQuit, opcReset,
opcNarrowS, opcNarrowU, opcNarrowS, opcNarrowU,
opcAddStrCh, opcAddStrCh,
opcAddStrStr, opcAddStrStr,
opcAddSeqElem, opcAddSeqElem,
opcRangeChck, opcRangeChck,
opcNAdd, opcNAdd,
opcNAddMultiple, opcNAddMultiple,
opcNKind, opcNKind,
opcNIntVal, opcNIntVal,
opcNFloatVal, opcNFloatVal,
opcNSymbol, opcNSymbol,
opcNIdent, opcNIdent,
opcNGetType, opcNGetType,
opcNStrVal, opcNStrVal,
opcNSetIntVal, opcNSetIntVal,
opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal, opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetType, opcNSetStrVal,
opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree, opcNDel, opcGenSym, opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree, opcNDel, opcGenSym,
opcSlurp, opcSlurp,
opcGorge, opcGorge,
opcParseExprToAst, opcParseExprToAst,
@ -100,7 +100,7 @@ type
opcEqIdent, opcEqIdent,
opcStrToIdent, opcStrToIdent,
opcIdentToStr, opcIdentToStr,
opcEcho, opcEcho,
opcIndCall, # dest = call regStart, n; where regStart = fn, arg1, ... opcIndCall, # dest = call regStart, n; where regStart = fn, arg1, ...
opcIndCallAsgn, # dest = call regStart, n; where regStart = fn, arg1, ... opcIndCallAsgn, # dest = call regStart, n; where regStart = fn, arg1, ...
@ -110,7 +110,7 @@ type
opcNSetChild, opcNSetChild,
opcCallSite, opcCallSite,
opcNewStr, opcNewStr,
opcTJmp, # jump Bx if A != 0 opcTJmp, # jump Bx if A != 0
opcFJmp, # jump Bx if A == 0 opcFJmp, # jump Bx if A == 0
opcJmp, # jump Bx opcJmp, # jump Bx
@ -178,13 +178,13 @@ type
slots*: pointer slots*: pointer
currentException*: PNode currentException*: PNode
VmCallback* = proc (args: VmArgs) {.closure.} VmCallback* = proc (args: VmArgs) {.closure.}
PCtx* = ref TCtx PCtx* = ref TCtx
TCtx* = object of passes.TPassContext # code gen context TCtx* = object of passes.TPassContext # code gen context
code*: seq[TInstr] code*: seq[TInstr]
debug*: seq[TLineInfo] # line info for every instruction; kept separate debug*: seq[TLineInfo] # line info for every instruction; kept separate
# to not slow down interpretation # to not slow down interpretation
globals*: PNode # globals*: PNode #
constants*: PNode # constant data constants*: PNode # constant data
types*: seq[PType] # some instructions reference types (e.g. 'except') types*: seq[PType] # some instructions reference types (e.g. 'except')
currentExceptionA*, currentExceptionB*: PNode currentExceptionA*, currentExceptionB*: PNode
@ -203,7 +203,7 @@ type
TPosition* = distinct int TPosition* = distinct int
PEvalContext* = PCtx PEvalContext* = PCtx
proc newCtx*(module: PSym): PCtx = proc newCtx*(module: PSym): PCtx =
PCtx(code: @[], debug: @[], PCtx(code: @[], debug: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],

View file

@ -1364,7 +1364,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyCString, tyString: of tyCString, tyString:
result = newNodeIT(nkStrLit, info, t) result = newNodeIT(nkStrLit, info, t)
of tyVar, tyPointer, tyPtr, tySequence, tyExpr, of tyVar, tyPointer, tyPtr, tySequence, tyExpr,
tyStmt, tyTypeDesc, tyStatic, tyRef: tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
result = newNodeIT(nkNilLit, info, t) result = newNodeIT(nkNilLit, info, t)
of tyProc: of tyProc:
if t.callConv != ccClosure: if t.callConv != ccClosure:
@ -1391,7 +1391,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
addSon(result, getNullValue(t.sons[i], info)) addSon(result, getNullValue(t.sons[i], info))
of tySet: of tySet:
result = newNodeIT(nkCurly, info, t) result = newNodeIT(nkCurly, info, t)
else: internalError("getNullValue: " & $t.kind) else: internalError(info, "getNullValue: " & $t.kind)
proc ldNullOpcode(t: PType): TOpcode = proc ldNullOpcode(t: PType): TOpcode =
if fitsRegister(t): opcLdNullReg else: opcLdNull if fitsRegister(t): opcLdNullReg else: opcLdNull
@ -1610,7 +1610,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
genBreak(c, n) genBreak(c, n)
of nkTryStmt: genTry(c, n, dest) of nkTryStmt: genTry(c, n, dest)
of nkStmtList: of nkStmtList:
unused(n, dest) #unused(n, dest)
# XXX Fix this bug properly, lexim triggers it
for x in n: gen(c, x) for x in n: gen(c, x)
of nkStmtListExpr: of nkStmtListExpr:
let L = n.len-1 let L = n.len-1