Age | Commit message (Collapse) | Author | Files | Lines |
|
It is convenient to be able to do just:
loop i 5 {
body
}
Where the start value is 0.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
This means that instead of just [list index 2+1], we can now do
[list index end-$n*2+1]
This applies to:
lindex, linsert, lreplace, lset, lrange, lsort, regexp, regsub
string index,first,last,range
Also add tests for both direct integer expressions and indexes.
Still needs doc update.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
This means that $variable references and [commands] are not expanded.
This should mitigate security concerns when using the 'integer expression' feature.
It means that you must do:
string repeat a $i*4
Not:
string repeat a {$i*4}
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
For convenience, many commands now accept integer expressions
rather than only simple integers.
These are:
loop, range, incr, string repeat, lrepeat, pack, unpack, rand
This simplifies many cases where previously expr {} or $() was required.
e.g.
foreach i [range 4+1 2*$b] { ... }
string repeat 2**$n a
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
This reverts commit 6b287b9c6b6ec8fbc62f1cbaad48547cf5a4b65c.
These are needed for reference counting.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
These stored the currently executing proc args and body
(the same as are available via info args and info body),
but were never used anywhere.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
It is especially convenient to add -1 for something like:
lindex $list end-$BACK-1
or:
string range $str $p $p+$len-1
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Add support for comments in expressions
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Fixes #183
Reported-by: Stuart Cassoff <stwo@bell.net>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Ensure that 'info complete' returns 0 for a script is missing
the end quote such as "abc$def
Fixes #181
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
|
|
Resolves #173.
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
|
|
TIP 342 (https://core.tcl-lang.org/tips/doc/trunk/tip/342.md)
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
TIP 461
|
|
TIP 472
|
|
[string last foo bar -1] gave segfault due to missing
check for invalid index.
Fixes #161
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Although the documentation has always stated that, like Tcl,
insertion order of dictionaries was preserved, this has never
been the case. Instead, dictionaries were implemented as simple
hash tables that did not preserve order.
Now, a new implementation of dictionaries preserves insertion
order and has a number of other benefits.
Instead of hashing keys and storing keys and values in the hash table,
the keys and values are not stored in a separate table, exactly as
lists are stored, with alternating key, value pairs. Iterating over the
dictionary is exactly like iterating over a list, where the order is consistent.
The hash table uses closed hashing rather than open hashing to avoid
allocatation of hash entry structures. Instead a fixed (but expandable)
hash table maps the key hash to the offset in the key/value table.
This use of offsets means that if the key/value table grows, the offsets
remain valid. Likewise, if the hash table needs to grow, the key, value table
remains unchanged.
In addition to the offset (which indexes to the value, and 0 means the hash table entry is unused),
the original hash is stored in the hash table. This reduces the need for object
comparisons on hash entry collisions.
The collision resolution algorithm is the same as that used by Python:
peturb >>= 5;
idx = (5 * idx + 1 + peturb) & dict->sizemask;
In order to reduce collisions, the hash table is expanded once it reaches
half full. This is more conservative that Python where the table is expanded
when it is two thirds full.
Note that if a hash collision occurs and then the original entry
that cased the hash collision is removed, we still need to continue
iterating when searching for the new key. Don't stop at the now-empty
slot. So these entries are marked with offset=-1 to indicate that
they need to be skipped.
In addition, the new faster hashing algorithm from Tcl 8.7 is used.
This the hash for integers to be calculated efficiently without requiring
them to be converted to string form first.
This implementation is modelled largely on the Python dict implementation.
Overall the performance should be an improvement over the current implementation,
whilst preserving order. Dictionary creating and insertion should be faster
as hash entries do not need to be allocated and resizing should be slightly faster.
Entry lookup should be about the same, except may be faster for pure integer keys.
Below are some indicative benchmarks.
OLD NEW
dict-create-1.1 Create empty dict 97.2ns .
dict-create-1.2 Create small dict 440ns -27%
dict-create-1.3 Create medium dict 1.54us -57%
dict-create-1.4 Create large dict (int keys) 130us -80%
dict-create-1.5 Create large dict (string keys) 143us -75%
dict-set-1.1 Replace existing item 258ns -34%
dict-set-1.2 Replace nonexistent item 365ns -49%
dict-exists-1.1 Find existing item 55.7ns -5%
dict-exists-1.2 Find nonexistent item 55.0ns -5%
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Now that proc names are stored as-is in the commands table, info commands
needs to take into account matching both foo::test and ::foo::test against
the pattern ::foo::*
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
We can simply use Jim_ReplaceHashEntry() when replacing a command
in non-local mode now that the proc epoch doesn't need to be incremented.
And JimRemoveHashEntry() only has one caller, so fold it into
Jim_DeleteHashEntry()
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Don't look up every object in the command table, since it can be slow
to do that. Only lookup if the object looks like a reference.
Also, script and expression objects can't contain references that
aren't already contained in sub-objects, so there is no need to
scan them for references.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
In this case, show the result as a decimal value
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Under some circumstances, such as lrepeat and lreverse we know
the length of the final list, so allocate the final size immediately
rather than growing the table in multiple steps.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Pass JIM_NONE to prevent an error message being generated
which is subsequently thrown away.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The changes in cdfa4637afe broke TEST 35 because the cmd
pointer is dereferenced before checking the procEpoch instead
of afterwards.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Instead of incrementing the proc epoch on every command removal
and some command creation, cache previous deleted commands
(empty structure only). Periodically increment the proc epoch
and invalide all cached commands.
This is especially a win when creating short lived commands.
e.g.
proc a {} {
local proc b {} {
# do something
}
# now b is removed
}
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The hash table used to store commands now uses Jim_Obj keys rather
than allocated char *, so embedded nulls are supported.
This means that some API function such as Jim_RenameCommand()
now take Jim_Obj * rather than const char *, however Jim_CreateCommand()
is retained with const char * for convenience and the new Jim_CreateCommandObj()
is added.
This is generally a performance win as the existing Jim_Obj can be used
as the key.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
string match, switch -glob, info commands, etc. all now support
patterns and strings with embedded nulls.
Fixes #143
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Hash tables used to store variables are now use Jim_Obj keys rather
than allocated char *, so embedded nulls are supported.
This is generally a performance win as the existing Jim_Obj can be used
as the key.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The fix for tailcall in 0d5a208e92 meant that a JIM_RETURN return
code from apply was no longer being converted to the appropriate
return code.o
Fixes: #157
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Fixes #155
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If the pattern begins with -, the internal invocation of regexp
will treat the pattern as an option. Fix this by adding -- to the
internal invocation of regexp.
Fixes #154
Reported-by: Barry Arthur <barry.arthur@gmail.com>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If exit is caught with catch -exit, it is currently not possible
to retrieve the exit value. If an exit code is provided, set it
as the interp result.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
In case the index is invalid, the string should contain -MAX_INT
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The string length was being checked in chars instead of bytes
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Also requires fixing 'debug' command so that the interpreter &
tcltest.tcl can tell it is not supported.
And the result of 'debug show' is now returned as the interpreter result
rather than being printed.
|
|
The expression tree nodes are freed with Jim_Free and should
be allocated with Jim_Alloc
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If an existing command was replaced when using local proc ...,
then renaming the command will break upcall from within the proc
because the command no longer exists in the namespace. To prevent
this case, disallow rename of such a command.
It is still OK to delete with rename <cmd> ""
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If a quote is missing inside a command, e.g.["command here]
the error should indicate that a quote is missing, not a bracket.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Should produce an error, but did not previously
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If a namespace is given, it is relative to the global namespace
not the current namespace.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
The purpose of a tailcall is to avoid using additional stack frames,
however although were were not creating an extra Tcl callframe we were
using C stack frames through the call sequence:
JimCallProcedure -> Jim_EvalObjList -> JimInvokeCommand -> JimCallProcedure
This meant that a large number of tailcalls would overflow the stack.
Instead we need to have JimCallProcedure return to JimInvokeCommand
where the tailcall can be handled by a subsequent call to JimCallProcedure.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Previously we stored lastCollectTime as time_t, but to support
more easily enabling 64 bit vs 32 bit time_t, convert this
to be JimClock() compatible (64 bit milliseconds).
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Should return the given return code, not JIM_RETURN (2)
Reported-by: dbohdan <dbohdan@dbohdan.com>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Reported-by: dbohdan <dbohdan@dbohdan.com>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
and Jim_FreeHashTable()
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
If an expression returns (e.g.), break, continue or exit, that
return code should be propagated, the same it is for [expr {}]
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|
|
Signed-off-by: Steve Bennett <steveb@workware.net.au>
|