RHS: I've been working on a package to examine and modify the bytecodes for a proc. Since I've actually gotten something working, I figured its time I put up a link to what I've done so far. The actual code (which is a combination of Tcl and C) can be found at [L1 ] where the rest of the things I've been working on are located.
What is it?
The general idea of the package is to allow one to get the bytecodes for a procedure, and then modify them. The current code implements:
::bytecode::get procname
::bytecode::setExceptionRanges procname ranges
I've also used the forward compatible dict code from forward-compatible dict, because it made the output from the get command much easier to understand when using dicts.
As a note, the code is full of memory leaks. The two main places I'm aware of where there are leaks are:
To Do
Once one can set all 4 of the above (the currently setable exception ranges being the 4th), I believe it will be possible to write a command that can define a proc from scratch using bytecodes, along the lines of:
::bytecode::byteproc args extraCompiledLocals compiledLiterals exceptionRanges byteCodes
Where:
proc testme {} {
set retval 0
for {set i 0} {$i < 10} {incr i} {
for {set j 0} {$j < 10} {incr j} {
incr retval
break
}
}
return $retval
}Would be
::bytecode::byteproc testme {} {
0 {Type scalar Name retval}
1 {Type scalar Name i}
2 {Type scalar Name j}
} {
0 1
1 10
2 {}
} {
0 {Level 1 Type loop PC {12 37} Continue 39 Break 50}
1 {Level 1 Type loop PC {39 41} Continue -1 Break 50}
2 {Level 2 Type loop PC {19 23} Continue 25 Break 36}
3 {Level 2 Type loop PC {25 27} Continue -1 Break 36}
} {
{push1 0}
{storeScalar1 0}
{pop}
{push1 0}
{storeScalar1 1}
{pop }
{jump1 33}
{push1 0}
{storeScalar1 2}
{pop }
{jump1 12}
{incrScalar1Imm 0 1}
{pop}
{break}
{pop}
{incrScalar1Imm 2 1}
{pop}
{loadScalar1 2}
{push1 1}
{lt}
{jumpTrue1 -15}
{push1 2}
{pop}
{incrScalar1Imm 1 1}
{pop}
{loadScalar1 1}
{push1 1}
{lt}
{jumpTrue1 -36}
{push1 2}
{pop}
{loadScalar1 0}
{done}
{done}
}As a note, if the 3rd exception (lindex 2) is changed from break 36 to break 50, breaks in the inner for loop now break the outter loop also, so proc returns 1 instead of 10 (that actuall the test I use for the setExceptionRange command).