Hello,
is it planned - or already possible - to have full trace support for XOTcl methods and procs? E.g.:
xotcl::Class A A instproc doit {args} { ... }
# later A trace add execution doit enterstep some_proc A trace add execution doit leavestep some_other_proc A trace add command doit rename some_proc
I know there are filters, but I am looking for an easier way to react on execution of particular methods/procs... for a mechanism that works for xotcl objects the same way as [trace] works for pure Tcl.
TIA Eckhard
On 31 Dec 2007, at 18:14, Eckhard Lehmann wrote:
I know there are filters, but I am looking for an easier way to react on execution of particular methods/procs... for a mechanism that works for xotcl objects the same way as [trace] works for pure Tcl.
Why not use filters with filterguards? I would've thought that would be the exact mechanism required.
Happy New Year!
I know there are filters, but I am looking for an easier way to
[..]
Why not use filters with filterguards? I would've thought that would be the exact mechanism required.
Yes, it would be possible to do it that way, but it is very complicated: - Register a filter that is by default applied to _all_ instprocs - restrict the appliance of this filter via a filterguard
Sounds like "shooting from behind through the brest into the eye". Why not simply add/remove execution of code to particular methods, like with [trace]? There is already a [trace] method for XOTcl objects, but just for variables (at least from the documentation)... Especially I look for a way to execute a proc before *every* statement inside an instproc. [trace] can do this via the "enterstep" and "leavestep" operators to [trace add execution]. Is this possible with filters and filterguards?
Thanks, Eckhard
On 1 Jan 2008, at 14:33, Eckhard Lehmann wrote:
Especially I look for a way to execute a proc before *every* statement inside an instproc. [trace] can do this via the "enterstep" and "leavestep" operators to [trace add execution]. Is this possible with filters and filterguards?
As you say, [trace] can do that. For XOTcl methods it is possible with filters as they are executed before the actual method, which only gets run when [next] is called. So with filters you can handle both the enter and the leave. Using filters you could easily build a framework that would allow you to specify which methods to catch. I've done this with my Memorisation class (for caching). I can specify which methods I want to cache and the filter deals with that. It was created before filterguards so it may be even easier (and faster) to do with today's filters.
Dear all,
first, a happy new year to everybody!
Eckhard Lehmann schrieb:
Especially I look for a way to execute a proc before *every* statement inside an instproc. [trace] can do this via the "enterstep" and "leavestep" operators to [trace add execution]. Is this possible with filters and filterguards?
Here is a small example for tracing the calls within a method ("doit"), which is somewhat similar to enterstep. Given is the following sample script:
========================== Class A A instproc foo {} { my set f 2 } A instproc doit {args} { my set a 3 } Class B -superclass A B instproc doit {args} { my set x 1 my foo next my set y 4 } B b1 ==========================
for this script, we can define a filter, which uses call stack introspection (self callingproc) to check, whether the current execution is within the method "doit".
========================== Class F F instproc traceFilter args { if {[self callingproc] eq "doit"} { puts "Call: [self] [self calledproc] $args" set r [next] puts "Exit: [self] [self calledproc] $args => $r" return $r } else { next } } ==========================
we add the method via mixin and register the filter to to all instances of Class B and call the method,
========================== B instmixin F B instfilter {{traceFilter}} b1 doit ==========================
The output is as follows:
Call: ::b1 set x 1 Exit: ::b1 set x 1 => 1 Call: ::b1 foo Exit: ::b1 foo => 2 Call: ::b1 set a 3 Exit: ::b1 set a 3 => 3 Call: ::b1 set y 4 Exit: ::b1 set y 4 => 4
Note, that it just traces on the level of doit. This is not the same, what tcl command traces provide (which is more of a debugging tool), but filters are in some respects more general: one can use traces as glueing code between invocations, restrict the traces to certain objects or instances of classes, one can stack multiple filters, or can provide different guard conditions for different subclasses, etc.
tcl command traces just know about tcl-commands and nothing about OO concepts, they allow to register other tcl commands to be executed at certain checkpoints (e.g. one command before the invocation, another command after invocation), but it does not provide e.g. means to pass information between the before and after calls. that is much easier with the "next" metapher in xotcl, which is uniform to all other supported concepts.
i have not felt so far the need for tcl command traces, but i understand, that for people used to it there is a change in the method-set and thinking involved to move from command traces towards filters/mixins.
Allthough all xotcl methods are commands, with the current framework, the tcl command traces are not called autmatically, since the basic invocation mechanisms (with inheritance, filters, mixins) are handled by xotcl. Without looking into the details, i think it should be possible with moderate effort to incorporate tcl command traces in xotcl. But one has to convince the developers, that adding yet another interception mechanism to xotcl adds more benefits than causing confusion.
-gustaf neumann
PS: The example above can be implemented nicer of filterGuards, but unfortuantely, there is a bug in the current release (most likely since ever) within the evaluation of callstack introspection commands from within a guard. This bug will be removed in the forthcoming release, where one can write:
F instproc traceFilter args { puts "Call: [self] [self calledproc] $args" set r [next] puts "Exit: [self] [self calledproc] $args => $r" return $r }
B instfilter {{traceFilter -guard { [self callingproc] eq "doit" }}}
Hello Gustaf,
first, a happy new year to everybody!
Ihnen auch ein frohes neues Jahr :)!
Here is a small example for tracing the calls within a method ("doit"), which is somewhat similar to enterstep. Given is the following sample script:
[...]
The example is very illustrative, thanks for that. However, it seems that only calls to object methods are traced. In practical code I have ordinary Tcl statements as well, e.g. the instproc "doit" could look like:
B instproc doit {args} { my set x 1 my foo set l {a b c d} for {set i 0} {$i < [llength $l]} {incr i} { puts $i my_old_tcl_proc $i [lindex $l $i] } # lots of other stuff... next my set y 4 }
When I run that, only the calls to [my set x 1], [my foo] etc. are intercepted, but not [set l {a b c d}] and [for].
Allthough all xotcl methods are commands, with the current framework, the tcl command traces are not called autmatically, since the basic invocation mechanisms (with inheritance, filters, mixins) are handled by xotcl. Without looking into the details, i think it should be possible with moderate effort to incorporate tcl command traces in xotcl. But one has to convince the developers, that adding yet another interception mechanism to xotcl adds more benefits than causing confusion.
I see that there is no need for another interception technique, but it would be really helpful to have the current filter techiques also applied to ordinary Tcl code inside methods.
To be more precise, I am looking for a way to debug larger XOTcl programs. http://wiki.tcl.tk/6007 describes a very nice and small debugger that uses [trace exec] and can be applied to ordinary Tcl proc's. I would like to extend that code, e.g. create an XOTcl class "Debugger", that provides methods for step, breakpoint etc. It should be possible to mixin this to any other XOTcl object for debugging purposes.
Thanks so far, Eckhard
On 2 Jan 2008, at 12:51, Eckhard Lehmann wrote:
I see that there is no need for another interception technique, but it would be really helpful to have the current filter techiques also applied to ordinary Tcl code inside methods.
Why not just use the Tcl [trace] command for the normal Tcl commands?
Kristoffer Lawson schrieb:
I see that there is no need for another interception technique, but it would be really helpful to have the current filter techiques also applied to ordinary Tcl code inside methods.
Why not just use the Tcl [trace] command for the normal Tcl commands?
How would you do that, together with filters? enterstep/leavestep work only in Tcl proc's, while filters work only on objects. How could this be mixed - as methods are composed of calls to objects (e.g. [my], [self]) as well as ordinary Tcl code? As long as it is separated, fine. But for Tcl statements in object methods it seems more difficult to me.
Eckhard
On 2 Jan 2008, at 21:26, Eckhard Lehmann wrote:
Kristoffer Lawson schrieb:
I see that there is no need for another interception technique, but it would be really helpful to have the current filter techiques also applied to ordinary Tcl code inside methods.
Why not just use the Tcl [trace] command for the normal Tcl commands?
How would you do that, together with filters? enterstep/leavestep work only in Tcl proc's, while filters work only on objects. How could this be mixed - as methods are composed of calls to objects (e.g. [my], [self]) as well as ordinary Tcl code? As long as it is separated, fine. But for Tcl statements in object methods it seems more difficult to me.
You could just wrap it in a package that sets a Tcl [trace] for normal commands combined with filters for the XOTcl stuff, just checking to see if the command names match, if necessary. Or maybe I've missed something here and I'm thinking to simple :-)
Kristoffer Lawson schrieb:
You could just wrap it in a package that sets a Tcl [trace] for normal commands combined with filters for the XOTcl stuff, just checking to see if the command names match, if necessary. Or maybe I've missed something here and I'm thinking to simple :-)
The problem is that I need something that is like enterstep/leavestep for [trace], but for XOTcl. Filters do only intercept calls to XOTcl objects but not to Tcl proc's. Consider the example from Gustaf above. I have extended it a little bit:
B instproc doit {args} { my set x 1 my foo set l {a b c d} ;# <------ for {set i 0} {$i < 10} {incr i} { ;# <------ puts $i ;# <------ } ;# <------ next my set y 4 }
The whole script is below, you can paste it into a file and run it. If you do so, the output is: ----- Call: ::b1 set x 1 Exit: ::b1 set x 1 => 1 Call: ::b1 foo Exit: ::b1 foo => 2 0 1 2 3 4 5 6 7 8 9 Call: ::b1 set a 3 Exit: ::b1 set a 3 => 3 Call: ::b1 set y 4 Exit: ::b1 set y 4 => 4 ----- As you can see, the calls to [my set x 1] and [my foo] are intercepted ("Call"/"Exit"), but the calls to [set l {a b c d}] and to the [for] loop are not. Therefore it is only partially useful, if yo want to intercept *every* statement in a method (which is what I want).
Eckhard
#----------------- Script -------------- Class A A instproc foo {} { my set f 2 } A instproc doit {args} { my set a 3 } Class B -superclass A B instproc doit {args} { my set x 1 my foo set l {a b c d} for {set i 0} {$i < 10} {incr i} { puts $i } next my set y 4 } B b1
Class F F instproc traceFilter args { if {[self callingproc] eq "doit"} { puts "Call: [self] [self calledproc] $args" set r [next] puts "Exit: [self] [self calledproc] $args => $r" return $r } else { next } }
B instmixin F B instfilter {{traceFilter}} b1 doit
On 2 Jan 2008, at 23:46, Eckhard Lehmann wrote:
Kristoffer Lawson schrieb:
You could just wrap it in a package that sets a Tcl [trace] for normal commands combined with filters for the XOTcl stuff, just checking to see if the command names match, if necessary. Or maybe I've missed something here and I'm thinking to simple :-)
The problem is that I need something that is like enterstep/ leavestep for [trace], but for XOTcl. Filters do only intercept calls to XOTcl objects but not to Tcl proc's.
I understand that requirement. That is why I am suggesting you use a combination of XOTcl filters and [trace]. It might be that even [trace] is enough, if it catches all Tcl command calls (I haven't looked at it). If not, have XOTcl filters for the XOTcl stuff and [trace] for the rest?
Kristoffer Lawson schrieb:
I understand that requirement. That is why I am suggesting you use a combination of XOTcl filters and [trace]. It might be that even [trace] is enough, if it catches all Tcl command calls (I haven't looked at it). If not, have XOTcl filters for the XOTcl stuff and [trace] for the rest?
one can set enterstep calls on next
proc CALL args {puts "CALL $args"} proc EXIT args {puts "EXIT $args"} trace add execution next enterstep CALL trace add execution next leavestep EXIT
and maybe add these two traces in the filter once on the first call (e.g. controlled via a global variable).
Alternatively, one could define a "proc n args {next}", register the traces on it and use in the filter "set r [n]" instead of "set r [next]". In this case multiple filter registrations are not a problem.
It is as well possible to register enterstep on the object/class names, trace add execution b1 enterstep CALL trace add execution b1 leavestep EXIT but there you might get as well too much output.
-gustaf neumann
/ http://www.scred.com/ / http://www.fishpool.com/~setok/
Xotcl mailing list Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
Kristoffer Lawson schrieb:
I understand that requirement. That is why I am suggesting you use a combination of XOTcl filters and [trace]. It might be that even [trace] is enough, if it catches all Tcl command calls (I haven't looked at it). If not, have XOTcl filters for the XOTcl stuff and [trace] for the rest?
one can set enterstep calls on next
proc CALL args {puts "CALL $args"} proc EXIT args {puts "EXIT $args"} trace add execution next enterstep CALL trace add execution next leavestep EXIT
and maybe add these two traces in the filter once on the first call (e.g. controlled via a global variable).
Alternatively, one could define a "proc n args {next}", register the traces on it and use in the filter "set r [n]" instead of "set r [next]". In this case multiple filter registrations are not a problem.
It is as well possible to register enterstep on the object/class names, trace add execution b1 enterstep CALL trace add execution b1 leavestep EXIT but there you might get as well too much output.
-gustaf neumann
/ http://www.scred.com/ / http://www.fishpool.com/~setok/
Xotcl mailing list Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl