Ah, I think I found a solution:
import macros, strutils
macro typecheckedAst(x: typed): untyped =
echo "calling typecheck on expression: ", x.repr
echo "with type: ", x.getType().treeRepr()
# We can build a type specific AST here:
let typ = x.getType()
if sameType(typ, bindSym"int"):
echo "it's an int"
result = newStrLitNode("AST for int")
elif sameType(typ, bindSym"string"):
echo "it's a string"
result = newStrLitNode("AST for string")
else:
echo "unknown type"
echo " => resulting type dependent AST: ", result.repr
macro fmt*(fmt: static[string]): untyped =
let fields = fmt.split(":")
assert fields.len == 2
let lhs = fields[0]
let rhs = fields[1]
# We probably can't get the type of `e` here, but we can delegate
# all type specific AST generation into the `typecheckedAst` macro
let e = parseExpr(lhs)
result = newCall(ident"typecheckedAst", e)
block:
let x = 1
echo fmt"x + x:<format-string>"
block:
let x = "test"
echo fmt"x & x:<format-string>"
So the trick is to use `parseExpr` in the outer macro and delegate the type
specific AST generation into a sub-macro which takes a `typed` expression.