Re: retrieving line number in case of error - "simple debugger"
- From: Wojciech Kocjan <hceicjow.backward@xxxxxxxxxx>
- Date: Thu, 29 Sep 2005 19:50:21 +0200
Bryan Oakley napisał(a):
set lineno 0
foreach line [split $script \n] {
if {![info exists command]} {
set command $line
} else {
append command \n $line
}
incr lineno
if {[info complete $command]} {
if {[catch $command err]} {
puts "error on line $lineno: $err"
}
unset command
}
}
That one's actually tricky.
(zoro) 55 % info complete "puts \\" 1 (zoro) 56 % eval "puts \\ x" x
So this would not get parsed correctly. The other tricky thing is:
(zoro) 57 % eval "puts \\\\ x"
Since it's the opposite. The moral of the story is that \\ at the end of a line are a PITA in this case. I think it is much safer to do info complete and check for an even number of \ at the end (0 is also even for me :-). But there's probably still some other issue (or issues) that do not make it work... Anyway, here's "info complete on steroids" :-)
proc checkIfReallyComplete {line} {
if {![info complete $line]} {
return false
}
set count 0
while {[string index $line end-$count] == "\\"} {
incr count
}
if {$count % 2} {
return false
} else {
return true
}
}So, perhaps the answer to your question is "info complete" and "catch". That is, you can use [info complete] to know if a line or lines of user-entered text is a complete command, and "catch" to execute the command and to retrieve the result.
I no longer believe in [info complete]. Well, it would be great if Tcl would have [info complete -strict] or something, that would actually check what the interpreter would do. For now, I guess most people could live with the equivalent above.
But, assuming he would have a proc called checkIfReallyComplete (or something), then it would be much better to:
set realcode ""
set script [.text get 1.0 end-1c]
set lineno 0
foreach line [split $script \n] {
if {![info exists command]} {
set command $line
} else {
append command \n $line
}
incr lineno
if {[checkIfReallyComplete $command]} {
append realcode [list set ::lineNumber $lineno] \n $command \n
}
}
if {[catch $realcode]} {
puts "Error in $::lineNumber $::errorInfo"
}And even better, this would allow storing the "debugable" version of the script.
Then we would probably come up with a problem with control statements like for/foreach/while/if and would have to emulate those (preferably at "parser" level). Well then we will have custom control statements... (ie expect command from expect or tcom::foreach). I think this is a messy situation. Well, not to mention considering namespaces while parsing (ie :
namespace eval tcom {
foreach ....
}is not quite obvious. Especially with the following "crude" code:
set ns tcom
namespace eval $ns {
foreach ....
}Then there's metaprogramming ;-)
I wonder if an universal parser could be produced this way - one that would return return something similar to command tree so that everyone could debug it the way they want to (GUI, logging, whatever).
Just my 2 cents in this matter. If anybody wants to pursue this, I would love to see the results. I wanted to, but got scared by the problems above. Anyway, for a plain Tcl script, those problems do not really exist :-) So just reparsing using info complete + for/foreach/while/if would easily debug 90% of the scripts.
-- WK .
- References:
- retrieving line number in case of error - "simple debugger"
- From: Nicolas Castagne
- Re: retrieving line number in case of error - "simple debugger"
- From: Don Porter
- Re: retrieving line number in case of error - "simple debugger"
- From: Nicolas Castagne
- Re: retrieving line number in case of error - "simple debugger"
- From: Bryan Oakley
- retrieving line number in case of error - "simple debugger"
- Prev by Date: Re: My own control structures are slow
- Next by Date: Re: retrieving line number in case of error - "simple debugger"
- Previous by thread: Re: retrieving line number in case of error - "simple debugger"
- Next by thread: Re: retrieving line number in case of error - "simple debugger"
- Index(es):
Relevant Pages
|