I want to make a macro that would do the following:
macro datatype(name, body: untyped) =
discard # ...
datatype Person:
name: string
age: Natural
friends = newSeq[Person]()
#[
# Turns into
type Person = object
name: string
age: Natural
friends: seq[Person]
proc initPerson(name: string, age: Natural, friends = newSeq[Person]()): Person =
Person(name: name, age: age, friends: friends)
]#
However, I'm confused about how to get the type of a given expression that's a NimNode. How would I go about doing that?
As @Hlaaftana says using a typeof approach is one option.
Another, but more complicated one, is to turn the macro logic into a 2 step process. Take the untyped macro and do the stuff you need the untyped tree for, then emit the code that needs type information to a 2nd - now typed - macro.
I wrote a similar macro that create a object type definition from a constructor proc https://github.com/demotomohiro/objectDef/blob/master/src/objectDef.nim
It works in the same way @Vindaar explained. objectDef macro takes a procedure with untyped parameter and create a AST that calls tupleCtorToObjectDef macro. tupleCtorToObjectDef takes generated AST as typed parameter and it can get the type with getTypeInst proc in macros module.