macros and templates can be expanded anywhere where a type is expected.
This allows for various type selection algorithms to be implemented. See tests / accept / compile / ttypeselectors.nim for examples.
This commit is contained in:
parent
ecd3c80e7e
commit
12bac28d23
6 changed files with 119 additions and 36 deletions
|
|
@ -400,10 +400,6 @@ proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
|||
else:
|
||||
nil
|
||||
|
||||
proc isCallExpr(n: PNode): bool =
|
||||
result = n.kind in {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit}
|
||||
|
||||
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||
if n.kind == nkHiddenDeref:
|
||||
checkSonsLen(n, 1)
|
||||
|
|
@ -922,32 +918,35 @@ proc expectStringArg(c: PContext, n: PNode, i: int): PNode =
|
|||
if result.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
||||
GlobalError(result.info, errStringLiteralExpected)
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
|
||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
|
||||
## The argument to the proc should be nkCall(...) or similar
|
||||
## Returns the macro/template symbol
|
||||
if not isCallExpr(n):
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
|
||||
|
||||
var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
|
||||
if expandedSym == nil:
|
||||
GlobalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
|
||||
|
||||
if expandedSym.kind notin {skMacro, skTemplate}:
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
|
||||
|
||||
result = expandedSym
|
||||
|
||||
proc semExpandToAst(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[1]
|
||||
var expandedSym = expectMacroOrTemplateCall(c, macroCall)
|
||||
|
||||
var macroCall = n.sons[1]
|
||||
|
||||
var expandedSym = qualifiedLookup(c, macroCall.sons[0], {checkUndeclared})
|
||||
if expandedSym == nil:
|
||||
GlobalError(n.info, errUndeclaredIdentifier, macroCall[0].renderTree)
|
||||
|
||||
if expandedSym.kind notin {skMacro, skTemplate}:
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
|
||||
|
||||
macroCall.sons[0] = newNodeI(nkSym, macroCall.info)
|
||||
macroCall.sons[0].sym = expandedSym
|
||||
macroCall.sons[0] = newSymNode(expandedSym, macroCall.info)
|
||||
markUsed(n, expandedSym)
|
||||
|
||||
for i in countup(1, macroCall.len-1):
|
||||
macroCall.sons[i] = semExprWithType(c, macroCall.sons[i], {efAllowType})
|
||||
macroCall.sons[i] = semExprWithType(c, macroCall[i], {efAllowType})
|
||||
|
||||
# Preserve the magic symbol in order to handled in evals.nim
|
||||
n.sons[0] = newNodeI(nkSym, n.info)
|
||||
n.sons[0].sym = magicSym
|
||||
|
||||
# Preserve the magic symbol in order to be handled in evals.nim
|
||||
n.sons[0] = newSymNode(magicSym, n.info)
|
||||
n.typ = expandedSym.getReturnType
|
||||
result = n
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue