Jumping back to another Tcl stack

Is there an easy way to expand the stack in Tcl? I have this weird problem where I have to go back to a specific stack frame, literally. I can get all the information about a frame using a command info

, but in order to actually navigate to a specific frame I will need to set some local variables in each procedure and check them accordingly. I was wondering if there is an easier way.

+3


source to share


3 answers


If you need to get the code to do a non-local return (i.e. skipping multiple levels), you can do it from 8.5 with the -level

before option return

. See this example:

proc foo-a {} {
    puts a-in
    foo-b
    puts a-out
}
proc foo-b {} {
    puts b-in
    foo-c
    puts b-out
}
proc foo-c {} {
    puts c-in
    foo-d
    puts c-out
}
proc foo-d {} {
    puts d-in
    bar
    puts d-out
}
proc bar {} {
    puts bar-in
    return -level 3
    puts bar-out
}
foo-a

      



This works by throwing a special kind of exception; the details are pretty hidden. Alternatively, you can also use try

and throw

if you have 8.6 or their script (see the Tcler Wiki for Tcl, which was used when discussing code in 8.6).

With older versions of Tcl, the simplest mechanism is to use return -code 42

and put some code in the up-stack location in a catch

custom exception and determine if it is a magic value (here 42, that would be the result catch

) and react accordingly. It can be quite efficient, but also messy. This is why 8.5 onwards provides you with tools that are easier to use.

+4


source


The short answer is that you are probably better off revisiting your design.



The longer answer is that the only real way (I can think of) to do this is to throw the error and catch it at the level necessary to stop it. Also, of course, a less fiery way of checking variables all over the call stack. However, using errors for control flow is ... bad form.

+3


source


If you are ready to bleed, coroutines (available in 8.6) may suit your needs.

Otherwise, you can try to mark the subroutine level you want to get when you are there (that is, set the global variable to [info level]) and then in a deeper procedure, [uplevel] to that absolute stack frame. Something like

proc need-to-be-here {} {
   set ::myframe [info level]
   deeper-calls
}

proc deepest-call {} {
   uplevel #$::myframe {what I need to do}
}

      

(unverified)

+1


source







All Articles