You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(19) |
Jul
(96) |
Aug
(144) |
Sep
(222) |
Oct
(496) |
Nov
(171) |
Dec
(6) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(4) |
Feb
(4) |
Mar
(9) |
Apr
(4) |
May
(12) |
Jun
(6) |
Jul
|
Aug
|
Sep
(1) |
Oct
(2) |
Nov
|
Dec
|
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(52) |
Aug
(47) |
Sep
(47) |
Oct
(95) |
Nov
(56) |
Dec
(34) |
| 2003 |
Jan
(99) |
Feb
(116) |
Mar
(125) |
Apr
(99) |
May
(123) |
Jun
(69) |
Jul
(110) |
Aug
(130) |
Sep
(289) |
Oct
(211) |
Nov
(98) |
Dec
(140) |
| 2004 |
Jan
(85) |
Feb
(87) |
Mar
(342) |
Apr
(125) |
May
(101) |
Jun
(60) |
Jul
(151) |
Aug
(118) |
Sep
(162) |
Oct
(117) |
Nov
(125) |
Dec
(95) |
| 2005 |
Jan
(141) |
Feb
(54) |
Mar
(79) |
Apr
(83) |
May
(74) |
Jun
(125) |
Jul
(63) |
Aug
(89) |
Sep
(130) |
Oct
(89) |
Nov
(34) |
Dec
(39) |
| 2006 |
Jan
(98) |
Feb
(62) |
Mar
(56) |
Apr
(94) |
May
(169) |
Jun
(41) |
Jul
(34) |
Aug
(35) |
Sep
(132) |
Oct
(722) |
Nov
(381) |
Dec
(36) |
| 2007 |
Jan
(34) |
Feb
(174) |
Mar
(15) |
Apr
(35) |
May
(74) |
Jun
(15) |
Jul
(8) |
Aug
(18) |
Sep
(39) |
Oct
(125) |
Nov
(89) |
Dec
(129) |
| 2008 |
Jan
(176) |
Feb
(91) |
Mar
(69) |
Apr
(178) |
May
(310) |
Jun
(434) |
Jul
(171) |
Aug
(73) |
Sep
(187) |
Oct
(132) |
Nov
(259) |
Dec
(292) |
| 2009 |
Jan
(27) |
Feb
(54) |
Mar
(35) |
Apr
(54) |
May
(93) |
Jun
(10) |
Jul
(36) |
Aug
(36) |
Sep
(93) |
Oct
(52) |
Nov
(45) |
Dec
(74) |
| 2010 |
Jan
(20) |
Feb
(120) |
Mar
(165) |
Apr
(101) |
May
(56) |
Jun
(12) |
Jul
(73) |
Aug
(306) |
Sep
(154) |
Oct
(82) |
Nov
(63) |
Dec
(42) |
| 2011 |
Jan
(176) |
Feb
(86) |
Mar
(199) |
Apr
(86) |
May
(237) |
Jun
(50) |
Jul
(26) |
Aug
(56) |
Sep
(42) |
Oct
(62) |
Nov
(62) |
Dec
(52) |
| 2012 |
Jan
(35) |
Feb
(33) |
Mar
(128) |
Apr
(152) |
May
(133) |
Jun
(21) |
Jul
(74) |
Aug
(423) |
Sep
(165) |
Oct
(129) |
Nov
(387) |
Dec
(276) |
| 2013 |
Jan
(105) |
Feb
(30) |
Mar
(130) |
Apr
(42) |
May
(60) |
Jun
(79) |
Jul
(101) |
Aug
(46) |
Sep
(81) |
Oct
(14) |
Nov
(43) |
Dec
(4) |
| 2014 |
Jan
(25) |
Feb
(32) |
Mar
(30) |
Apr
(80) |
May
(42) |
Jun
(23) |
Jul
(68) |
Aug
(127) |
Sep
(112) |
Oct
(72) |
Nov
(29) |
Dec
(69) |
| 2015 |
Jan
(35) |
Feb
(49) |
Mar
(95) |
Apr
(10) |
May
(70) |
Jun
(64) |
Jul
(93) |
Aug
(85) |
Sep
(43) |
Oct
(38) |
Nov
(124) |
Dec
(29) |
| 2016 |
Jan
(253) |
Feb
(181) |
Mar
(132) |
Apr
(419) |
May
(68) |
Jun
(90) |
Jul
(52) |
Aug
(142) |
Sep
(131) |
Oct
(80) |
Nov
(84) |
Dec
(192) |
| 2017 |
Jan
(329) |
Feb
(842) |
Mar
(248) |
Apr
(85) |
May
(247) |
Jun
(186) |
Jul
(37) |
Aug
(73) |
Sep
(98) |
Oct
(108) |
Nov
(143) |
Dec
(143) |
| 2018 |
Jan
(155) |
Feb
(139) |
Mar
(72) |
Apr
(112) |
May
(82) |
Jun
(119) |
Jul
(24) |
Aug
(33) |
Sep
(179) |
Oct
(295) |
Nov
(111) |
Dec
(34) |
| 2019 |
Jan
(20) |
Feb
(29) |
Mar
(49) |
Apr
(89) |
May
(185) |
Jun
(131) |
Jul
(9) |
Aug
(59) |
Sep
(30) |
Oct
(44) |
Nov
(118) |
Dec
(53) |
| 2020 |
Jan
(70) |
Feb
(108) |
Mar
(50) |
Apr
(9) |
May
(70) |
Jun
(24) |
Jul
(103) |
Aug
(82) |
Sep
(132) |
Oct
(119) |
Nov
(174) |
Dec
(169) |
| 2021 |
Jan
(75) |
Feb
(51) |
Mar
(76) |
Apr
(73) |
May
(53) |
Jun
(120) |
Jul
(114) |
Aug
(73) |
Sep
(70) |
Oct
(18) |
Nov
(26) |
Dec
|
| 2022 |
Jan
(26) |
Feb
(63) |
Mar
(64) |
Apr
(64) |
May
(48) |
Jun
(74) |
Jul
(129) |
Aug
(106) |
Sep
(238) |
Oct
(169) |
Nov
(149) |
Dec
(111) |
| 2023 |
Jan
(110) |
Feb
(47) |
Mar
(82) |
Apr
(106) |
May
(168) |
Jun
(101) |
Jul
(155) |
Aug
(35) |
Sep
(51) |
Oct
(55) |
Nov
(134) |
Dec
(202) |
| 2024 |
Jan
(103) |
Feb
(129) |
Mar
(154) |
Apr
(89) |
May
(60) |
Jun
(162) |
Jul
(201) |
Aug
(61) |
Sep
(167) |
Oct
(111) |
Nov
(133) |
Dec
(141) |
| 2025 |
Jan
(122) |
Feb
(88) |
Mar
(106) |
Apr
(113) |
May
(203) |
Jun
(185) |
Jul
(124) |
Aug
(202) |
Sep
(176) |
Oct
(206) |
Nov
(259) |
Dec
(276) |
| 2026 |
Jan
(207) |
Feb
(180) |
Mar
(303) |
Apr
(326) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Alan <ala...@gm...> - 2026-04-26 23:29:52
|
Hi, New release v1.0.1 available: https://github.com/AlaoPrado/voo/releases/tag/v1.0.1! There is now a migration guide in https://github.com/AlaoPrado/voo/blob/main/MIGRATION.md. Furthermore, the README.md file was updated to provide new guidelines along the sections, and general coding guidelines for VOO in https://github.com/AlaoPrado/voo/blob/main/MIGRATION.md <https://github.com/AlaoPrado/voo/blob/main/MIGRATION.md>. Kind Regards, Alan On Thu, Apr 16, 2026 at 9:00 PM Alan <ala...@gm...> wrote: > Hi Rene, > > Ok. Thanks for the feedback. I'm going to review the documentation for the > suggested points of improvement. It might be worth to have a side-by-side > equivalent table between different patterns of existing frameworks (e.g.: > TclOO, Tk). > > Few comments below: > - The "next" command alone without any parameter might require some > additional instrospection for recovering the method name and parameter. > This can be possible, but I need to review the performance bottleneck. It > might be more eficient to call `[class.parent]::<method_name> <args>` > instead. > - Instead o cget a config, voo has get.<field>, set.<field>, and > update.<name> for managing field. > - The default value for each field is defined when declaring de field with > <type>_t commands. > > Kind Regards, > Alan > > Em qui., 16 de abr. de 2026 08:46, Zaumseil René <RZa...@kk...> > escreveu: > >> Hi Alan >> >> >> >> I have to figure out the github fork thing. >> >> I'm currently also in adding/changing parts of ruff! and adopting my >> documentation style. >> >> So I'm not experimenting with your VOO in the next time. >> >> >> >> A special "next" method would be fine. Alternatively you could mention >> the calling of <parent_class_ns>::<method_name> in the docs. >> >> >> >> For object configuration a cget/configure out of the box would be fine. >> >> May be with support of "option default" and tk-like "option dbclass >> dbname default". >> >> You could use the option name as method name like in my tko. >> >> >> >> And a compare list of features of tcloo and voo with examples would also >> be nice. >> >> >> >> HTH >> >> rene >> >> >> >> *Von:* Alan <ala...@gm...> >> *Gesendet:* Donnerstag, 16. April 2026 13:30 >> *An:* Zaumseil René <RZa...@kk...> >> *Cc:* Arjen Markus via Tcl-Core <tcl...@li...> >> *Betreff:* Re: [Ext] [TCLCORE] Vanilla Object Orientation (VOO): A >> Value-Semantics Approach to Classes in Tcl >> >> >> >> Hi Zaumseil, >> >> >> >> Thanks! >> >> >> >> In case parent class an method is virtual, you can call >> <parent_class_ns>::base.<method_name> to call orginal method. You can call >> any <parent_class_ns>::<method_name> anyway. There could be a >> [class.parent] to get <parent_class_ns> easily. I'm thinking about the >> perfomance cost of implementing a [class.next] (or a potentially >> non-ambiguous alternative name) for automatially returning >> <parent_class_ns>::<method_name> or the base.<method_name> variant in case >> of virtual... >> >> >> >> What do you think? Would you like to start some experiments on your side? >> Feel free to fork and open a PR on main repository. >> >> >> >> Kind Regards, >> >> Alan. >> >> >> >> Em qui., 16 de abr. de 2026 06:41, Zaumseil René <RZa...@kk...> >> escreveu: >> >> Hi Alan >> >> >> >> This looks impresing. >> >> >> >> I remember another tcl proc oo system at: >> thedev.nhi1.de/theLib/main/index.htm >> >> May be you could some ideas from this one. >> >> >> >> I currently miss the "next" method from tcloo. Is there a workaround for >> this one? >> >> >> >> Regards >> >> Rene >> >> >> >> *Von:* Alan <ala...@gm...> >> *Gesendet:* Mittwoch, 15. April 2026 21:47 >> *An:* Arjen Markus via Tcl-Core <tcl...@li...> >> *Betreff:* [Ext] [TCLCORE] Vanilla Object Orientation (VOO): A >> Value-Semantics Approach to Classes in Tcl >> >> >> >> Hi folks, >> >> >> >> I'm glad to announce VOO, a lightweight, native, and efficient, OO >> framework for Tcl. It follows a Value-Semantics approach instead of the >> traditional reference-by-procedure of other frameworks (TclOO, Itcl, etc). >> This brings interesting advantages w.r.t. both scalability and >> maintainability of Tcl projects. >> >> >> >> I'd like to hear from you all what you think about the implementation and >> results, and if it makes sense to have its package available in the default >> packages shipped with Tcl, or in tcllib. Its source code is fully written >> in Tcl, so it is easy to integrate it into any demo project for local >> experiments. >> >> >> >> Below you can find the abstract, the link for the white paper and the >> link for the code repository. >> >> >> >> *Abstract* >> >> *I present Vanilla Object Orientation (VOO), a framework that composes >> classes from Tcl's native data structures -- lists and dictionaries -- >> rather than introducing additional framework infrastructure. VOO objects >> are plain Tcl lists with automatic memory management through copy-on-write >> semantics, eliminating the destructor burden inherent in TclOO and Itcl. >> Benchmarks on Tcl 8.6.13 and Tcl 9.0 show VOO achieves 7--18x faster object >> creation and 4--6x superior memory efficiency compared to TclOO. A >> companion C++ migration path (VOO C++) further improves field-access speed >> (setter 2.3--2.6x faster) and memory (6.8--9.8x lighter than TclOO), while >> preserving an identical Tcl call-site API. Cross-version analysis confirms >> that VOO's compositional design scales better than framework-based >> approaches as the interpreter evolves.* >> >> >> >> *Lisks* >> >> White Paper: https://arxiv.org/abs/2604.10399 >> >> Code Repository: https://github.com/AlaoPrado/voo >> >> >> >> Thanks, and Kind Regards, >> >> Alan >> >> |
|
From: Donal F. <don...@ma...> - 2026-04-26 11:03:07
|
Hi everyone This is a call for votes on two self-contained TIPs that I've been sitting on for far too long. TIP 735: Simpler List Filtering<https://core.tcl-lang.org/tips/doc/trunk/tip/735.md> This adds a global lfilter command, because the current idiom for filtering out items of a list (when lsearch -inline -all -not can't do it) is weird. I've tried using an expression for the filter (that was the initial version of the TIP but not the current one), which works but feels more annoying to me than using a script (with expressions available by calling expr). I can be talked round to doing this the other way, but the current way is marginally simpler to implement (on the interpreted side; the compiled version is pretty much identically complex). TIP 745: Functions from C99<https://core.tcl-lang.org/tips/doc/trunk/tip/745.md> This imports virtually all the remaining math functions from C99<https://en.cppreference.com/w/c/numeric/math.html> into Tcl, pretty much as-is (bearing in mind that some "return" multiple values, which maps differently in Tcl; see below) with most just going into the ::tcl::mathfunc namespace and so having limited global impact. Implementation bugs in the functions' C implementations are exactly bugs in the corresponding Tcl functions; I do not propose we reimplement them (except for signbit, which is extended to directly cover all Tcl numeric values). NB: Introduces four new global commands for the multiple-value-returners: divmod, frexp, modf, remquo. They don't sit nicely as standard functions. Implementation branches exist for both TIPs (tip-735<https://core.tcl-lang.org/tcl/timeline?r=tip-735>, c11-functions<https://core.tcl-lang.org/tcl/timeline?r=c11-functions>). Votes in the standard form to this mailing list. Vote closes at 12:00 my time, 4 May 2026, [clock format 1777892400]. My votes follow: TIP 735: YES TIP 745: YES Donal. |
|
From: KEITH N. <k.j...@us...> - 2026-04-26 09:16:02
|
Hi All, Version 2.1.0 of package starkit is available, including documentation and tests. https://chiselapp.com/user/kjnash/repository/Starkit/home The package goals are to: 1. enable zip-based starkits that can be executed by a Tcl 9 installation or by a "tclkit" (zipkit) 2. provide the same facilities for zip-based starkits that version 1.3.3 of starkit package provides for mk4 (Metakit) starkits 3. make porting from mk4 starkits as easy as possible * if its code is Tcl-9-compatible, unwrapping the mk4 starkit and rewrapping it in zip format will suffice 4. run mk4 starkits without modification if their code is Tcl-9-compatible * EITHER the Tcl 9 installation or Tclkit must provide dynamic libraries for vlerq and vfs * OR starkit will use the included package readkit (which still has bugs) to unwrap the mk4 archive 5. preserve the tclkit + starkit format as a distribution mechanism for Tcl applications All that is needed to make Tcl 9 compatible with zip-based starkits is to provide the starkit library (29kB source, 17kB if comments stripped, plus 20kB if readkit is needed for mk4 packages). The starkit package could be included in the tcl_library. I would be willing to write a TIP for this if it is wanted. A few issues to discuss first: * Are starkit facilities still wanted? I use them in my own work, but they seem to have lost popularity over the last 20 years. * Are the goals/features listed above suitable? For example, the package could be smaller and simpler if mk4 compatibility is not required. * The library is derived from starkit package version 1.3.3 by JCW, which did not have a license statement. Will this matter? * Version 2 of the starkit package is compatible with Tcl 9.0 upwards, because it uses Tcl's zipfs facilities. Which version of Tcl should the TIP target? Keith. |
|
From: Phillip B. <phi...@um...> - 2026-04-26 05:40:31
|
I have checked into the main branch the Windows makefile changes needed for ARM64 cross compilation and removal of the x86_64-w64-mingw32-nmakehlp.exe binary from the fossil source tree. Let me know if you see any issues. ARM64 cross compilation also now works on x86 machines for the following projects on the main trunk: tcl, tk, itcl, tdbc, tdbcsqlite3, tdbcodbc, tdbcpostgres, tdbcmysql, thread As before, cross compilation requires that a native x86 tclsh shell be identified with the TCLSH_NATIVE environment variable. That value is now also used to identify the location of an nmakehlp.exe executable in the same install tree as TCLSH_NATIVE assuming that if .../bin/tclsh? is the location of the Tcl shell, the .../lib/nmake/nmakehlp.exe is the location of the nmakehlp executable to be used for cross compilation. If that is not the case, then the NMAKEHLP_NATIVE environment variable can be set explicitly for the cross compilation build. The sqlite3 project still needs to be updated, I hope we can get to that in the next few days. I have a question for the release managers - will all of the above projects be released from main for the June Tcl/Tk 9.1 beta build? I want to make sure that I don't have to worry about x86_64-w64-mingw32-nmakehlp.exe binaries in the signed Windows release build project that I am working on for the 9.1 Windows binary release. The checkins for each project have this comment: Remove x86_64-w64-mingw32-nmakehlp.exe. In its place, use the NMAKEHLP_NATIVE variable to find an nmakehlp.exe during cross compilation. If you are aware of any other projects that contain the file x86_64-w64-mingw32-nmakehlp.exe let me know, especially if they would be useful in the Tcl/Tk 9.1 signed release for Windows. Phil |
|
From: Kevin W. <kw...@co...> - 2026-04-26 02:29:11
|
<html class="apple-mail-supports-explicit-dark-mode"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">One additional note. There are two remaining bugs with bidi text on Tk X11 that we probably need to document as known issues that cannot be corrected at this time:. <div><br></div><div> 1. Harfbuzz badly renders CJK fonts with spacing that is too tight. Christian Werner has reported this, and I can reproduce it. This appears to be an upstream bug in Harfbuzz that will not be addressed: <a href="https://github.com/harfbuzz/harfbuzz/issues/4651?utm_source=copilot.com">https://github.com/harfbuzz/harfbuzz/issues/4651</a></div><div><br></div><div> 2. RTL text gets subtly darker when I click the cursor through it then gets lighter when the cursor leaves. This is probably an upstream Xft drawing bug involving partial vs. full redraws in the XRender pipeline. I am not aware of a solution. </div><div><br></div><div>-Kevin<br id="lineBreakAtBeginningOfSignature"><div dir="ltr"><div>—</div>Kevin Walzer kw...@co...</div><div dir="ltr"><br><blockquote type="cite">On Apr 25, 2026, at 7:33 PM, Kevin Walzer <kw...@co...> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><span>Quick update:</span><br><span></span><br><span>1. I have modified "configure" to run "--enable-bidi" by default on X11. Bidi support is already the default on macOS and Windows.</span><br><span></span><br><span>2. I've spent a couple of days working on updating the test suite. I've modified six or seven tests to recognize different results because of the internal changes to bidi, set a win32 constraint on one test, and made a few tweaks to C code.</span><br><span></span><br><span>I think this is as good as I can make it, and I'd like to request some testing. I will be AFK next week for work, so this will give everyone some time to review the changes.</span><br><span></span><br><span>-Kevin</span><br><span></span><br><span>On 4/24/26 9:23 AM, Kevin Walzer wrote:</span><br><blockquote type="cite"><span>The test failures may come later IMHO. Of cause, it is important.</span><br></blockquote><blockquote type="cite"><span>But I would prefer first a comment by other experts, if they agree with the proposed change. </span><br></blockquote><span></span><br><span>-- </span><br><span>Kevin Walzer kw...@co...</span><br><span></span><br><span></span><br><span></span><br><span>_______________________________________________</span><br><span>Tcl-Core mailing list</span><br><span>Tcl...@li...</span><br><span>https://lists.sourceforge.net/lists/listinfo/tcl-core</span><br></div></blockquote></div></body></html> |
|
From: Kevin W. <kw...@co...> - 2026-04-25 23:32:51
|
Quick update: 1. I have modified "configure" to run "--enable-bidi" by default on X11. Bidi support is already the default on macOS and Windows. 2. I've spent a couple of days working on updating the test suite. I've modified six or seven tests to recognize different results because of the internal changes to bidi, set a win32 constraint on one test, and made a few tweaks to C code. I think this is as good as I can make it, and I'd like to request some testing. I will be AFK next week for work, so this will give everyone some time to review the changes. -Kevin On 4/24/26 9:23 AM, Kevin Walzer wrote: > The test failures may come later IMHO. Of cause, it is important. > But I would prefer first a comment by other experts, if they agree > with the proposed change. -- Kevin Walzer kw...@co... |
|
From: Marc C. <cul...@gm...> - 2026-04-24 22:16:53
|
I have just pushed a change to the implementation of TIP 750, and I will shortly update the text of the TIP. Those who have already voted need to be aware of this. The change is that the implementation now fully supports the "auto" value for the appearance attribute of a toplevel on Windows. Specifically: 1) The default value of the appearance attribute is now "auto". 2) When a new toplevel is created (with appearance "auto") it will be displayed with the light or dark theme as specified by the AppsUseLightTheme Registry variable, which can be set from the system Settings app. 3) When the value of that setting is changed, all "auto" toplevels will be re-rendered with the new choice of theme. For example, if the user has a tool like "Light Switch" that automatically changes to dark mode at a certain time, all "auto" toplevels will switch to having black title bars when the change occurs. 4} A toplevel with appearance "light" or "dark" has opted to override the system setting, and it will not change color when the Settings variable toggles between light and dark. 5) When an "auto" toplevel changes theme as a result of a change to the value of AppsUseLightTheme, e.g. by choosing "dark" in the Settings, it will receive a virtual event <<AppearanceChanged>> with data string "appearance light" or "appearance dark" as appropriate for the new theme. This should allow a Tk app to support dark mode in its window content by changing the color palette within the binding script for that virtual event. I anticipate that someday more fields will be added to the data string, for example specifying accent colors. But this TIP only relates to the light and dark themes. Emiliano has kindly tested the latest version on Windows 10 and reports that it works. I have tested on Windows 11 with the same report. - Marc |
|
From: <av...@lo...> - 2026-04-24 21:53:06
|
Now at least 11 ;-) See you in ... uhm ... Bologna ... > We are looking forward to meeting you in Bologna. > > Many thanks, > The Organization Committee ... seems like a relict from last year (in the welcome Mail after reg). Not yet sure about doing a short talk, maybe, if slots are still vacant lateron... -- avl Am 2026-04-24 11:42, schrieb Harald Oehlmann: > Dear Tcl/Tk team members, > > The OpenACS/TCL/Tk user meeting in Vienna 16/17th of July 2026 will > take place. We just had the wrap-up call. 10 people registered, mainly > from Tcl/Tk side. So, the critical mass is reached. > > https://openacs.km.at > > It is a community meeting. Each participant is motivated to show its > work in a small presentation. And we will have the panels about > Tcl/Tk/Naviserver/OpenACS. > The location is the same great cosy room at the University of Economics > as in 2024. > Newcomers are also invited. Helpful people and information will be > there! > > So, feel welcomed to the great meeting. > > See you in July in Vienna! > > Gustaf, Stefan and Harald > > _______________________________________________ > Tcl-Core mailing list > Tcl...@li... > https://lists.sourceforge.net/lists/listinfo/tcl-core |
|
From: B H. <bra...@gm...> - 2026-04-24 19:28:53
|
Hello Tclers. I've been working in Tk, specifically w image, and would like run a proposal passed Core. In struct Tk_ImageType, generic/tk.h L1257 there is a "char *reserved", which was last updated by Brent Welch nearly 30 (c. 1998) years ago, is semantically marked as a placeholder for some future expansion, and as far as i can tell, not actually referenced anywhere. Proposal: can we take this and formally give it to developers as a ClientData clientData entry in the struct? As far as i can tell, it would functionally be a documentation update, not breaking any public APIs or ABIs. Best, -bch |
|
From: EricT <tw...@gm...> - 2026-04-24 13:50:41
|
Yes, you are right about the drawback to using tcl::unsupported::assemble.
That is certainly the Achilles heel of my little Calc project. But I'm only
in it for the subs and likes, anyway. However, I do notice I have 0
followers and 0 likes on my github page😭
It will likely be quite difficult to get that assembler made public. On the
other hand, it sure seems like a waste of 4400 lines of great code, not to
mention another 1600 lines or so in the disassembly.
I'm not sure if vecTCL would benefit or not, but that was also mentioned in
the telco.
Now that the frenzy is dying down, how about you. Did you really debug your
code just using printf? You should have plenty of time now getting VS 2026
installed and then you would see how super their debugger for C is. I used
it to find the code that was doing pointer arithmetic across tokens that
caused my $(...) code to crash. I can't imagine finding that with just
printf.
Anyway, good luck with your project.
Eric
On Fri, Apr 24, 2026 at 3:39 AM Florent Merlet <flo...@gm...>
wrote:
> Hi Eric,
> I ve noticed at bytecodes analysis that inst_invoke_stk has a cost while
> building list.
>
> The correction is to create a "LIST" lexeme, to set it instead of FUNC,
> then emit the list bytecodes inst while compiling the tree.
> Then I can remove this list FUNC from table of math FUNC. I was planning
> to do it.
>
> But, this is a question of optimisation, that can be seen later, if ever
> the proposal become a TIP.
>
> Build : I saw a TIP about encoding and wish.exe.manifest.in, from Ashok.
> Surely he can say something about this.
> I must clean tclVar.c. There is no change in this file, since i dismissed
> array index expr shorthand.
>
> You are saying you follow this direction, because you want it to be
> independant from the core. But, finally, you have to ask for a core change,
> because it would be too slow without bytecodes compilation.
>
> So in fact, you can't be independant from the core, also.
>
> Yes, the possibility to generate bytecodes could serve many purposes (and
> my proposal is still on the table) but the core team people said, they want
> to be free to refactor it if they need to.
>
> If you rely on it, you may loose compatibility at any time. That would be
> a problem also.
>
> So, your proposal, done to be "independant from the core" is shown to be
> "dependant on the core", in a contradiction with your initial intention.
>
> Maybe the only solution for you is to produce native code ? Would it be
> possible with critcl ?
>
> Regards,
> Florent.
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> Le ven. 24 avr. 2026, 11:16, EricT <tw...@gm...> a écrit :
>
>> Hi Florent,
>>
>> On your three points:
>>
>> 1. The timerate example -- timerate is a development and benchmarking tool, not production code. And actually the [: ...] inline form does not need to start on its own line at all, so the side by side comparison is straightforward:
>>
>> proc= test {x y} {
>> puts orig:[timerate {list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]}]
>> puts colon:[timerate {[: list(x-10,x+20,y-20,y+20)]}]
>> }
>>
>> The : standalone statement form does need to be on its own line, which is a deliberate tradeoff -- no full Tcl parser, no surgery on the existing one, no TIP, no requiring consensus from programmers all over the world. Completely optional -- if one person uses it, everyone else is entirely unaffected.
>>
>> 2. Of course proc= adds a new command -- it is a module, not a core change. Every package ever written adds new commands. The real question is whether those commands require a TIP and core team consensus, and mine do not.
>>
>> But I notice your approach also adds a new command -- list as a mathfunc in BuiltinFuncDef. Unlike proc= which is optional and only affects those who load the module, your list addition is a permanent core modification that affects every Tcl program. And it is slower -- your list(1,2,3) generates:
>>
>> push "tcl::mathfunc::list"
>> invokeStk n
>>
>> whereas my list() generates the direct list bytecode instruction -- no push of a fully qualified name, no command dispatch at all. The core modification buys you worse performance.
>>
>> 3. Your inline flexibility with for, foreach, if, switch, eval is a genuine advantage of your approach. But the transformation cost of proc= is negligible and happens only once at program startup when the procs are defined -- much like sourcing any Tcl file, or namespace eval which evaluates a script in a particular context. Nobody argues that namespace eval is a bad pattern because it requires wrapping code in a block.
>>
>> Also, my module works in 8.6 and 9.x now. I don't have to build tcl from a modified source.
>>
>> BTW, I can't run your static wish/tclsh exe's because I don't have the compiler you use.
>>
>> I was unable to get your tk to build something about a wish.exe.manifest.in. Also, you had an unused variable "len" in TclLookupArrayElement which tripped the warnings are errors on my build. After fixing that I could run your code in tclsh.
>>
>>
>> Best regards,
>> Eric
>>
>>
>>
>> On Fri, Apr 24, 2026 at 12:27 AM Florent Merlet <
>> flo...@gm...> wrote:
>>
>>> Ok.
>>>
>>> Notice that my proposal doesn't need any new command named 'proc='.
>>>
>>> I can just do :
>>> proc test {x y} {
>>> puts orig:[timerate {list [ .... ]}]
>>> puts shorthand:[timerate {( ... )}]
>>> }
>>> to compare two bytecodes.
>>>
>>> can you do this with your proposal ?
>>>
>>> proc test {x y} {
>>> puts orig:[timerate {list [ .... ]}]
>>> puts colon:[timerate {: ... }]
>>> }
>>>
>>>
>>> If i want to compile a whole proc as expression, i can do :
>>>
>>> proc p args {( ... )}
>>>
>>> How will you get this effect with your proposal ?
>>>
>>> proc p args {: { ... }}
>>> proc= p args { ... }
>>>
>>> The last one is 1 char shorther, but need a new command.
>>>
>>> With my proposal, you can do :
>>> eval {( .... )}
>>> for {( .... )} {....} {( .... )} {( .... )}
>>> If { } then {( .... )} else {( .... )}
>>> Switch $a { case {( .... )} default {( .... )} }
>>> Foreach i $L {( .... )}
>>> Lmap j $K {( .... )}
>>> ... Etc
>>> And get it bytecompiled with the expression parser where there is
>>> parenthesis.
>>>
>>> Can your proposal do this ?
>>>
>>> Regards,
>>> Florent
>>>
>>>
>>>
>>> Le ven. 24 avr. 2026, 07:42, EricT <tw...@gm...> a écrit :
>>>
>>>> Hi Florent,
>>>>
>>>> The ugliness of my test case was simply my uncertainty about how timerate works. After Serg's clarification I realized that transform= can handle : inside a timerate block as long as the : command starts on its own line. My transform= is not a full Tcl parser -- it uses 5 or 6 regexps and doesn't count brace nesting levels -- so I accept that compromise. Here is the cleaner test Serg suggested:
>>>>
>>>> % proc= test {x y} {
>>>> timerate {
>>>> : list(x-10,x+20,y-20,y+20)
>>>> }
>>>> }
>>>> % test 5 20
>>>> 0.260845 µs/# 3833681 #/sec 999.997 net-ms
>>>>
>>>> % proc test2 {x y} {
>>>> timerate {
>>>> list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
>>>> }
>>>> }
>>>> % test2 5 10
>>>> 0.253317 µs/# 3947624 #/sec 1000.000 net-ms
>>>>
>>>> Essentially identical -- and the disassembly confirms why: both produce exactly the same bytecode.
>>>>
>>>> As for why I used an infix expression compiler rather than extending expr -- two reasons. First, Colin had already written a beautiful pure Tcl Pratt parser that I could build on immediately. Second, at the time I had no understanding of how bytecode and the assembler worked, so using Colin's compiler as a front end to generate TAL was the obvious path. It turned out to be a fortunate choice since it required no core changes at all.
>>>>
>>>> Regarding your bytecode interface proposal -- I think you may be underestimating the scope of what tclAssembly.c actually does. The parser touch points you list are just the entry points. The 4400 lines handle label resolution, stack depth verification, LVT management, exception range tracking, operand encoding, and error reporting for 130+ opcodes. That infrastructure already exists and works -- which is exactly why I am arguing for a public interface to it rather than new parser syntax on top of it.
>>>>
>>>> Best regards,
>>>> Eric
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Thu, Apr 23, 2026 at 9:53 PM Florent Merlet <
>>>> flo...@gm...> wrote:
>>>>
>>>>> Hi Eric,
>>>>>
>>>>> my computer is more than 15 years old...
>>>>> You may try with the tcl there :
>>>>>
>>>>> https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
>>>>> to check with your own machine.
>>>>>
>>>>> Le 24/04/2026 à 00:11, EricT a écrit :
>>>>>
>>>>> timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] "
>>>>> ;# 0 0 = non-proc3.
>>>>>
>>>>> Beauty is in the eye of the beholder... This last point should be
>>>>> obvious.
>>>>>
>>>>> For me :
>>>>> % timerate {($x-10, $x+20, $y-20, $y+20)}
>>>>>
>>>>> is obviously more beautifull than :
>>>>>
>>>>> % timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0]
>>>>> "
>>>>>
>>>>> There will never be a consensus on what syntax is best.
>>>>>
>>>>> A syntax is just an apparence, a shape. It's an interface to something
>>>>> deeper (for instance : bytecode).
>>>>> The goal of an interface is to make easy to work with a toolset.
>>>>>
>>>>> Command interface is well suited to work with list of strings. (Tk
>>>>> beauty and concision)
>>>>> But it is not well suited to work with numbers (operators as command
>>>>> are rarely used).
>>>>>
>>>>> For numbers, Tcl propose an expr interface. Why not use it ?
>>>>>
>>>>> I didn't choose the syntax in expr interface. I'm not fond of dollars
>>>>> signs for variable, but I accept it as it is.
>>>>>
>>>>> It is from all Tcl, as well as '[ ]' substitution.
>>>>>
>>>>> So, I don't want espacially to propose a new syntax (even if I must
>>>>> have one to achieve the proposal),
>>>>> I choosed [(y=$x;)], but it could have been also : ≺y=$x;≻ or ⎨ y
>>>>> =$x; ⎬ or ⟦ y = $x⟧ or ⟪ y = $x; ⟫
>>>>>
>>>>> I want to suggest a principle.
>>>>>
>>>>> In Tcl, there is 2 parsing interfaces :
>>>>> * a command parsing interface, more convenient for strings and lists
>>>>> (using *a prefix notation*)
>>>>> * an expression parsing interface, more convenient for numbers and
>>>>> assignement (using *an infix notation*)
>>>>>
>>>>> These 2 interfaces should be of equal right, so we can choose the more
>>>>> convenient for a task to be done.
>>>>>
>>>>> To do so, I needed to achieve two things here :
>>>>> * expression substitution, to get a value from the infix parsing
>>>>> interface
>>>>> * expression script signalisation, to signal when a script must be
>>>>> compiled with the infix parsing interface
>>>>>
>>>>> Then, I can get the better of this two worlds. This, in less than 260
>>>>> lines of code !
>>>>>
>>>>> There is already 4400 lines of C code in generic/tclAssembly.c that as
>>>>> far as I can tell is used only to assist in the debugging of new bytecode.
>>>>>
>>>>> If I'm wrong, please tell me since that would provide another reason
>>>>> to provide a public interface to tcl::unsupported::assemble. I have used
>>>>> the Tcl assemble command to produce performance par with expr without
>>>>> modification to the core. Other's could make use of a public interface as
>>>>> well. Then many design specific languages (DSL) could be built upon Tcl
>>>>> with high performance.
>>>>>
>>>>> Yes, Assemble bytecode is proposing its own interface, in "*postfix
>>>>> notation*".
>>>>>
>>>>> On this matter, we can adopt exactly the same principles I adopted
>>>>> above to resolve it.
>>>>> We need :
>>>>> * Bytecode substitution : e.g. => [! ... !]
>>>>> * Bytecode script signalisation : e.g. => {! ... !}
>>>>>
>>>>> set a [! load x, push 10, sub; load x, push 20, add; load y, push 20,
>>>>> sub; load y, push 20, add; list 4 !]
>>>>>
>>>>> proc A {} {!
>>>>> load x, push 10, sub load x, push 20, add load y, push 20, sub load
>>>>> y, push 20, add list 4
>>>>> !}
>>>>>
>>>>> To achieve this, it should be very similar with as what I did for the
>>>>> expr shorthand, in exactly the same codes location (except the ones
>>>>> specific to expr, of course)
>>>>> * Just need a TCL_TOKEN_BYTECODE in the parser
>>>>> * recognize the syntax :
>>>>> ** in ParseCommand
>>>>> ** in ParseToken
>>>>> * route correctly the compilation int TclCompileScript.
>>>>> * route correctly the compilation int TclSetBytecodefromAny.
>>>>> * Do what it has be done with this TOKEN
>>>>> ** in TclSubstToken
>>>>> ** in TclCompileToken
>>>>> That's all !
>>>>>
>>>>> This proposal is very interesting : We could even get the better of
>>>>> three worlds !
>>>>>
>>>>> That said, this "*postfix notation*" interface is not the more
>>>>> convenient for the Job. As you know, *Infix notation* is better here :
>>>>>
>>>>> set a [($x+20, $x-20, $y+20, $y-20 )]
>>>>> proc A {} {($x+20, $x-20, $y+20, $y-20)}
>>>>>
>>>>> At the end, you will have to create your own code to translate from
>>>>> your new and expr-like interface to this new bytecode interface.
>>>>> That is what you did.
>>>>>
>>>>> Then, this question arise : why not just have used the expr interface
>>>>> from the begining ?
>>>>>
>>>>>
>>>>> Regards,
>>>>> Florent
>>>>> _______________________________________________
>>>>> Tcl-Core mailing list
>>>>> Tcl...@li...
>>>>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>>>>
>>>> _______________________________________________
>>> Tcl-Core mailing list
>>> Tcl...@li...
>>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>>
>> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
|
|
From: Kevin W. <kw...@co...> - 2026-04-24 13:23:47
|
Hi Harald, On 4/24/26 7:41 AM, Harald Oehlmann wrote: > thanks for all the work, this is highly appreciated. > I suppose, that the branch rtl_text is ready for testing: > > https://core.tcl-lang.org/tk/timeline?r=rtl_text&c=2026-04-23+12%3A05%3A22 > Almost. I am reviewing the test failures to determine what the issues might be. I don't want to cause regressions with bidi text in addressing the test failures - looking into the test suite is part of making sure the bidi changes are as stable as I can make them. One known bug that I can't fix - CJK text spacing is still too tight in the text widget when mixed with other encodings (Latin/RTL). > > It is only about the text widget, right? Correct. > > It would be great to give other experts a week of time to digest. > Christian and Csaba understand the internals, Jan and Emiliano are > also in. Maybe, they may comment. Agree - when I am satisfied it is as stable as I can make it, I want as much input as possible. > > The test failures may come later IMHO. Of cause, it is important. > But I would prefer first a comment by other experts, if they agree > with the proposed change. See above. > > I would really love to have this feature in 9.1. We don't need a TIP. > But it is for sure a breaking feature which solves a long standing > miss-functioning. As I have recently observed with font and rotation, > bug fixes may create new bugs found years after... > > If it may be the default on Linux: "yes of cause", says the Windows > guy. AFAI understood, there are new dependencies to the "harfbuzz" > library. So, the question is, if this dependency is ok. > Con't we test by the configure script, if this dependency is ok? > Some distribution people? Reinhard? As part of testing, I will set up configure to make bidi the default on X11 - so simply running "configure" will activate both bidi and Xft. Harfbuzz is not a niche library, it is as widely installed as dbus or Xlib, so I don't believe it will present an issue. But let's see what others think. I'll send out a formal invitation for testing soon. > > Thanks for all and take care, > Harald > Thank you, Kevin -- Kevin Walzer kw...@co... |
|
From: Harald O. <har...@el...> - 2026-04-24 11:41:32
|
Dear Kevin, thanks for all the work, this is highly appreciated. I suppose, that the branch rtl_text is ready for testing: https://core.tcl-lang.org/tk/timeline?r=rtl_text&c=2026-04-23+12%3A05%3A22 It is only about the text widget, right? It would be great to give other experts a week of time to digest. Christian and Csaba understand the internals, Jan and Emiliano are also in. Maybe, they may comment. The test failures may come later IMHO. Of cause, it is important. But I would prefer first a comment by other experts, if they agree with the proposed change. I would really love to have this feature in 9.1. We don't need a TIP. But it is for sure a breaking feature which solves a long standing miss-functioning. As I have recently observed with font and rotation, bug fixes may create new bugs found years after... If it may be the default on Linux: "yes of cause", says the Windows guy. AFAI understood, there are new dependencies to the "harfbuzz" library. So, the question is, if this dependency is ok. Con't we test by the configure script, if this dependency is ok? Some distribution people? Reinhard? Thanks for all and take care, Harald Am 24.04.2026 um 02:50 schrieb Kevin Walzer: > Hello, > > I am continuing to work on improving Tk's support for bidi/RTL text in > the rtl_text branch. Here is the latest: > > 1. Users can now click through RTL text (such as Arabic or Hebrew) > without the visual glitches we saw before (glyphs getting wrenched into > LTR position during cursor movement). > > 2. Key to this was defining the following: > > #define TK_LAYOUT_WITH_BASE_CHUNKS 1 > #define TK_DRAW_IN_CONTEXT 1 > > This triggered the specific blocks in Tk's text widget code that drew an > entire line of text and considered that in measuring and rendering. Many > of the required hooks were already present, but additional modifications > of the platform-specific code (to call the platform-specific API's) and > tkTextDisp.c (to provide the text widget calls) were required to support > this. > > 3. These changes initially caused segfaults and hangs on X11 and > Windows. Further modifications to tkTextDisp.c were necessary, and these > required separate branches for Windows and X11 code to ensure stability > on both platforms. Things are now running without crashes, in my testing. > > 4. Because there have been numerous updates, some of the tests in > textDisp.test are now failing. There seems to be some variation across > platforms. What is the best way to address this? Because the bidi text > work is complex, I do not want to revert any of those updates just to > ensure that a test passes. Nor do I simply want to skip the test. I > would appreciate some advice on how to proceed here. > > 5. The final question I am looking at is whether to make bidi the > default across all platforms, including X11. I had planned not to, but > now that the final major issue (visual glitches in cursor movement) is > close to being addressed, I am reconsidering this. I know it's getting > close of the release of 9.1, but I do not see a compelling reason to NOT > make bidi the default mode at this point assuming others' testing > confirms stability and effectiveness. > > For what it's worth, Xft was added to X11 twenty-some years ago without > a TIP, so I do not believe it's required here, either. > > Thanks for your input. > > - Kevin > |
|
From: Florent M. <flo...@gm...> - 2026-04-24 10:38:52
|
Hi Eric,
I ve noticed at bytecodes analysis that inst_invoke_stk has a cost while
building list.
The correction is to create a "LIST" lexeme, to set it instead of FUNC,
then emit the list bytecodes inst while compiling the tree.
Then I can remove this list FUNC from table of math FUNC. I was planning to
do it.
But, this is a question of optimisation, that can be seen later, if ever
the proposal become a TIP.
Build : I saw a TIP about encoding and wish.exe.manifest.in, from Ashok.
Surely he can say something about this.
I must clean tclVar.c. There is no change in this file, since i dismissed
array index expr shorthand.
You are saying you follow this direction, because you want it to be
independant from the core. But, finally, you have to ask for a core change,
because it would be too slow without bytecodes compilation.
So in fact, you can't be independant from the core, also.
Yes, the possibility to generate bytecodes could serve many purposes (and
my proposal is still on the table) but the core team people said, they want
to be free to refactor it if they need to.
If you rely on it, you may loose compatibility at any time. That would be a
problem also.
So, your proposal, done to be "independant from the core" is shown to be
"dependant on the core", in a contradiction with your initial intention.
Maybe the only solution for you is to produce native code ? Would it be
possible with critcl ?
Regards,
Florent.
Le ven. 24 avr. 2026, 11:16, EricT <tw...@gm...> a écrit :
> Hi Florent,
>
> On your three points:
>
> 1. The timerate example -- timerate is a development and benchmarking tool, not production code. And actually the [: ...] inline form does not need to start on its own line at all, so the side by side comparison is straightforward:
>
> proc= test {x y} {
> puts orig:[timerate {list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]}]
> puts colon:[timerate {[: list(x-10,x+20,y-20,y+20)]}]
> }
>
> The : standalone statement form does need to be on its own line, which is a deliberate tradeoff -- no full Tcl parser, no surgery on the existing one, no TIP, no requiring consensus from programmers all over the world. Completely optional -- if one person uses it, everyone else is entirely unaffected.
>
> 2. Of course proc= adds a new command -- it is a module, not a core change. Every package ever written adds new commands. The real question is whether those commands require a TIP and core team consensus, and mine do not.
>
> But I notice your approach also adds a new command -- list as a mathfunc in BuiltinFuncDef. Unlike proc= which is optional and only affects those who load the module, your list addition is a permanent core modification that affects every Tcl program. And it is slower -- your list(1,2,3) generates:
>
> push "tcl::mathfunc::list"
> invokeStk n
>
> whereas my list() generates the direct list bytecode instruction -- no push of a fully qualified name, no command dispatch at all. The core modification buys you worse performance.
>
> 3. Your inline flexibility with for, foreach, if, switch, eval is a genuine advantage of your approach. But the transformation cost of proc= is negligible and happens only once at program startup when the procs are defined -- much like sourcing any Tcl file, or namespace eval which evaluates a script in a particular context. Nobody argues that namespace eval is a bad pattern because it requires wrapping code in a block.
>
> Also, my module works in 8.6 and 9.x now. I don't have to build tcl from a modified source.
>
> BTW, I can't run your static wish/tclsh exe's because I don't have the compiler you use.
>
> I was unable to get your tk to build something about a wish.exe.manifest.in. Also, you had an unused variable "len" in TclLookupArrayElement which tripped the warnings are errors on my build. After fixing that I could run your code in tclsh.
>
>
> Best regards,
> Eric
>
>
>
> On Fri, Apr 24, 2026 at 12:27 AM Florent Merlet <flo...@gm...>
> wrote:
>
>> Ok.
>>
>> Notice that my proposal doesn't need any new command named 'proc='.
>>
>> I can just do :
>> proc test {x y} {
>> puts orig:[timerate {list [ .... ]}]
>> puts shorthand:[timerate {( ... )}]
>> }
>> to compare two bytecodes.
>>
>> can you do this with your proposal ?
>>
>> proc test {x y} {
>> puts orig:[timerate {list [ .... ]}]
>> puts colon:[timerate {: ... }]
>> }
>>
>>
>> If i want to compile a whole proc as expression, i can do :
>>
>> proc p args {( ... )}
>>
>> How will you get this effect with your proposal ?
>>
>> proc p args {: { ... }}
>> proc= p args { ... }
>>
>> The last one is 1 char shorther, but need a new command.
>>
>> With my proposal, you can do :
>> eval {( .... )}
>> for {( .... )} {....} {( .... )} {( .... )}
>> If { } then {( .... )} else {( .... )}
>> Switch $a { case {( .... )} default {( .... )} }
>> Foreach i $L {( .... )}
>> Lmap j $K {( .... )}
>> ... Etc
>> And get it bytecompiled with the expression parser where there is
>> parenthesis.
>>
>> Can your proposal do this ?
>>
>> Regards,
>> Florent
>>
>>
>>
>> Le ven. 24 avr. 2026, 07:42, EricT <tw...@gm...> a écrit :
>>
>>> Hi Florent,
>>>
>>> The ugliness of my test case was simply my uncertainty about how timerate works. After Serg's clarification I realized that transform= can handle : inside a timerate block as long as the : command starts on its own line. My transform= is not a full Tcl parser -- it uses 5 or 6 regexps and doesn't count brace nesting levels -- so I accept that compromise. Here is the cleaner test Serg suggested:
>>>
>>> % proc= test {x y} {
>>> timerate {
>>> : list(x-10,x+20,y-20,y+20)
>>> }
>>> }
>>> % test 5 20
>>> 0.260845 µs/# 3833681 #/sec 999.997 net-ms
>>>
>>> % proc test2 {x y} {
>>> timerate {
>>> list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
>>> }
>>> }
>>> % test2 5 10
>>> 0.253317 µs/# 3947624 #/sec 1000.000 net-ms
>>>
>>> Essentially identical -- and the disassembly confirms why: both produce exactly the same bytecode.
>>>
>>> As for why I used an infix expression compiler rather than extending expr -- two reasons. First, Colin had already written a beautiful pure Tcl Pratt parser that I could build on immediately. Second, at the time I had no understanding of how bytecode and the assembler worked, so using Colin's compiler as a front end to generate TAL was the obvious path. It turned out to be a fortunate choice since it required no core changes at all.
>>>
>>> Regarding your bytecode interface proposal -- I think you may be underestimating the scope of what tclAssembly.c actually does. The parser touch points you list are just the entry points. The 4400 lines handle label resolution, stack depth verification, LVT management, exception range tracking, operand encoding, and error reporting for 130+ opcodes. That infrastructure already exists and works -- which is exactly why I am arguing for a public interface to it rather than new parser syntax on top of it.
>>>
>>> Best regards,
>>> Eric
>>>
>>>
>>>
>>>
>>>
>>> On Thu, Apr 23, 2026 at 9:53 PM Florent Merlet <
>>> flo...@gm...> wrote:
>>>
>>>> Hi Eric,
>>>>
>>>> my computer is more than 15 years old...
>>>> You may try with the tcl there :
>>>>
>>>> https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
>>>> to check with your own machine.
>>>>
>>>> Le 24/04/2026 à 00:11, EricT a écrit :
>>>>
>>>> timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] "
>>>> ;# 0 0 = non-proc3.
>>>>
>>>> Beauty is in the eye of the beholder... This last point should be
>>>> obvious.
>>>>
>>>> For me :
>>>> % timerate {($x-10, $x+20, $y-20, $y+20)}
>>>>
>>>> is obviously more beautifull than :
>>>>
>>>> % timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] "
>>>>
>>>> There will never be a consensus on what syntax is best.
>>>>
>>>> A syntax is just an apparence, a shape. It's an interface to something
>>>> deeper (for instance : bytecode).
>>>> The goal of an interface is to make easy to work with a toolset.
>>>>
>>>> Command interface is well suited to work with list of strings. (Tk
>>>> beauty and concision)
>>>> But it is not well suited to work with numbers (operators as command
>>>> are rarely used).
>>>>
>>>> For numbers, Tcl propose an expr interface. Why not use it ?
>>>>
>>>> I didn't choose the syntax in expr interface. I'm not fond of dollars
>>>> signs for variable, but I accept it as it is.
>>>>
>>>> It is from all Tcl, as well as '[ ]' substitution.
>>>>
>>>> So, I don't want espacially to propose a new syntax (even if I must
>>>> have one to achieve the proposal),
>>>> I choosed [(y=$x;)], but it could have been also : ≺y=$x;≻ or ⎨ y =$x;
>>>> ⎬ or ⟦ y = $x⟧ or ⟪ y = $x; ⟫
>>>>
>>>> I want to suggest a principle.
>>>>
>>>> In Tcl, there is 2 parsing interfaces :
>>>> * a command parsing interface, more convenient for strings and lists
>>>> (using *a prefix notation*)
>>>> * an expression parsing interface, more convenient for numbers and
>>>> assignement (using *an infix notation*)
>>>>
>>>> These 2 interfaces should be of equal right, so we can choose the more
>>>> convenient for a task to be done.
>>>>
>>>> To do so, I needed to achieve two things here :
>>>> * expression substitution, to get a value from the infix parsing
>>>> interface
>>>> * expression script signalisation, to signal when a script must be
>>>> compiled with the infix parsing interface
>>>>
>>>> Then, I can get the better of this two worlds. This, in less than 260
>>>> lines of code !
>>>>
>>>> There is already 4400 lines of C code in generic/tclAssembly.c that as
>>>> far as I can tell is used only to assist in the debugging of new bytecode.
>>>>
>>>> If I'm wrong, please tell me since that would provide another reason to
>>>> provide a public interface to tcl::unsupported::assemble. I have used the
>>>> Tcl assemble command to produce performance par with expr without
>>>> modification to the core. Other's could make use of a public interface as
>>>> well. Then many design specific languages (DSL) could be built upon Tcl
>>>> with high performance.
>>>>
>>>> Yes, Assemble bytecode is proposing its own interface, in "*postfix
>>>> notation*".
>>>>
>>>> On this matter, we can adopt exactly the same principles I adopted
>>>> above to resolve it.
>>>> We need :
>>>> * Bytecode substitution : e.g. => [! ... !]
>>>> * Bytecode script signalisation : e.g. => {! ... !}
>>>>
>>>> set a [! load x, push 10, sub; load x, push 20, add; load y, push 20,
>>>> sub; load y, push 20, add; list 4 !]
>>>>
>>>> proc A {} {!
>>>> load x, push 10, sub load x, push 20, add load y, push 20, sub load y,
>>>> push 20, add list 4
>>>> !}
>>>>
>>>> To achieve this, it should be very similar with as what I did for the
>>>> expr shorthand, in exactly the same codes location (except the ones
>>>> specific to expr, of course)
>>>> * Just need a TCL_TOKEN_BYTECODE in the parser
>>>> * recognize the syntax :
>>>> ** in ParseCommand
>>>> ** in ParseToken
>>>> * route correctly the compilation int TclCompileScript.
>>>> * route correctly the compilation int TclSetBytecodefromAny.
>>>> * Do what it has be done with this TOKEN
>>>> ** in TclSubstToken
>>>> ** in TclCompileToken
>>>> That's all !
>>>>
>>>> This proposal is very interesting : We could even get the better of
>>>> three worlds !
>>>>
>>>> That said, this "*postfix notation*" interface is not the more
>>>> convenient for the Job. As you know, *Infix notation* is better here :
>>>>
>>>> set a [($x+20, $x-20, $y+20, $y-20 )]
>>>> proc A {} {($x+20, $x-20, $y+20, $y-20)}
>>>>
>>>> At the end, you will have to create your own code to translate from
>>>> your new and expr-like interface to this new bytecode interface.
>>>> That is what you did.
>>>>
>>>> Then, this question arise : why not just have used the expr interface
>>>> from the begining ?
>>>>
>>>>
>>>> Regards,
>>>> Florent
>>>> _______________________________________________
>>>> Tcl-Core mailing list
>>>> Tcl...@li...
>>>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>>>
>>> _______________________________________________
>> Tcl-Core mailing list
>> Tcl...@li...
>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>
>
|
|
From: Harald O. <har...@el...> - 2026-04-24 09:43:08
|
Dear Tcl/Tk team members, The OpenACS/TCL/Tk user meeting in Vienna 16/17th of July 2026 will take place. We just had the wrap-up call. 10 people registered, mainly from Tcl/Tk side. So, the critical mass is reached. https://openacs.km.at It is a community meeting. Each participant is motivated to show its work in a small presentation. And we will have the panels about Tcl/Tk/Naviserver/OpenACS. The location is the same great cosy room at the University of Economics as in 2024. Newcomers are also invited. Helpful people and information will be there! So, feel welcomed to the great meeting. See you in July in Vienna! Gustaf, Stefan and Harald |
|
From: EricT <tw...@gm...> - 2026-04-24 09:16:23
|
Hi Florent,
On your three points:
1. The timerate example -- timerate is a development and benchmarking
tool, not production code. And actually the [: ...] inline form does
not need to start on its own line at all, so the side by side
comparison is straightforward:
proc= test {x y} {
puts orig:[timerate {list [expr {$x-10}] [expr {$x+20}] [expr
{$y-20}] [expr {$y+20}]}]
puts colon:[timerate {[: list(x-10,x+20,y-20,y+20)]}]
}
The : standalone statement form does need to be on its own line, which
is a deliberate tradeoff -- no full Tcl parser, no surgery on the
existing one, no TIP, no requiring consensus from programmers all over
the world. Completely optional -- if one person uses it, everyone else
is entirely unaffected.
2. Of course proc= adds a new command -- it is a module, not a core
change. Every package ever written adds new commands. The real
question is whether those commands require a TIP and core team
consensus, and mine do not.
But I notice your approach also adds a new command -- list as a
mathfunc in BuiltinFuncDef. Unlike proc= which is optional and only
affects those who load the module, your list addition is a permanent
core modification that affects every Tcl program. And it is slower --
your list(1,2,3) generates:
push "tcl::mathfunc::list"
invokeStk n
whereas my list() generates the direct list bytecode instruction -- no
push of a fully qualified name, no command dispatch at all. The core
modification buys you worse performance.
3. Your inline flexibility with for, foreach, if, switch, eval is a
genuine advantage of your approach. But the transformation cost of
proc= is negligible and happens only once at program startup when the
procs are defined -- much like sourcing any Tcl file, or namespace
eval which evaluates a script in a particular context. Nobody argues
that namespace eval is a bad pattern because it requires wrapping code
in a block.
Also, my module works in 8.6 and 9.x now. I don't have to build tcl
from a modified source.
BTW, I can't run your static wish/tclsh exe's because I don't have the
compiler you use.
I was unable to get your tk to build something about a
wish.exe.manifest.in. Also, you had an unused variable "len" in
TclLookupArrayElement which tripped the warnings are errors on my
build. After fixing that I could run your code in tclsh.
Best regards,
Eric
On Fri, Apr 24, 2026 at 12:27 AM Florent Merlet <flo...@gm...>
wrote:
> Ok.
>
> Notice that my proposal doesn't need any new command named 'proc='.
>
> I can just do :
> proc test {x y} {
> puts orig:[timerate {list [ .... ]}]
> puts shorthand:[timerate {( ... )}]
> }
> to compare two bytecodes.
>
> can you do this with your proposal ?
>
> proc test {x y} {
> puts orig:[timerate {list [ .... ]}]
> puts colon:[timerate {: ... }]
> }
>
>
> If i want to compile a whole proc as expression, i can do :
>
> proc p args {( ... )}
>
> How will you get this effect with your proposal ?
>
> proc p args {: { ... }}
> proc= p args { ... }
>
> The last one is 1 char shorther, but need a new command.
>
> With my proposal, you can do :
> eval {( .... )}
> for {( .... )} {....} {( .... )} {( .... )}
> If { } then {( .... )} else {( .... )}
> Switch $a { case {( .... )} default {( .... )} }
> Foreach i $L {( .... )}
> Lmap j $K {( .... )}
> ... Etc
> And get it bytecompiled with the expression parser where there is
> parenthesis.
>
> Can your proposal do this ?
>
> Regards,
> Florent
>
>
>
> Le ven. 24 avr. 2026, 07:42, EricT <tw...@gm...> a écrit :
>
>> Hi Florent,
>>
>> The ugliness of my test case was simply my uncertainty about how timerate works. After Serg's clarification I realized that transform= can handle : inside a timerate block as long as the : command starts on its own line. My transform= is not a full Tcl parser -- it uses 5 or 6 regexps and doesn't count brace nesting levels -- so I accept that compromise. Here is the cleaner test Serg suggested:
>>
>> % proc= test {x y} {
>> timerate {
>> : list(x-10,x+20,y-20,y+20)
>> }
>> }
>> % test 5 20
>> 0.260845 µs/# 3833681 #/sec 999.997 net-ms
>>
>> % proc test2 {x y} {
>> timerate {
>> list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
>> }
>> }
>> % test2 5 10
>> 0.253317 µs/# 3947624 #/sec 1000.000 net-ms
>>
>> Essentially identical -- and the disassembly confirms why: both produce exactly the same bytecode.
>>
>> As for why I used an infix expression compiler rather than extending expr -- two reasons. First, Colin had already written a beautiful pure Tcl Pratt parser that I could build on immediately. Second, at the time I had no understanding of how bytecode and the assembler worked, so using Colin's compiler as a front end to generate TAL was the obvious path. It turned out to be a fortunate choice since it required no core changes at all.
>>
>> Regarding your bytecode interface proposal -- I think you may be underestimating the scope of what tclAssembly.c actually does. The parser touch points you list are just the entry points. The 4400 lines handle label resolution, stack depth verification, LVT management, exception range tracking, operand encoding, and error reporting for 130+ opcodes. That infrastructure already exists and works -- which is exactly why I am arguing for a public interface to it rather than new parser syntax on top of it.
>>
>> Best regards,
>> Eric
>>
>>
>>
>>
>>
>> On Thu, Apr 23, 2026 at 9:53 PM Florent Merlet <flo...@gm...>
>> wrote:
>>
>>> Hi Eric,
>>>
>>> my computer is more than 15 years old...
>>> You may try with the tcl there :
>>> https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
>>> to check with your own machine.
>>>
>>> Le 24/04/2026 à 00:11, EricT a écrit :
>>>
>>> timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] " ;#
>>> 0 0 = non-proc3.
>>>
>>> Beauty is in the eye of the beholder... This last point should be
>>> obvious.
>>>
>>> For me :
>>> % timerate {($x-10, $x+20, $y-20, $y+20)}
>>>
>>> is obviously more beautifull than :
>>>
>>> % timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] "
>>>
>>> There will never be a consensus on what syntax is best.
>>>
>>> A syntax is just an apparence, a shape. It's an interface to something
>>> deeper (for instance : bytecode).
>>> The goal of an interface is to make easy to work with a toolset.
>>>
>>> Command interface is well suited to work with list of strings. (Tk
>>> beauty and concision)
>>> But it is not well suited to work with numbers (operators as command are
>>> rarely used).
>>>
>>> For numbers, Tcl propose an expr interface. Why not use it ?
>>>
>>> I didn't choose the syntax in expr interface. I'm not fond of dollars
>>> signs for variable, but I accept it as it is.
>>>
>>> It is from all Tcl, as well as '[ ]' substitution.
>>>
>>> So, I don't want espacially to propose a new syntax (even if I must have
>>> one to achieve the proposal),
>>> I choosed [(y=$x;)], but it could have been also : ≺y=$x;≻ or ⎨ y =$x;
>>> ⎬ or ⟦ y = $x⟧ or ⟪ y = $x; ⟫
>>>
>>> I want to suggest a principle.
>>>
>>> In Tcl, there is 2 parsing interfaces :
>>> * a command parsing interface, more convenient for strings and lists
>>> (using *a prefix notation*)
>>> * an expression parsing interface, more convenient for numbers and
>>> assignement (using *an infix notation*)
>>>
>>> These 2 interfaces should be of equal right, so we can choose the more
>>> convenient for a task to be done.
>>>
>>> To do so, I needed to achieve two things here :
>>> * expression substitution, to get a value from the infix parsing
>>> interface
>>> * expression script signalisation, to signal when a script must be
>>> compiled with the infix parsing interface
>>>
>>> Then, I can get the better of this two worlds. This, in less than 260
>>> lines of code !
>>>
>>> There is already 4400 lines of C code in generic/tclAssembly.c that as
>>> far as I can tell is used only to assist in the debugging of new bytecode.
>>>
>>> If I'm wrong, please tell me since that would provide another reason to
>>> provide a public interface to tcl::unsupported::assemble. I have used the
>>> Tcl assemble command to produce performance par with expr without
>>> modification to the core. Other's could make use of a public interface as
>>> well. Then many design specific languages (DSL) could be built upon Tcl
>>> with high performance.
>>>
>>> Yes, Assemble bytecode is proposing its own interface, in "*postfix
>>> notation*".
>>>
>>> On this matter, we can adopt exactly the same principles I adopted above
>>> to resolve it.
>>> We need :
>>> * Bytecode substitution : e.g. => [! ... !]
>>> * Bytecode script signalisation : e.g. => {! ... !}
>>>
>>> set a [! load x, push 10, sub; load x, push 20, add; load y, push 20,
>>> sub; load y, push 20, add; list 4 !]
>>>
>>> proc A {} {!
>>> load x, push 10, sub load x, push 20, add load y, push 20, sub load y,
>>> push 20, add list 4
>>> !}
>>>
>>> To achieve this, it should be very similar with as what I did for the
>>> expr shorthand, in exactly the same codes location (except the ones
>>> specific to expr, of course)
>>> * Just need a TCL_TOKEN_BYTECODE in the parser
>>> * recognize the syntax :
>>> ** in ParseCommand
>>> ** in ParseToken
>>> * route correctly the compilation int TclCompileScript.
>>> * route correctly the compilation int TclSetBytecodefromAny.
>>> * Do what it has be done with this TOKEN
>>> ** in TclSubstToken
>>> ** in TclCompileToken
>>> That's all !
>>>
>>> This proposal is very interesting : We could even get the better of
>>> three worlds !
>>>
>>> That said, this "*postfix notation*" interface is not the more
>>> convenient for the Job. As you know, *Infix notation* is better here :
>>>
>>> set a [($x+20, $x-20, $y+20, $y-20 )]
>>> proc A {} {($x+20, $x-20, $y+20, $y-20)}
>>>
>>> At the end, you will have to create your own code to translate from your
>>> new and expr-like interface to this new bytecode interface.
>>> That is what you did.
>>>
>>> Then, this question arise : why not just have used the expr interface
>>> from the begining ?
>>>
>>>
>>> Regards,
>>> Florent
>>> _______________________________________________
>>> Tcl-Core mailing list
>>> Tcl...@li...
>>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>>
>> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
|
|
From: Florent M. <flo...@gm...> - 2026-04-24 07:27:16
|
Ok.
Notice that my proposal doesn't need any new command named 'proc='.
I can just do :
proc test {x y} {
puts orig:[timerate {list [ .... ]}]
puts shorthand:[timerate {( ... )}]
}
to compare two bytecodes.
can you do this with your proposal ?
proc test {x y} {
puts orig:[timerate {list [ .... ]}]
puts colon:[timerate {: ... }]
}
If i want to compile a whole proc as expression, i can do :
proc p args {( ... )}
How will you get this effect with your proposal ?
proc p args {: { ... }}
proc= p args { ... }
The last one is 1 char shorther, but need a new command.
With my proposal, you can do :
eval {( .... )}
for {( .... )} {....} {( .... )} {( .... )}
If { } then {( .... )} else {( .... )}
Switch $a { case {( .... )} default {( .... )} }
Foreach i $L {( .... )}
Lmap j $K {( .... )}
... Etc
And get it bytecompiled with the expression parser where there is
parenthesis.
Can your proposal do this ?
Regards,
Florent
Le ven. 24 avr. 2026, 07:42, EricT <tw...@gm...> a écrit :
> Hi Florent,
>
> The ugliness of my test case was simply my uncertainty about how timerate works. After Serg's clarification I realized that transform= can handle : inside a timerate block as long as the : command starts on its own line. My transform= is not a full Tcl parser -- it uses 5 or 6 regexps and doesn't count brace nesting levels -- so I accept that compromise. Here is the cleaner test Serg suggested:
>
> % proc= test {x y} {
> timerate {
> : list(x-10,x+20,y-20,y+20)
> }
> }
> % test 5 20
> 0.260845 µs/# 3833681 #/sec 999.997 net-ms
>
> % proc test2 {x y} {
> timerate {
> list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
> }
> }
> % test2 5 10
> 0.253317 µs/# 3947624 #/sec 1000.000 net-ms
>
> Essentially identical -- and the disassembly confirms why: both produce exactly the same bytecode.
>
> As for why I used an infix expression compiler rather than extending expr -- two reasons. First, Colin had already written a beautiful pure Tcl Pratt parser that I could build on immediately. Second, at the time I had no understanding of how bytecode and the assembler worked, so using Colin's compiler as a front end to generate TAL was the obvious path. It turned out to be a fortunate choice since it required no core changes at all.
>
> Regarding your bytecode interface proposal -- I think you may be underestimating the scope of what tclAssembly.c actually does. The parser touch points you list are just the entry points. The 4400 lines handle label resolution, stack depth verification, LVT management, exception range tracking, operand encoding, and error reporting for 130+ opcodes. That infrastructure already exists and works -- which is exactly why I am arguing for a public interface to it rather than new parser syntax on top of it.
>
> Best regards,
> Eric
>
>
>
>
>
> On Thu, Apr 23, 2026 at 9:53 PM Florent Merlet <flo...@gm...>
> wrote:
>
>> Hi Eric,
>>
>> my computer is more than 15 years old...
>> You may try with the tcl there :
>> https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
>> to check with your own machine.
>>
>> Le 24/04/2026 à 00:11, EricT a écrit :
>>
>> timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] " ;#
>> 0 0 = non-proc3.
>>
>> Beauty is in the eye of the beholder... This last point should be obvious.
>>
>> For me :
>> % timerate {($x-10, $x+20, $y-20, $y+20)}
>>
>> is obviously more beautifull than :
>>
>> % timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] "
>>
>> There will never be a consensus on what syntax is best.
>>
>> A syntax is just an apparence, a shape. It's an interface to something
>> deeper (for instance : bytecode).
>> The goal of an interface is to make easy to work with a toolset.
>>
>> Command interface is well suited to work with list of strings. (Tk beauty
>> and concision)
>> But it is not well suited to work with numbers (operators as command are
>> rarely used).
>>
>> For numbers, Tcl propose an expr interface. Why not use it ?
>>
>> I didn't choose the syntax in expr interface. I'm not fond of dollars
>> signs for variable, but I accept it as it is.
>>
>> It is from all Tcl, as well as '[ ]' substitution.
>>
>> So, I don't want espacially to propose a new syntax (even if I must have
>> one to achieve the proposal),
>> I choosed [(y=$x;)], but it could have been also : ≺y=$x;≻ or ⎨ y =$x; ⎬
>> or ⟦ y = $x⟧ or ⟪ y = $x; ⟫
>>
>> I want to suggest a principle.
>>
>> In Tcl, there is 2 parsing interfaces :
>> * a command parsing interface, more convenient for strings and lists
>> (using *a prefix notation*)
>> * an expression parsing interface, more convenient for numbers and
>> assignement (using *an infix notation*)
>>
>> These 2 interfaces should be of equal right, so we can choose the more
>> convenient for a task to be done.
>>
>> To do so, I needed to achieve two things here :
>> * expression substitution, to get a value from the infix parsing interface
>> * expression script signalisation, to signal when a script must be
>> compiled with the infix parsing interface
>>
>> Then, I can get the better of this two worlds. This, in less than 260
>> lines of code !
>>
>> There is already 4400 lines of C code in generic/tclAssembly.c that as
>> far as I can tell is used only to assist in the debugging of new bytecode.
>>
>> If I'm wrong, please tell me since that would provide another reason to
>> provide a public interface to tcl::unsupported::assemble. I have used the
>> Tcl assemble command to produce performance par with expr without
>> modification to the core. Other's could make use of a public interface as
>> well. Then many design specific languages (DSL) could be built upon Tcl
>> with high performance.
>>
>> Yes, Assemble bytecode is proposing its own interface, in "*postfix
>> notation*".
>>
>> On this matter, we can adopt exactly the same principles I adopted above
>> to resolve it.
>> We need :
>> * Bytecode substitution : e.g. => [! ... !]
>> * Bytecode script signalisation : e.g. => {! ... !}
>>
>> set a [! load x, push 10, sub; load x, push 20, add; load y, push 20,
>> sub; load y, push 20, add; list 4 !]
>>
>> proc A {} {!
>> load x, push 10, sub load x, push 20, add load y, push 20, sub load y,
>> push 20, add list 4
>> !}
>>
>> To achieve this, it should be very similar with as what I did for the
>> expr shorthand, in exactly the same codes location (except the ones
>> specific to expr, of course)
>> * Just need a TCL_TOKEN_BYTECODE in the parser
>> * recognize the syntax :
>> ** in ParseCommand
>> ** in ParseToken
>> * route correctly the compilation int TclCompileScript.
>> * route correctly the compilation int TclSetBytecodefromAny.
>> * Do what it has be done with this TOKEN
>> ** in TclSubstToken
>> ** in TclCompileToken
>> That's all !
>>
>> This proposal is very interesting : We could even get the better of three
>> worlds !
>>
>> That said, this "*postfix notation*" interface is not the more
>> convenient for the Job. As you know, *Infix notation* is better here :
>>
>> set a [($x+20, $x-20, $y+20, $y-20 )]
>> proc A {} {($x+20, $x-20, $y+20, $y-20)}
>>
>> At the end, you will have to create your own code to translate from your
>> new and expr-like interface to this new bytecode interface.
>> That is what you did.
>>
>> Then, this question arise : why not just have used the expr interface
>> from the begining ?
>>
>>
>> Regards,
>> Florent
>> _______________________________________________
>> Tcl-Core mailing list
>> Tcl...@li...
>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>
>
|
|
From: EricT <tw...@gm...> - 2026-04-24 05:42:34
|
Hi Florent,
The ugliness of my test case was simply my uncertainty about how
timerate works. After Serg's clarification I realized that transform=
can handle : inside a timerate block as long as the : command starts
on its own line. My transform= is not a full Tcl parser -- it uses 5
or 6 regexps and doesn't count brace nesting levels -- so I accept
that compromise. Here is the cleaner test Serg suggested:
% proc= test {x y} {
timerate {
: list(x-10,x+20,y-20,y+20)
}
}
% test 5 20
0.260845 µs/# 3833681 #/sec 999.997 net-ms
% proc test2 {x y} {
timerate {
list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
}
}
% test2 5 10
0.253317 µs/# 3947624 #/sec 1000.000 net-ms
Essentially identical -- and the disassembly confirms why: both
produce exactly the same bytecode.
As for why I used an infix expression compiler rather than extending
expr -- two reasons. First, Colin had already written a beautiful pure
Tcl Pratt parser that I could build on immediately. Second, at the
time I had no understanding of how bytecode and the assembler worked,
so using Colin's compiler as a front end to generate TAL was the
obvious path. It turned out to be a fortunate choice since it required
no core changes at all.
Regarding your bytecode interface proposal -- I think you may be
underestimating the scope of what tclAssembly.c actually does. The
parser touch points you list are just the entry points. The 4400 lines
handle label resolution, stack depth verification, LVT management,
exception range tracking, operand encoding, and error reporting for
130+ opcodes. That infrastructure already exists and works -- which is
exactly why I am arguing for a public interface to it rather than new
parser syntax on top of it.
Best regards,
Eric
On Thu, Apr 23, 2026 at 9:53 PM Florent Merlet <flo...@gm...>
wrote:
> Hi Eric,
>
> my computer is more than 15 years old...
> You may try with the tcl there :
> https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
> to check with your own machine.
>
> Le 24/04/2026 à 00:11, EricT a écrit :
>
> timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] " ;# 0
> 0 = non-proc3.
>
> Beauty is in the eye of the beholder... This last point should be obvious.
>
> For me :
> % timerate {($x-10, $x+20, $y-20, $y+20)}
>
> is obviously more beautifull than :
>
> % timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] "
>
> There will never be a consensus on what syntax is best.
>
> A syntax is just an apparence, a shape. It's an interface to something
> deeper (for instance : bytecode).
> The goal of an interface is to make easy to work with a toolset.
>
> Command interface is well suited to work with list of strings. (Tk beauty
> and concision)
> But it is not well suited to work with numbers (operators as command are
> rarely used).
>
> For numbers, Tcl propose an expr interface. Why not use it ?
>
> I didn't choose the syntax in expr interface. I'm not fond of dollars
> signs for variable, but I accept it as it is.
>
> It is from all Tcl, as well as '[ ]' substitution.
>
> So, I don't want espacially to propose a new syntax (even if I must have
> one to achieve the proposal),
> I choosed [(y=$x;)], but it could have been also : ≺y=$x;≻ or ⎨ y =$x; ⎬
> or ⟦ y = $x⟧ or ⟪ y = $x; ⟫
>
> I want to suggest a principle.
>
> In Tcl, there is 2 parsing interfaces :
> * a command parsing interface, more convenient for strings and lists
> (using *a prefix notation*)
> * an expression parsing interface, more convenient for numbers and
> assignement (using *an infix notation*)
>
> These 2 interfaces should be of equal right, so we can choose the more
> convenient for a task to be done.
>
> To do so, I needed to achieve two things here :
> * expression substitution, to get a value from the infix parsing interface
> * expression script signalisation, to signal when a script must be
> compiled with the infix parsing interface
>
> Then, I can get the better of this two worlds. This, in less than 260
> lines of code !
>
> There is already 4400 lines of C code in generic/tclAssembly.c that as far
> as I can tell is used only to assist in the debugging of new bytecode.
>
> If I'm wrong, please tell me since that would provide another reason to
> provide a public interface to tcl::unsupported::assemble. I have used the
> Tcl assemble command to produce performance par with expr without
> modification to the core. Other's could make use of a public interface as
> well. Then many design specific languages (DSL) could be built upon Tcl
> with high performance.
>
> Yes, Assemble bytecode is proposing its own interface, in "*postfix
> notation*".
>
> On this matter, we can adopt exactly the same principles I adopted above
> to resolve it.
> We need :
> * Bytecode substitution : e.g. => [! ... !]
> * Bytecode script signalisation : e.g. => {! ... !}
>
> set a [! load x, push 10, sub; load x, push 20, add; load y, push 20,
> sub; load y, push 20, add; list 4 !]
>
> proc A {} {!
> load x, push 10, sub load x, push 20, add load y, push 20, sub load y,
> push 20, add list 4
> !}
>
> To achieve this, it should be very similar with as what I did for the expr
> shorthand, in exactly the same codes location (except the ones specific to
> expr, of course)
> * Just need a TCL_TOKEN_BYTECODE in the parser
> * recognize the syntax :
> ** in ParseCommand
> ** in ParseToken
> * route correctly the compilation int TclCompileScript.
> * route correctly the compilation int TclSetBytecodefromAny.
> * Do what it has be done with this TOKEN
> ** in TclSubstToken
> ** in TclCompileToken
> That's all !
>
> This proposal is very interesting : We could even get the better of three
> worlds !
>
> That said, this "*postfix notation*" interface is not the more convenient
> for the Job. As you know, *Infix notation* is better here :
>
> set a [($x+20, $x-20, $y+20, $y-20 )]
> proc A {} {($x+20, $x-20, $y+20, $y-20)}
>
> At the end, you will have to create your own code to translate from your
> new and expr-like interface to this new bytecode interface.
> That is what you did.
>
> Then, this question arise : why not just have used the expr interface from
> the begining ?
>
>
> Regards,
> Florent
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
|
|
From: Florent M. <flo...@gm...> - 2026-04-24 04:53:42
|
Hi Eric, my computer is more than 15 years old... You may try with the tcl there : https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH to check with your own machine. Le 24/04/2026 à 00:11, EricT a écrit : > timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] " > ;# 0 0 = non-proc3. > Beauty is in the eye of the beholder... This last point should be obvious. For me : % timerate {($x-10, $x+20, $y-20, $y+20)} is obviously more beautifull than : % timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0] " > There will never be a consensus on what syntax is best. A syntax is just an apparence, a shape. It's an interface to something deeper (for instance : bytecode). The goal of an interface is to make easy to work with a toolset. Command interface is well suited to work with list of strings. (Tk beauty and concision) But it is not well suited to work with numbers (operators as command are rarely used). For numbers, Tcl propose an expr interface. Why not use it ? I didn't choose the syntax in expr interface. I'm not fond of dollars signs for variable, but I accept it as it is. It is from all Tcl, as well as '[ ]' substitution. So, I don't want espacially to propose a new syntax (even if I must have one to achieve the proposal), I choosed [(y=$x;)], but it could have been also : ≺y=$x;≻ or ⎨ y =$x; ⎬ or ⟦ y = $x⟧ or ⟪ y = $x; ⟫ I want to suggest a principle. In Tcl, there is 2 parsing interfaces : * a command parsing interface, more convenient for strings and lists (using /a _prefix notation_/) * an expression parsing interface, more convenient for numbers and assignement (using /an _infix notation_/) These 2 interfaces should be of equal right, so we can choose the more convenient for a task to be done. To do so, I needed to achieve two things here : * expression substitution, to get a value from the infix parsing interface * expression script signalisation, to signal when a script must be compiled with the infix parsing interface Then, I can get the better of this two worlds. This, in less than 260 lines of code ! > There is already 4400 lines of C code in generic/tclAssembly.c that as > far as I can tell is used only to assist in the debugging of new > bytecode. > If I'm wrong, please tell me since that would provide another reason > to provide a public interface to tcl::unsupported::assemble. I have > used the Tcl assemble command to produce performance par with expr > without modification to the core. Other's could make use of a public > interface as well. Then many design specific languages (DSL) could be > built upon Tcl with high performance. Yes, Assemble bytecode is proposing its own interface, in "/_postfix notation_/". On this matter, we can adopt exactly the same principles I adopted above to resolve it. We need : * Bytecode substitution : e.g. => [! ... !] * Bytecode script signalisation : e.g. => {! ... !} set a [! load x, push 10, sub; load x, push 20, add; load y, push 20, sub; load y, push 20, add; list 4 !] proc A {} {! load x, push 10, sub load x, push 20, add load y, push 20, sub load y, push 20, add list 4 !} To achieve this, it should be very similar with as what I did for the expr shorthand, in exactly the same codes location (except the ones specific to expr, of course) * Just need a TCL_TOKEN_BYTECODE in the parser * recognize the syntax : ** in ParseCommand ** in ParseToken * route correctly the compilation int TclCompileScript. * route correctly the compilation int TclSetBytecodefromAny. * Do what it has be done with this TOKEN ** in TclSubstToken ** in TclCompileToken That's all ! This proposal is very interesting : We could even get the better of three worlds ! That said, this "/_postfix notation_/" interface is not the more convenient for the Job. As you know, /Infix notation/ is better here : set a [($x+20, $x-20, $y+20, $y-20 )] proc A {} {($x+20, $x-20, $y+20, $y-20)} At the end, you will have to create your own code to translate from your new and expr-like interface to this new bytecode interface. That is what you did. Then, this question arise : why not just have used the expr interface from the begining ? Regards, Florent |
|
From: EricT <tw...@gm...> - 2026-04-24 04:27:25
|
Serg,
Thank you again for the timerate tip. I tried to use your approach,
however, transform= cannot rewrite code inside a braced timerate block
since it's not a full tcl parser; another approach is to simply wrap
each version in its own proc and then timerate the proc calls:
proc= test {x y} {
: list(x-10,x+20,y-20,y+20)
}
proc test2 {x y} {
list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
}
timerate {test 5 10}
0.450080 µs/# 2221826 # 2221826 #/sec 1000.000 net-ms
timerate {test2 5 10}
0.474814 µs/# 2106085 # 2106087 #/sec 999.999 net-ms
But perhaps the most useful comparison is simply the disassembly. Both
produce identical bytecode -- 50 instructions, 2 literal objects, same
loadScalar/push/sub/add/list sequence throughout. The only differences
are the number of command boundaries (2 vs 5) and the source text size
(175 vs 70 bytes), the latter being slightly larger in the proc=
version since the original source is preserved for debugging purposes.
The executable bytecode is identical, and timerate confirms it.
Best regards,
Eric
% tcl::unsupported::disassemble proc test
ByteCode 0x295e052dcc0, refCt 1, epoch 23, interp 0x295dc374210 (epoch 23)
Source "\nif {0} { : list(x-10,x+20,y-20,y+20) } { tcl::uns..."
Cmds 2, src 175, inst 50, litObjs 2, aux 0, stkDepth 5, code/src 0.00
Proc 0x295e05a7a60, refCt 1, args 2, compiled locals 2
slot 0, scalar, arg, "x"
slot 1, scalar, arg, "y"
Commands 2:
1: pc 0-48, src 1-172 2: pc 0-48, src 46-171
Command 1: "if {0} { : list(x-10,x+20,y-20,y+20) } { tcl::unsup..."
Command 2: "tcl::unsupported::assemble {load x; push 10; sub; load ..."
(0) loadScalar %v0 # var "x"
(5) push 0 # "10"
(10) sub
(11) loadScalar %v0 # var "x"
(16) push 1 # "20"
(21) add
(22) loadScalar %v1 # var "y"
(27) push 1 # "20"
(32) sub
(33) loadScalar %v1 # var "y"
(38) push 1 # "20"
(43) add
(44) list 4
(49) done
% tcl::unsupported::disassemble proc test2
ByteCode 0x295e053d700, refCt 1, epoch 23, interp 0x295dc374210 (epoch 23)
Source "\n list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}]..."
Cmds 5, src 70, inst 50, litObjs 2, aux 0, stkDepth 5, code/src 0.00
Proc 0x295e05a88e0, refCt 1, args 2, compiled locals 2
slot 0, scalar, arg, "x"
slot 1, scalar, arg, "y"
Commands 5:
1: pc 0-48, src 5-68 2: pc 0-10, src 11-22
3: pc 11-21, src 26-37 4: pc 22-32, src 41-52
5: pc 33-43, src 56-67
Command 1: "list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr..."
Command 2: "expr {$x-10}..."
(0) loadScalar %v0 # var "x"
(5) push 0 # "10"
(10) sub
Command 3: "expr {$x+20}..."
(11) loadScalar %v0 # var "x"
(16) push 1 # "20"
(21) add
Command 4: "expr {$y-20}..."
(22) loadScalar %v1 # var "y"
(27) push 1 # "20"
(32) sub
Command 5: "expr {$y+20}..."
(33) loadScalar %v1 # var "y"
(38) push 1 # "20"
(43) add
(44) list 4
(49) done
On Thu, Apr 23, 2026 at 8:48 PM EricT <tw...@gm...> wrote:
> Serg,
>
> You are correct, and thank you for the clarification. My statement was
> imprecise.
>
> The transform= function has an inproc flag that tells it whether it is
> compiling code inside a proc context or not. When inproc is true, the
> peephole optimiser generates the `load` instruction for variable access,
> which requires a proc LVT context. When inproc is false it falls back to
> `push x; loadStk` which works anywhere. The proc= compiler correctly passes
> inproc=1, but transform= could in principle also be used for toplevel code
> with inproc=0.
>
> The reason I ran timerate at the toplevel was to compare apples with
> apples since Florent's benchmarks were also at the toplevel. Your approach
> of wrapping in a proc or apply is actually more informative since it shows
> the full potential — I was not aware that timerate itself could be used
> that way and the 5x difference between toplevel and proc is striking.
>
> Best regards,
> Eric
>
> On Thu, Apr 23, 2026 at 7:12 PM Dipl. Ing. Sergey G. Brester via Tcl-Core <
> tcl...@li...> wrote:
>
>> I did not followed the whole discussion and don't want express my opinion
>> again (basically I already said everything about this and similar sugar),
>> but...
>>
>> 24.04.2026 00:11, EricT wrote:
>>
>> timerate does not work in the context of a proc.
>>
>> This assumption is definitely not correct - timerate works in the context
>> of a proc pretty well, it'd even compile better in proc or lambda frame
>> (because Tcl will compile better there).
>>
>> % set x 10; set y 20; timerate {expr {$x + $y}}
>> 0.109328 µs/# 7046239 # 9146766 #/sec 770.353 net-ms
>> % apply {{x y} { timerate {expr {$x + $y}} }} 10 20
>> 0.021571 µs/# 18462900 # 46358096 #/sec 398.267 net-ms
>> % proc test {x y} { timerate {expr {$x + $y}} }; test 10 20
>> 0.021645 µs/# 18437793 # 46200049 #/sec 399.086 net-ms
>>
>> So it'd be probably your code that doesn't work in frame properly.
>>
>> Hope this helps,
>> Serg.
>> _______________________________________________
>> Tcl-Core mailing list
>> Tcl...@li...
>> https://lists.sourceforge.net/lists/listinfo/tcl-core
>>
>
|
|
From: EricT <tw...@gm...> - 2026-04-24 03:49:20
|
Serg,
You are correct, and thank you for the clarification. My statement was
imprecise.
The transform= function has an inproc flag that tells it whether it is
compiling code inside a proc context or not. When inproc is true, the
peephole optimiser generates the `load` instruction for variable access,
which requires a proc LVT context. When inproc is false it falls back to
`push x; loadStk` which works anywhere. The proc= compiler correctly passes
inproc=1, but transform= could in principle also be used for toplevel code
with inproc=0.
The reason I ran timerate at the toplevel was to compare apples with apples
since Florent's benchmarks were also at the toplevel. Your approach of
wrapping in a proc or apply is actually more informative since it shows the
full potential — I was not aware that timerate itself could be used that
way and the 5x difference between toplevel and proc is striking.
Best regards,
Eric
On Thu, Apr 23, 2026 at 7:12 PM Dipl. Ing. Sergey G. Brester via Tcl-Core <
tcl...@li...> wrote:
> I did not followed the whole discussion and don't want express my opinion
> again (basically I already said everything about this and similar sugar),
> but...
>
> 24.04.2026 00:11, EricT wrote:
>
> timerate does not work in the context of a proc.
>
> This assumption is definitely not correct - timerate works in the context
> of a proc pretty well, it'd even compile better in proc or lambda frame
> (because Tcl will compile better there).
>
> % set x 10; set y 20; timerate {expr {$x + $y}}
> 0.109328 µs/# 7046239 # 9146766 #/sec 770.353 net-ms
> % apply {{x y} { timerate {expr {$x + $y}} }} 10 20
> 0.021571 µs/# 18462900 # 46358096 #/sec 398.267 net-ms
> % proc test {x y} { timerate {expr {$x + $y}} }; test 10 20
> 0.021645 µs/# 18437793 # 46200049 #/sec 399.086 net-ms
>
> So it'd be probably your code that doesn't work in frame properly.
>
> Hope this helps,
> Serg.
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
|
|
From: Dipl. I. S. G. B. <se...@us...> - 2026-04-24 02:11:46
|
I did not followed the whole discussion and don't want express my
opinion again (basically I already said everything about this and
similar sugar), but...
24.04.2026 00:11, EricT wrote:
> timerate does not work in the context of a proc.
This assumption is definitely not correct - timerate works in the
context of a proc pretty well, it'd even compile better in proc or
lambda frame (because Tcl will compile better there).
% set x 10; set y 20; timerate {expr {$x + $y}}
0.109328 µs/# 7046239 # 9146766 #/sec 770.353 net-ms
% apply {{x y} { timerate {expr {$x + $y}} }} 10 20
0.021571 µs/# 18462900 # 46358096 #/sec 398.267 net-ms
% proc test {x y} { timerate {expr {$x + $y}} }; test 10 20
0.021645 µs/# 18437793 # 46200049 #/sec 399.086 net-ms
So it'd be probably your code that doesn't work in frame properly.
Hope this helps,
Serg. |
|
From: Kevin W. <kw...@co...> - 2026-04-24 00:50:52
|
Hello, I am continuing to work on improving Tk's support for bidi/RTL text in the rtl_text branch. Here is the latest: 1. Users can now click through RTL text (such as Arabic or Hebrew) without the visual glitches we saw before (glyphs getting wrenched into LTR position during cursor movement). 2. Key to this was defining the following: #define TK_LAYOUT_WITH_BASE_CHUNKS 1 #define TK_DRAW_IN_CONTEXT 1 This triggered the specific blocks in Tk's text widget code that drew an entire line of text and considered that in measuring and rendering. Many of the required hooks were already present, but additional modifications of the platform-specific code (to call the platform-specific API's) and tkTextDisp.c (to provide the text widget calls) were required to support this. 3. These changes initially caused segfaults and hangs on X11 and Windows. Further modifications to tkTextDisp.c were necessary, and these required separate branches for Windows and X11 code to ensure stability on both platforms. Things are now running without crashes, in my testing. 4. Because there have been numerous updates, some of the tests in textDisp.test are now failing. There seems to be some variation across platforms. What is the best way to address this? Because the bidi text work is complex, I do not want to revert any of those updates just to ensure that a test passes. Nor do I simply want to skip the test. I would appreciate some advice on how to proceed here. 5. The final question I am looking at is whether to make bidi the default across all platforms, including X11. I had planned not to, but now that the final major issue (visual glitches in cursor movement) is close to being addressed, I am reconsidering this. I know it's getting close of the release of 9.1, but I do not see a compelling reason to NOT make bidi the default mode at this point assuming others' testing confirms stability and effectiveness. For what it's worth, Xft was added to X11 twenty-some years ago without a TIP, so I do not believe it's required here, either. Thanks for your input. - Kevin -- Kevin Walzer kw...@co... |
|
From: EricT <tw...@gm...> - 2026-04-23 22:11:38
|
Florent, Yorick, and everyone:
Florent, I'm not sure why your times are so large, my cpu is over 10
years old, but since expr is the gold standard:
% : y = (x = 3*3.14)*2 ;# command name is a single colon :
18.84
% set x
9.42
% set y
18.84
timerate { list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr
{$y+20}]} ;# benchmark standard
0.439883 µs/# 2273332 # 2273332 #/sec 1000.000 net-ms
Below is when using the compiler for my : code, the first one fails
because it compiles for a proc environment, so I must specify not
inside a proc.
% timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 1 0]
" ;# 1 0 = proc
cannot use this instruction to create a variable in a non-proc context
% timerate " [Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0]
" ;# 0 0 = non-proc
0.430974 µs/# 2320322 # 2320324 #/sec 999.999 net-ms
A word of explanation.
timerate does not work in the context of a proc. My peephole optimizer
can do better inside of a proc, where the "load var;" bytecode is
permitted. Here are the outputs of the above two choices that timerate
actually tested (but one got the error):
% Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 0 0 ;# outside of a proc
tcl::unsupported::assemble {push x; loadStk; push 10; sub; push x; loadStk;
push 20; add; push y; loadStk; push 20; sub; push y; loadStk; push
20; add; list 4; }
% Calc::transform= {} {: list(x-10,x+20,y-20,y+20) } 1 0 ;# inside of a proc
tcl::unsupported::assemble {load x; push 10; sub; load x; push 20; add;
load y; push 20; sub; load y; push 20; add; list 4; }
The difference is that the peephole can fold "push x; loadStk;" ->
"load x;" which is faster but this is only permitted inside a proc
environment (or a method).
What has become apparent from our 3 proposals this last year,
$(...) jimtcl (mine)
[= ....] Colin's
[(...)] Florent's
is that all 3 are doomed because they require changes to the core.
Each requires a TIP. The difficulty with making changes to the core
are these:
1. One size does NOT fit all in Tcl
2. Performance counts
3. Beauty is in the eye of the beholder
This last point should be obvious. In Colin's = command, I prefer to
use the : character and I also prefer to have a function named "list",
rather than an empty function name as Florent's proposal.
One size does NOT fit all!
There will never be a consensus on what syntax is best. Thus there
needs to be a way to achieve performance, while allowing for different
proposals to be implemented by the users themselves - outside of the
core.
Yorick is right. It is far better to leave the core alone and code in
pure tcl. However, as was discussed in the last telco,
The machinery to extend the language should improve.
-> there is no interface to bytecode extension.
-> due to that missing, "=" must go to the core.
-> C invocation from the bytecode compiler is slow.
However, the answer is in plain sight:
There is already 4400 lines of C code in generic/tclAssembly.c that as
far as I can tell is used only to assist in the debugging of new
bytecode. If I'm wrong, please tell me since that would provide
another reason to provide a public interface to
tcl::unsupported::assemble.
I have used the Tcl assemble command to produce performance par with
expr without modification to the core. Other's could make use of a
public interface as well. Then many design specific languages (DSL)
could be built upon Tcl with high performance.
As always, I want to thank Colin for his fine work, both his C code
and his pure tcl prototype which I have built my compiler on, which
can be found here:
https://github.com/rocketship88/colin-parser
Eric
On Thu, Apr 23, 2026 at 1:07 PM Florent Merlet <flo...@gm...>
wrote:
> Hi Rene,
> There begins to be a lot of commands into the core.
>
> Every new release, new commands appears.
> Is the memory of people infinite, so they can learn a continuous
> extending set of commands ?
>
> The problem is : How do we interface command with math calculation ?
>
> There is many possibilities :
> * we expect to make a calculation and return the result (expr)
> * we expect to make calculation and return no result, just make a side
> effect somewhere in the interpreter (???)
> * we expect a to produce list of calculations (lexpr)
> * we expect to set a list of vars from calculations (let)
> * we expect to apply expr to each elements of a list (foreach / lmap +
> expr)
> * ...
>
> Are you sure that to have one command for each possibility is the viable
> solution ?
> What about the inflation of command names in the command Table ?
>
> With my proposal, you can get all this without any new command beeing
> added anywhere.
> set L [(1,2,3,4)] ; # set a list
> [(a=1; b=3; c=3;)]; # set as many variables as you want
>
> You can even set a list, while setting individual element to a value. Ex :
>
> % [(P = (x=1, y=2, z=3) ;)]
> 1 2 3
> (bin) 41 % set x
> 1
> (bin) 42 % set y
> 2
> (bin) 43 % set z
> 3
> (bin) 44 % set P
> 1 2 3
>
> What would be the name of this last command for you ? ellexpr ? lelexpr ?
>
> You may also choose to set a matrix, record its rows in an array, and
> set its individuals elements to variable
>
> [( M = (
> "row(0)" = (a = 1, b = 2, c = 3),
> "row(1)" = (d = 4, e = 5, f = 6),
> "row(2)" = (g = 7, h = 8, i = 9)
> )
> ;)]
>
> (bin) 51 % set M
> {1 2 3} {4 5 6} {7 8 9}
> (bin) 52 % set row(0)
> 1 2 3
> (bin) 53 % set row(1)
> 4 5 6
> (bin) 54 % set row(2)
> 7 8 9
> (bin) 55 % list $a $b $c $d $e $f $g $h $i
> 1 2 3 4 5 6 7 8 9
>
> What would be the name of this last command for you ? elArrMAtexpr ?
> MatArraelexpr ?
>
> How many lines to get this effect with the command interface ?
> I think we can quickly get a limit.
>
> The command interface is very good for some think, very efficient.
> For some other things, it is too poor.
>
> I will never use an expr-like syntax for widget, or strings lists, or dicts
> But why insisting to use command-like syntax for calculation ?
> expr is allready there. Why not just use it in its full capabilities ?
>
> Try this (on windows, static compiled with mingwin)
>
> https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
>
> Regards,
> Florent
>
> Le 23/04/2026 à 16:15, Zaumseil René via Tcl-Core a écrit :
> > Hello Yorick
> >
> > Very cool. It reminds me of my own "let" proposal.
> > Imho these 2 functions should go at least in the ::tcl namespace.
> > The big problem is to find proper names.
> >
> > For the first "= {..} {..}" I would propose "tcl::lexpr ..
> > For the second "= x .. y.." I would propose "tcl::let .."
> >
> > This is like TIP 760.
> >
> > Thank you
> > rene
> >
> >
> > -----Ursprüngliche Nachricht-----
> > Von: Poor Yorick <org...@po...>
> > Gesendet: Donnerstag, 23. April 2026 11:36
> > An: tcl...@li...
> > Betreff: [Ext] Re: [TCLCORE] TIP 676 results - doesn't pass
> >
> > On 2026-04-23 11:28, EricT wrote:
> >> Hi Poor,
> >>
> >> Can you elaborate on your = helper here?
> >>
> >> Is this something that takes each argument and passes it on to expr,
> >> and then returns a list of results? If so, can you pass it to expr
> >> braced so it compiles efficiently?
> >>
> >> Regards,
> >>
> >> Eric
> > Here is it is:
> >
> > proc = args {
> > lmap item $args[set args {}] {uplevel 1 [list ::expr
> $item]}
> > }
> >
> > Example:
> >
> > .canvas addtag enclosed {*}[= {$x-20} {$x+20} {$y-20} {$y+20}]
> >
> >
> > If that isn't efficient enough, then making the necessary to changes to
> Tcl to make it more efficient would be a good direction.
> >
> > But I would call that something like lexpr so that = could be used to
> make expr more convenient:
> >
> > proc = args {
> > uplevel 1 [join [lmap {varname expr} $args[set args {}] {
> > lindex "::set [list $varname] \[::expr [list
> $expr]]"
> > }] \n]
> > }
> >
> > Example:
> >
> > = x {3 * 3.14} y {$x * 2}
> >
> > Those two procedures make doing math in Tcl pretty reasonable, without
> any language modification.
> >
> > --
> > Yorick
> >
> >
> > _______________________________________________
> > Tcl-Core mailing list
> > Tcl...@li...
> > https://lists.sourceforge.net/lists/listinfo/tcl-core
> >
> >
> > _______________________________________________
> > Tcl-Core mailing list
> > Tcl...@li...
> > https://lists.sourceforge.net/lists/listinfo/tcl-core
>
> --
> <center>
> <hr/>
> <b>Florent MERLET</b><br/>
> <i>4 rue Johann Strauss<br/>
> Logement 7<br/>
> 86180 BUXEROLLES</i><br/>
> <hr/>
> <b>Mél.</b> : <i>flo...@gm...</i><br/>
> <b>Tél.</b> : <i>06 70 00 63 48</i>
> </center>
>
>
>
>
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
|
|
From: Florent M. <flo...@gm...> - 2026-04-23 20:07:44
|
Hi Rene,
There begins to be a lot of commands into the core.
Every new release, new commands appears.
Is the memory of people infinite, so they can learn a continuous
extending set of commands ?
The problem is : How do we interface command with math calculation ?
There is many possibilities :
* we expect to make a calculation and return the result (expr)
* we expect to make calculation and return no result, just make a side
effect somewhere in the interpreter (???)
* we expect a to produce list of calculations (lexpr)
* we expect to set a list of vars from calculations (let)
* we expect to apply expr to each elements of a list (foreach / lmap +
expr)
* ...
Are you sure that to have one command for each possibility is the viable
solution ?
What about the inflation of command names in the command Table ?
With my proposal, you can get all this without any new command beeing
added anywhere.
set L [(1,2,3,4)] ; # set a list
[(a=1; b=3; c=3;)]; # set as many variables as you want
You can even set a list, while setting individual element to a value. Ex :
% [(P = (x=1, y=2, z=3) ;)]
1 2 3
(bin) 41 % set x
1
(bin) 42 % set y
2
(bin) 43 % set z
3
(bin) 44 % set P
1 2 3
What would be the name of this last command for you ? ellexpr ? lelexpr ?
You may also choose to set a matrix, record its rows in an array, and
set its individuals elements to variable
[( M = (
"row(0)" = (a = 1, b = 2, c = 3),
"row(1)" = (d = 4, e = 5, f = 6),
"row(2)" = (g = 7, h = 8, i = 9)
)
;)]
(bin) 51 % set M
{1 2 3} {4 5 6} {7 8 9}
(bin) 52 % set row(0)
1 2 3
(bin) 53 % set row(1)
4 5 6
(bin) 54 % set row(2)
7 8 9
(bin) 55 % list $a $b $c $d $e $f $g $h $i
1 2 3 4 5 6 7 8 9
What would be the name of this last command for you ? elArrMAtexpr ?
MatArraelexpr ?
How many lines to get this effect with the command interface ?
I think we can quickly get a limit.
The command interface is very good for some think, very efficient.
For some other things, it is too poor.
I will never use an expr-like syntax for widget, or strings lists, or dicts
But why insisting to use command-like syntax for calculation ?
expr is allready there. Why not just use it in its full capabilities ?
Try this (on windows, static compiled with mingwin)
https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
Regards,
Florent
Le 23/04/2026 à 16:15, Zaumseil René via Tcl-Core a écrit :
> Hello Yorick
>
> Very cool. It reminds me of my own "let" proposal.
> Imho these 2 functions should go at least in the ::tcl namespace.
> The big problem is to find proper names.
>
> For the first "= {..} {..}" I would propose "tcl::lexpr ..
> For the second "= x .. y.." I would propose "tcl::let .."
>
> This is like TIP 760.
>
> Thank you
> rene
>
>
> -----Ursprüngliche Nachricht-----
> Von: Poor Yorick <org...@po...>
> Gesendet: Donnerstag, 23. April 2026 11:36
> An: tcl...@li...
> Betreff: [Ext] Re: [TCLCORE] TIP 676 results - doesn't pass
>
> On 2026-04-23 11:28, EricT wrote:
>> Hi Poor,
>>
>> Can you elaborate on your = helper here?
>>
>> Is this something that takes each argument and passes it on to expr,
>> and then returns a list of results? If so, can you pass it to expr
>> braced so it compiles efficiently?
>>
>> Regards,
>>
>> Eric
> Here is it is:
>
> proc = args {
> lmap item $args[set args {}] {uplevel 1 [list ::expr $item]}
> }
>
> Example:
>
> .canvas addtag enclosed {*}[= {$x-20} {$x+20} {$y-20} {$y+20}]
>
>
> If that isn't efficient enough, then making the necessary to changes to Tcl to make it more efficient would be a good direction.
>
> But I would call that something like lexpr so that = could be used to make expr more convenient:
>
> proc = args {
> uplevel 1 [join [lmap {varname expr} $args[set args {}] {
> lindex "::set [list $varname] \[::expr [list $expr]]"
> }] \n]
> }
>
> Example:
>
> = x {3 * 3.14} y {$x * 2}
>
> Those two procedures make doing math in Tcl pretty reasonable, without any language modification.
>
> --
> Yorick
>
>
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
>
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
--
<center>
<hr/>
<b>Florent MERLET</b><br/>
<i>4 rue Johann Strauss<br/>
Logement 7<br/>
86180 BUXEROLLES</i><br/>
<hr/>
<b>Mél.</b> : <i>flo...@gm...</i><br/>
<b>Tél.</b> : <i>06 70 00 63 48</i>
</center>
|
|
From: Florent M. <flo...@gm...> - 2026-04-23 19:57:52
|
Hi Eric, Hi Yoric, Hi all,
Here the result I get for it :
(bin) 70 % timerate {
set x [expr {3*3.14}]; set y [expr {$x*2}]
}
1.191671 µs/# 839156 # 839157 #/sec 999.998 net-ms
(bin) 71 % timerate {(
y = (x = 3*3.14)*2
)}
1.180498 µs/# 847099 # 847099 #/sec 999.999 net-ms
(bin) 72 % timerate {
list [expr {$x-10}] [expr {$x+20}] [expr {$y-20}] [expr {$y+20}]
}
2.816785 µs/# 355014 # 355014 #/sec 999.998 net-ms
(bin) 73 % timerate {(
$x-10, $x+20, $y-20, $y+20
)}
2.844616 µs/# 351541 # 351541 #/sec 999.999 net-ms
Shorter, more readable, as fast as the original !
Just check there :
https://github.com/florentis/tcl90-exprSH/tree/core-9-0-branch/install_SH
Regards,
Florent
Le 23/04/2026 à 17:33, EricT a écrit :
> Hi Yorik,
>
> Thanks for those 2 procedures.
>
> The first one compared to code using braced expr has about a 4.5x
> performance decrease.
>
> However, the second example, was quite more, there I found a 40x decrease.
>
> Do you find the same results?
>
> Eric
>
>
>
>
> On Thu, Apr 23, 2026 at 7:30 AM Zaumseil René via Tcl-Core
> <tcl...@li...> wrote:
>
> Hello Yorick
>
> Very cool. It reminds me of my own "let" proposal.
> Imho these 2 functions should go at least in the ::tcl namespace.
> The big problem is to find proper names.
>
> For the first "= {..} {..}" I would propose "tcl::lexpr ..
> For the second "= x .. y.." I would propose "tcl::let .."
>
> This is like TIP 760.
>
> Thank you
> rene
>
>
> -----Ursprüngliche Nachricht-----
> Von: Poor Yorick <org...@po...>
> Gesendet: Donnerstag, 23. April 2026 11:36
> An: tcl...@li...
> Betreff: [Ext] Re: [TCLCORE] TIP 676 results - doesn't pass
>
> On 2026-04-23 11:28, EricT wrote:
> > Hi Poor,
> >
> > Can you elaborate on your = helper here?
> >
> > Is this something that takes each argument and passes it on to
> expr,
> > and then returns a list of results? If so, can you pass it to expr
> > braced so it compiles efficiently?
> >
> > Regards,
> >
> > Eric
>
> Here is it is:
>
> proc = args {
> lmap item $args[set args {}] {uplevel 1 [list
> ::expr $item]}
> }
>
> Example:
>
> .canvas addtag enclosed {*}[= {$x-20} {$x+20} {$y-20} {$y+20}]
>
>
> If that isn't efficient enough, then making the necessary to
> changes to Tcl to make it more efficient would be a good direction.
>
> But I would call that something like lexpr so that = could be used
> to make expr more convenient:
>
> proc = args {
> uplevel 1 [join [lmap {varname expr} $args[set
> args {}] {
> lindex "::set [list $varname] \[::expr
> [list $expr]]"
> }] \n]
> }
>
> Example:
>
> = x {3 * 3.14} y {$x * 2}
>
> Those two procedures make doing math in Tcl pretty reasonable,
> without any language modification.
>
> --
> Yorick
>
>
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
>
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core
>
>
>
> _______________________________________________
> Tcl-Core mailing list
> Tcl...@li...
> https://lists.sourceforge.net/lists/listinfo/tcl-core |