Someone asked on chat why the unknown stuff (e.g., typing an unknown command name into the console) in tkcon "broke" after doing:
package require xotcl::upvar-compat
I looked at the code there, and the uplevel redef isn't actually compatible because it ignores error codes. Instead of:
::xotcl::tcl_uplevel 1 \ [list eval ::xotcl::tcl_uplevel $lvl $args]
you need something like:
set code [catch {::xotcl::tcl_uplevel 1 \ [list eval ::xotcl::tcl_uplevel $lvl $args]} msg] return -code $code $msg
Just an FYI for anyone using it. I'm not sure what effect this would have, if any, on the xotcl use case.
Regards,
Jeff
Jeff Hobbs schrieb:
Someone asked on chat why the unknown stuff (e.g., typing an unknown command name into the console) in tkcon "broke" after doing:
package require xotcl::upvar-compat
Thanks for reporting. I rewrote the functions to use catch, as you suggested, and tried to make clearer what happend in the code. This changes will be in the next release of XOTcl, and are already checked in the xotcl code repository.
For the curious, some background about upvar-compat:
Suppose, one has a script like
Class C
C method foo {varname} { upvar $varname v ... }
C method bar {} { ... my foo x puts "bar x=$x" ... }
C create c1 c1 bar
where a variable name is passed to the method foo. The variable is in the proc scope of the method var. This example works perfectly fine with plain tcl upvar, the package upvar-compat is not needed.
However, suppose, one adds an interceptor (e.g. filters, or a mixin class). For dynamic composition, one should be able to add functionality (e.g. tracing via filters), without breaking the original code, otherwise these interceptors are quite useless. Therefore, interceptor transparency is desired.
Let us take a simple example, adding a per object-mixin
Class M M method foo args { set x 200 next puts M.foo.x=$x }
c1 mixin M
In general the intensions is that the upvar linkage from C.foo to C.bar should not be affected by the mixin, which should be transparent. However, when c1 bar is called, M.foo lies in the callstack between C.bar and C.foo. Plain Tcl upvar has no clue, that M.foo is an interceptor, and refers to M.foo instead of to C.bar. The old behavior is broken. The situation is even more drastic when filters are used.
The recommended way to achive interceptor transparency is to use the XOTcl methods upvar and uplevel instead of the Tcl commands. In the example above, this would be
C method foo {varname} { my upvar $varname v ... }
The package xotcl::upvar-compat changes the global commands ::upvar and ::ulevel to behave like the XOTcl methods, when used within XOTcl methods.
The approach with the package xotcl::upvar-compat is not recommended, but supplied for making the application writers life more convenient.
My feeling is that we should drop this package from the xotcl distribution in the future.
Hope this explains the background. -gustaf neumann