First of all, avoid using const sequences, use arrays if possible. Also, _stmt_ is depreciated, use _untyped_ instead.
You don't really need to store fields' names anywhere, actually. Nim's macros do code transformations at the compile time, when fields' names are known. Try it with: echo treeRepr(x.getType) where x is any variable you put into the macro. It will show you how the AST tree for the type. How to utilize this information? As you run the above command on your type, you'll see it (and any object type, actually), has three children: * pragmas associated with the type (none here) * parent information (none here) * field information Which means the information you need can be access through _obj.getType[2]_. Also, it means the macro can generate code for any object type, not just mtcars. import strutils macro dif(obj: typed): untyped = result = newStmtList() for col in obj.getType[2]: result.add parseStmt("result.$1 = x.$1 - y.$1" % [$col]) You can also pass a typedesc instead, then using _typeName.getType_ will convert typedesc into a NimNode (BracketExpr, to be specific). It has two elements, the second of which is a Sym corresponding to the type. So you need _typeName.getType[1].getType[2]_. Macros can be also used to actually create the needed procedure so you don't have to write "proc - (x, y: A): B = dif(x)". You can do it either by using parseExpr/quote or by-hand, using newProc. Of course I advice you to write a more universal macro so that it can generate any given code for all the given type's fields. Remember that the code is actually duplicated, not generalized.