Here's something that took me by surprise.
If you have a macro that you're using as a pragma, and the parameter type of the macro is declared as stmt rather than expr, you get a different abstract syntax tree.
Specifically, in the expr case, the ProcDef will include the proc name as an Ident, followed by a postfix Ident of an asterisk (*) if the proc is to be exported from the module. This is what is documented in the macros module documentation for the nnkPostfix postfix operator.
But in the stmt case, the ProcDef will include the proc name as a Sym, without any export asterisk included.
Here are the salient differences in the treeRepr:
testexport.nim(4, 8) Hint: pragmaArgExpr [User]
testexport.nim(5, 8) Hint: ProcDef
Postfix
Ident !"*"
Ident !"foo2"
Empty
Empty
FormalParams
vs:
testexport.nim(8, 8) Hint: pragmaArgStmt [User]
testexport.nim(9, 8) Hint: ProcDef
Sym "foo3"
Empty
Empty
FormalParams
If instead of using treeRepr from inside a pragma macro, I use a dumpTree block, the Ident and postfix asterisk come back:
StmtList
StrLit dumpTree
ProcDef
Postfix
Ident !"*"
Ident !"foo1"
Empty
Empty
FormalParams
If you want to play along at home, here is the test code I used:
import macros
macro pragmaArgExpr(e: expr): stmt =
hint("pragmaArgExpr")
hint(treeRepr(e))
macro pragmaArgStmt(s: stmt): stmt =
hint("pragmaArgStmt")
hint(treeRepr(s))
dumpTree:
"dumpTree"
proc foo1*(i: int): int = return 1
proc foo2*(i: int): int {.pragmaArgExpr.} = return 1
proc foo3*(i: int): int {.pragmaArgStmt.} = return 1
Is this difference intended? I couldn't find any mention of it in the Nim manual or macros module doc.
If it is an intentional difference, what's the purpose?
Thanks for any insight anyone can offer.
Ah, very interesting. Thanks for the explanation.
(I've also wished for more semantic checking in macros & templates.)
Thanks.
Hi @Araq, thanks for the info.
To respond to your point #3, I'm simply wondering whether dumpTree will print a version of the AST before or after semantic checking, that's all.
Currently, dumpTree is declared with parameter of stmt, which (according to your explanation) would mean that it would print the AST after semantic checking (when identifiers have become symbols, etc.). That's why I was asking whether the definition of dumpTree would change (to instead take a parameter of expr, for example).