• Re: new control structure, uplevel and proper error forwarding

    From Gerald Lester@21:1/5 to Petro Kazmirchuk on Tue Jan 3 08:47:21 2023
    On 1/3/23 08:43, Petro Kazmirchuk wrote:
    there's a lot of information on Tcl Wiki on the subject, but most of it pre-dates 8.6
    I've read a whole lot, and still couldn't figure out a clean way to remove my new control structure from an error's callstack.

    Consider:
    proc duration {script varName} {
    upvar 1 $varName elapsed
    set now [clock millis]
    uplevel 1 $script
    set elapsed [expr {[clock millis] - $now}]
    }
    to be used as:
    duration {
    set result [foo]
    } elapsed
    I don't care about return codes "break" and "continue"
    I save the return value of $script myself
    The problem is that if [foo] raises an error, and I catch it outside [duration], the -errorstack will contain things like "UP 1 CALL duration" that I'd prefer to hide. Experimenting with return -level 2 didn't help, and I can't use tailcall because
    then I can't compute $elapsed.
    I've looked at Tcllib's ascaller.tcl, but it clearly pre-dates 8.6 too, and I don't want to rely on it just for the sake of one proc.
    Thanks in advance

    You need to catch it in duration and reraise the error with the stack information you want via the error or return commands (depending on what
    you want).

    --
    +----------------------------------------------------------------------+
    | Gerald W. Lester, President, KNG Consulting LLC |
    | Email: [email protected] | +----------------------------------------------------------------------+

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Petro Kazmirchuk@21:1/5 to All on Tue Jan 3 06:43:06 2023
    there's a lot of information on Tcl Wiki on the subject, but most of it pre-dates 8.6
    I've read a whole lot, and still couldn't figure out a clean way to remove my new control structure from an error's callstack.

    Consider:
    proc duration {script varName} {
    upvar 1 $varName elapsed
    set now [clock millis]
    uplevel 1 $script
    set elapsed [expr {[clock millis] - $now}]
    }
    to be used as:
    duration {
    set result [foo]
    } elapsed
    I don't care about return codes "break" and "continue"
    I save the return value of $script myself
    The problem is that if [foo] raises an error, and I catch it outside [duration], the -errorstack will contain things like "UP 1 CALL duration" that I'd prefer to hide. Experimenting with return -level 2 didn't help, and I can't use tailcall because then
    I can't compute $elapsed.
    I've looked at Tcllib's ascaller.tcl, but it clearly pre-dates 8.6 too, and I don't want to rely on it just for the sake of one proc.
    Thanks in advance

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Petro Kazmirchuk@21:1/5 to All on Tue Jan 3 07:36:45 2023
    This is how -errorinfo looks when I call [foo] directly:

    my error
    while executing
    "throw AAA "my error""
    (procedure "bar" line 2)
    invoked from within
    "bar"
    (procedure "foo" line 2)
    invoked from within
    "foo"
    ("try" body line 3)

    nice and clean - this is what I want to achieve with [duration]

    Let's try to handle the error:
    proc duration {script varName} {
    upvar 1 $varName elapsed
    set now [clock millis]
    if {[catch {uplevel 1 $script} result errOpts]} {
    dict incr errOpts -level ;# makes no difference, but I did my due diligence
    return -options $errOpts $result
    }
    set elapsed [expr {[clock millis] - $now}]
    }

    resulting -errorinfo:

    my error
    while executing
    "throw AAA "my error""
    (procedure "bar" line 2)
    invoked from within
    "bar"
    (procedure "foo" line 2)
    invoked from within
    "foo"
    ("uplevel" body line 2)
    invoked from within
    "uplevel 1 $script"
    invoked from within
    "duration {
    foo
    } elapsed"
    ("try" body line 2)

    P.S. is it possible to format Tcl code somehow here? it becomes really unreadable after posting :(

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerald Lester@21:1/5 to Petro Kazmirchuk on Wed Jan 4 07:43:48 2023
    On 1/3/23 09:36, Petro Kazmirchuk wrote:
    This is how -errorinfo looks when I call [foo] directly:

    my error
    while executing
    "throw AAA "my error""
    (procedure "bar" line 2)
    invoked from within
    "bar"
    (procedure "foo" line 2)
    invoked from within
    "foo"
    ("try" body line 3)

    nice and clean - this is what I want to achieve with [duration]

    Let's try to handle the error:
    proc duration {script varName} {
    upvar 1 $varName elapsed
    set now [clock millis]
    if {[catch {uplevel 1 $script} result errOpts]} {
    dict incr errOpts -level ;# makes no difference, but I did my due diligence
    return -options $errOpts $result
    }
    set elapsed [expr {[clock millis] - $now}]
    }

    resulting -errorinfo:

    my error
    while executing
    "throw AAA "my error""
    (procedure "bar" line 2)
    invoked from within
    "bar"
    (procedure "foo" line 2)
    invoked from within
    "foo"
    ("uplevel" body line 2)
    invoked from within
    "uplevel 1 $script"
    invoked from within
    "duration {
    foo
    } elapsed"
    ("try" body line 2)

    P.S. is it possible to format Tcl code somehow here? it becomes really unreadable after posting :(

    You only did part of the work -- remove the uplevel from the trace in
    errOpts (any anything else you want).

    It is all under your control.
    --
    +----------------------------------------------------------------------+
    | Gerald W. Lester, President, KNG Consulting LLC |
    | Email: [email protected] | +----------------------------------------------------------------------+

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)