The following problem showed up in aolserver, which produces a blueprint of all tcl-commands for initializing per-thread interpreter. This blueprint contains app procs, .... and as well ensembles. When a Tcl ensemble (e.g. info) is recreated, it looses its compileProc, which has the consequence that e.g. "info exists" is not compiled properly anymore. Not sure, if this qualifies as a bug, but it is certainly "unexpected behavior".
The problem at hand can be "solved" by reconfiguring instead of redefining preexisting ensembles (my current fix), but i would think that using TclCompileEnsemble() would make as well sense for user ensembles, which could benefit as well from the compiler, when the ensemble contains e.g. "info exists". I would have expected, that all ensembles have the same compileProc.
The details: the script below shows the bytecode before and after a scripted ensemble definition. before, "info exists" is compiled to
Command 1: "info exists foo"
(0) existScalar %v0 # var "foo"
(5) done
after, it is just the "info command"
Command 1: "info exists foo"
(0) push1 0 # "info"
(2) push1 1 # "exists"
(4) push1 2 # "foo"
(6) invokeStk1 3
(8) done
This was observed with tcl 8.5.9 and tcl 8.6b*, mac os x and debian/ubuntu linux (32 and 64bit)
-gustaf neumann
======================================
proc foo {} {info exists foo}
puts [::tcl::unsupported::disassemble proc foo]
namespace eval ::tcl::info {
namespace ensemble create -command ::info -unknown {} -subcommands {} -prefixes 1 -map {
args ::tcl::info::args body ::tcl::info::body cmdcount ::tcl::info::cmdcount
commands ::tcl::info::commands complete ::tcl::info::complete default ::tcl::info::default
exists ::tcl::info::exists frame ::tcl::info::frame functions ::tcl::info::functions
globals ::tcl::info::globals hostname ::tcl::info::hostname level ::tcl::info::level
library ::tcl::info::library loaded ::tcl::info::loaded locals ::tcl::info::locals
nameofexecutable ::tcl::info::nameofexecutable patchlevel ::tcl::info::patchlevel
procs ::tcl::info::procs script ::tcl::info::script
sharedlibextension ::tcl::info::sharedlibextension tclversion ::tcl::info::tclversion
vars ::tcl::info::vars}
}
proc foo {} {info exists foo}
puts [::tcl::unsupported::disassemble proc foo]
I know it's awkward, but the problem is that being compilable adds a fairly heavy overhead to the ensemble; every time the ensemble is modified, it causes a flush of all existing bytecodes and a rebuild from source of everything (well, it bumps an epoch counter which has that effect). I didn't want to inflict that cost on everything so non-compiled ensembles are much cheaper to modify (so packages like Snit weren't massively punished) but that has the side effect of meaning that these complexity costs are necessarily borne *somewhere*.
Maybe it would be easier to do something smarter... but I don't know what to do right now. This was the best compromise I could think of. :-)
A workaround is to simply update the existing ::info ensemble with a new -map