prevent eval crashes due to PContext-dependent ops not being available in evalConstExpr

This commit is contained in:
Zahary Karadjov 2013-08-25 18:11:05 +03:00
commit 89086a8e19
4 changed files with 40 additions and 42 deletions

View file

@ -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]

View file

@ -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)

View file

@ -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

View file

@ -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