I've defined a proc which is supposed to be a control structure that iterates over the children of an object. There's a problem, though, when I nest calls.
Here's some code:
Object instproc each {objName body} { puts " *** level = [info level]" puts " *** self callinglevel = [self callinglevel]" uplevel [self callinglevel] [list foreach $objName [lsort [[self] info children]] $body] }
Class TestB
Class TestA
TestA instproc init {args} { next TestB [self]::b1 TestB [self]::b2 TestB [self]::b3 }
Class Test
Test instproc init {args} { next TestA [self]::a1 TestA [self]::a2 TestA [self]::a3 }
Test instproc loop1 {} { set i 0 [self] each a { incr i puts "$a" } puts "Total = $i" }
Test instproc loop2 {} { set i 0 [self] each a { incr i puts "$a" $a each b { incr i puts " $b" } } puts "Total = $i" }
Test t
t loop1 t loop2
Here's some output:
*** level = 2 *** self callinglevel = #1 ::t::a1 ::t::a2 ::t::a3 Total = 3 *** level = 2 *** self callinglevel = #1 ::t::a1 *** level = 2 *** self callinglevel = #2 can't read "i": no such variable (reading value of variable to increment) invoked from within "incr i" ("foreach" body line 2) invoked from within "foreach b {::t::a1::b1 ::t::a1::b2 ::t::a1::b3} { incr i puts " $b" }" ("uplevel" body line 1) invoked from within "uplevel [self callinglevel] [list foreach $objName [lsort [[self] info children ]] $body]" (procedure "each" line 5) ::t::a1 ::xotcl::Object->each invoked from within "$a each b { incr i puts " $b" }" ("foreach" body line 4) invoked from within "foreach a {::t::a1 ::t::a2 ::t::a3} { incr i puts "$a" $a each b { incr i puts " ..." ("uplevel" body line 1) invoked from within "uplevel [self callinglevel] [list foreach $objName [lsort [[self] info children ]] $body]" (procedure "each" line 5) ::t ::xotcl::Object->each invoked from within "[self] each a { incr i puts "$a" $a each b { incr i puts " $b" } ..." (procedure "loop2" line 4) ::t ::Test->loop2 invoked from within "t loop2" invoked from within "if 1 { Object instproc each {objName body} { puts " *** level = [info level]" puts " *** self callinglevel = [self cal..." (file "XOTcl-test.tcl" line 7)
You can see that the one-level iterator succeeds, but the two-level iterator can't see the variable defined in the outer loop. You can also see that the first time "level" and "callinglevel" are different (as you would expect) but the second time they're the same (which looks like it might be an XOTcl bug). Any ideas?
(I can work around this for now, of course, but it would be nice to figure out what's wrong.)
You can see that the one-level iterator succeeds, but the two-level iterator can't see the variable defined in the outer loop. You can also see that the first time "level" and "callinglevel" are different (as you would expect) but the second time they're the same (which looks like it might be an XOTcl bug). Any ideas?
(I can work around this for now, of course, but it would be nice to figure out what's wrong.)
Hi Michael,
the problem was the [self callinglevel] in the nesting uplevel calls. Tcl reports in the nesting case a [info level] of 2 although there are three levels on the stack. xotcl tries to skip filters and mixin-frames and it pointed incorrectly to the invocation frame and not to the variable frame. I have fixed the problem at least for your example, all regressions tests continue to work. If you come up with more such examples, please let me know.
the problem is fixed in the current working release and should be available soon.
best regards -gustaf neumann