mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-29 10:01:39 +00:00
getAst works correctly with existing AST values as template/macro arguments
This commit is contained in:
@@ -904,26 +904,52 @@ proc expectStringArg(c: PContext, n: PNode, i: int): PNode =
|
||||
if result.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
||||
GlobalError(result.info, errStringLiteralExpected)
|
||||
|
||||
proc semExpandMacroToAst(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc isAstValue(n: PNode): bool =
|
||||
result = n.typ.sym.name.s in [ "expr", "stmt", "PNimrodNode" ]
|
||||
|
||||
proc semExpandMacroToAst(c: PContext, n: PNode, magicSym: PSym, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) == 2:
|
||||
if not isCallExpr(n.sons[1]):
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
|
||||
|
||||
var macroCall = n.sons[1]
|
||||
|
||||
var s = qualifiedLookup(c, macroCall.sons[0], {checkUndeclared})
|
||||
if s == nil:
|
||||
var expandedSym = qualifiedLookup(c, macroCall.sons[0], {checkUndeclared})
|
||||
if expandedSym == nil:
|
||||
GlobalError(n.info, errUndeclaredIdentifier, macroCall.sons[0].renderTree)
|
||||
|
||||
var expanded : Pnode
|
||||
if not (expandedSym.kind in { skMacro, skTemplate }):
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
|
||||
|
||||
case s.kind
|
||||
of skMacro: expanded = semMacroExpr(c, macroCall, s, false)
|
||||
of skTemplate: expanded = semTemplateExpr(c, macroCall, s, false)
|
||||
else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
|
||||
macroCall.sons[0] = newNodeI(nkSym, macroCall.info)
|
||||
macroCall.sons[0].sym = expandedSym
|
||||
markUsed(n, expandedSym)
|
||||
|
||||
var macroRetType = newTypeS(s.typ.sons[0].kind, c)
|
||||
result = newMetaNodeIT(expanded, n.info, macroRetType)
|
||||
# Any macro arguments that are already AST values are passed as such
|
||||
# All other expressions within the arguments are converted to AST as
|
||||
# in normal macro/template expansion.
|
||||
# The actual expansion does not happen here, but in evals.nim, where
|
||||
# the dynamic AST values will be known.
|
||||
for i in countup(1, macroCall.sonsLen - 1):
|
||||
var argAst = macroCall.sons[i]
|
||||
var typedArg = semExprWithType(c, argAst, {efAllowType})
|
||||
if isAstValue(typedArg):
|
||||
macroCall.sons[i] = typedArg
|
||||
else:
|
||||
macroCall.sons[i] = newMetaNodeIT(argAst, argAst.info, newTypeS(tyExpr, c))
|
||||
|
||||
# Preserve the magic symbol in order to handled in evals.nim
|
||||
n.sons[0] = newNodeI(nkSym, n.info)
|
||||
n.sons[0].sym = magicSym
|
||||
|
||||
# XXX:
|
||||
# Hmm, expandedSym.typ is something like proc (e: expr): stmt
|
||||
# In theory, it should be better here to report the actual return type,
|
||||
# but the code is working fine so far with tyStmt, so I am leaving it
|
||||
# here for someone more knowledgable to see ;)
|
||||
n.typ = newTypeS(tyStmt, c) # expandedSym.typ
|
||||
|
||||
result = n
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
@@ -963,7 +989,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
of mSlurp: result = semSlurp(c, n, flags)
|
||||
of mExpandMacroToAst: result = semExpandMacroToAst(c, n, flags)
|
||||
of mExpandMacroToAst: result = semExpandMacroToAst(c, n, s, flags)
|
||||
else: result = semDirectOp(c, n, flags)
|
||||
|
||||
proc semIfExpr(c: PContext, n: PNode): PNode =
|
||||
|
||||
Reference in New Issue
Block a user