I am learning macro system and trying to solve this issue (nim 2.2.6)
macro class(name: untyped, body: untyped): untyped =
result = quote("@") do:
type `@name` = ref object of system.RootObj
`@body`
class TestClass:
b = 10 This produces error - Error: ':' or '=' expected, but got 'class'
if i change indentation like this
macro class(name: untyped, body: untyped): untyped =
result = quote("@") do:
type `@name` = ref object of system.RootObj
`@body`
class TestClass:
b = 10
I get - Error: undeclared identifier: 'b'
What is happening? (I tried searching but the documentation for quote do, how body works is scarce)
Macros can be a bit confusing sometimes. Part of this is caused by similar looking code generating quite different abstract syntax trees (AST, the input and output from a macro).
As I mention in my article about metaprogramming the best way to create a macro is to first write what you want your output to be, then use dumpTree to see what AST you need to create. For your code we expect it to generate:
type
TestClass = ref object of RootObj # The system part isn't necessary
b = 10
Looking at the output from dumpTree, it's long and a bit confusing, but don't worry:
StmtList
TypeSection
TypeDef
Ident "TestClass"
Empty
RefTy
ObjectTy
Empty
OfInherit
DotExpr
Ident "system"
Ident "RootObj"
RecList
IdentDefs
Ident "b"
Empty
IntLit 10
We see that everything is wrapped in a StmtList but this is just an implementation detail of dumpTree. The interesting bits are the TypeSection, particularly where the Ident "TestClass" and IdentDefs(Ident "b", Empty, IntLit 10) appear. If we now take a look at your inputs:
name:
Ident "TestClass"
body:
StmtList
Asgn
Ident "b"
IntLit 10
We can see that the name input is Ident "TestClass" which is what we need for the output TypeSection, but the body is a StmtList(Asgn(Ident "b", IntLit 10)) which isn't what we need. In order to fix this you need to write some code that traverses the body, then generate a RecList of IdentDefs instead and patch them into the tree generated by quote do.
It's a bit confusing, and I wish the macros module had more tools to reshape trees like this, but at least for now it's a bit of a manual process.
I have been tinkering with the AST to graphViz code and I am able to produce with a simple code:
astToImage("type_forum_question", "Type with Root Obj", "jpg", "pictures"):
type
TestClass = ref object of RootObj
b = 10 the following image (sorry for the double StmtList and unuseful nnks):

Distinguishing leaves from structural nodes in this kind of output may help @treeRepr understanding the AST better than only from the raw output of dumpTree.
Note that a class macro example doing this tree traversal is given in this macro tutorial: https://nim-by-example.github.io/macros/
The difference with your macro is it does not force to inherit of RootObj but requires the user to specify the inherited class themself.