Open sebres opened 7 years ago
About sub procs. Here is a small comparison between original tcl and tclSE:
Original tcl-code (subroutine sub
faked):
proc test {a b} {
set c $a; incr c $b
set sub {
set prev_c $c
incr c 100
puts "c != a + b: $c != $a + $b"
set c $prev_c
}
puts "== 1st time: =="
puts "c == a + b: $c == $a + $b"
set i 3; while {[incr i -1]} $sub
puts "c == a + b: $c == $a + $b"
puts "== 2nd time: =="
puts "c == a + b: $c == $a + $b"
set i 3; while {[incr i -1]} $sub
puts "c == a + b: $c == $a + $b"
}
% test 10 20
== 1st time: ==
c == a + b: 30 == 10 + 20
c != a + b: 130 != 10 + 20
c != a + b: 130 != 10 + 20
c == a + b: 30 == 10 + 20
== 2nd time: ==
c == a + b: 30 == 10 + 20
c != a + b: 130 != 10 + 20
c != a + b: 130 != 10 + 20
c == a + b: 30 == 10 + 20
tclSE-code (subroutine sub
is real sub proc), same result here:
proc test {a b} {
set c $a; incr c $b
sub-proc sub {} {
## c is local variable now after declaration bellow ("set" does it not):
var c $c
incr c 100
puts "c != a + b: $c != $a + $b"
}
puts "== 1st time: =="
puts "c == a + b: $c == $a + $b"
set i 3; while {[incr i -1]} { sub }
puts "c == a + b: $c == $a + $b"
puts "== 2nd time: =="
puts "c == a + b: $c == $a + $b"
set i 3; while {[incr i -1]} { sub }
puts "c == a + b: $c == $a + $b"
}
The pros are obvious:
local
or var
(also upvar
can be used)
This should be a collection of all kinds of changes, fixes, refactorings in relation of the differences between both editions, and should basically describe my aim resp. the inspiration for writing of own tcl-fork (tclSE).
Not part of this repository (no public access ATM)
[Q] Why:
What I always had been missing in original tcl edition, was the inconsistent handling round about oo-objects of all kinds (no matter which engine - xotcl, itcl, etc.), the absence of many primitives and goodies that are already long time a part of many other modern languages.
Nevertheless I love tcl (and it has always been and remains my favourite language), but...
I mean:
But all the tcl oo-objects are commands with namespaces (yes, I mean the objects not the classes). And so have many disadvantages, namely:
{}
. So this object may switch its internal representation multiple times during of execution of small code pieces. Recently it was tclDictType now it is a tclListType, and below it will be unicode object. Bad is that thereby previous representations are lost. You can increment refCount of such objects, but it does not prevent the switching of the internal representation. So if some code currently works with dict/list innards and the object switches its type in-between during the iteration (e. g. any of the TclEvals executed in-between, something like foreach), then segfaults are the best what will happen here (worse if it occurs much later, so no chance to find the actual error). The only way to prevent such situations is to duplicate objects right before (and original tcl does it also very often). But, IMHO it is a very wrong resp. questionable way. Thereby in the tclSE the only reasons to duplicate objects would be:if $GLOBAL_VAR {...}
, but it is not the same as real preprocessor).This list is not completed and will grow, once I'll remember about something again...
[Q] What is tclSE:
Currently it is my private tcl engine, that resolves good almost all abovementioned problems. It is fast, robust and comfortable. But thereby not 100% compatible.
Here is a small list of important changes (only):
It describes now also which kind of references or pointing features this type supports (ref, smart, shared or weak object pointers).
script.tclc
(and auto-recompile it by checking of modification time of original), or even encrypting or signing of the byte code additionally etc;if something not exists ...
, searching somewhere in hashes, global and namespace references etc.)For example it's a way to build dynamically calculated constants or the constants dependent on some value, object even class.
source
(if shared - only once);virtual
for methods may be redefined in inheritances, oroverride
that allow however to replace a non-virtual method in current inheritance (also if that will be called in inherited class without this). Or for example predicatesilent
, that allows to disable call stack expansion inside by throwing errors from this scope (if the routine is "safe", but throws many exceptions, and the stack of calls inside it should be definitely not included). This handling may be disabled if running under debugger.To be continued...