prevent eval crashes due to PContext-dependent ops not being available in evalConstExpr
This commit is contained in:
parent
6378fbd66e
commit
89086a8e19
4 changed files with 40 additions and 42 deletions
|
|
@ -1440,8 +1440,7 @@ proc eval*(c: PEvalContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
stackTrace(c, result.info, errCannotInterpretNodeX, renderTree(n))
|
stackTrace(c, result.info, errCannotInterpretNodeX, renderTree(n))
|
||||||
|
|
||||||
proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode =
|
proc evalConstExprAux*(p: PEvalContext, module, prc: PSym, e: PNode): PNode =
|
||||||
var p = newEvalContext(module, mode)
|
|
||||||
var s = newStackFrame()
|
var s = newStackFrame()
|
||||||
s.call = e
|
s.call = e
|
||||||
s.prc = prc
|
s.prc = prc
|
||||||
|
|
@ -1450,12 +1449,6 @@ proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode =
|
||||||
if result != nil and result.kind == nkExceptBranch: result = nil
|
if result != nil and result.kind == nkExceptBranch: result = nil
|
||||||
popStackFrame(p)
|
popStackFrame(p)
|
||||||
|
|
||||||
proc evalConstExpr*(module: PSym, e: PNode): PNode =
|
|
||||||
result = evalConstExprAux(module, nil, e, emConst)
|
|
||||||
|
|
||||||
proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
|
|
||||||
result = evalConstExprAux(module, prc, e, emStatic)
|
|
||||||
|
|
||||||
proc setupMacroParam(x: PNode): PNode =
|
proc setupMacroParam(x: PNode): PNode =
|
||||||
result = x
|
result = x
|
||||||
if result.kind == nkHiddenStdConv: result = result.sons[1]
|
if result.kind == nkHiddenStdConv: result = result.sons[1]
|
||||||
|
|
|
||||||
|
|
@ -132,14 +132,42 @@ proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||||
LocalError(typ.n.info, errXisNoType, typeToString(typ))
|
LocalError(typ.n.info, errXisNoType, typeToString(typ))
|
||||||
|
|
||||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
||||||
|
|
||||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
||||||
|
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
|
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||||
|
proc IsOpImpl(c: PContext, n: PNode): PNode
|
||||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
semCheck: bool = true): PNode
|
semCheck: bool = true): PNode
|
||||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
|
||||||
|
|
||||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
proc symFromType(t: PType, info: TLineInfo): PSym =
|
||||||
|
if t.sym != nil: return t.sym
|
||||||
|
result = newSym(skType, getIdent"AnonType", t.owner, info)
|
||||||
|
result.flags.incl sfAnon
|
||||||
|
result.typ = t
|
||||||
|
|
||||||
|
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
|
||||||
|
result = newSymNode(symFromType(t, info), info)
|
||||||
|
result.typ = makeTypeDesc(c, t)
|
||||||
|
|
||||||
|
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
|
||||||
|
result = newEvalContext(c.module, mode)
|
||||||
|
result.getType = proc (n: PNode): PNode =
|
||||||
|
var e = tryExpr(c, n)
|
||||||
|
if e == nil:
|
||||||
|
result = symNodeFromType(c, errorType(c), n.info)
|
||||||
|
elif e.typ == nil:
|
||||||
|
result = newSymNode(getSysSym"void")
|
||||||
|
else:
|
||||||
|
result = symNodeFromType(c, e.typ, n.info)
|
||||||
|
|
||||||
|
result.handleIsOperator = proc (n: PNode): PNode =
|
||||||
|
result = IsOpImpl(c, n)
|
||||||
|
|
||||||
|
proc evalConstExpr(c: PContext, module: PSym, e: PNode): PNode =
|
||||||
|
result = evalConstExprAux(c.createEvalContext(emConst), module, nil, e)
|
||||||
|
|
||||||
|
proc evalStaticExpr(c: PContext, module: PSym, e: PNode, prc: PSym): PNode =
|
||||||
|
result = evalConstExprAux(c.createEvalContext(emStatic), module, prc, e)
|
||||||
|
|
||||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||||
var e = semExprWithType(c, n)
|
var e = semExprWithType(c, n)
|
||||||
|
|
@ -148,7 +176,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||||
return n
|
return n
|
||||||
result = getConstExpr(c.module, e)
|
result = getConstExpr(c.module, e)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = evalConstExpr(c.module, e)
|
result = evalConstExpr(c, c.module, e)
|
||||||
if result == nil or result.kind == nkEmpty:
|
if result == nil or result.kind == nkEmpty:
|
||||||
if e.info != n.info:
|
if e.info != n.info:
|
||||||
pushInfoContext(n.info)
|
pushInfoContext(n.info)
|
||||||
|
|
@ -161,16 +189,6 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
include hlo, seminst, semcall
|
include hlo, seminst, semcall
|
||||||
|
|
||||||
proc symFromType(t: PType, info: TLineInfo): PSym =
|
|
||||||
if t.sym != nil: return t.sym
|
|
||||||
result = newSym(skType, getIdent"AnonType", t.owner, info)
|
|
||||||
result.flags.incl sfAnon
|
|
||||||
result.typ = t
|
|
||||||
|
|
||||||
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
|
|
||||||
result = newSymNode(symFromType(t, info), info)
|
|
||||||
result.typ = makeTypeDesc(c, t)
|
|
||||||
|
|
||||||
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
inc(evalTemplateCounter)
|
inc(evalTemplateCounter)
|
||||||
if evalTemplateCounter > 100:
|
if evalTemplateCounter > 100:
|
||||||
|
|
@ -198,8 +216,6 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
||||||
dec(evalTemplateCounter)
|
dec(evalTemplateCounter)
|
||||||
|
|
||||||
proc IsOpImpl(c: PContext, n: PNode): PNode
|
|
||||||
|
|
||||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
semCheck: bool = true): PNode =
|
semCheck: bool = true): PNode =
|
||||||
markUsed(n, sym)
|
markUsed(n, sym)
|
||||||
|
|
@ -207,18 +223,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
|
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
|
||||||
|
|
||||||
if c.evalContext == nil:
|
if c.evalContext == nil:
|
||||||
c.evalContext = newEvalContext(c.module, emStatic)
|
c.evalContext = c.createEvalContext(emStatic)
|
||||||
c.evalContext.getType = proc (n: PNode): PNode =
|
|
||||||
var e = tryExpr(c, n)
|
|
||||||
if e == nil:
|
|
||||||
result = symNodeFromType(c, errorType(c), n.info)
|
|
||||||
elif e.typ == nil:
|
|
||||||
result = newSymNode(getSysSym"void")
|
|
||||||
else:
|
|
||||||
result = symNodeFromType(c, e.typ, n.info)
|
|
||||||
|
|
||||||
c.evalContext.handleIsOperator = proc (n: PNode): PNode =
|
|
||||||
result = IsOpImpl(c, n)
|
|
||||||
|
|
||||||
result = evalMacroCall(c.evalContext, n, nOrig, sym)
|
result = evalMacroCall(c.evalContext, n, nOrig, sym)
|
||||||
if semCheck: result = semAfterMacroCall(c, result, sym)
|
if semCheck: result = semAfterMacroCall(c, result, sym)
|
||||||
|
|
|
||||||
|
|
@ -627,18 +627,18 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||||
call.add(a)
|
call.add(a)
|
||||||
#echo "NOW evaluating at compile time: ", call.renderTree
|
#echo "NOW evaluating at compile time: ", call.renderTree
|
||||||
if sfCompileTime in callee.flags:
|
if sfCompileTime in callee.flags:
|
||||||
result = evalStaticExpr(c.module, call, c.p.owner)
|
result = evalStaticExpr(c, c.module, call, c.p.owner)
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(call))
|
LocalError(n.info, errCannotInterpretNodeX, renderTree(call))
|
||||||
else:
|
else:
|
||||||
result = evalConstExpr(c.module, call)
|
result = evalConstExpr(c, c.module, call)
|
||||||
if result.isNil: result = n
|
if result.isNil: result = n
|
||||||
#if result != n:
|
#if result != n:
|
||||||
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
||||||
|
|
||||||
proc semStaticExpr(c: PContext, n: PNode): PNode =
|
proc semStaticExpr(c: PContext, n: PNode): PNode =
|
||||||
let a = semExpr(c, n.sons[0])
|
let a = semExpr(c, n.sons[0])
|
||||||
result = evalStaticExpr(c.module, a, c.p.owner)
|
result = evalStaticExpr(c, c.module, a, c.p.owner)
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||||
result = emptyNode
|
result = emptyNode
|
||||||
|
|
|
||||||
|
|
@ -1144,7 +1144,7 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
proc semStaticStmt(c: PContext, n: PNode): PNode =
|
proc semStaticStmt(c: PContext, n: PNode): PNode =
|
||||||
let a = semStmt(c, n.sons[0])
|
let a = semStmt(c, n.sons[0])
|
||||||
result = evalStaticExpr(c.module, a, c.p.owner)
|
result = evalStaticExpr(c, c.module, a, c.p.owner)
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||||
result = emptyNode
|
result = emptyNode
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue