mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
more modules compile again
This commit is contained in:
@@ -34,10 +34,10 @@ proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
|
||||
of nkOfBranch, nkElse:
|
||||
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
|
||||
if result == arYes: return
|
||||
else: internalError("isPartOfAux(record case branch)")
|
||||
else: discard "isPartOfAux(record case branch)"
|
||||
of nkSym:
|
||||
result = isPartOfAux(n.sym.typ, b, marker)
|
||||
else: internalError(n.info, "isPartOfAux()")
|
||||
else: discard
|
||||
|
||||
proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
|
||||
result = arNo
|
||||
|
||||
@@ -14,11 +14,12 @@ import
|
||||
rodread
|
||||
|
||||
type
|
||||
TemplCtx {.pure, final.} = object
|
||||
TemplCtx = object
|
||||
owner, genSymOwner: PSym
|
||||
instLines: bool # use the instantiation lines numbers
|
||||
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
|
||||
# new symbol
|
||||
config: ConfigRef
|
||||
|
||||
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
|
||||
result = copyNode(a)
|
||||
@@ -42,7 +43,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam:
|
||||
handleParam actual.sons[s.owner.typ.len + s.position - 1]
|
||||
else:
|
||||
internalAssert sfGenSym in s.flags or s.kind == skType
|
||||
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
|
||||
var x = PSym(idTableGet(c.mapping, s))
|
||||
if x == nil:
|
||||
x = copySym(s, false)
|
||||
@@ -59,7 +60,12 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
evalTemplateAux(templ.sons[i], actual, c, res)
|
||||
result.add res
|
||||
|
||||
proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
|
||||
const
|
||||
errWrongNumberOfArguments = "wrong number of arguments"
|
||||
errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"
|
||||
errTemplateInstantiationTooNested = "template instantiation too nested"
|
||||
|
||||
proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode =
|
||||
# if the template has zero arguments, it can be called without ``()``
|
||||
# `n` is then a nkSym or something similar
|
||||
var totalParams = case n.kind
|
||||
@@ -82,10 +88,10 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
|
||||
if givenRegularParams < 0: givenRegularParams = 0
|
||||
|
||||
if totalParams > expectedRegularParams + genericParams:
|
||||
globalError(n.info, errWrongNumberOfArguments)
|
||||
globalError(conf, n.info, errWrongNumberOfArguments)
|
||||
|
||||
if totalParams < genericParams:
|
||||
globalError(n.info, errMissingGenericParamsForTemplate,
|
||||
globalError(conf, n.info, errMissingGenericParamsForTemplate %
|
||||
n.renderTree)
|
||||
|
||||
result = newNodeI(nkArgList, n.info)
|
||||
@@ -97,7 +103,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
|
||||
for i in givenRegularParams+1 .. expectedRegularParams:
|
||||
let default = s.typ.n.sons[i].sym.ast
|
||||
if default.isNil or default.kind == nkEmpty:
|
||||
localError(n.info, errWrongNumberOfArguments)
|
||||
localError(conf, n.info, errWrongNumberOfArguments)
|
||||
addSon(result, ast.emptyNode)
|
||||
else:
|
||||
addSon(result, default.copyTree)
|
||||
@@ -132,17 +138,19 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
|
||||
result.add res
|
||||
result.typ = res.typ
|
||||
|
||||
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode =
|
||||
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||
conf: ConfigRef; fromHlo=false): PNode =
|
||||
inc(evalTemplateCounter)
|
||||
if evalTemplateCounter > evalTemplateLimit:
|
||||
globalError(n.info, errTemplateInstantiationTooNested)
|
||||
globalError(conf, n.info, errTemplateInstantiationTooNested)
|
||||
result = n
|
||||
|
||||
# replace each param by the corresponding node:
|
||||
var args = evalTemplateArgs(n, tmpl, fromHlo)
|
||||
var args = evalTemplateArgs(n, tmpl, conf, fromHlo)
|
||||
var ctx: TemplCtx
|
||||
ctx.owner = tmpl
|
||||
ctx.genSymOwner = genSymOwner
|
||||
ctx.config = conf
|
||||
initIdTable(ctx.mapping)
|
||||
|
||||
let body = tmpl.getBody
|
||||
@@ -151,7 +159,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode =
|
||||
evalTemplateAux(body, args, ctx, result)
|
||||
if result.len == 1: result = result.sons[0]
|
||||
else:
|
||||
localError(result.info, errIllFormedAstX,
|
||||
localError(conf, result.info, "illformed AST: " &
|
||||
renderTree(result, {renderNoComments}))
|
||||
else:
|
||||
result = copyNode(body)
|
||||
|
||||
@@ -330,8 +330,8 @@ proc canon*(n: PNode; o: Operators): PNode =
|
||||
result.sons[2] = y[1]
|
||||
else: discard
|
||||
|
||||
#proc `+@`*(a: PNode; b: BiggestInt): PNode =
|
||||
# canon(if b != 0: opAdd.buildCall(a, nkIntLit.newIntNode(b)) else: a)
|
||||
proc buildAdd*(a: PNode; b: BiggestInt; o: Operators): PNode =
|
||||
canon(if b != 0: o.opAdd.buildCall(a, nkIntLit.newIntNode(b)) else: a, o)
|
||||
|
||||
proc usefulFact(n: PNode; o: Operators): PNode =
|
||||
case n.getMagic
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
proc hlo(c: PContext, n: PNode): PNode
|
||||
|
||||
proc evalPattern(c: PContext, n, orig: PNode): PNode =
|
||||
internalAssert n.kind == nkCall and n.sons[0].kind == nkSym
|
||||
internalAssert c.config, n.kind == nkCall and n.sons[0].kind == nkSym
|
||||
# we need to ensure that the resulting AST is semchecked. However, it's
|
||||
# aweful to semcheck before macro invocation, so we don't and treat
|
||||
# templates and macros as immediate in this context.
|
||||
|
||||
@@ -150,7 +150,7 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
|
||||
of "*": result = matchNested(c, p, n, rpn=false)
|
||||
of "**": result = matchNested(c, p, n, rpn=true)
|
||||
of "~": result = not matches(c, p.sons[1], n)
|
||||
else: internalError(p.info, "invalid pattern")
|
||||
else: doAssert(false, "invalid pattern")
|
||||
# template {add(a, `&` * b)}(a: string{noalias}, b: varargs[string]) =
|
||||
# add(a, b)
|
||||
elif p.kind == nkCurlyExpr:
|
||||
@@ -289,7 +289,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
|
||||
# constraint not fulfilled:
|
||||
if not ok: return nil
|
||||
|
||||
markUsed(n.info, s, c.graph.usageSym)
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
if ctx.subMatch:
|
||||
assert m.len == 3
|
||||
m.sons[1] = result
|
||||
|
||||
@@ -17,21 +17,21 @@ proc iterToProcImpl(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
let iter = n[1]
|
||||
if iter.kind != nkSym or iter.sym.kind != skIterator:
|
||||
localError(iter.info, "first argument needs to be an iterator")
|
||||
localError(c.config, iter.info, "first argument needs to be an iterator")
|
||||
return
|
||||
if n[2].typ.isNil:
|
||||
localError(n[2].info, "second argument needs to be a type")
|
||||
localError(c.config, n[2].info, "second argument needs to be a type")
|
||||
return
|
||||
if n[3].kind != nkIdent:
|
||||
localError(n[3].info, "third argument needs to be an identifier")
|
||||
localError(c.config, n[3].info, "third argument needs to be an identifier")
|
||||
return
|
||||
|
||||
let t = n[2].typ.skipTypes({tyTypeDesc, tyGenericInst})
|
||||
if t.kind notin {tyRef, tyPtr} or t.lastSon.kind != tyObject:
|
||||
localError(n[2].info,
|
||||
localError(c.config, n[2].info,
|
||||
"type must be a non-generic ref|ptr to object with state field")
|
||||
return
|
||||
let body = liftIterToProc(iter.sym, iter.sym.getBody, t)
|
||||
let body = liftIterToProc(c.graph, iter.sym, iter.sym.getBody, t)
|
||||
|
||||
let prc = newSym(skProc, n[3].ident, iter.sym.owner, iter.sym.info)
|
||||
prc.typ = copyType(iter.sym.typ, prc, false)
|
||||
|
||||
@@ -71,7 +71,7 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
if arg.typ.isNil:
|
||||
localError(arg.info, errExprXHasNoType,
|
||||
localError(c.config, arg.info, "expression has no type: " &
|
||||
renderTree(arg, {renderNoComments}))
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
@@ -79,7 +79,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
else:
|
||||
result = indexTypesMatch(c, formal, arg.typ, arg)
|
||||
if result == nil:
|
||||
typeMismatch(info, formal, arg.typ)
|
||||
typeMismatch(c.config, info, formal, arg.typ)
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
@@ -180,7 +180,7 @@ proc commonType*(x: PType, y: PNode): PType =
|
||||
commonType(x, y.typ)
|
||||
|
||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(c), n.info)
|
||||
result = newSym(kind, considerQuotedIdent(c.config, n), getCurrOwner(c), n.info)
|
||||
when defined(nimsuggest):
|
||||
suggestDecl(c, n, result)
|
||||
|
||||
@@ -192,7 +192,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
# and sfGenSym in n.sym.flags:
|
||||
result = n.sym
|
||||
if result.kind != kind:
|
||||
localError(n.info, "cannot use symbol of kind '" &
|
||||
localError(c.config, n.info, "cannot use symbol of kind '" &
|
||||
$result.kind & "' as a '" & $kind & "'")
|
||||
if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
|
||||
# declarative context, so produce a fresh gensym:
|
||||
@@ -204,7 +204,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
# template; we must fix it here: see #909
|
||||
result.owner = getCurrOwner(c)
|
||||
else:
|
||||
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(c), n.info)
|
||||
result = newSym(kind, considerQuotedIdent(c.config, n), getCurrOwner(c), n.info)
|
||||
#if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule:
|
||||
# incl(result.flags, sfGlobal)
|
||||
when defined(nimsuggest):
|
||||
@@ -216,20 +216,20 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||
allowed: TSymFlags): PSym
|
||||
|
||||
proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind;
|
||||
proc typeAllowedCheck(conf: ConfigRef; info: TLineInfo; typ: PType; kind: TSymKind;
|
||||
flags: TTypeAllowedFlags = {}) =
|
||||
let t = typeAllowed(typ, kind, flags)
|
||||
if t != nil:
|
||||
if t == typ:
|
||||
localError(info, "invalid type: '" & typeToString(typ) &
|
||||
localError(conf, info, "invalid type: '" & typeToString(typ) &
|
||||
"' for " & substr($kind, 2).toLowerAscii)
|
||||
else:
|
||||
localError(info, "invalid type: '" & typeToString(t) &
|
||||
localError(conf, info, "invalid type: '" & typeToString(t) &
|
||||
"' in this context: '" & typeToString(typ) &
|
||||
"' for " & substr($kind, 2).toLowerAscii)
|
||||
|
||||
proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||
typeAllowedCheck(typ.n.info, typ, skProc)
|
||||
typeAllowedCheck(c.config, typ.n.info, typ, skProc)
|
||||
|
||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
@@ -282,10 +282,10 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
|
||||
result = evaluated
|
||||
let expectedType = eOrig.typ.skipTypes({tyStatic})
|
||||
if hasCycle(result):
|
||||
globalError(eOrig.info, "the resulting AST is cyclic and cannot be processed further")
|
||||
globalError(c.config, eOrig.info, "the resulting AST is cyclic and cannot be processed further")
|
||||
result = errorNode(c, eOrig)
|
||||
else:
|
||||
semmacrosanity.annotateType(result, expectedType)
|
||||
semmacrosanity.annotateType(result, expectedType, c.config)
|
||||
else:
|
||||
result = semExprWithType(c, evaluated)
|
||||
#result = fitNode(c, e.typ, result) inlined with special case:
|
||||
@@ -302,18 +302,18 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
|
||||
var e = semExprWithType(c, n)
|
||||
if e == nil: return
|
||||
|
||||
result = getConstExpr(c.module, e)
|
||||
result = getConstExpr(c.module, e, c.graph)
|
||||
if result != nil: return
|
||||
|
||||
let oldErrorCount = msgs.gErrorCounter
|
||||
let oldErrorMax = msgs.gErrorMax
|
||||
let oldErrorCount = c.config.errorCounter
|
||||
let oldErrorMax = c.config.errorMax
|
||||
let oldErrorOutputs = errorOutputs
|
||||
|
||||
errorOutputs = {}
|
||||
msgs.gErrorMax = high(int)
|
||||
c.config.errorMax = high(int)
|
||||
|
||||
try:
|
||||
result = evalConstExpr(c.module, c.cache, c.graph.config, e)
|
||||
result = evalConstExpr(c.module, c.cache, c.graph, e)
|
||||
if result == nil or result.kind == nkEmpty:
|
||||
result = nil
|
||||
else:
|
||||
@@ -322,26 +322,29 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
|
||||
except ERecoverableError:
|
||||
result = nil
|
||||
|
||||
msgs.gErrorCounter = oldErrorCount
|
||||
msgs.gErrorMax = oldErrorMax
|
||||
c.config.errorCounter = oldErrorCount
|
||||
c.config.errorMax = oldErrorMax
|
||||
errorOutputs = oldErrorOutputs
|
||||
|
||||
const
|
||||
errConstExprExpected = "constant expression expected"
|
||||
|
||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
var e = semExprWithType(c, n)
|
||||
if e == nil:
|
||||
localError(n.info, errConstExprExpected)
|
||||
localError(c.config, n.info, errConstExprExpected)
|
||||
return n
|
||||
result = getConstExpr(c.module, e)
|
||||
result = getConstExpr(c.module, e, c.graph)
|
||||
if result == nil:
|
||||
#if e.kind == nkEmpty: globalError(n.info, errConstExprExpected)
|
||||
result = evalConstExpr(c.module, c.cache, c.graph.config, e)
|
||||
result = evalConstExpr(c.module, c.cache, c.graph, e)
|
||||
if result == nil or result.kind == nkEmpty:
|
||||
if e.info != n.info:
|
||||
pushInfoContext(n.info)
|
||||
localError(e.info, errConstExprExpected)
|
||||
localError(c.config, e.info, errConstExprExpected)
|
||||
popInfoContext()
|
||||
else:
|
||||
localError(e.info, errConstExprExpected)
|
||||
localError(c.config, e.info, errConstExprExpected)
|
||||
# error correction:
|
||||
result = e
|
||||
else:
|
||||
@@ -356,7 +359,7 @@ proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else:
|
||||
result = semExprWithType(c, n, flags)
|
||||
if efPreferStatic in flags:
|
||||
var evaluated = getConstExpr(c.module, result)
|
||||
var evaluated = getConstExpr(c.module, result, c.graph)
|
||||
if evaluated != nil: return evaluated
|
||||
evaluated = evalAtCompileTime(c, result)
|
||||
if evaluated != nil: return evaluated
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## Implements type sanity checking for ASTs resulting from macros. Lots of
|
||||
## room for improvement here.
|
||||
|
||||
import ast, astalgo, msgs, types
|
||||
import ast, astalgo, msgs, types, options
|
||||
|
||||
proc ithField(n: PNode, field: var int): PSym =
|
||||
result = nil
|
||||
@@ -20,7 +20,7 @@ proc ithField(n: PNode, field: var int): PSym =
|
||||
result = ithField(n.sons[i], field)
|
||||
if result != nil: return
|
||||
of nkRecCase:
|
||||
if n.sons[0].kind != nkSym: internalError(n.info, "ithField")
|
||||
if n.sons[0].kind != nkSym: return
|
||||
result = ithField(n.sons[0], field)
|
||||
if result != nil: return
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
@@ -28,13 +28,13 @@ proc ithField(n: PNode, field: var int): PSym =
|
||||
of nkOfBranch, nkElse:
|
||||
result = ithField(lastSon(n.sons[i]), field)
|
||||
if result != nil: return
|
||||
else: internalError(n.info, "ithField(record case branch)")
|
||||
else: discard
|
||||
of nkSym:
|
||||
if field == 0: result = n.sym
|
||||
else: dec(field)
|
||||
else: discard
|
||||
|
||||
proc annotateType*(n: PNode, t: PType) =
|
||||
proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
|
||||
let x = t.skipTypes(abstractInst+{tyRange})
|
||||
# Note: x can be unequal to t and we need to be careful to use 't'
|
||||
# to not to skip tyGenericInst
|
||||
@@ -46,50 +46,50 @@ proc annotateType*(n: PNode, t: PType) =
|
||||
var j = i-1
|
||||
let field = x.n.ithField(j)
|
||||
if field.isNil:
|
||||
globalError n.info, "invalid field at index " & $i
|
||||
globalError conf, n.info, "invalid field at index " & $i
|
||||
else:
|
||||
internalAssert(n.sons[i].kind == nkExprColonExpr)
|
||||
annotateType(n.sons[i].sons[1], field.typ)
|
||||
internalAssert(conf, n.sons[i].kind == nkExprColonExpr)
|
||||
annotateType(n.sons[i].sons[1], field.typ, conf)
|
||||
of nkPar, nkTupleConstr:
|
||||
if x.kind == tyTuple:
|
||||
n.typ = t
|
||||
for i in 0 ..< n.len:
|
||||
if i >= x.len: globalError n.info, "invalid field at index " & $i
|
||||
else: annotateType(n.sons[i], x.sons[i])
|
||||
if i >= x.len: globalError conf, n.info, "invalid field at index " & $i
|
||||
else: annotateType(n.sons[i], x.sons[i], conf)
|
||||
elif x.kind == tyProc and x.callConv == ccClosure:
|
||||
n.typ = t
|
||||
else:
|
||||
globalError(n.info, "() must have a tuple type")
|
||||
globalError(conf, n.info, "() must have a tuple type")
|
||||
of nkBracket:
|
||||
if x.kind in {tyArray, tySequence, tyOpenArray}:
|
||||
n.typ = t
|
||||
for m in n: annotateType(m, x.elemType)
|
||||
for m in n: annotateType(m, x.elemType, conf)
|
||||
else:
|
||||
globalError(n.info, "[] must have some form of array type")
|
||||
globalError(conf, n.info, "[] must have some form of array type")
|
||||
of nkCurly:
|
||||
if x.kind in {tySet}:
|
||||
n.typ = t
|
||||
for m in n: annotateType(m, x.elemType)
|
||||
for m in n: annotateType(m, x.elemType, conf)
|
||||
else:
|
||||
globalError(n.info, "{} must have the set type")
|
||||
globalError(conf, n.info, "{} must have the set type")
|
||||
of nkFloatLit..nkFloat128Lit:
|
||||
if x.kind in {tyFloat..tyFloat128}:
|
||||
n.typ = t
|
||||
else:
|
||||
globalError(n.info, "float literal must have some float type")
|
||||
globalError(conf, n.info, "float literal must have some float type")
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
|
||||
n.typ = t
|
||||
else:
|
||||
globalError(n.info, "integer literal must have some int type")
|
||||
globalError(conf, n.info, "integer literal must have some int type")
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if x.kind in {tyString, tyCString}:
|
||||
n.typ = t
|
||||
else:
|
||||
globalError(n.info, "string literal must be of some string type")
|
||||
globalError(conf, n.info, "string literal must be of some string type")
|
||||
of nkNilLit:
|
||||
if x.kind in NilableTypes:
|
||||
n.typ = t
|
||||
else:
|
||||
globalError(n.info, "nil literal must be of some pointer type")
|
||||
globalError(conf, n.info, "nil literal must be of some pointer type")
|
||||
else: discard
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
|
||||
import
|
||||
ast, astalgo, idents, lowerings, magicsys, guards, sempass2, msgs,
|
||||
renderer, types
|
||||
renderer, types, modulegraphs, options
|
||||
|
||||
from trees import getMagic
|
||||
from strutils import `%`
|
||||
|
||||
@@ -73,12 +74,15 @@ type
|
||||
# the 'parallel' section
|
||||
currentSpawnId: int
|
||||
inLoop: int
|
||||
graph: ModuleGraph
|
||||
|
||||
proc initAnalysisCtx(): AnalysisCtx =
|
||||
proc initAnalysisCtx(g: ModuleGraph): AnalysisCtx =
|
||||
result.locals = @[]
|
||||
result.slices = @[]
|
||||
result.args = @[]
|
||||
result.guards = @[]
|
||||
result.guards.s = @[]
|
||||
result.guards.o = initOperators(g)
|
||||
result.graph = g
|
||||
|
||||
proc lookupSlot(c: AnalysisCtx; s: PSym): int =
|
||||
for i in 0..<c.locals.len:
|
||||
@@ -117,7 +121,7 @@ proc checkLocal(c: AnalysisCtx; n: PNode) =
|
||||
if isLocal(n):
|
||||
let s = c.lookupSlot(n.sym)
|
||||
if s >= 0 and c.locals[s].stride != nil:
|
||||
localError(n.info, "invalid usage of counter after increment")
|
||||
localError(c.graph.config, n.info, "invalid usage of counter after increment")
|
||||
else:
|
||||
for i in 0 ..< n.safeLen: checkLocal(c, n.sons[i])
|
||||
|
||||
@@ -126,14 +130,14 @@ template `?`(x): untyped = x.renderTree
|
||||
proc checkLe(c: AnalysisCtx; a, b: PNode) =
|
||||
case proveLe(c.guards, a, b)
|
||||
of impUnknown:
|
||||
localError(a.info, "cannot prove: " & ?a & " <= " & ?b & " (bounds check)")
|
||||
localError(c.graph.config, a.info, "cannot prove: " & ?a & " <= " & ?b & " (bounds check)")
|
||||
of impYes: discard
|
||||
of impNo:
|
||||
localError(a.info, "can prove: " & ?a & " > " & ?b & " (bounds check)")
|
||||
localError(c.graph.config, a.info, "can prove: " & ?a & " > " & ?b & " (bounds check)")
|
||||
|
||||
proc checkBounds(c: AnalysisCtx; arr, idx: PNode) =
|
||||
checkLe(c, arr.lowBound, idx)
|
||||
checkLe(c, idx, arr.highBound)
|
||||
checkLe(c, idx, arr.highBound(c.guards.o))
|
||||
|
||||
proc addLowerBoundAsFacts(c: var AnalysisCtx) =
|
||||
for v in c.locals:
|
||||
@@ -142,34 +146,34 @@ proc addLowerBoundAsFacts(c: var AnalysisCtx) =
|
||||
|
||||
proc addSlice(c: var AnalysisCtx; n: PNode; x, le, ri: PNode) =
|
||||
checkLocal(c, n)
|
||||
let le = le.canon
|
||||
let ri = ri.canon
|
||||
let le = le.canon(c.guards.o)
|
||||
let ri = ri.canon(c.guards.o)
|
||||
# perform static bounds checking here; and not later!
|
||||
let oldState = c.guards.len
|
||||
let oldState = c.guards.s.len
|
||||
addLowerBoundAsFacts(c)
|
||||
c.checkBounds(x, le)
|
||||
c.checkBounds(x, ri)
|
||||
c.guards.setLen(oldState)
|
||||
c.guards.s.setLen(oldState)
|
||||
c.slices.add((x, le, ri, c.currentSpawnId, c.inLoop > 0))
|
||||
|
||||
proc overlap(m: TModel; x,y,c,d: PNode) =
|
||||
proc overlap(m: TModel; conf: ConfigRef; x,y,c,d: PNode) =
|
||||
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
||||
case proveLe(m, c, y)
|
||||
of impUnknown:
|
||||
case proveLe(m, x, d)
|
||||
of impNo: discard
|
||||
of impUnknown, impYes:
|
||||
localError(x.info,
|
||||
localError(conf, x.info,
|
||||
"cannot prove: $# > $#; required for ($#)..($#) disjoint from ($#)..($#)" %
|
||||
[?c, ?y, ?x, ?y, ?c, ?d])
|
||||
of impYes:
|
||||
case proveLe(m, x, d)
|
||||
of impUnknown:
|
||||
localError(x.info,
|
||||
localError(conf, x.info,
|
||||
"cannot prove: $# > $#; required for ($#)..($#) disjoint from ($#)..($#)" %
|
||||
[?x, ?d, ?x, ?y, ?c, ?d])
|
||||
of impYes:
|
||||
localError(x.info, "($#)..($#) not disjoint from ($#)..($#)" %
|
||||
localError(conf, x.info, "($#)..($#) not disjoint from ($#)..($#)" %
|
||||
[?c, ?y, ?x, ?y, ?c, ?d])
|
||||
of impNo: discard
|
||||
of impNo: discard
|
||||
@@ -187,7 +191,7 @@ proc subStride(c: AnalysisCtx; n: PNode): PNode =
|
||||
if isLocal(n):
|
||||
let s = c.lookupSlot(n.sym)
|
||||
if s >= 0 and c.locals[s].stride != nil:
|
||||
result = n +@ c.locals[s].stride.intVal
|
||||
result = buildAdd(n, c.locals[s].stride.intVal, c.guards.o)
|
||||
else:
|
||||
result = n
|
||||
elif n.safeLen > 0:
|
||||
@@ -203,7 +207,7 @@ proc checkSlicesAreDisjoint(c: var AnalysisCtx) =
|
||||
addLowerBoundAsFacts(c)
|
||||
# Every slice used in a loop needs to be disjoint with itself:
|
||||
for x,a,b,id,inLoop in items(c.slices):
|
||||
if inLoop: overlap(c.guards, a,b, c.subStride(a), c.subStride(b))
|
||||
if inLoop: overlap(c.guards, c.graph.config, a,b, c.subStride(a), c.subStride(b))
|
||||
# Another tricky example is:
|
||||
# while true:
|
||||
# spawn f(a[i])
|
||||
@@ -231,21 +235,21 @@ proc checkSlicesAreDisjoint(c: var AnalysisCtx) =
|
||||
# XXX strictly speaking, 'or' is not correct here and it needs to
|
||||
# be 'and'. However this prevents too many obviously correct programs
|
||||
# like f(a[0..x]); for i in x+1 .. a.high: f(a[i])
|
||||
overlap(c.guards, x.a, x.b, y.a, y.b)
|
||||
overlap(c.guards, c.graph.config, x.a, x.b, y.a, y.b)
|
||||
elif (let k = simpleSlice(x.a, x.b); let m = simpleSlice(y.a, y.b);
|
||||
k >= 0 and m >= 0):
|
||||
# ah I cannot resist the temptation and add another sweet heuristic:
|
||||
# if both slices have the form (i+k)..(i+k) and (i+m)..(i+m) we
|
||||
# check they are disjoint and k < stride and m < stride:
|
||||
overlap(c.guards, x.a, x.b, y.a, y.b)
|
||||
overlap(c.guards, c.graph.config, x.a, x.b, y.a, y.b)
|
||||
let stride = min(c.stride(x.a), c.stride(y.a))
|
||||
if k < stride and m < stride:
|
||||
discard
|
||||
else:
|
||||
localError(x.x.info, "cannot prove ($#)..($#) disjoint from ($#)..($#)" %
|
||||
localError(c.graph.config, x.x.info, "cannot prove ($#)..($#) disjoint from ($#)..($#)" %
|
||||
[?x.a, ?x.b, ?y.a, ?y.b])
|
||||
else:
|
||||
localError(x.x.info, "cannot prove ($#)..($#) disjoint from ($#)..($#)" %
|
||||
localError(c.graph.config, x.x.info, "cannot prove ($#)..($#) disjoint from ($#)..($#)" %
|
||||
[?x.a, ?x.b, ?y.a, ?y.b])
|
||||
|
||||
proc analyse(c: var AnalysisCtx; n: PNode)
|
||||
@@ -292,31 +296,31 @@ proc analyseCall(c: var AnalysisCtx; n: PNode; op: PSym) =
|
||||
|
||||
proc analyseCase(c: var AnalysisCtx; n: PNode) =
|
||||
analyse(c, n.sons[0])
|
||||
let oldFacts = c.guards.len
|
||||
let oldFacts = c.guards.s.len
|
||||
for i in 1..<n.len:
|
||||
let branch = n.sons[i]
|
||||
setLen(c.guards, oldFacts)
|
||||
setLen(c.guards.s, oldFacts)
|
||||
addCaseBranchFacts(c.guards, n, i)
|
||||
for i in 0 ..< branch.len:
|
||||
analyse(c, branch.sons[i])
|
||||
setLen(c.guards, oldFacts)
|
||||
setLen(c.guards.s, oldFacts)
|
||||
|
||||
proc analyseIf(c: var AnalysisCtx; n: PNode) =
|
||||
analyse(c, n.sons[0].sons[0])
|
||||
let oldFacts = c.guards.len
|
||||
addFact(c.guards, canon(n.sons[0].sons[0]))
|
||||
let oldFacts = c.guards.s.len
|
||||
addFact(c.guards, canon(n.sons[0].sons[0], c.guards.o))
|
||||
|
||||
analyse(c, n.sons[0].sons[1])
|
||||
for i in 1..<n.len:
|
||||
let branch = n.sons[i]
|
||||
setLen(c.guards, oldFacts)
|
||||
setLen(c.guards.s, oldFacts)
|
||||
for j in 0..i-1:
|
||||
addFactNeg(c.guards, canon(n.sons[j].sons[0]))
|
||||
addFactNeg(c.guards, canon(n.sons[j].sons[0], c.guards.o))
|
||||
if branch.len > 1:
|
||||
addFact(c.guards, canon(branch.sons[0]))
|
||||
addFact(c.guards, canon(branch.sons[0], c.guards.o))
|
||||
for i in 0 ..< branch.len:
|
||||
analyse(c, branch.sons[i])
|
||||
setLen(c.guards, oldFacts)
|
||||
setLen(c.guards.s, oldFacts)
|
||||
|
||||
proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
case n.kind
|
||||
@@ -349,7 +353,7 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
c.addSlice(n, n[0], n[1], n[1])
|
||||
analyseSons(c, n)
|
||||
of nkReturnStmt, nkRaiseStmt, nkTryStmt:
|
||||
localError(n.info, "invalid control flow for 'parallel'")
|
||||
localError(c.graph.config, n.info, "invalid control flow for 'parallel'")
|
||||
# 'break' that leaves the 'parallel' section is not valid either
|
||||
# or maybe we should generate a 'try' XXX
|
||||
of nkVarSection, nkLetSection:
|
||||
@@ -365,7 +369,7 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
if it[j].isLocal:
|
||||
let slot = c.getSlot(it[j].sym)
|
||||
if slot.lower.isNil: slot.lower = value
|
||||
else: internalError(it.info, "slot already has a lower bound")
|
||||
else: internalError(c.graph.config, it.info, "slot already has a lower bound")
|
||||
if not isSpawned: analyse(c, value)
|
||||
of nkCaseStmt: analyseCase(c, n)
|
||||
of nkWhen, nkIfStmt, nkIfExpr: analyseIf(c, n)
|
||||
@@ -378,14 +382,14 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
else:
|
||||
# loop may never execute:
|
||||
let oldState = c.locals.len
|
||||
let oldFacts = c.guards.len
|
||||
addFact(c.guards, canon(n.sons[0]))
|
||||
let oldFacts = c.guards.s.len
|
||||
addFact(c.guards, canon(n.sons[0], c.guards.o))
|
||||
analyse(c, n.sons[1])
|
||||
setLen(c.locals, oldState)
|
||||
setLen(c.guards, oldFacts)
|
||||
setLen(c.guards.s, oldFacts)
|
||||
# we know after the loop the negation holds:
|
||||
if not hasSubnodeWith(n.sons[1], nkBreakStmt):
|
||||
addFactNeg(c.guards, canon(n.sons[0]))
|
||||
addFactNeg(c.guards, canon(n.sons[0], c.guards.o))
|
||||
dec c.inLoop
|
||||
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
||||
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef:
|
||||
@@ -393,13 +397,13 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
else:
|
||||
analyseSons(c, n)
|
||||
|
||||
proc transformSlices(n: PNode): PNode =
|
||||
proc transformSlices(g: ModuleGraph; n: PNode): PNode =
|
||||
if n.kind in nkCallKinds and n[0].kind == nkSym:
|
||||
let op = n[0].sym
|
||||
if op.name.s == "[]" and op.fromSystem:
|
||||
result = copyNode(n)
|
||||
let opSlice = newSymNode(createMagic("slice", mSlice))
|
||||
opSlice.typ = getSysType(tyInt)
|
||||
let opSlice = newSymNode(createMagic(g, "slice", mSlice))
|
||||
opSlice.typ = getSysType(g, n.info, tyInt)
|
||||
result.add opSlice
|
||||
result.add n[1]
|
||||
let slice = n[2].skipStmtList
|
||||
@@ -409,49 +413,49 @@ proc transformSlices(n: PNode): PNode =
|
||||
if n.safeLen > 0:
|
||||
result = shallowCopy(n)
|
||||
for i in 0 ..< n.len:
|
||||
result.sons[i] = transformSlices(n.sons[i])
|
||||
result.sons[i] = transformSlices(g, n.sons[i])
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc transformSpawn(owner: PSym; n, barrier: PNode): PNode
|
||||
proc transformSpawnSons(owner: PSym; n, barrier: PNode): PNode =
|
||||
proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode
|
||||
proc transformSpawnSons(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode =
|
||||
result = shallowCopy(n)
|
||||
for i in 0 ..< n.len:
|
||||
result.sons[i] = transformSpawn(owner, n.sons[i], barrier)
|
||||
result.sons[i] = transformSpawn(g, owner, n.sons[i], barrier)
|
||||
|
||||
proc transformSpawn(owner: PSym; n, barrier: PNode): PNode =
|
||||
proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode =
|
||||
case n.kind
|
||||
of nkVarSection, nkLetSection:
|
||||
result = nil
|
||||
for it in n:
|
||||
let b = it.lastSon
|
||||
if getMagic(b) == mSpawn:
|
||||
if it.len != 3: localError(it.info, "invalid context for 'spawn'")
|
||||
let m = transformSlices(b)
|
||||
if it.len != 3: localError(g.config, it.info, "invalid context for 'spawn'")
|
||||
let m = transformSlices(g, b)
|
||||
if result.isNil:
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
result.add n
|
||||
let t = b[1][0].typ.sons[0]
|
||||
if spawnResult(t, true) == srByVar:
|
||||
result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0])
|
||||
result.add wrapProcForSpawn(g, owner, m, b.typ, barrier, it[0])
|
||||
it.sons[it.len-1] = emptyNode
|
||||
else:
|
||||
it.sons[it.len-1] = wrapProcForSpawn(owner, m, b.typ, barrier, nil)
|
||||
it.sons[it.len-1] = wrapProcForSpawn(g, owner, m, b.typ, barrier, nil)
|
||||
if result.isNil: result = n
|
||||
of nkAsgn, nkFastAsgn:
|
||||
let b = n[1]
|
||||
if getMagic(b) == mSpawn and (let t = b[1][0].typ.sons[0];
|
||||
spawnResult(t, true) == srByVar):
|
||||
let m = transformSlices(b)
|
||||
return wrapProcForSpawn(owner, m, b.typ, barrier, n[0])
|
||||
result = transformSpawnSons(owner, n, barrier)
|
||||
let m = transformSlices(g, b)
|
||||
return wrapProcForSpawn(g, owner, m, b.typ, barrier, n[0])
|
||||
result = transformSpawnSons(g, owner, n, barrier)
|
||||
of nkCallKinds:
|
||||
if getMagic(n) == mSpawn:
|
||||
result = transformSlices(n)
|
||||
return wrapProcForSpawn(owner, result, n.typ, barrier, nil)
|
||||
result = transformSpawnSons(owner, n, barrier)
|
||||
result = transformSlices(g, n)
|
||||
return wrapProcForSpawn(g, owner, result, n.typ, barrier, nil)
|
||||
result = transformSpawnSons(g, owner, n, barrier)
|
||||
elif n.safeLen > 0:
|
||||
result = transformSpawnSons(owner, n, barrier)
|
||||
result = transformSpawnSons(g, owner, n, barrier)
|
||||
else:
|
||||
result = n
|
||||
|
||||
@@ -461,7 +465,7 @@ proc checkArgs(a: var AnalysisCtx; n: PNode) =
|
||||
proc generateAliasChecks(a: AnalysisCtx; result: PNode) =
|
||||
discard "too implement"
|
||||
|
||||
proc liftParallel*(owner: PSym; n: PNode): PNode =
|
||||
proc liftParallel*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||
# this needs to be called after the 'for' loop elimination
|
||||
|
||||
# first pass:
|
||||
@@ -470,17 +474,17 @@ proc liftParallel*(owner: PSym; n: PNode): PNode =
|
||||
# - detect used arguments
|
||||
#echo "PAR ", renderTree(n)
|
||||
|
||||
var a = initAnalysisCtx()
|
||||
var a = initAnalysisCtx(g)
|
||||
let body = n.lastSon
|
||||
analyse(a, body)
|
||||
if a.spawns == 0:
|
||||
localError(n.info, "'parallel' section without 'spawn'")
|
||||
localError(g.config, n.info, "'parallel' section without 'spawn'")
|
||||
checkSlicesAreDisjoint(a)
|
||||
checkArgs(a, body)
|
||||
|
||||
var varSection = newNodeI(nkVarSection, n.info)
|
||||
var temp = newSym(skTemp, getIdent"barrier", owner, n.info)
|
||||
temp.typ = magicsys.getCompilerProc("Barrier").typ
|
||||
temp.typ = magicsys.getCompilerProc(g, "Barrier").typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
let tempNode = newSymNode(temp)
|
||||
varSection.addVar tempNode
|
||||
@@ -489,6 +493,6 @@ proc liftParallel*(owner: PSym; n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
generateAliasChecks(a, result)
|
||||
result.add varSection
|
||||
result.add callCodegenProc("openBarrier", barrier)
|
||||
result.add transformSpawn(owner, body, barrier)
|
||||
result.add callCodegenProc("closeBarrier", barrier)
|
||||
result.add callCodegenProc(g, "openBarrier", barrier)
|
||||
result.add transformSpawn(g, owner, body, barrier)
|
||||
result.add callCodegenProc(g, "closeBarrier", barrier)
|
||||
|
||||
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
|
||||
|
||||
@@ -208,6 +208,7 @@ type
|
||||
cache*: IdentCache
|
||||
config*: ConfigRef
|
||||
graph*: ModuleGraph
|
||||
oldErrorCount*: int
|
||||
|
||||
TPosition* = distinct int
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
|
||||
|
||||
from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir
|
||||
|
||||
from options import gProjectPath
|
||||
|
||||
template mathop(op) {.dirty.} =
|
||||
registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
|
||||
|
||||
@@ -77,15 +75,15 @@ proc staticWalkDirImpl(path: string, relative: bool): PNode =
|
||||
result.add newTree(nkTupleConstr, newIntNode(nkIntLit, k.ord),
|
||||
newStrNode(nkStrLit, f))
|
||||
|
||||
proc gorgeExWrapper(a: VmArgs) {.nimcall.} =
|
||||
let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
|
||||
a.currentLineInfo)
|
||||
setResult a, newTree(nkTupleConstr, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
|
||||
|
||||
proc getProjectPathWrapper(a: VmArgs) {.nimcall.} =
|
||||
setResult a, gProjectPath
|
||||
|
||||
proc registerAdditionalOps*(c: PCtx) =
|
||||
proc gorgeExWrapper(a: VmArgs) =
|
||||
let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
|
||||
a.currentLineInfo, c.config)
|
||||
setResult a, newTree(nkTupleConstr, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
|
||||
|
||||
proc getProjectPathWrapper(a: VmArgs) =
|
||||
setResult a, c.config.projectPath
|
||||
|
||||
wrap1f_math(sqrt)
|
||||
wrap1f_math(ln)
|
||||
wrap1f_math(log10)
|
||||
|
||||
Reference in New Issue
Block a user