Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

new control structure, uplevel and proper error forwarding

65 views
Skip to first unread message

Petro Kazmirchuk

unread,
Jan 3, 2023, 9:43:08 AM1/3/23
to
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

Gerald Lester

unread,
Jan 3, 2023, 9:47:26 AM1/3/23
to
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: Gerald...@kng-consulting.net |
+----------------------------------------------------------------------+

Petro Kazmirchuk

unread,
Jan 3, 2023, 10:36:48 AM1/3/23
to
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 :(

Gerald Lester

unread,
Jan 4, 2023, 8:43:55 AM1/4/23
to
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.
0 new messages