I'm traversing NimNode and collecting parent nnkStmtList NimNodes, along with child index to remove/modify later. But this way it collects copies, and operations do not affect traversed NimNode.
How to get references to StmtList and store them in sequence?
proc is_section (n:NimNode): bool =
result = (n.kind == nnkCall) and
(toStrLit(n[0]) == newStrLitNode("Section") or
toStrLit(n[0]) == newStrLitNode("Given") or
toStrLit(n[0]) == newStrLitNode("When") or
toStrLit(n[0]) == newStrLitNode("Then") )
type
# seq of section branch levels, starting from root
SectionTree = seq[seq[InfoNode]]
# root section : index == -1 , parent is root section
# non root : index == child index, parent is StmtList
InfoNode = tuple [parent:NimNode, sectIndex:int]
proc get_child_level(stmtList:NimNode): seq[InfoNode] =
result = @[]
var i = 0
for c in stmtList:
if is_section(c):
var info:InfoNode = (parent: stmtList, sectIndex:i)
result.add info
else:
for child in c:
if child.kind == nnkStmtList:
result = result.concat get_child_level(c)
break
inc i
proc get_next_level(level:seq[InfoNode]): seq[InfoNode] =
result = @[]
for info in level:
var sect = if info.sectIndex != -1 : info.parent[info.sectIndex] else: info.parent
for c in sect:
if c.kind == nnkStmtList:
result = result.concat get_child_level(c)
break
proc get_section_tree(sectNode:NimNode): SectionTree =
var root:InfoNode = (parent: sectNode, sectIndex: -1)
var rootLevel = @[root]
result = @[rootLevel]
var levelSections = get_next_level(rootLevel)
while levelSections.len != 0:
result.add levelSections
levelSections = get_next_level(levelSections)
for child in c:
and for c in sect:
returned copies of node children. They invoke iterator items and proc '[]' which is in turn also return copies. Strange indeed, because a brief look at VM opcNChild command, no copyTree. A bug inside VM maybe? because for user defined ref types, and executed at compile time, this problem not occured. the problem only happened for NimNode