MS: Following a question on the chat, here is an explanation of when and how a proc is compiled to bytecodes. Why compile to bytecode is a separate question.
This reflects my present understanding of all this, AFAIK essentially correct - I am aware of a lot of simplifications here, which I hope result in more clarity and not confusion. In particular, there is no mention of Tcl_Obj
I also do not address the behaviour of variables here.
In case of doubt, read the source, Luke ... and do correct me please!
What happens when you *define* a proc?
Not much, actually: the source is saved as text, a command is created in the corresponding namespace. (The text may still have syntax errors or whatever - see procs as data structures).
What happens when you *invoke* a proc?
What happens when a command B is invoked in the body of proc A
What happens when bytecodes are executed?
Example
# define B proc B x { if $x { this is an error } else { set a b } } # define A proc A x {B $x} # invoke A: this causes compilation of A, start running A, # then invoke B (which cause its compilation). Both are # compiled OK A 0 ;# returns b A 1 ;# runtime error: invalid command name "this" A 0 ;# returns b, all is still OK # define a proc "this" proc this args {return "OK now"} # invoke A; previous bytecodes of both A and B are used; # at the invocation of 'this', it is found, parsed, # compiled and run A 1 ;# "this" is now found, returns "OK now" # redefine B, now using a bcc'ed command. B's previous # bytecodes are discarded, B is saved as text, no error proc B x { if $x { # this is a compile-time error set a b c } else { set a b } } # invoke A: use existing compilation of A, start running A, # then invoke B which cause its compilation. The error is at # compile time due to the bcc'ed [set] (this is an open bug, # actually), even the "correct" case fails: A 0 ;# wrong # args: should be "set varName ?newValue?"
The global variable 'tcl_traceCompile' permits observation of the compiler's activity - 1 tells you when compilation takes place, 2 shows you the bytecodes too.
The variable 'tcl_traceExec' permits observation of the execution engine: 1 tells you whenever a proc is invoked, 2 whenever a command is invoked, 3 shows the actual bytecodes being executed.
(You must compile tcl with the -DTCL_COMPILE_DEBUG flag, to make this work. de.)
Is there any good reason that this isn't enabled by default? Does it impose a significant overhead? I suppose it must. Cmcc Indeed it does. --strick
DKF: Compilation debugging is now (8.4) enable-able using a suitable flag to configure, at least on UNIX.
See also tcl::unsupported::disassemble, and be aware that it forces compilation of the things it disassembles. (Not very surprising that!)