Thank you! I am a real beginner in Nim macros. Your example snippet will serve really helpful to me as I am learning this more.
\--- I'd also like to thank @JasperJenkins (from Gitter) for offering his solution to this problem on IRC here: [https://irclogs.nim-lang.org/14-06-2019.html#18:34:24](https://irclogs.nim-lang.org/14-06-2019.html#18:34:24) Here's the Nim playground link he shared: [https://play.nim-lang.org/index.html?ix=1LMY](https://play.nim-lang.org/index.html?ix=1LMY) For convenience, that solution is inlined below: import macros {.experimental: "forLoopMacros".} type Obj = object a, b, c: int proc replace(n: NimNode, symbolic, real: NimNode): NimNode = if n.kind == nnkIdent and n.eqIdent(symbolic): # this identifier is the for loop variable: return a real field ident instead return real else: result = n # return unchanged verbatim # continure recursion on children for i in 0 ..< n.len: n[i] = replace(n[i], symbolic, real) macro replaceField(forLoop: ForLoopStmt): untyped = echo "\nCode before:\n", toStrLit(forLoop).strVal result = newTree(nnkStmtList) let forVar = forLoop[0] # k fields = forLoop[1][1] # ["a", "b", "c"] stmts = forLoop[2] # loop body for f in fields: # Copy the loop body since the loop gets unrolled. # We need a block so any variables don't collide. let stmtsCopy = newBlockStmt(copyNimTree(stmts)) # recursively replace the forVar with a new identifer. result.add(replace( stmtsCopy, # this fields copy of the stmts forVar, # identifier to replace ident(f.strVal))) # new identifer made from one of the real obj fields echo "\nCode after:", toStrLit(result).strVal, "\n" var obj = Obj(a: 1, b: 2, c: 3) echo obj for k in replaceField(["a", "b", "c"]): # more elaborate example that would fail without a block statement let num = obj.k for i in 1 .. num: obj.k *= i echo obj Run \--- This is awesome! I now have more than one solutions to understand more complex macros than the `quote do` ones.
