try this: import macros proc replaceSymAndIdent(a : NimNode, b : NimNode, c : NimNode, isLit : static[bool] = true) = for i in 0..len(a)-1: if a[i].kind == nnkSym: if ident(strVal(a[i])) == b: a[i] = c elif a[i].kind == nnkClosedSymChoice or a[i].kind == nnkOpenSymChoice: if ident(strVal(a[i][^1])) == b: a[i] = c elif a[i].kind == nnkIdent: if a[i] == b: a[i] = c elif a[i].len != 0: if a[i].kind == nnkDotExpr: when not isLit: if a[i][0].kind == nnkSym: if ident(strVal(a[i][0])) == b: a[i][0] = c elif a[i][0].kind == nnkClosedSymChoice or a[i][0].kind == nnkOpenSymChoice: if ident(strVal(a[i][0][^1])) == b: a[i][0] = c elif a[i][0].kind == nnkIdent: if a[i][0] == b: a[i][0] = c else: replaceSymAndIdent(a[i], b, c, isLit) macro iterateSeq(a : untyped, b : static[seq[string]], code : untyped) : untyped = let a = if a.kind == nnkSym: ident($a) elif a.kind == nnkClosedSymChoice or a.kind == nnkOpenSymChoice: ident($a[^1]) else: a #echo type(a) result = newStmtList() for item in b: var newCode = code.copy() replaceSymAndIdent(newCode, a, newLit(item), isLit = true) result.add(newCode) #echo treeRepr result #echo repr result #echo "" #result = newStmtList() macro assignField*(obj, fieldName, value: typed) : untyped = let fieldSym = newIdentNode($`fieldName`) result = quote do: `obj`.`fieldSym`=`value` type SomeObj* = object a* : int b* : int c* : int var foo = SomeObj() iterateSeq(field, @["a", "c"]): assignField(foo, field, 50) echo foo assignField(foo, "a", 100) assignField(foo, "c", 200) block: assignField(foo, "b", 300) echo foo Run
Also, I noticed you were missing a return type on your macro so I don't know how your code compiled at all.