One thing is that for upvar things are passed around by
reference (i.e. their name, not their value).
Here is an example:
set x(10) foo
proc y { v } {
puts $v
upvar $v zim
puts $zim
}
% y x(10)
x(10)
foo
% y x
x
can't read "zim": variable is array
% y $x(10)
foo
can't read "zim": no such variable
% y $x
can't read "x": variable is array
So when you call
get_tree $children [lindex $elements $i] $parent $level
$parent is not a string it's an array. What you really want
is the string literal "parent" (or some other string literal
I did not read the code that closely).