• Experiment: inline bytecode for [lrange] with variable indices(written by Claude)

    From et99@[email protected] to comp.lang.tcl on Tue Oct 6 18:19:19 2026
    From Newsgroup: comp.lang.tcl

    Hi all:

    A note first: in the last few months my Claude account (a Pro subscription, not the free tier) has gained the ability to build and run code in its own Linux sandbox. Before that, Claude could only hand me code and I had to do all the testing on my own machine. I don't know whether this is just my account or a general rollout.

    This experiment started as a side effect of a tool Claude and I wrote to scan every proc in every package of a Magicsplat install, looking for bytecode problems. I extended it to count which commands are called through the command table (invokeStk) instead of being compiled inline. Most of what came up does real work per call (format, regsub, lsort, ...), so call overhead is a small part of the cost. The one cheap command that stood out was [lrange] with a non-literal index: [lrange $l 1 3] already compiles to listRangeImm, but [lrange $l $i $j] and [lrange $l 1 end-$n] fall back to a full command call.

    I asked Claude (Anthropic's AI assistant), working in its sandbox with access to the GitHub mirror of the Tcl source, to add a new listRange instruction that always takes exactly three values from the stack: the list and both indices. It took about 20 minutes to get a complete patch with tests, after many build and test runs in the sandbox, including AddressSanitizer, Tcl's memory-debug build and the TCL_COMPILE_DEBUG build. I copied the changed files into my own tree, built, and ran the tests and a benchmark on two of my machines. Claude ran the same benchmark in its sandbox, which is the third column below.

    Base: Tcl main, commit 78dedf7 (2026-10-05, GitHub mirror).

    What changed (66 lines of C added, 16 removed; 161 lines of tests added):

    generic/tclCompile.h +1 new opcode INST_LIST_RANGE
    generic/tclCompile.c +7 instruction table entry
    generic/tclExecute.c +34 the instruction
    generic/tclCompCmdsGR.c +23 -16 compile non-literal indices to it
    generic/tclAssembly.c +1 tcl::unsupported::assemble can use it
    tests/lrange.test +85 lrange-6.1 .. 6.14
    tests/compile.test +38 compile-22.1 .. 22.5
    tests/assemble.test +38 assemble-7.47 .. 7.50

    The instruction does what Tcl_LrangeObjCmd does, in the same order, so error messages and error precedence are the same as for the command. A test compares the compiled form against the command for 6 lists and 20 index forms each way, with no differences.

    Tests: the full suite gives 509,285 tests (23 more than before), the same 8 failures before and after (httpProxy.test, which needs network access). disassemble and getbytecode show the new instruction.

    Timing (ns per call, 10-element list, best of 7, before -> after):

    machine 1 machine 2 Claude's sandbox
    lrange $l $i $j 193 -> 126 117 -> 72 152 -> 98
    lrange $l $i end 232 -> 165 130 -> 93 172 -> 123
    lrange $l 1 end-$n 368 -> 291 200 -> 161 270 -> 212
    lrange $l 1 3 (literal) 38 -> 39 24 -> 23 32 -> 34

    The sandbox is a small shared VM, so its numbers are noisier than mine. The literal case compiles to identical bytecode in both builds, and its difference changes direction between machines, so I take it to be build-layout noise. The end-$n gain is smaller because the string "end-N" is still built and parsed on every call.

    Limits: Linux only. I have not built it on Windows or macOS, so MSVC has not seen it. I have not tried an integer fast path for end-$n.

    I am posting this as a data point more than as a proposal. If anyone on the core team thinks it is worth a ticket, I will file one with the patch. The patch, the test results and the benchmark script are here: https://github.com/rocketship88/lrange-inline .

    On a side note, I have also found the same assistant good at drafting documentation for my own projects, especially when using the AI to build the projects. It needs a human to check the facts, but it makes a decent first draft. The Readme at github was also written by Claude.

    Eric

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ashok@[email protected] to comp.lang.tcl on Wed Oct 7 08:53:33 2026
    From Newsgroup: comp.lang.tcl

    Certainly worth pursuing I think. My knowledge of the Tcl byte code is
    mostly based on cargo culting (blush) so creating a branch in the Tcl repository so more knowledgeable folks can take a look is worthwhile.
    I'm not sure everyone reads c.l.t.

    As an aside, I'm a bit surprised that this was not already compiled. The string range command is very similar to lrange and afaict that compiles
    in much the same fashion as your patch for lrange with support for
    non-literal arguments (which leads me to wonder if Claude might have
    used it as the basis for what it produced). Not sure why lrange was not implemented the same way.

    On a different topic, I wonder if you could ask Claude to optimize
    invokeStk* bytecode implementation. I wonder if it is something that
    needs to be inherently slower because the additional work involved or if
    there is scope there for improvement.

    /Ashok

    On 10/7/2026 6:49 AM, et99 wrote:
    Hi all:

    A note first: in the last few months my Claude account (a Pro
    subscription, not the free tier) has gained the ability to build and run code in its own Linux sandbox. Before that, Claude could only hand me
    code and I had to do all the testing on my own machine. I don't know
    whether this is just my account or a general rollout.

    This experiment started as a side effect of a tool Claude and I wrote to scan every proc in every package of a Magicsplat install, looking for bytecode problems. I extended it to count which commands are called
    through the command table (invokeStk) instead of being compiled inline.
    Most of what came up does real work per call (format, regsub,
    lsort, ...), so call overhead is a small part of the cost. The one cheap command that stood out was [lrange] with a non-literal index: [lrange $l
    1 3] already compiles to listRangeImm, but [lrange $l $i $j] and [lrange
    $l 1 end-$n] fall back to a full command call.

    I asked Claude (Anthropic's AI assistant), working in its sandbox with access to the GitHub mirror of the Tcl source, to add a new listRange instruction that always takes exactly three values from the stack: the
    list and both indices. It took about 20 minutes to get a complete patch
    with tests, after many build and test runs in the sandbox, including AddressSanitizer, Tcl's memory-debug build and the TCL_COMPILE_DEBUG
    build. I copied the changed files into my own tree, built, and ran the
    tests and a benchmark on two of my machines. Claude ran the same
    benchmark in its sandbox, which is the third column below.

    Base: Tcl main, commit 78dedf7 (2026-10-05, GitHub mirror).

    What changed (66 lines of C added, 16 removed; 161 lines of tests added):

      generic/tclCompile.h       +1         new opcode INST_LIST_RANGE
      generic/tclCompile.c       +7         instruction table entry
      generic/tclExecute.c       +34        the instruction
      generic/tclCompCmdsGR.c    +23 -16   compile non-literal indices to it
      generic/tclAssembly.c      +1         tcl::unsupported::assemble can
    use it
      tests/lrange.test          +85        lrange-6.1 .. 6.14
      tests/compile.test         +38        compile-22.1 .. 22.5
      tests/assemble.test        +38        assemble-7.47 .. 7.50

    The instruction does what Tcl_LrangeObjCmd does, in the same order, so
    error messages and error precedence are the same as for the command. A
    test compares the compiled form against the command for 6 lists and 20
    index forms each way, with no differences.

    Tests: the full suite gives 509,285 tests (23 more than before), the
    same 8 failures before and after (httpProxy.test, which needs network access). disassemble and getbytecode show the new instruction.

    Timing (ns per call, 10-element list, best of 7, before -> after):

                              machine 1    machine 2   Claude's sandbox
      lrange $l $i $j         193 -> 126   117 -> 72   152 -> 98
      lrange $l $i end        232 -> 165   130 -> 93   172 -> 123
      lrange $l 1 end-$n      368 -> 291   200 -> 161  270 -> 212
      lrange $l 1 3 (literal)  38 -> 39     24 -> 23    32 -> 34

    The sandbox is a small shared VM, so its numbers are noisier than mine.
    The literal case compiles to identical bytecode in both builds, and its difference changes direction between machines, so I take it to be build- layout noise. The end-$n gain is smaller because the string "end-N" is
    still built and parsed on every call.

    Limits: Linux only. I have not built it on Windows or macOS, so MSVC has
    not seen it. I have not tried an integer fast path for end-$n.

    I am posting this as a data point more than as a proposal. If anyone on
    the core team thinks it is worth a ticket, I will file one with the
    patch. The patch, the test results and the benchmark script are here: https://github.com/rocketship88/lrange-inline .

    On a side note, I have also found the same assistant good at drafting documentation for my own projects, especially when using the AI to build
    the projects. It needs a human to check the facts, but it makes a decent first draft. The Readme at github was also written by Claude.

    Eric


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Wed Oct 7 00:07:59 2026
    From Newsgroup: comp.lang.tcl


    Ashok,

    Thanks for the encouragement. I've created an account on
    core.tcl-lang.org (username: rocketship88) and have the change
    committed locally on a Fossil branch called lrange-inline, based on
    trunk check-in a675fa55 (2026-10-05). I can't push it yet because I
    don't have write permission.

    Could someone grant me rights to push it, or tell me who to ask? Or, if
    you'd rather not, a diff made by Fossil (trunk vs. the branch) is here:

    https://github.com/rocketship88/lrange-inline/blob/main/lrange.diff

    It touches 8 files under generic/ and tests/. The rest of the experiment (README, benchmark script, the base files and the changed ones as
    side-by-side commits) is at:

    https://github.com/rocketship88/lrange-inline

    As in my first post, the code and tests were written by Claude and I
    reviewed, built and tested them locally. The tests pass on my builds.


    Claude writes:

    Ashok asked whether I looked at [string range]. I did, but only after he
    asked, so it had no part in how I wrote the code. Having read it now, the two are very similar: both have an immediate form for literal indices and a three-value form for the rest.

    As for why [lrange] was never done that way, a comment above TclCompileLrangeCmd says "We only bother because we needed the opcode anyway for lassign." So listRangeImm was added for lassign, and compiling [lrange] with literal indices came along as a side benefit. The non-literal case
    doesn't seem to have been considered.

    As for optimizing invokeStk, I haven't tried. It is a much bigger and riskier change than this one, because that path leaves the bytecode loop through TclNREvalObjv. We measured about 44 ns of call overhead on the faster of our machines. If the core team is interested, I'd start by profiling that path
    with callgrind, with no code change, and see where the time goes.




    -Eric


    On 10/6/2026 8:23 PM, Ashok wrote:
    Certainly worth pursuing I think. My knowledge of the Tcl byte code is mostly based on cargo culting (blush) so creating a branch in the Tcl repository so more knowledgeable folks can take a look is worthwhile. I'm not sure everyone reads c.l.t.

    As an aside, I'm a bit surprised that this was not already compiled. The string range command is very similar to lrange and afaict that compiles in much the same fashion as your patch for lrange with support for non-literal arguments (which leads me to wonder if Claude might have used it as the basis for what it produced). Not sure why lrange was not implemented the same way.

    On a different topic, I wonder if you could ask Claude to optimize invokeStk* bytecode implementation. I wonder if it is something that needs to be inherently slower because the additional work involved or if there is scope there for improvement.

    /Ashok

    On 10/7/2026 6:49 AM, et99 wrote:
    Hi all:

    A note first: in the last few months my Claude account (a Pro subscription, not the free tier) has gained the ability to build and run code in its own Linux sandbox. Before that, Claude could only hand me code and I had to do all the testing on my own machine. I don't know whether this is just my account or a general rollout.

    This experiment started as a side effect of a tool Claude and I wrote to scan every proc in every package of a Magicsplat install, looking for bytecode problems. I extended it to count which commands are called through the command table (invokeStk) instead of being compiled inline. Most of what came up does real work per call (format, regsub, lsort, ...), so call overhead is a small part of the cost. The one cheap command that stood out was [lrange] with a non-literal index: [lrange $l 1 3] already compiles to listRangeImm, but [lrange $l $i $j] and [lrange $l 1 end-$n] fall back to a full command call.

    I asked Claude (Anthropic's AI assistant), working in its sandbox with access to the GitHub mirror of the Tcl source, to add a new listRange instruction that always takes exactly three values from the stack: the list and both indices. It took about 20 minutes to get a complete patch with tests, after many build and test runs in the sandbox, including AddressSanitizer, Tcl's memory-debug build and the TCL_COMPILE_DEBUG build. I copied the changed files into my own tree, built, and ran the tests and a benchmark on two of my machines. Claude ran the same benchmark in its sandbox, which is the third column below.

    Base: Tcl main, commit 78dedf7 (2026-10-05, GitHub mirror).

    What changed (66 lines of C added, 16 removed; 161 lines of tests added):

       generic/tclCompile.h       +1         new opcode INST_LIST_RANGE
       generic/tclCompile.c       +7         instruction table entry
       generic/tclExecute.c       +34        the instruction
       generic/tclCompCmdsGR.c    +23 -16   compile non-literal indices to it
       generic/tclAssembly.c      +1         tcl::unsupported::assemble can use it
       tests/lrange.test          +85        lrange-6.1 .. 6.14
       tests/compile.test         +38        compile-22.1 .. 22.5
       tests/assemble.test        +38        assemble-7.47 .. 7.50

    The instruction does what Tcl_LrangeObjCmd does, in the same order, so error messages and error precedence are the same as for the command. A test compares the compiled form against the command for 6 lists and 20 index forms each way, with no differences.

    Tests: the full suite gives 509,285 tests (23 more than before), the same 8 failures before and after (httpProxy.test, which needs network access). disassemble and getbytecode show the new instruction.

    Timing (ns per call, 10-element list, best of 7, before -> after):

                               machine 1    machine 2   Claude's sandbox
       lrange $l $i $j         193 -> 126   117 -> 72   152 -> 98 >>    lrange $l $i end        232 -> 165   130 -> 93   172 -> 123 >>    lrange $l 1 end-$n      368 -> 291   200 -> 161  270 -> 212
       lrange $l 1 3 (literal)  38 -> 39     24 -> 23    32 -> 34

    The sandbox is a small shared VM, so its numbers are noisier than mine. The literal case compiles to identical bytecode in both builds, and its difference changes direction between machines, so I take it to be build- layout noise. The end-$n gain is smaller because the string "end-N" is still built and parsed on every call.

    Limits: Linux only. I have not built it on Windows or macOS, so MSVC has not seen it. I have not tried an integer fast path for end-$n.

    I am posting this as a data point more than as a proposal. If anyone on the core team thinks it is worth a ticket, I will file one with the patch. The patch, the test results and the benchmark script are here: https://github.com/rocketship88/lrange-inline .

    On a side note, I have also found the same assistant good at drafting documentation for my own projects, especially when using the AI to build the projects. It needs a human to check the facts, but it makes a decent first draft. The Readme at github was also written by Claude.

    Eric



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ashok@[email protected] to comp.lang.tcl on Wed Oct 7 18:44:08 2026
    From Newsgroup: comp.lang.tcl

    You should have access now. Please retry.


    On 10/7/2026 12:37 PM, et99 wrote:

    Ashok,

    Thanks for the encouragement. I've created an account on
    core.tcl-lang.org (username: rocketship88) and have the change
    committed locally on a Fossil branch called lrange-inline, based on
    trunk check-in a675fa55 (2026-10-05). I can't push it yet because I
    don't have write permission.

    Could someone grant me rights to push it, or tell me who to ask? Or, if
    you'd rather not, a diff made by Fossil (trunk vs. the branch) is here:

        https://github.com/rocketship88/lrange-inline/blob/main/lrange.diff

    It touches 8 files under generic/ and tests/. The rest of the experiment (README, benchmark script, the base files and the changed ones as side-by-side commits) is at:

        https://github.com/rocketship88/lrange-inline

    As in my first post, the code and tests were written by Claude and I reviewed, built and tested them locally. The tests pass on my builds.


    Claude writes:

    Ashok asked whether I looked at [string range]. I did, but only after he asked, so it had no part in how I wrote the code. Having read it now,
    the two
    are very similar: both have an immediate form for literal indices and a three-value form for the rest.

    As for why [lrange] was never done that way, a comment above TclCompileLrangeCmd says "We only bother because we needed the opcode
    anyway
    for lassign." So listRangeImm was added for lassign, and compiling [lrange] with literal indices came along as a side benefit. The non-literal case doesn't seem to have been considered.

    As for optimizing invokeStk, I haven't tried. It is a much bigger and riskier
    change than this one, because that path leaves the bytecode loop through TclNREvalObjv. We measured about 44 ns of call overhead on the faster of
    our
    machines. If the core team is interested, I'd start by profiling that path with callgrind, with no code change, and see where the time goes.




    -Eric


    On 10/6/2026 8:23 PM, Ashok wrote:
    Certainly worth pursuing I think. My knowledge of the Tcl byte code is
    mostly based on cargo culting (blush) so creating a branch in the Tcl
    repository so more knowledgeable folks can take a look is worthwhile.
    I'm not sure everyone reads c.l.t.

    As an aside, I'm a bit surprised that this was not already compiled.
    The string range command is very similar to lrange and afaict that
    compiles in much the same fashion as your patch for lrange with
    support for non-literal arguments (which leads me to wonder if Claude
    might have used it as the basis for what it produced). Not sure why
    lrange was not implemented the same way.

    On a different topic, I wonder if you could ask Claude to optimize
    invokeStk* bytecode implementation. I wonder if it is something that
    needs to be inherently slower because the additional work involved or
    if there is scope there for improvement.

    /Ashok

    On 10/7/2026 6:49 AM, et99 wrote:
    Hi all:

    A note first: in the last few months my Claude account (a Pro
    subscription, not the free tier) has gained the ability to build and
    run code in its own Linux sandbox. Before that, Claude could only
    hand me code and I had to do all the testing on my own machine. I
    don't know whether this is just my account or a general rollout.

    This experiment started as a side effect of a tool Claude and I wrote
    to scan every proc in every package of a Magicsplat install, looking
    for bytecode problems. I extended it to count which commands are
    called through the command table (invokeStk) instead of being
    compiled inline. Most of what came up does real work per call
    (format, regsub, lsort, ...), so call overhead is a small part of the
    cost. The one cheap command that stood out was [lrange] with a non-
    literal index: [lrange $l 1 3] already compiles to listRangeImm, but
    [lrange $l $i $j] and [lrange $l 1 end-$n] fall back to a full
    command call.

    I asked Claude (Anthropic's AI assistant), working in its sandbox
    with access to the GitHub mirror of the Tcl source, to add a new
    listRange instruction that always takes exactly three values from the
    stack: the list and both indices. It took about 20 minutes to get a
    complete patch with tests, after many build and test runs in the
    sandbox, including AddressSanitizer, Tcl's memory-debug build and the
    TCL_COMPILE_DEBUG build. I copied the changed files into my own tree,
    built, and ran the tests and a benchmark on two of my machines.
    Claude ran the same benchmark in its sandbox, which is the third
    column below.

    Base: Tcl main, commit 78dedf7 (2026-10-05, GitHub mirror).

    What changed (66 lines of C added, 16 removed; 161 lines of tests
    added):

       generic/tclCompile.h       +1         new opcode INST_LIST_RANGE
       generic/tclCompile.c       +7         instruction table entry
       generic/tclExecute.c       +34        the instruction
       generic/tclCompCmdsGR.c    +23 -16   compile non-literal indices >>> to it
       generic/tclAssembly.c      +1         tcl::unsupported::assemble
    can use it
       tests/lrange.test          +85        lrange-6.1 .. 6.14
       tests/compile.test         +38        compile-22.1 .. 22.5
       tests/assemble.test        +38        assemble-7.47 .. 7.50

    The instruction does what Tcl_LrangeObjCmd does, in the same order,
    so error messages and error precedence are the same as for the
    command. A test compares the compiled form against the command for 6
    lists and 20 index forms each way, with no differences.

    Tests: the full suite gives 509,285 tests (23 more than before), the
    same 8 failures before and after (httpProxy.test, which needs network
    access). disassemble and getbytecode show the new instruction.

    Timing (ns per call, 10-element list, best of 7, before -> after):

                               machine 1    machine 2   Claude's sandbox
       lrange $l $i $j         193 -> 126   117 -> 72   152 -> 98 >>>    lrange $l $i end        232 -> 165   130 -> 93   172 -> 123 >>>    lrange $l 1 end-$n      368 -> 291   200 -> 161  270 -> 212 >>>    lrange $l 1 3 (literal)  38 -> 39     24 -> 23    32 -> 34

    The sandbox is a small shared VM, so its numbers are noisier than
    mine. The literal case compiles to identical bytecode in both builds,
    and its difference changes direction between machines, so I take it
    to be build- layout noise. The end-$n gain is smaller because the
    string "end-N" is still built and parsed on every call.

    Limits: Linux only. I have not built it on Windows or macOS, so MSVC
    has not seen it. I have not tried an integer fast path for end-$n.

    I am posting this as a data point more than as a proposal. If anyone
    on the core team thinks it is worth a ticket, I will file one with
    the patch. The patch, the test results and the benchmark script are
    here: https://github.com/rocketship88/lrange-inline .

    On a side note, I have also found the same assistant good at drafting
    documentation for my own projects, especially when using the AI to
    build the projects. It needs a human to check the facts, but it makes
    a decent first draft. The Readme at github was also written by Claude.

    Eric




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Wed Oct 7 08:23:05 2026
    From Newsgroup: comp.lang.tcl


    Thanks, Ashok.

    The push worked. (A correction to my earlier post: my
    Fossil username is rocketship98; rocketship88 is my GitHub name.) The
    branch is now on core.tcl-lang.org as lrange-inline, check-in 5c9d6b18,
    based on trunk a675fa55:

    https://core.tcl-lang.org/tcl/info/5c9d6b18

    Some follow-up findings. Claude profiled the call path in its sandbox
    with callgrind. These are exact instruction counts, not times, and
    nothing in the source was changed.

    (I haven't repeated the callgrind runs myself so consider this his
    preliminary findings).


    -------------------------------------------------------------------

    Where the cost of a non-inlined call goes. Inline [lrange] saves
    about 690 instructions per call:

    Table 1. [lrange] forms, instructions per call

    form invokeStk listRange fewer
    lrange $l 1 3 82 82 0% (already inline)
    lrange $l $i $j 1718 1027 40%
    lrange $l $i end 2064 1369 34%
    lrange $l 1 end-$n 3246 2557 21%

    Table 2. Where the 694 saved instructions per call go
    (lrange $l $i $j)

    evaluator trampoline (EvalObjvCore, TclNRRunCallbacks,
    TclNREvalObjv, NRCommand and others) 299
    invokeStk instruction + re-entering the bytecode loop 127
    interpreter result handling 82
    extra object allocation and thread-data lookups 76
    Tcl_LrangeObjCmd's own argument handling 66
    command lookup (Tcl_GetCommandFromObj) 31
    other small items 13
    total 694

    So the command lookup is not the problem: the name is a literal object
    with a cached lookup, and it is only 31 instructions. The cost is the
    machinery around the call, and every non-inlined command and every proc
    call pays it.



    (here Claude and I took a look at what I suggested might be something that could be done for heavy math compute code to avoid the invokeStk entirely)




    The math functions show the same thing. All 58 commands in
    ::tcl::mathfunc compile as push "tcl::mathfunc::NAME" followed by
    invokeStk, including with constant arguments. None are inlined.
    [expr {abs($x)}] compiles to:

    push "tcl::mathfunc::abs"; loadScalar x; invokeStk 2;
    tryCvtToNumeric

    To estimate what an inline abs could achieve before anyone writes one,
    Claude used the assembler ([tcl::unsupported::assemble]) to write
    variants of abs directly in TAL, and counted each variant with
    callgrind. The rows are:

    - "load x; nop" is a probable floor. It loads the value and does no
    work, so no real abs bytecode can beat it.
    - "load x; uminus" and "load x; uplus" are existing instructions that
    do the kind of work an abs would: uminus allocates a new number (as
    abs must for a negative value), and uplus checks that the value is
    numeric. They approximate what a real abs bytecode might cost.
    - "call, as expr emits it" is the real thing, including the final
    tryCvtToNumeric.
    - The last two rows (marked *) are variants without that final
    instruction, or built by hand from existing instructions
    (load x; dup; push 0; lt; jumpFalse; uminus). They work today with
    no C changes, but they are not exactly equivalent to expr; see the
    note below.

    x = 7 takes the non-negative path (abs returns its argument); x = -5
    takes the negative one (abs creates a new number).

    Table 3. abs, instructions per call

    variant x = 7 x = -5
    load x; nop (floor, no work) 74 74
    load x; uminus 218 218
    load x; uplus 252 252
    call, as expr emits it (with
    tryCvtToNumeric) 1075 1069
    call, without that final instruction * 861 1013
    hand-written in TAL * 298 447

    Note on the final instruction. tryCvtToNumeric is not redundant. It
    gives the result the canonical string form of its value: with it,
    expr {abs($x)} returns 16 for x = 0x10, 7 for x = 0007 and 100.0 for
    x = 1e2; without it, the same call returns the argument unchanged. It
    costs 56 instructions when abs creates a new number, but 214 when abs
    returns its argument, since the shared object has to be copied to drop
    the old string form. So an inline abs has to normalize its result in
    the same way, which is why the rows marked * understate the cost of an
    exact replacement.

    Table 4 repeats the comparison for a few other functions, through the
    normal expr route. The "by hand" figures are approximate equivalents
    written as plain expr operators. They don't treat -0.0 or mixed
    integer/double arguments in exactly the same way, so read them as a
    guide, not a precise ratio. The functions with no equivalent (int,
    sqrt, sin) cost about the same as the others, so for them nearly all
    of it is call overhead.

    Table 4. expr function calls vs hand-written equivalents
    (x = -5, y = 3)

    expression call by hand
    abs($x) 1069 512
    max($x,$y) 1263 504
    double($x) 1030 438
    int($x) 1073 -
    sqrt($y) 1045 -
    sin($y) 1167 -

    Only about 110 of the roughly 1070 instructions for abs are the abs
    work itself. The existing unary instructions (uminus, uplus), which also produce normalized numbers, cost 220 to 250, so a dedicated abs
    bytecode would probably land around 250: about 4 times fewer
    instructions per call. That is an estimate, since no such opcode exists
    yet, and it is per call, not for a whole program. Functions that do real
    work, such as sin, would gain less in proportion, because the libm call remains.

    If invokeStk itself can't be made cheaper, the next best thing is to
    avoid it where possible: more inline compile routines (what the
    lrange branch does), and bytecodes for the common math functions (abs,
    int, double, round, min, max, sqrt, sin, cos and so on), emitted by the expression compiler with a guard so that redefining a function in
    tcl::mathfunc still takes effect. Together with TIP 760 (making
    [assemble] public), such bytecodes could also be used directly from
    assembler code in heavy numeric procs.

    An alternative that avoids the redefinition question is opt-in names
    for the fast versions, for example absx or cosx (the naming is open),
    which expr would compile straight to the bytecodes, while the ordinary
    names keep their current behavior. Transparent inlining helps existing
    code, and opt-in names are simpler and safer. Either one is a small,
    bounded change per function, similar in size to the listRange change.
    I haven't built any of this: the numbers above are measurements of the
    current code plus estimates.

    Eric



    On 10/7/2026 6:14 AM, Ashok wrote:
    You should have access now. Please retry.


    On 10/7/2026 12:37 PM, et99 wrote:

    Ashok,

    Thanks for the encouragement. I've created an account on
    core.tcl-lang.org (username: rocketship88) and have the change
    committed locally on a Fossil branch called lrange-inline, based on
    trunk check-in a675fa55 (2026-10-05). I can't push it yet because I
    don't have write permission.

    Could someone grant me rights to push it, or tell me who to ask? Or, if
    you'd rather not, a diff made by Fossil (trunk vs. the branch) is here:

         https://github.com/rocketship88/lrange-inline/blob/main/lrange.diff >>
    It touches 8 files under generic/ and tests/. The rest of the experiment
    (README, benchmark script, the base files and the changed ones as
    side-by-side commits) is at:

         https://github.com/rocketship88/lrange-inline

    As in my first post, the code and tests were written by Claude and I
    reviewed, built and tested them locally. The tests pass on my builds.


    Claude writes:

    Ashok asked whether I looked at [string range]. I did, but only after he
    asked, so it had no part in how I wrote the code. Having read it now, the two
    are very similar: both have an immediate form for literal indices and a
    three-value form for the rest.

    As for why [lrange] was never done that way, a comment above
    TclCompileLrangeCmd says "We only bother because we needed the opcode anyway >> for lassign." So listRangeImm was added for lassign, and compiling [lrange] >> with literal indices came along as a side benefit. The non-literal case
    doesn't seem to have been considered.

    As for optimizing invokeStk, I haven't tried. It is a much bigger and riskier
    change than this one, because that path leaves the bytecode loop through
    TclNREvalObjv. We measured about 44 ns of call overhead on the faster of our >> machines. If the core team is interested, I'd start by profiling that path >> with callgrind, with no code change, and see where the time goes.




    -Eric


    On 10/6/2026 8:23 PM, Ashok wrote:
    Certainly worth pursuing I think. My knowledge of the Tcl byte code is mostly based on cargo culting (blush) so creating a branch in the Tcl repository so more knowledgeable folks can take a look is worthwhile. I'm not sure everyone reads c.l.t.

    As an aside, I'm a bit surprised that this was not already compiled. The string range command is very similar to lrange and afaict that compiles in much the same fashion as your patch for lrange with support for non-literal arguments (which leads me to wonder if Claude might have used it as the basis for what it produced). Not sure why lrange was not implemented the same way.

    On a different topic, I wonder if you could ask Claude to optimize invokeStk* bytecode implementation. I wonder if it is something that needs to be inherently slower because the additional work involved or if there is scope there for improvement.

    /Ashok

    On 10/7/2026 6:49 AM, et99 wrote:
    Hi all:

    A note first: in the last few months my Claude account (a Pro subscription, not the free tier) has gained the ability to build and run code in its own Linux sandbox. Before that, Claude could only hand me code and I had to do all the testing on my own machine. I don't know whether this is just my account or a general rollout.

    This experiment started as a side effect of a tool Claude and I wrote to scan every proc in every package of a Magicsplat install, looking for bytecode problems. I extended it to count which commands are called through the command table (invokeStk) instead of being compiled inline. Most of what came up does real work per call (format, regsub, lsort, ...), so call overhead is a small part of the cost. The one cheap command that stood out was [lrange] with a non- literal index: [lrange $l 1 3] already compiles to listRangeImm, but [lrange $l $i $j] and [lrange $l 1 end-$n] fall back to a full command call.

    I asked Claude (Anthropic's AI assistant), working in its sandbox with access to the GitHub mirror of the Tcl source, to add a new listRange instruction that always takes exactly three values from the stack: the list and both indices. It took about 20 minutes to get a complete patch with tests, after many build and test runs in the sandbox, including AddressSanitizer, Tcl's memory-debug build and the TCL_COMPILE_DEBUG build. I copied the changed files into my own tree, built, and ran the tests and a benchmark on two of my machines. Claude ran the same benchmark in its sandbox, which is the third column below.

    Base: Tcl main, commit 78dedf7 (2026-10-05, GitHub mirror).

    What changed (66 lines of C added, 16 removed; 161 lines of tests added): >>>>
       generic/tclCompile.h       +1         new opcode INST_LIST_RANGE
       generic/tclCompile.c       +7         instruction table entry
       generic/tclExecute.c       +34        the instruction >>>>    generic/tclCompCmdsGR.c    +23 -16   compile non-literal indices to it
       generic/tclAssembly.c      +1         tcl::unsupported::assemble can use it
       tests/lrange.test          +85        lrange-6.1 .. 6.14
       tests/compile.test         +38        compile-22.1 .. 22.5
       tests/assemble.test        +38        assemble-7.47 .. 7.50

    The instruction does what Tcl_LrangeObjCmd does, in the same order, so error messages and error precedence are the same as for the command. A test compares the compiled form against the command for 6 lists and 20 index forms each way, with no differences.

    Tests: the full suite gives 509,285 tests (23 more than before), the same 8 failures before and after (httpProxy.test, which needs network access). disassemble and getbytecode show the new instruction.

    Timing (ns per call, 10-element list, best of 7, before -> after):

                               machine 1    machine 2   Claude's sandbox
       lrange $l $i $j         193 -> 126   117 -> 72   152 -> 98
       lrange $l $i end        232 -> 165   130 -> 93   172 -> 123
       lrange $l 1 end-$n      368 -> 291   200 -> 161  270 -> 212 >>>>    lrange $l 1 3 (literal)  38 -> 39     24 -> 23    32 -> 34 >>>>
    The sandbox is a small shared VM, so its numbers are noisier than mine. The literal case compiles to identical bytecode in both builds, and its difference changes direction between machines, so I take it to be build- layout noise. The end-$n gain is smaller because the string "end-N" is still built and parsed on every call.

    Limits: Linux only. I have not built it on Windows or macOS, so MSVC has not seen it. I have not tried an integer fast path for end-$n.

    I am posting this as a data point more than as a proposal. If anyone on the core team thinks it is worth a ticket, I will file one with the patch. The patch, the test results and the benchmark script are here: https://github.com/rocketship88/lrange-inline .

    On a side note, I have also found the same assistant good at drafting documentation for my own projects, especially when using the AI to build the projects. It needs a human to check the facts, but it makes a decent first draft. The Readme at github was also written by Claude.

    Eric





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Olivier@[email protected] to comp.lang.tcl on Wed Oct 7 19:25:31 2026
    From Newsgroup: comp.lang.tcl


    et99 <[email protected]> posted:

    Hi all:

    This experiment started as a side effect of a tool Claude and
    I wrote to scan every proc in every package of a Magicsplat install,
    looking for bytecode problems.

    Eric


    Is your work something similar to Donal Fellows ("Optimizing Tcl Bytecode") ?
    I mean by supplying Donal Fellow's recommendations to Claude, it could
    improve something in Tcl speed, at least in the range of functionalities you have explored ?

    In fact I don't know if his work has been applied or not.

    Olivier.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Wed Oct 7 21:58:55 2026
    From Newsgroup: comp.lang.tcl

    On 10/7/2026 12:25 PM, Olivier wrote:

    et99 <[email protected]> posted:

    Hi all:

    This experiment started as a side effect of a tool Claude and
    I wrote to scan every proc in every package of a Magicsplat install,
    looking for bytecode problems.

    Eric


    Is your work something similar to Donal Fellows ("Optimizing Tcl Bytecode") ? I mean by supplying Donal Fellow's recommendations to Claude, it could improve something in Tcl speed, at least in the range of functionalities you have explored ?

    In fact I don't know if his work has been applied or not.

    Olivier.

    Hi Olivier:

    Short answer: kinda, I'm aware of Donal's peephole work in the core, and the assemble documentation has a section on it. But I imagine he's also working on other optimizations. My own scanning is a different thing, though. It's read-only analysis of compiled bytecode, not an optimizer.

    It started with my calc tool (Colin's original = command). All the bytecode tools are unsupported, which is why I wrote TIP 760 to make assemble a supported command. To prepare, I had Claude read the assembler source and explain it to me.

    One interesting find along the way: when a command's compile routine hits an error (for example [format %d notanumber] or [string is bogus x]), the compiler doesn't raise a script-level error. It bakes a "syntax" bytecode into the code, which I found in about 8 places in the source. The error only appears at run time, and only if that code is reached, so a mistake can sit dormant in production code for years.

    So Claude and I wrote a scanner. Under Magicsplat, with its large package set, we loaded every package we could and used [info proc] to list every proc, since sourcing defines them without running them. Then we used disassemble/getbytecode to force all of them to compile, over 20k procs, and searched the bytecode for the syntax instruction. We found only 8 or 9.

    I then added checks for patterns a peephole could optimize. One example is a temp variable whose bytecode could be dropped, but only when no trace or uplevel is in play, since either could need the temp to stay.

    Next I looked for commands that were heavily used but not inlined, and found lrange. Since Claude can now build Tcl in his sandbox and test his own code, I asked him to inline it. He did, and he used validation tools I'd never heard of.

    I'm having tons of fun with this. It may be my $20 a month level that makes it work so well, but it beats a cable subscription. :)

    -eric
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Olivier@[email protected] to comp.lang.tcl on Thu Oct 8 08:23:37 2026
    From Newsgroup: comp.lang.tcl


    et99 <[email protected]> posted:

    On 10/7/2026 12:25 PM, Olivier wrote:

    et99 <[email protected]> posted:

    Hi all:

    This experiment started as a side effect of a tool Claude and
    I wrote to scan every proc in every package of a Magicsplat install,
    looking for bytecode problems.

    Eric


    Is your work something similar to Donal Fellows ("Optimizing Tcl Bytecode") ?
    I mean by supplying Donal Fellow's recommendations to Claude, it could improve something in Tcl speed, at least in the range of functionalities you have explored ?

    In fact I don't know if his work has been applied or not.

    Olivier.

    Hi Olivier:

    Short answer: kinda, I'm aware of Donal's peephole work in the core, and the assemble documentation has a section on it. But I imagine he's also working on other optimizations. My own scanning is a different thing, though. It's read-only analysis of compiled bytecode, not an optimizer.

    Next I looked for commands that were heavily used but not inlined, and found lrange. Since Claude can now build Tcl in his sandbox and test his own code, I asked him to inline it. He did, and he used validation tools I'd never heard of.

    I'm having tons of fun with this. It may be my $20 a month level that makes it work so well, but it beats a cable subscription. :)

    -eric

    This is the question I had in mind but dare not to ask. 20 $ to analyze
    20 000 procedures, it is not expensive but there is probably some dumping
    at the moment. Improving code with AI under the look of experimented programmers
    can be a good thing once we really know the actual cost for it.
    Thanks for having report your work, it is very interesting.

    Olivier.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Rich@[email protected] to comp.lang.tcl on Thu Oct 8 14:07:16 2026
    From Newsgroup: comp.lang.tcl

    et99 <[email protected]> wrote:
    One interesting find along the way: when a command's compile routine
    hits an error (for example [format %d notanumber] or [string is bogus
    x]), the compiler doesn't raise a script-level error. It bakes a
    "syntax" bytecode into the code, which I found in about 8 places in
    the source. The error only appears at run time, and only if that
    code is reached, so a mistake can sit dormant in production code for
    years.

    That is likely to match Tcl interpreted script behavior. An 'if'
    clause (say for checking for an incorrect data in a var) that is not
    exercised by an explicit test can also hold a syntax error (the
    interpreter will only care that the 'if' body has matching curly braces
    at parse time) that can lay dormant until one day, years in the future,
    the incorrect data being tested for finally makes the 'if' test true,
    then the body is executed, and the syntax error can manifest itself.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From saito@[email protected] to comp.lang.tcl on Thu Oct 8 14:34:12 2026
    From Newsgroup: comp.lang.tcl

    On 10/6/2026 9:19 PM, et99 wrote:

    I asked Claude (Anthropic's AI assistant), working in its sandbox with access to the GitHub mirror of the Tcl source, to add a new listRange instruction that always takes exactly three values from the stack: the
    list and both indices. It took about 20 minutes to get a complete patch
    with tests, after many build and test runs in the sandbox, including AddressSanitizer, Tcl's memory-debug build and the TCL_COMPILE_DEBUG
    build. I copied the changed files into my own tree, built, and ran the
    tests and a benchmark on two of my machines. Claude ran the same
    benchmark in its sandbox, which is the third column below.


    An AI assistant already knows about bytecodes to the degree that it can optimize it? Truly impressive.

    Question/Suggestion: Expect on Windows is basically abandoned software
    at this point, and other platforms may follow suit soon. It is a nice
    piece of software and it seems to be popular enough to receive attention
    in articles and blogs here and there.

    I wonder with your experience in directing Claude if it can offer a
    solution.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Thu Oct 8 11:35:47 2026
    From Newsgroup: comp.lang.tcl

    On 10/8/2026 7:07 AM, Rich wrote:
    et99 <[email protected]> wrote:
    One interesting find along the way: when a command's compile routine
    hits an error (for example [format %d notanumber] or [string is bogus
    x]), the compiler doesn't raise a script-level error. It bakes a
    "syntax" bytecode into the code, which I found in about 8 places in
    the source. The error only appears at run time, and only if that
    code is reached, so a mistake can sit dormant in production code for
    years.

    That is likely to match Tcl interpreted script behavior. An 'if'
    clause (say for checking for an incorrect data in a var) that is not exercised by an explicit test can also hold a syntax error (the
    interpreter will only care that the 'if' body has matching curly braces
    at parse time) that can lay dormant until one day, years in the future,
    the incorrect data being tested for finally makes the 'if' test true,
    then the body is executed, and the syntax error can manifest itself.

    Yes, quite true. The trick here was to use the fact that the compiler already found an error, but simply stashed that info away. Using getbytecode (better than disassemble, since the later truncates some text) one can find the syntax error bytecode. It has a specific signature, two pushes and then the syntax bytecode.

    In order to load all the packages, I needed to use a subprocess to first try to do the package require, since many would fail, and a few would crash or hang tcl when trying, maybe on loading a dll. If they loaded, then the main process would use them.

    The ones that are t1-t7 were my test cases based on finding them in the tcl core code via a grep search.

    if { $known } {
    proc t1 {} {format %d nontanumber; set foo bar; format %x foo}
    proc t2 {} { throw {"} "some message" }
    proc t3 {} { subst {[format}} ;# "
    proc t4 {} { string is bogus "somevalue" }
    proc t5 {} { tcl::unsupported::assemble {push 1
    push 2} }
    proc t6 {} { tcl::unsupported::assemble {bogusOpcode} }


    # t7: trips TclCompileScript's own "too many nested compilations (infinite
    # loop?)" guard (iPtr->numLevels / 5 > iPtr->maxNestingDepth / 4). This is a
    # compile-time recursion-depth check against runaway nested compilation of
    # things like deeply nested "if" bodies -- 2000 levels comfortably clears
    # the default threshold (~1250 with the default recursionlimit of 1000)
    # with margin to spare on builds with a different default.
    proc make_nested_if_body {n} {
    set open [string repeat "if {1} {" $n]
    set close [string repeat "}" $n]
    return "${open}set x 1${close}"
    }
    interp recursionlimit {} 50
    proc t7 {} [make_nested_if_body 500]
    }


    Here's the output. There's one that appears to have been the result of copy/paste of some code into several places. In the case of format, it only does this if everything is literal text, i.e. not a variable.


    Discovered 917 package(s); 804 loaded into this interpreter, 113 failed.

    === Packages that failed to load ===

    <snip>

    Found 22991 procs - scanning now please wait

    === Procs that errored during getbytecode ===
    :::: ":::" isn't a procedure

    === Procs with a bytecode-level (dormant) error opcode ===




    <These were from my test cases>:




    ::t1 (2 occurrence(s))
    at offset 10:
    message : expected integer but got "nontanumber"
    errorcode: TCL VALUE NUMBER
    -code : 1

    at offset 41:
    message : expected integer but got "foo"
    errorcode: TCL VALUE NUMBER
    -code : 1

    ::t2 (1 occurrence(s))
    at offset 16:
    message : unmatched open quote in list
    errorcode: TCL VALUE LIST QUOTE
    -code : 1

    ::t3 (1 occurrence(s))
    at offset 15:
    message : missing close-bracket
    errorcode: NONE
    -code : 1

    ::t4 (1 occurrence(s))
    at offset 10:
    message : bad class "bogus": must be alnum, alpha, ascii, control, boolean, dict, digit, double, entier, false, graph, integer, li... (truncated, 197 chars total)
    errorcode: TCL LOOKUP INDEX class bogus
    -code : 1

    ::t5 (1 occurrence(s))
    at offset 10:
    message : stack is unbalanced on exit from the code (depth=2)
    errorcode: TCL ASSEM BADSTACK
    -code : 1

    ::t6 (1 occurrence(s))
    at offset 10:
    message : bad instruction "bogusOpcode": must be push, add, append, appendArray, appendArrayStk, appendStk, arrayExistsImm, arrayE... (truncated, 1661 chars total)
    errorcode: TCL LOOKUP INDEX instruction bogusOpcode
    -code : 1

    ::t7 (1 occurrence(s))
    at offset 10:
    message : too many nested compilations (infinite loop?)
    errorcode: TCL LIMIT STACK
    -code : 1



    <These are from the packages>:




    ::asn::asnGetT61String (1 occurrence(s))
    at offset 444:
    message : not enough arguments for all format specifiers
    errorcode: TCL FORMAT FIELDVARMISMATCH
    -code : 1

    ::controlwidget::verticalAxis::Snit_methodcomputeLogHeight (1 occurrence(s))
    at offset 279:
    message : unbalanced open paren
    in expression "...tom) - $options(-ytop)"
    errorcode: TCL PARSE EXPR UNBALANCED
    -code : 1

    ::math::geometry::areaParallellogram (1 occurrence(s))
    at offset 88:
    message : unbalanced open paren
    in expression "...($x2 * $y1 - $x1 * $y2"
    errorcode: TCL PARSE EXPR UNBALANCED
    -code : 1

    ::critcl::MakeScalarLimited (1 occurrence(s))
    at offset 2155:
    message : missing operator at _@_
    in expression "$minop_@_$maxop eq ">=<=")"
    errorcode: TCL PARSE EXPR MISSING
    -code : 1

    ::diagram::core::geo::areaParallellogram (1 occurrence(s))
    at offset 88:
    message : unbalanced open paren
    in expression "...($x2 * $y1 - $x1 * $y2"
    errorcode: TCL PARSE EXPR UNBALANCED
    -code : 1

    ::diagram::basic::geo::areaParallellogram (1 occurrence(s))
    at offset 88:
    message : unbalanced open paren
    in expression "...($x2 * $y1 - $x1 * $y2"
    errorcode: TCL PARSE EXPR UNBALANCED
    -code : 1

    ::diagram::element::geo::areaParallellogram (1 occurrence(s))
    at offset 88:
    message : unbalanced open paren
    in expression "...($x2 * $y1 - $x1 * $y2"
    errorcode: TCL PARSE EXPR UNBALANCED
    -code : 1

    ::diagram::point::geo::areaParallellogram (1 occurrence(s))
    at offset 88:
    message : unbalanced open paren
    in expression "...($x2 * $y1 - $x1 * $y2"
    errorcode: TCL PARSE EXPR UNBALANCED
    -code : 1

    Done


    -et


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Thu Oct 8 12:09:11 2026
    From Newsgroup: comp.lang.tcl

    On 10/8/2026 1:23 AM, Olivier wrote:
    <snip>
    This is the question I had in mind but dare not to ask. 20 $ to analyze
    20 000 procedures, it is not expensive but there is probably some dumping
    at the moment. Improving code with AI under the look of experimented programmers
    can be a good thing once we really know the actual cost for it.
    Thanks for having report your work, it is very interesting.

    Olivier.


    The $20 isn't the cost of doing the scan. That I did on my own computer, although claude also ran it in his sandbox to check the coding. The $20 pro subscription lets me work with claude without interruption where the free tier would often make you wait for a new 5 hour block to start using again. There's also a weekly limit, but I've never exceeded that. The 5 hour limit is still there with pro, but allows me much more usage. You can check the status page to see where you are and when getting close it tells you.

    I also have a small $10 wallet that can be used (and replenished) on a per use to continue after reaching the limit. This year, I've used only $2.70 of it.

    I think the 20 minutes he took to analyze then code the inlining of lrange might have used 5-10% of my 5 hour allocation.

    -et



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Thu Oct 8 12:24:56 2026
    From Newsgroup: comp.lang.tcl

    On 10/8/2026 11:34 AM, saito wrote:
    On 10/6/2026 9:19 PM, et99 wrote:

    I asked Claude (Anthropic's AI assistant), working in its sandbox with access to the GitHub mirror of the Tcl source, to add a new listRange instruction that always takes exactly three values from the stack: the list and both indices. It took about 20 minutes to get a complete patch with tests, after many build and test runs in the sandbox, including AddressSanitizer, Tcl's memory-debug build and the TCL_COMPILE_DEBUG build. I copied the changed files into my own tree, built, and ran the tests and a benchmark on two of my machines. Claude ran the same benchmark in its sandbox, which is the third column below.


    An AI assistant already knows about bytecodes to the degree that it can optimize it? Truly impressive.

    Question/Suggestion: Expect on Windows is basically abandoned software at this point, and other platforms may follow suit soon. It is a nice piece of software and it seems to be popular enough to receive attention in articles and blogs here and there.

    I wonder with your experience in directing Claude if it can offer a solution.



    Well, the only way to find out is to give him the code to look at. In my bytecode experimenting I found some wiki code written back in 2013 by Richard Suchenwirth which no longer worked because of changes in the dissasembler output. Claude read the code, and resurrected it. This was a small case, but, if you can paste in all the code, he could probably give you an answer.

    The one thing that does come up a lot is that he isn't able to read just everything on the internet. Many sites block his access. He had to find a way to get to the tcl source code using a github mirror, where I normally just access it directly at https://core.tcl-lang.org.

    He only seems to have a linux sandbox, so you would have to do the testing for him. But with the sandbox, things are so much faster, he gives me code that he's checked himself now rather than code that I have to test. This means much less back and forth. I'm afraid with Expect on windows, you'd have to be his tester.

    -et

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Thu Oct 8 15:41:17 2026
    From Newsgroup: comp.lang.tcl

    On 10/8/2026 12:24 PM, et99 wrote:
    On 10/8/2026 11:34 AM, saito wrote:
    On 10/6/2026 9:19 PM, et99 wrote:

    I'm afraid with Expect on windows, you'd have to be his tester.

    I stand corrected on this, if you look at today's core email by Serhiy Storchaka on the bug fixes he's been working on lately, and quite rapidly, he says he uses claude code and it does have a vm sandbox for windows 11.

    Claude code is a different product/tier than the claude pro I use.

    -e

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From saito@[email protected] to comp.lang.tcl on Fri Oct 9 17:10:24 2026
    From Newsgroup: comp.lang.tcl

    On 10/8/2026 6:41 PM, et99 wrote:
    On 10/8/2026 12:24 PM, et99 wrote:
    On 10/8/2026 11:34 AM, saito wrote:
    On 10/6/2026 9:19 PM, et99 wrote:

    I'm afraid with Expect on windows, you'd have to be his tester.

    I stand corrected on this, if you look at today's core email by Serhiy Storchaka on the bug fixes he's been working on lately, and quite
    rapidly, he says he uses claude code and it does have a vm sandbox for windows 11.

    Claude code is a different product/tier than the claude pro I use.

    Thanks for the info. I can test it if there is a package ready for
    package req command. Otherwise, I am not able to spend any time on this unfortunately at the moment. Indeed it would be interesting to spend
    sometime with these agents to build and fix things.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@[email protected] to comp.lang.tcl on Sat Oct 10 13:11:57 2026
    From Newsgroup: comp.lang.tcl

    Well, again I was wrong. Claude doesn't have a windows vm, it appears that Serhly has one and allows claude access to it over ssh. I found that the pro level includes claude code, but it's rather command line oriented, and I don't know if there's a web interface also.

    I did however just load the claude app on my phone, but couldn't figure out how to get notifications to show up on the phone for knowing when claude on my desktop needed to ask permission or tell me he was done. But it has a text to speech button with a very nice voice.

    -et



    On 10/9/2026 2:10 PM, saito wrote:
    On 10/8/2026 6:41 PM, et99 wrote:
    On 10/8/2026 12:24 PM, et99 wrote:
    On 10/8/2026 11:34 AM, saito wrote:
    On 10/6/2026 9:19 PM, et99 wrote:

    I'm afraid with Expect on windows, you'd have to be his tester.

    I stand corrected on this, if you look at today's core email by Serhiy Storchaka on the bug fixes he's been working on lately, and quite rapidly, he says he uses claude code and it does have a vm sandbox for windows 11.

    Claude code is a different product/tier than the claude pro I use.

    Thanks for the info. I can test it if there is a package ready for package req command. Otherwise, I am not able to spend any time on this unfortunately at the moment. Indeed it would be interesting to spend sometime with these agents to build and fix things.



    --- Synchronet 3.22a-Linux NewsLink 1.2