experimental support for querying the type of expressions within macros

normalised the line endings of macros.nim (minor edits otherwise)
This commit is contained in:
Zahary Karadjov 2012-10-03 01:50:26 +03:00
commit 2e5265bef5
5 changed files with 369 additions and 344 deletions

View file

@ -41,6 +41,7 @@ type
callsite: PNode # for 'callsite' magic
mode*: TEvalMode
globals*: TIdNodeTable # state of global vars
getType*: proc(n: PNode): PNode
PEvalContext* = ref TEvalContext
@ -1091,7 +1092,10 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {})
if isSpecial(result): return
if result.kind != nkIdent: stackTrace(c, n, errFieldXNotFound, "ident")
of mNGetType: result = evalAux(c, n.sons[1], {})
of mNGetType:
var ast = evalAux(c, n.sons[1], {})
InternalAssert c.getType != nil
result = c.getType(ast)
of mNStrVal:
result = evalAux(c, n.sons[1], {})
if isSpecial(result): return
@ -1152,7 +1156,8 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
var a = result
result = evalAux(c, n.sons[2], {efLValue})
if isSpecial(result): return
a.typ = result.typ # XXX: exception handling?
InternalAssert result.kind == nkSym and result.sym.kind == skType
a.typ = result.sym.typ
result = emptyNode
of mNSetStrVal:
result = evalAux(c, n.sons[1], {efLValue})

View file

@ -43,6 +43,7 @@ proc addParams(c: PContext, n: PNode, kind: TSymKind)
proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind)
proc addResultNode(c: PContext, n: PNode)
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
proc typeMismatch(n: PNode, formal, actual: PType) =
if formal.kind != tyError and actual.kind != tyError:
@ -156,8 +157,18 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
markUsed(n, sym)
if sym == c.p.owner:
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
if c.evalContext == nil:
c.evalContext = newEvalContext(c.module, "", 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)
result = evalMacroCall(c.evalContext, n, nOrig, sym)
if semCheck: result = semAfterMacroCall(c, result, sym)

View file

@ -1237,12 +1237,7 @@ proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
else:
result = semDirectOp(c, n, flags)
proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
# we replace this node by a 'true' or 'false' node:
if sonsLen(n) != 2: return semDirectOp(c, n, flags)
result = newIntNode(nkIntLit, 0)
result.info = n.info
result.typ = getSysType(tyBool)
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# watch out, hacks ahead:
let oldErrorCount = msgs.gErrorCounter
let oldErrorMax = msgs.gErrorMax
@ -1264,8 +1259,8 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
let oldProcCon = c.p
c.generics = newGenericsCache()
try:
discard semExpr(c, n.sons[1])
result.intVal = ord(msgs.gErrorCounter == oldErrorCount)
result = semExpr(c, n, flags)
if msgs.gErrorCounter != oldErrorCount: result = nil
except ERecoverableError:
nil
# undo symbol table changes (as far as it's possible):
@ -1282,6 +1277,14 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
msgs.gErrorCounter = oldErrorCount
msgs.gErrorMax = oldErrorMax
proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
# we replace this node by a 'true' or 'false' node:
if sonsLen(n) != 2: return semDirectOp(c, n, flags)
result = newIntNode(nkIntLit, ord(tryExpr(c, n, flags) != nil))
result.info = n.info
result.typ = getSysType(tyBool)
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
if sonsLen(n) == 3:
# XXX ugh this is really a hack: shallowCopy() can be overloaded only