diff options
author | Steve Bennett <steveb@workware.net.au> | 2023-05-18 15:34:26 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2023-06-21 09:17:47 +1000 |
commit | 0b08e74e656c6bfb65c6f38657be05bb463f54e6 (patch) | |
tree | faa80db8a2cd6f24cf890ad6730c00f4d7dd2738 /stdlib.tcl | |
parent | f07c53e38d55f0c7c648b7818798138d91053527 (diff) | |
download | jimtcl-0b08e74e656c6bfb65c6f38657be05bb463f54e6.zip jimtcl-0b08e74e656c6bfb65c6f38657be05bb463f54e6.tar.gz jimtcl-0b08e74e656c6bfb65c6f38657be05bb463f54e6.tar.bz2 |
core: Display errors in a more "pythonesque" way
A typical error message now looks like this:
t4.tcl:2: Error: syntax error in expression: "blah"
Traceback (most recent call last):
File "t4.tcl", line 14
c 1 2 3
File "t4.tcl", line 10, in c
b a c
File "t4.tcl", line 6, in b
a A14
File "t4.tcl", line 2, in a
expr blah
This is produced by stackdump (that can be replaced), called by errorInfo.
Note that now stacktraces (stacktrace, info stacktrace, $opts(-errorinfo)) include
the running command at each level in addition to proc, file, line. In order for
scripts to detect this new format, a new entry tcl_platform entry has been added:
tcl_platform(stackFormat) = 4 (to signify 4 elements per frame)
In addition, instead of building the error stack frame as the stack
is unwound in response to an error, instead the entire current stack trace
is captured by stacktrace. This means that the trace extends beyond the try/catch
right back to the initial interpreter command.
The 'stacktrace' command is now implemented in C based on the same
code that generates the error stacktrace.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'stdlib.tcl')
-rw-r--r-- | stdlib.tcl | 39 |
1 files changed, 13 insertions, 26 deletions
@@ -33,39 +33,28 @@ proc function {value} { return $value } -# Returns a live stack trace as a list of proc filename line ... -# with 3 entries for each stack frame (proc), -# (deepest level first) -proc stacktrace {{skip 0}} { - set frames {} - loop level $skip+1 [info frame] { - set frame [info frame -$level] - if {[dict exists $frame proc]} { - lappend frames $frame(proc) $frame(file) $frame(line) - } - } - return $frames -} - # Returns a human-readable version of a stack trace proc stackdump {stacktrace} { set lines {} - foreach {l f p} [lreverse $stacktrace] { + lappend lines "Traceback (most recent call last):" + foreach {cmd l f p} [lreverse $stacktrace] { set line {} - if {$p ne ""} { - append line "in procedure '$p' " - if {$f ne ""} { - append line "called " - } - } if {$f ne ""} { - append line "at file \"$f\", line $l" + append line " File \"$f\", line $l" + } + if {$p ne ""} { + append line ", in $p" } if {$line ne ""} { lappend lines $line + if {$cmd ne ""} { + lappend lines " $cmd" + } } } - join $lines \n + if {[llength $lines] > 1} { + return [join $lines \n] + } } # Add the given script to $jim::defer, to be evaluated when the current @@ -81,10 +70,8 @@ proc errorInfo {msg {stacktrace ""}} { if {$stacktrace eq ""} { # By default add the stack backtrace and the live stacktrace set stacktrace [info stacktrace] - # omit the procedure 'errorInfo' from the stack - lappend stacktrace {*}[stacktrace 1] } - lassign $stacktrace p f l + lassign $stacktrace p f l cmd if {$f ne ""} { set result "$f:$l: Error: " } |