more modules compile again
This commit is contained in:
parent
fedc136985
commit
05724645f8
12 changed files with 260 additions and 236 deletions
210
compiler/vm.nim
210
compiler/vm.nim
|
|
@ -19,7 +19,7 @@ import ast except getstr
|
|||
import
|
||||
strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes,
|
||||
parser, vmdeps, idents, trees, renderer, options, transf, parseutils,
|
||||
vmmarshal, gorgeimpl
|
||||
vmmarshal, gorgeimpl, configuration
|
||||
|
||||
from semfold import leValueConv, ordinalValToString
|
||||
from evaltempl import evalTemplate
|
||||
|
|
@ -81,16 +81,16 @@ proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
|
|||
msgWriteln(s)
|
||||
|
||||
proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
|
||||
msg: TMsgKind, arg = "", n: PNode = nil) =
|
||||
msg: string, n: PNode = nil) =
|
||||
msgWriteln("stack trace: (most recent call last)")
|
||||
stackTraceAux(c, tos, pc)
|
||||
# XXX test if we want 'globalError' for every mode
|
||||
let lineInfo = if n == nil: c.debug[pc] else: n.info
|
||||
if c.mode == emRepl: globalError(lineInfo, msg, arg)
|
||||
else: localError(lineInfo, msg, arg)
|
||||
if c.mode == emRepl: globalError(c.config, lineInfo, msg)
|
||||
else: localError(c.config, lineInfo, msg)
|
||||
|
||||
proc bailOut(c: PCtx; tos: PStackFrame) =
|
||||
stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX,
|
||||
stackTrace(c, tos, c.exceptionInstr, "unhandled exception: " &
|
||||
c.currentExceptionA.sons[3].skipColon.strVal)
|
||||
|
||||
when not defined(nimComputedGoto):
|
||||
|
|
@ -308,7 +308,7 @@ proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
|
|||
return pc
|
||||
return -1
|
||||
|
||||
proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
|
||||
proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
|
||||
if desttyp.kind == tyString:
|
||||
if dest.kind != rkNode:
|
||||
myreset(dest)
|
||||
|
|
@ -323,7 +323,7 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
|
|||
dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
if n.sons[i].kind != nkSym: internalError("opConv for enum")
|
||||
if n.sons[i].kind != nkSym: internalError(c.config, "opConv for enum")
|
||||
let f = n.sons[i].sym
|
||||
if f.position == x:
|
||||
dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
|
||||
|
|
@ -353,7 +353,7 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
|
|||
of tyChar:
|
||||
dest.node.strVal = $chr(src.intVal)
|
||||
else:
|
||||
internalError("cannot convert to string " & desttyp.typeToString)
|
||||
internalError(c.config, "cannot convert to string " & desttyp.typeToString)
|
||||
else:
|
||||
case skipTypes(desttyp, abstractRange).kind
|
||||
of tyInt..tyInt64:
|
||||
|
|
@ -404,7 +404,7 @@ template handleJmpBack() {.dirty.} =
|
|||
else:
|
||||
msgWriteln("stack trace: (most recent call last)")
|
||||
stackTraceAux(c, tos, pc)
|
||||
globalError(c.debug[pc], errTooManyIterations)
|
||||
globalError(c.config, c.debug[pc], errTooManyIterations)
|
||||
dec(c.loopIterations)
|
||||
|
||||
proc recSetFlagIsRef(arg: PNode) =
|
||||
|
|
@ -434,6 +434,17 @@ proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
|
|||
for i in oldLen ..< newLen:
|
||||
node.sons[i] = newNodeI(typeKind, info)
|
||||
|
||||
const
|
||||
errIndexOutOfBounds = "index ouf of bounds"
|
||||
errNilAccess = "attempt to access a nil address"
|
||||
errOverOrUnderflow = "over- or underflow"
|
||||
errConstantDivisionByZero = "division by zero"
|
||||
errIllegalConvFromXtoY = "illegal conversion from '$1' to '$2'"
|
||||
errTooManyIterations = "interpretation requires too many iterations; " &
|
||||
"if you are sure this is not a bug in your code edit " &
|
||||
"compiler/vmdef.MaxLoopIterations and rebuild the compiler"
|
||||
errFieldXNotFound = "node lacks field: "
|
||||
|
||||
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
var pc = start
|
||||
var tos = tos
|
||||
|
|
@ -447,7 +458,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
#if c.traceActive:
|
||||
when traceCode:
|
||||
echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
|
||||
# message(c.debug[pc], warnUser, "Trace")
|
||||
# message(c.config, c.debug[pc], warnUser, "Trace")
|
||||
|
||||
case instr.opcode
|
||||
of opcEof: return regs[ra]
|
||||
|
|
@ -580,7 +591,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
if regs[rb].kind == rkNode:
|
||||
regs[ra].nodeAddr = addr(regs[rb].node)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "limited VM support for 'addr'")
|
||||
stackTrace(c, tos, pc, "limited VM support for 'addr'")
|
||||
of opcLdDeref:
|
||||
# a = b[]
|
||||
let ra = instr.regA
|
||||
|
|
@ -623,7 +634,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||
of opcAddImmInt:
|
||||
decodeBImm(rkInt)
|
||||
#message(c.debug[pc], warnUser, "came here")
|
||||
#message(c.config, c.debug[pc], warnUser, "came here")
|
||||
#debug regs[rb].node
|
||||
let
|
||||
bVal = regs[rb].intVal
|
||||
|
|
@ -892,7 +903,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit)
|
||||
else: copyTree(a.sym.ast)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "node is not a symbol")
|
||||
stackTrace(c, tos, pc, "node is not a symbol")
|
||||
of opcEcho:
|
||||
let rb = instr.regB
|
||||
if rb == 1:
|
||||
|
|
@ -931,9 +942,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
let rc = instr.regC
|
||||
if not (leValueConv(regs[rb].regToNode, regs[ra].regToNode) and
|
||||
leValueConv(regs[ra].regToNode, regs[rc].regToNode)):
|
||||
stackTrace(c, tos, pc, errGenerated,
|
||||
msgKindToString(errIllegalConvFromXtoY) % [
|
||||
$regs[ra].regToNode, "[" & $regs[rb].regToNode & ".." & $regs[rc].regToNode & "]"])
|
||||
stackTrace(c, tos, pc,
|
||||
errIllegalConvFromXtoY % [
|
||||
$regs[ra].regToNode, "[" & $regs[rb].regToNode & ".." & $regs[rc].regToNode & "]"])
|
||||
of opcIndCall, opcIndCallAsgn:
|
||||
# dest = call regStart, n; where regStart = fn, arg1, ...
|
||||
let rb = instr.regB
|
||||
|
|
@ -949,20 +960,20 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
currentLineInfo: c.debug[pc]))
|
||||
elif sfImportc in prc.flags:
|
||||
if allowFFI notin c.features:
|
||||
globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI")
|
||||
globalError(c.config, c.debug[pc], "VM not allowed to do FFI")
|
||||
# we pass 'tos.slots' instead of 'regs' so that the compiler can keep
|
||||
# 'regs' in a register:
|
||||
when hasFFI:
|
||||
let prcValue = c.globals.sons[prc.position-1]
|
||||
if prcValue.kind == nkEmpty:
|
||||
globalError(c.debug[pc], errGenerated, "canot run " & prc.name.s)
|
||||
globalError(c.config, c.debug[pc], "canot run " & prc.name.s)
|
||||
let newValue = callForeignFunction(prcValue, prc.typ, tos.slots,
|
||||
rb+1, rc-1, c.debug[pc])
|
||||
if newValue.kind != nkEmpty:
|
||||
assert instr.opcode == opcIndCallAsgn
|
||||
putIntoReg(regs[ra], newValue)
|
||||
else:
|
||||
globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
|
||||
globalError(c.config, c.debug[pc], "VM not built with FFI support")
|
||||
elif prc.kind != skTemplate:
|
||||
let newPc = compile(c, prc)
|
||||
# tricky: a recursion is also a jump back, so we use the same
|
||||
|
|
@ -972,7 +983,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
|
||||
newSeq(newFrame.slots, prc.offset+ord(isClosure))
|
||||
if not isEmptyType(prc.typ.sons[0]) or prc.kind == skMacro:
|
||||
putIntoReg(newFrame.slots[0], getNullValue(prc.typ.sons[0], prc.info))
|
||||
putIntoReg(newFrame.slots[0], getNullValue(prc.typ.sons[0], prc.info, c.config))
|
||||
for i in 1 .. rc-1:
|
||||
newFrame.slots[i] = regs[rb+i]
|
||||
if isClosure:
|
||||
|
|
@ -994,7 +1005,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
let node = regs[rb+i].regToNode
|
||||
node.info = c.debug[pc]
|
||||
macroCall.add(node)
|
||||
var a = evalTemplate(macroCall, prc, genSymOwner)
|
||||
var a = evalTemplate(macroCall, prc, genSymOwner, c.config)
|
||||
if a.kind == nkStmtList and a.len == 1: a = a[0]
|
||||
a.recSetFlagIsRef
|
||||
ensureKind(rkNode)
|
||||
|
|
@ -1079,7 +1090,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
of opcNew:
|
||||
ensureKind(rkNode)
|
||||
let typ = c.types[instr.regBx - wordExcess]
|
||||
regs[ra].node = getNullValue(typ, c.debug[pc])
|
||||
regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
|
||||
regs[ra].node.flags.incl nfIsRef
|
||||
of opcNewSeq:
|
||||
let typ = c.types[instr.regBx - wordExcess]
|
||||
|
|
@ -1091,7 +1102,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
regs[ra].node.typ = typ
|
||||
newSeq(regs[ra].node.sons, count)
|
||||
for i in 0 ..< count:
|
||||
regs[ra].node.sons[i] = getNullValue(typ.sons[0], c.debug[pc])
|
||||
regs[ra].node.sons[i] = getNullValue(typ.sons[0], c.debug[pc], c.config)
|
||||
of opcNewStr:
|
||||
decodeB(rkNode)
|
||||
regs[ra].node = newNodeI(nkStrLit, c.debug[pc])
|
||||
|
|
@ -1103,7 +1114,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
of opcLdNull:
|
||||
ensureKind(rkNode)
|
||||
let typ = c.types[instr.regBx - wordExcess]
|
||||
regs[ra].node = getNullValue(typ, c.debug[pc])
|
||||
regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
|
||||
# opcLdNull really is the gist of the VM's problems: should it load
|
||||
# a fresh null to regs[ra].node or to regs[ra].node[]? This really
|
||||
# depends on whether regs[ra] represents the variable itself or wether
|
||||
|
|
@ -1150,7 +1161,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
regs[ra].node.strVal = renderTree(regs[rb].regToNode, {renderNoComments, renderDocComments})
|
||||
of opcQuit:
|
||||
if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
|
||||
message(c.debug[pc], hintQuitCalled)
|
||||
message(c.config, c.debug[pc], hintQuitCalled)
|
||||
msgQuit(int8(getOrdValue(regs[ra].regToNode)))
|
||||
else:
|
||||
return TFullReg(kind: rkNone)
|
||||
|
|
@ -1176,14 +1187,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
|
||||
else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
|
||||
of opcReset:
|
||||
internalError(c.debug[pc], "too implement")
|
||||
internalError(c.config, c.debug[pc], "too implement")
|
||||
of opcNarrowS:
|
||||
decodeB(rkInt)
|
||||
let min = -(1.BiggestInt shl (rb-1))
|
||||
let max = (1.BiggestInt shl (rb-1))-1
|
||||
if regs[ra].intVal < min or regs[ra].intVal > max:
|
||||
stackTrace(c, tos, pc, errGenerated,
|
||||
msgKindToString(errUnhandledExceptionX) % "value out of range")
|
||||
stackTrace(c, tos, pc, "unhandled exception: value out of range")
|
||||
of opcNarrowU:
|
||||
decodeB(rkInt)
|
||||
regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
|
||||
|
|
@ -1217,7 +1227,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
if u.kind notin {nkEmpty..nkNilLit}:
|
||||
u.add(regs[rc].node)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "cannot add to node kind: " & $u.kind)
|
||||
stackTrace(c, tos, pc, "cannot add to node kind: " & $u.kind)
|
||||
regs[ra].node = u
|
||||
of opcNAddMultiple:
|
||||
decodeBC(rkNode)
|
||||
|
|
@ -1227,7 +1237,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
# XXX can be optimized:
|
||||
for i in 0..<x.len: u.add(x.sons[i])
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "cannot add to node kind: " & $u.kind)
|
||||
stackTrace(c, tos, pc, "cannot add to node kind: " & $u.kind)
|
||||
regs[ra].node = u
|
||||
of opcNKind:
|
||||
decodeB(rkInt)
|
||||
|
|
@ -1239,34 +1249,34 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
if a.kind == nkSym:
|
||||
regs[ra].intVal = ord(a.sym.kind)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "node is not a symbol")
|
||||
stackTrace(c, tos, pc, "node is not a symbol")
|
||||
c.comesFromHeuristic = regs[rb].node.info
|
||||
of opcNIntVal:
|
||||
decodeB(rkInt)
|
||||
let a = regs[rb].node
|
||||
case a.kind
|
||||
of nkCharLit..nkUInt64Lit: regs[ra].intVal = a.intVal
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound & "intVal")
|
||||
of opcNFloatVal:
|
||||
decodeB(rkFloat)
|
||||
let a = regs[rb].node
|
||||
case a.kind
|
||||
of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
|
||||
of opcNSymbol:
|
||||
decodeB(rkNode)
|
||||
let a = regs[rb].node
|
||||
if a.kind == nkSym:
|
||||
regs[ra].node = copyNode(a)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
|
||||
of opcNIdent:
|
||||
decodeB(rkNode)
|
||||
let a = regs[rb].node
|
||||
if a.kind == nkIdent:
|
||||
regs[ra].node = copyNode(a)
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "ident")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "ident")
|
||||
of opcNGetType:
|
||||
let rb = instr.regB
|
||||
let rc = instr.regC
|
||||
|
|
@ -1277,28 +1287,28 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||
regs[ra].node = opMapTypeToAst(regs[rb].node.typ, c.debug[pc])
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
of 1:
|
||||
# typeKind opcode:
|
||||
ensureKind(rkInt)
|
||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||
regs[ra].intVal = ord(regs[rb].node.typ.kind)
|
||||
#else:
|
||||
# stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||
# stackTrace(c, tos, pc, "node has no type")
|
||||
of 2:
|
||||
# getTypeInst opcode:
|
||||
ensureKind(rkNode)
|
||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||
regs[ra].node = opMapTypeInstToAst(regs[rb].node.typ, c.debug[pc])
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
else:
|
||||
# getTypeImpl opcode:
|
||||
ensureKind(rkNode)
|
||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||
regs[ra].node = opMapTypeImplToAst(regs[rb].node.typ, c.debug[pc])
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||
stackTrace(c, tos, pc, "node has no type")
|
||||
of opcNStrVal:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
|
|
@ -1313,12 +1323,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
of nkSym:
|
||||
regs[ra].node.strVal = a.sym.name.s
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
|
||||
of opcSlurp:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
|
||||
c.module)
|
||||
c.module, c.config)
|
||||
of opcGorge:
|
||||
decodeBC(rkNode)
|
||||
inc pc
|
||||
|
|
@ -1327,29 +1337,30 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
createStr regs[ra]
|
||||
regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
|
||||
regs[rc].node.strVal, regs[rd].node.strVal,
|
||||
c.debug[pc])[0]
|
||||
c.debug[pc], c.config)[0]
|
||||
of opcNError:
|
||||
decodeB(rkNode)
|
||||
let a = regs[ra].node
|
||||
let b = regs[rb].node
|
||||
stackTrace(c, tos, pc, errUser, a.strVal, if b.kind == nkNilLit: nil else: b)
|
||||
stackTrace(c, tos, pc, a.strVal, if b.kind == nkNilLit: nil else: b)
|
||||
of opcNWarning:
|
||||
message(c.debug[pc], warnUser, regs[ra].node.strVal)
|
||||
message(c.config, c.debug[pc], warnUser, regs[ra].node.strVal)
|
||||
of opcNHint:
|
||||
message(c.debug[pc], hintUser, regs[ra].node.strVal)
|
||||
message(c.config, c.debug[pc], hintUser, regs[ra].node.strVal)
|
||||
of opcParseExprToAst:
|
||||
decodeB(rkNode)
|
||||
# c.debug[pc].line.int - countLines(regs[rb].strVal) ?
|
||||
var error: string
|
||||
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
|
||||
c.debug[pc].toFullPath, c.debug[pc].line.int,
|
||||
proc (info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||
if error.isNil and msg <= msgs.errMax:
|
||||
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||
if error.isNil and msg <= errMax:
|
||||
error = formatMsg(info, msg, arg))
|
||||
if not error.isNil:
|
||||
c.errorFlag = error
|
||||
elif sonsLen(ast) != 1:
|
||||
c.errorFlag = formatMsg(c.debug[pc], errExprExpected, "multiple statements")
|
||||
c.errorFlag = formatMsg(c.debug[pc], errGenerated,
|
||||
"expected expression, but got multiple statements")
|
||||
else:
|
||||
regs[ra].node = ast.sons[0]
|
||||
of opcParseStmtToAst:
|
||||
|
|
@ -1357,8 +1368,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
var error: string
|
||||
let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
|
||||
c.debug[pc].toFullPath, c.debug[pc].line.int,
|
||||
proc (info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||
if error.isNil and msg <= msgs.errMax:
|
||||
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||
if error.isNil and msg <= errMax:
|
||||
error = formatMsg(info, msg, arg))
|
||||
if not error.isNil:
|
||||
c.errorFlag = error
|
||||
|
|
@ -1371,7 +1382,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
of opcCallSite:
|
||||
ensureKind(rkNode)
|
||||
if c.callsite != nil: regs[ra].node = c.callsite
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite")
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound & "callsite")
|
||||
of opcNGetFile:
|
||||
decodeB(rkNode)
|
||||
let n = regs[rb].node
|
||||
|
|
@ -1433,13 +1444,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
of opcStrToIdent:
|
||||
decodeB(rkNode)
|
||||
if regs[rb].node.kind notin {nkStrLit..nkTripleStrLit}:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
|
||||
else:
|
||||
regs[ra].node = newNodeI(nkIdent, c.debug[pc])
|
||||
regs[ra].node.ident = getIdent(regs[rb].node.strVal)
|
||||
of opcSetType:
|
||||
if regs[ra].kind != rkNode:
|
||||
internalError(c.debug[pc], "cannot set type")
|
||||
internalError(c.config, c.debug[pc], "cannot set type")
|
||||
regs[ra].node.typ = c.types[instr.regBx - wordExcess]
|
||||
of opcConv:
|
||||
let rb = instr.regB
|
||||
|
|
@ -1448,9 +1459,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
inc pc
|
||||
let srctyp = c.types[c.code[pc].regBx - wordExcess]
|
||||
|
||||
if opConv(regs[ra], regs[rb], desttyp, srctyp):
|
||||
stackTrace(c, tos, pc, errGenerated,
|
||||
msgKindToString(errIllegalConvFromXtoY) % [
|
||||
if opConv(c, regs[ra], regs[rb], desttyp, srctyp):
|
||||
stackTrace(c, tos, pc,
|
||||
errIllegalConvFromXtoY % [
|
||||
typeToString(srctyp), typeToString(desttyp)])
|
||||
of opcCast:
|
||||
let rb = instr.regB
|
||||
|
|
@ -1463,7 +1474,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
let dest = fficast(regs[rb], desttyp)
|
||||
asgnRef(regs[ra], dest)
|
||||
else:
|
||||
globalError(c.debug[pc], "cannot evaluate cast")
|
||||
globalError(c.config, c.debug[pc], "cannot evaluate cast")
|
||||
of opcNSetIntVal:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
|
|
@ -1471,7 +1482,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
regs[rb].kind in {rkInt}:
|
||||
dest.intVal = regs[rb].intVal
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "intVal")
|
||||
of opcNSetFloatVal:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
|
|
@ -1479,26 +1490,26 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
regs[rb].kind in {rkFloat}:
|
||||
dest.floatVal = regs[rb].floatVal
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
|
||||
of opcNSetSymbol:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
if dest.kind == nkSym and regs[rb].node.kind == nkSym:
|
||||
dest.sym = regs[rb].node.sym
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
|
||||
of opcNSetIdent:
|
||||
decodeB(rkNode)
|
||||
var dest = regs[ra].node
|
||||
if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
|
||||
dest.ident = regs[rb].node.ident
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "ident")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "ident")
|
||||
of opcNSetType:
|
||||
decodeB(rkNode)
|
||||
let b = regs[rb].node
|
||||
internalAssert b.kind == nkSym and b.sym.kind == skType
|
||||
internalAssert regs[ra].node != nil
|
||||
internalAssert c.config, b.kind == nkSym and b.sym.kind == skType
|
||||
internalAssert c.config, regs[ra].node != nil
|
||||
regs[ra].node.typ = b.sym.typ
|
||||
of opcNSetStrVal:
|
||||
decodeB(rkNode)
|
||||
|
|
@ -1509,12 +1520,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
elif dest.kind == nkCommentStmt and regs[rb].kind in {rkNode}:
|
||||
dest.comment = regs[rb].node.strVal
|
||||
else:
|
||||
stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
|
||||
stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
|
||||
of opcNNewNimNode:
|
||||
decodeBC(rkNode)
|
||||
var k = regs[rb].intVal
|
||||
if k < 0 or k > ord(high(TNodeKind)):
|
||||
internalError(c.debug[pc],
|
||||
internalError(c.config, c.debug[pc],
|
||||
"request to create a NimNode of invalid kind")
|
||||
let cc = regs[rc].node
|
||||
|
||||
|
|
@ -1548,7 +1559,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
let name = if regs[rc].node.strVal.len == 0: ":tmp"
|
||||
else: regs[rc].node.strVal
|
||||
if k < 0 or k > ord(high(TSymKind)):
|
||||
internalError(c.debug[pc], "request to create symbol of invalid kind")
|
||||
internalError(c.config, c.debug[pc], "request to create symbol of invalid kind")
|
||||
var sym = newSym(k.TSymKind, name.getIdent, c.module.owner, c.debug[pc])
|
||||
incl(sym.flags, sfGenSym)
|
||||
regs[ra].node = newSymNode(sym)
|
||||
|
|
@ -1557,7 +1568,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
# type trait operation
|
||||
decodeB(rkNode)
|
||||
var typ = regs[rb].node.typ
|
||||
internalAssert typ != nil
|
||||
internalAssert c.config, typ != nil
|
||||
while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
|
||||
createStr regs[ra]
|
||||
regs[ra].node.strVal = typ.typeToString(preferExported)
|
||||
|
|
@ -1566,14 +1577,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
let rb = instr.regB
|
||||
inc pc
|
||||
let typ = c.types[c.code[pc].regBx - wordExcess]
|
||||
putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ))
|
||||
putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ, c.config))
|
||||
of opcMarshalStore:
|
||||
decodeB(rkNode)
|
||||
inc pc
|
||||
let typ = c.types[c.code[pc].regBx - wordExcess]
|
||||
createStrKeepNode(regs[ra])
|
||||
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
|
||||
storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode)
|
||||
storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode, c.config)
|
||||
of opcToNarrowInt:
|
||||
decodeBC(rkInt)
|
||||
let mask = (1'i64 shl rc) - 1 # 0xFF
|
||||
|
|
@ -1595,7 +1606,7 @@ proc execute(c: PCtx, start: int): PNode =
|
|||
proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
||||
if sym.kind in routineKinds:
|
||||
if sym.typ.len-1 != args.len:
|
||||
localError(sym.info,
|
||||
localError(c.config, sym.info,
|
||||
"NimScript: expected $# arguments, but got $#" % [
|
||||
$(sym.typ.len-1), $args.len])
|
||||
else:
|
||||
|
|
@ -1607,18 +1618,18 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
|||
|
||||
# setup parameters:
|
||||
if not isEmptyType(sym.typ.sons[0]) or sym.kind == skMacro:
|
||||
putIntoReg(tos.slots[0], getNullValue(sym.typ.sons[0], sym.info))
|
||||
putIntoReg(tos.slots[0], getNullValue(sym.typ.sons[0], sym.info, c.config))
|
||||
# XXX We could perform some type checking here.
|
||||
for i in 1..<sym.typ.len:
|
||||
putIntoReg(tos.slots[i], args[i-1])
|
||||
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
else:
|
||||
localError(sym.info,
|
||||
localError(c.config, sym.info,
|
||||
"NimScript: attempt to call non-routine: " & sym.name.s)
|
||||
|
||||
proc evalStmt*(c: PCtx, n: PNode) =
|
||||
let n = transformExpr(c.module, n)
|
||||
let n = transformExpr(c.graph, c.module, n)
|
||||
let start = genStmt(c, n)
|
||||
# execute new instructions; this redundant opcEof check saves us lots
|
||||
# of allocations in 'execute':
|
||||
|
|
@ -1626,13 +1637,13 @@ proc evalStmt*(c: PCtx, n: PNode) =
|
|||
discard execute(c, start)
|
||||
|
||||
proc evalExpr*(c: PCtx, n: PNode): PNode =
|
||||
let n = transformExpr(c.module, n)
|
||||
let n = transformExpr(c.graph, c.module, n)
|
||||
let start = genExpr(c, n)
|
||||
assert c.code[start].opcode != opcEof
|
||||
result = execute(c, start)
|
||||
|
||||
proc getGlobalValue*(c: PCtx; s: PSym): PNode =
|
||||
internalAssert s.kind in {skLet, skVar} and sfGlobal in s.flags
|
||||
internalAssert c.config, s.kind in {skLet, skVar} and sfGlobal in s.flags
|
||||
result = c.globals.sons[s.position-1]
|
||||
|
||||
include vmops
|
||||
|
|
@ -1643,9 +1654,9 @@ include vmops
|
|||
var
|
||||
globalCtx*: PCtx
|
||||
|
||||
proc setupGlobalCtx(module: PSym; cache: IdentCache; config: ConfigRef) =
|
||||
proc setupGlobalCtx(module: PSym; cache: IdentCache; graph: ModuleGraph) =
|
||||
if globalCtx.isNil:
|
||||
globalCtx = newCtx(module, cache, config)
|
||||
globalCtx = newCtx(module, cache, graph)
|
||||
registerAdditionalOps(globalCtx)
|
||||
else:
|
||||
refresh(globalCtx, module)
|
||||
|
|
@ -1656,21 +1667,20 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
|
|||
#pushStackFrame(c, newStackFrame())
|
||||
|
||||
# XXX produce a new 'globals' environment here:
|
||||
setupGlobalCtx(module, cache, graph.config)
|
||||
setupGlobalCtx(module, cache, graph)
|
||||
result = globalCtx
|
||||
when hasFFI:
|
||||
globalCtx.features = {allowFFI, allowCast}
|
||||
|
||||
var oldErrorCount: int
|
||||
|
||||
proc myProcess(c: PPassContext, n: PNode): PNode =
|
||||
let c = PCtx(c)
|
||||
# don't eval errornous code:
|
||||
if oldErrorCount == msgs.gErrorCounter:
|
||||
if c.oldErrorCount == c.config.errorCounter:
|
||||
evalStmt(PCtx(c), n)
|
||||
result = emptyNode
|
||||
else:
|
||||
result = n
|
||||
oldErrorCount = msgs.gErrorCounter
|
||||
c.oldErrorCount = c.config.errorCounter
|
||||
|
||||
proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
|
||||
myProcess(c, n)
|
||||
|
|
@ -1678,10 +1688,10 @@ proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
|
|||
const evalPass* = makePass(myOpen, nil, myProcess, myClose)
|
||||
|
||||
proc evalConstExprAux(module: PSym; cache: IdentCache;
|
||||
config: ConfigRef; prc: PSym, n: PNode,
|
||||
g: ModuleGraph; prc: PSym, n: PNode,
|
||||
mode: TEvalMode): PNode =
|
||||
let n = transformExpr(module, n)
|
||||
setupGlobalCtx(module, cache, config)
|
||||
let n = transformExpr(g, module, n)
|
||||
setupGlobalCtx(module, cache, g)
|
||||
var c = globalCtx
|
||||
let oldMode = c.mode
|
||||
defer: c.mode = oldMode
|
||||
|
|
@ -1696,17 +1706,17 @@ proc evalConstExprAux(module: PSym; cache: IdentCache;
|
|||
result = rawExecute(c, start, tos).regToNode
|
||||
if result.info.col < 0: result.info = n.info
|
||||
|
||||
proc evalConstExpr*(module: PSym; cache: IdentCache, config: ConfigRef; e: PNode): PNode =
|
||||
result = evalConstExprAux(module, cache, config, nil, e, emConst)
|
||||
proc evalConstExpr*(module: PSym; cache: IdentCache, g: ModuleGraph; e: PNode): PNode =
|
||||
result = evalConstExprAux(module, cache, g, nil, e, emConst)
|
||||
|
||||
proc evalStaticExpr*(module: PSym; cache: IdentCache, config: ConfigRef; e: PNode, prc: PSym): PNode =
|
||||
result = evalConstExprAux(module, cache, config, prc, e, emStaticExpr)
|
||||
proc evalStaticExpr*(module: PSym; cache: IdentCache, g: ModuleGraph; e: PNode, prc: PSym): PNode =
|
||||
result = evalConstExprAux(module, cache, g, prc, e, emStaticExpr)
|
||||
|
||||
proc evalStaticStmt*(module: PSym; cache: IdentCache, config: ConfigRef; e: PNode, prc: PSym) =
|
||||
discard evalConstExprAux(module, cache, config, prc, e, emStaticStmt)
|
||||
proc evalStaticStmt*(module: PSym; cache: IdentCache, g: ModuleGraph; e: PNode, prc: PSym) =
|
||||
discard evalConstExprAux(module, cache, g, prc, e, emStaticStmt)
|
||||
|
||||
proc setupCompileTimeVar*(module: PSym; cache: IdentCache, config: ConfigRef; n: PNode) =
|
||||
discard evalConstExprAux(module, cache, config, nil, n, emStaticStmt)
|
||||
proc setupCompileTimeVar*(module: PSym; cache: IdentCache, g: ModuleGraph; n: PNode) =
|
||||
discard evalConstExprAux(module, cache, g, nil, n, emStaticStmt)
|
||||
|
||||
proc setupMacroParam(x: PNode, typ: PType): TFullReg =
|
||||
case typ.kind
|
||||
|
|
@ -1734,20 +1744,20 @@ iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
|
|||
const evalMacroLimit = 1000
|
||||
var evalMacroCounter: int
|
||||
|
||||
proc evalMacroCall*(module: PSym; cache: IdentCache; config: ConfigRef;
|
||||
proc evalMacroCall*(module: PSym; cache: IdentCache; g: ModuleGraph;
|
||||
n, nOrig: PNode, sym: PSym): PNode =
|
||||
# XXX globalError() is ugly here, but I don't know a better solution for now
|
||||
inc(evalMacroCounter)
|
||||
if evalMacroCounter > evalMacroLimit:
|
||||
globalError(n.info, errMacroInstantiationTooNested)
|
||||
globalError(g.config, n.info, "macro instantiation too nested")
|
||||
|
||||
# immediate macros can bypass any type and arity checking so we check the
|
||||
# arity here too:
|
||||
if sym.typ.len > n.safeLen and sym.typ.len > 1:
|
||||
globalError(n.info, "in call '$#' got $#, but expected $# argument(s)" % [
|
||||
globalError(g.config, n.info, "in call '$#' got $#, but expected $# argument(s)" % [
|
||||
n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)])
|
||||
|
||||
setupGlobalCtx(module, cache, config)
|
||||
setupGlobalCtx(module, cache, g)
|
||||
var c = globalCtx
|
||||
c.comesFromHeuristic.line = 0'u16
|
||||
|
||||
|
|
@ -1781,16 +1791,16 @@ proc evalMacroCall*(module: PSym; cache: IdentCache; config: ConfigRef;
|
|||
else:
|
||||
dec(evalMacroCounter)
|
||||
c.callsite = nil
|
||||
localError(n.info, "expected " & $gp.len &
|
||||
localError(c.config, n.info, "expected " & $gp.len &
|
||||
" generic parameter(s)")
|
||||
elif gp[i].sym.typ.kind in {tyStatic, tyTypeDesc}:
|
||||
dec(evalMacroCounter)
|
||||
c.callsite = nil
|
||||
globalError(n.info, "static[T] or typedesc nor supported for .immediate macros")
|
||||
globalError(c.config, n.info, "static[T] or typedesc nor supported for .immediate macros")
|
||||
# temporary storage:
|
||||
#for i in L ..< maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
if result.info.line < 0: result.info = n.info
|
||||
if cyclicTree(result): globalError(n.info, errCyclicTree)
|
||||
if cyclicTree(result): globalError(c.config, n.info, "macro produced a cyclic tree")
|
||||
dec(evalMacroCounter)
|
||||
c.callsite = nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue