TBCX

Tcl Bytecode eXchange tbcx 1.0 Oct 22, 2025

NAME

tbcx - serialize, load, and inspect precompiled Tcl 9.1 bytecode (procs, OO methods, and lambdas)

SYNOPSIS

        
          tbcx::save in out
          tbcx::load in
          tbcx::dump filename
      

DESCRIPTION

The tbcx extension provides three subcommands that enable an efficient save → load → eval pipeline for Tcl 9.1 scripts.

The goal is to pay the cost of parsing/compiling at save time so that loading is as fast as reading a compact binary, while remaining functionally equivalent to source of the original script.

Artifacts store the compiled top-level, precompiled proc bodies, TclOO method/ctor/dtor bodies, and lambda literals for use with apply. Loading installs these into the current interpreter and executes the top-level block in the caller's current namespace.

COMMANDS

tbcx::save in out

Synopsis

Compile a script and write a .tbcx artifact.

Parameters

in One of:

  • String - a Tcl string value containing the script text.
  • Readable channel - an open channel; the command enforces binary-safe reads.
  • Readable path - a filesystem path to a script file; it is opened, read, and closed by tbcx::save.

out One of:

  • Writable channel - an open channel; the command writes binary data and does not close the channel.
  • Writable path - a filesystem path for the new .tbcx file; it is created/truncated and closed on return.

Behavior

  • Compiles the top-level block, discovers and precompiles proc bodies and TclOO method/ctor/dtor bodies, and captures lambda literals as lambda-bytecode literals (for apply).
  • Serializes the header, top-level block, Procs table, Classes catalog (advisory), and Methods table.

Returns

The output object: either the normalized path written, or the writable channel handle.

Errors

Typical errors include: unreadable input; unwritable output; version/format mismatch; unknown/unsupported AuxData; size limit exceeded (code, literals, AuxData, exception ranges, strings); short read/write.

The interpreter result contains a descriptive message.

Notes

  • Channels are treated as binary for portability; encodings are not altered on the caller's behalf, and channels are not closed.
  • The produced artifact is intended for Tcl 9.1; other versions are rejected at load time.

Examples

          # Save from path \-> path
            set path [tbcx::save ./app.tcl ./app.tbcx]
            # Save from string value \-> path
            set script {proc hi {} {puts Hello}; hi}
            tbcx::save $script ./hello.tbcx
            # Save from channel \-> channel
            set in  [open ./lib/foo.tcl r]
            set out [open ./foo.tbcx w]
            fconfigure $in  -translation binary -eofchar {}
            fconfigure $out -translation binary -eofchar {}
            try {
              tbcx::save $in $out
            } finally {
              close $in
              close $out
            }
          
        

tbcx::load in

Synopsis

Load a .tbcx artifact, install precompiled entities, and execute the top-level block.

Parameters

in One of:

  • Readable channel - an open channel positioned at the beginning of a .tbcx stream (binary).
  • Readable path - a filesystem path to a .tbcx file.

Behavior

  • Validates header and producer version; deserializes sections.
  • Materializes procs and TclOO methods (ctors/dtors) from precompiled bodies.
  • Rehydrates lambda-bytecode literals so the first apply incurs no compilation.
  • Executes the precompiled top-level block in the caller's current namespace.

Returns

Empty string on success.

Errors

Typical errors include: unreadable input; bad header; incompatible Tcl version; malformed/unknown section; size limit exceeded; short read; class or namespace creation errors during top-level evaluation.

Notes

  • Load in a specific namespace by wrapping the call: namespace eval ::pkg { tbcx::load ./app.tbcx }
  • Loading executes code; only load artifacts from trusted sources.

Examples

          # Load into current namespace
          tbcx::load ./app.tbcx
          # Load into a dedicated namespace
          namespace eval ::app { tbcx::load ./app.tbcx }
          # Load from an open channel
          set ch [open ./app.tbcx r]
          fconfigure $ch -translation binary -eofchar {}
          try {
          tbcx::load $ch
          } finally {
          close $ch
          }
          
        

tbcx::dump filename

Synopsis

Disassemble and describe a .tbcx artifact in human-readable form.

Parameters

filename A readable path to a .tbcx file.

Behavior

Reads the artifact and prints: header fields; section summaries; literals and AuxData; exception ranges;

and a disassembly of the top-level, proc, method, and lambda bodies.

Returns

A string containing the formatted dump.

Errors

Unreadable file; bad header; malformed section; short read.

Examples

          % package require tbcx
          % tbcx::save {set a 1} out
          % tbcx::dump out
          TBCX Header:
          magic = 0x58434254 ('T''B''C''X')
          format = 9
          tcl_version = 9.1.0 (type 0)
          top: code=12, except=0, lits=2, aux=0, locals=1, stack=2
          Top-level block:
          Disassembly (top-level):
          ByteCode 0x7f9963089e10, refCt 1, epoch 20, interp 0x7f9963816a10 (epoch 20)
          Source ""
          Cmds 0, src 0, inst 11, litObjs 1, aux 0, stkDepth 1, code/src 0.00
          (0) push 0 	# "1"
          (5) storeScalar %v0
          (10) done
          code=11, stack=1, lits=1, aux=0, except=0
          Locals (1):
          [0] "a"
          Literals:
          [0] (bignum) 1
          Procs: 0
          Classes: 0
          Methods: 0
          
        

FILE FORMAT (OVERVIEW)

This section summarizes the on-disk structure.

Header Magic + format version + producing Tcl version; size/count metadata for the top-level block (code length, literal count, AuxData count, exception ranges, locals, max stack).

Sections (order) (1) Top-level block (code, literals, AuxData, exceptions, locals epilogue); (2) Procs (FQN, ns, arg spec, compiled block); (3) Classes (advisory catalog; actual creation occurs at load time); (4) Methods (class, kind, name, args, compiled block).

Literal kinds boolean, (wide)int/uint, double, bignum, string, bytearray, list, dict, embedded bytecode, and lambda-bytecode literals for use with apply.

AuxData families jump tables (string or numeric), dictupdate, foreach (legacy/new).

LAMBDA SUPPORT

Literals in the script that represent lambdas for apply (lists of the form {args body ns?}) are compiled and serialized as lambda-bytecode literals at save time.

On load, both the compiled body and the optional namespace element are rehydrated so that the first call to apply does not trigger compilation.

SEMANTICS AND PERFORMANCE

Artifacts are portable across little- and big-endian hosts. The loader detects host byte order once and applies a tight in-place swap over bulk sections that require conversion, avoiding per-field branching so cross-endian loads remain close to native performance.

Loading executes the precompiled top-level, then installs precompiled proc/method bodies and rehydrates lambda literals. The intent is to be functionally indistinguishable from source of the original script, with the benefit of faster startup due to avoided parsing/compilation.

LIMITS

Sanity caps exist for code size, literal count (including lambdas), AuxData count, exception ranges, and string lengths. Exceeding limits produces an error.

DIAGNOSTICS

Representative messages include: "bad header", "incompatible Tcl version", "short read/write", "unsupported AuxData kind", "input is neither an open channel nor a readable file", and "errors while evaluating top-level".

SECURITY

Loading executes code. Only load artifacts you trust.

SEE ALSO

source(n), TclOO(n)

© 2025 Miguel Banon

MIT License.

↑ Top