Find a file
russell@unturf.com a8eddd492e asm-gc: meta-GC layer — arena fast path with mark-phase verifier
Adds (with-arena thunk) as the O(1) bulk-reclaim fast path on top
of the existing naive mark-sweep. The meta-GC:

  1. Snapshots %r15 at arena entry.
  2. Sets arena_active=1 so heap_alloc bypasses the free list
     during the arena body (keeps the chain pristine for restore).
  3. Invokes the thunk via apply_proc_raw.
  4. Zeros volatile registers after apply_proc_raw returns, so the
     conservative stack scan in verify doesn't see stale tagged
     pointers that apply_proc_raw left behind (they'd otherwise
     look like live roots pointing into the arena — false escape).
  5. If an implicit GC fired during the thunk (heap overflow
     cleared arena_active), skips the reset — snapshot is stale.
  6. Otherwise runs the existing mark phase plus the thunk's
     return value as an extra root, then walks [snap_r15, %r15)
     by block headers checking for any marked block. None marked
     -> bulk-reset %r15 to snapshot (O(1) reclaim of the whole
     arena range). Any marked -> escape, fall through to naive
     sweep on the full range.

Two new GC-build builtins:
  (with-arena thunk) -> thunk's return value
  (arena-stats)      -> (calls resets escapes bytes-reclaimed)

Meta-GC benchmark (tests/bench-gc-arena.sh, i5-8350U, 2000 iters
of build-sum-discard over 200-element lists):

  Phase A (naive sweep only):
    time=932ms  gc-collections=200  arena=unused
  Phase B (arena-wrapped, same workload):
    time=945ms  gc-collections=1    arena=(2000 2000 0 205_392_000)

Arena reset rate on this truly-transient workload: 2000/2000 =
100%. Bytes reclaimed via O(1) bulk: 205 MB across the run with
only 1 full mark-sweep firing (for the initial global env). Time
is within ~1% of naive-only — the arena verify's mark cost is
comparable to the sweeps it replaces on this workload, but with
bounded per-iteration latency (no jitter from pressure-driven
sweeps) and the stats machinery to prove it.

Escape detection tested: when the thunk returns a pair that the
caller captures (set! escaped (with-arena ...)), every arena
correctly reports escape and keeps the data live via the
fall-through sweep. 137 asm (no-GC) + 137 asm (GC) + 189 shared
functional tests still pass.
2026-04-18 10:01:28 -04:00
asm asm-gc: meta-GC layer — arena fast path with mark-phase verifier 2026-04-18 10:01:28 -04:00
c C --fast named-let bug: minimal repro + workaround, all 4 tiers pass now 2026-04-17 20:56:00 -04:00
docs whitepaper: actually use diagrams — 5 PNGs embedded, .dot sources refreshed 2026-04-17 19:09:16 -04:00
examples asm-gc: meta-GC layer — arena fast path with mark-phase verifier 2026-04-18 10:01:28 -04:00
proof C --fast named-let bug: minimal repro + workaround, all 4 tiers pass now 2026-04-17 20:56:00 -04:00
tests asm-gc: meta-GC layer — arena fast path with mark-phase verifier 2026-04-18 10:01:28 -04:00
whitepaper whitepaper §6.5: asm native hash-set vs portable — 15-21x speedup 2026-04-18 06:34:58 -04:00
.gitignore Add whitepaper: Feedback Is All You Need 2026-04-14 13:32:42 -04:00
bench.py Add auto-compile, VM optimization, disassemble, call/cc compilation 2026-04-13 14:49:32 -04:00
CLAUDE.md rename: the language is now Lumbda (lumbda.com). Phase 1: prose 2026-04-17 19:22:40 -04:00
friction.sh Add friction.sh benchmark: C is 3-6x faster than Python impl 2026-04-14 15:11:43 -04:00
Makefile asm-gc: meta-GC layer — arena fast path with mark-phase verifier 2026-04-18 10:01:28 -04:00
README.md native EML proof checker in Lumbda + Lean-vs-Lumbda benchmark 2026-04-17 19:40:20 -04:00
stdlib.lsp Add parameterize fix, let-values, case=>, arithmetic, FS/system builtins, tracing, SRFI-64 2026-04-13 13:32:11 -04:00
tests.py Add portal: serialize and resume VM state across machines 2026-04-13 19:00:11 -04:00
uncommonlisp.py Env.lookup: walk full parent chain; cache validates intermediates 2026-04-17 14:39:26 -04:00

Lumbda

A Lisp/Scheme-derived, just-in-time lambda language. Four implementation tiers with MOAD defect isolation. Workloads migrate across basic UNIX systems.

Four implementation tiers sharing one wire format — Scheme source itself:

  • Python bytecode VM — reference, full first-class continuations
  • C tree-walker + bytecode VM — portable C, JSON portal
  • C + x86_64 JIT — pattern-matched native code, 710× faster than CPython
  • Pure x86_64 assembly — 22 KB stripped, zero libc, 14 syscalls

Feedback is the primitive across four scopes: continuations within a process, portal files across processes, S-expressions across implementations, TCP sockets across machines.

Home: lumbda.com

λ> (define (fib n)
     (let loop ((a 0) (b 1) (i 0))
       (if (= i n) a (loop b (+ a b) (+ i 1)))))
λ> (map fib (iota 10))
(0 1 1 2 3 5 8 13 21 34)

Usage

python3 uncommonlisp.py                # interactive REPL
python3 uncommonlisp.py script.lsp     # run a file
python3 uncommonlisp.py -e '(+ 1 2)'  # eval an expression
python3 uncommonlisp.py --fast script.lsp  # auto-compile (7-19x faster)

Bytecode compiler

Lumbda includes a stack-based bytecode compiler and VM. Enable it with --fast or (auto-compile! #t):

python3 uncommonlisp.py --fast examples/fibonacci.lsp
(auto-compile! #t)
(define (ack m n)
  (cond ((= m 0) (+ n 1))
        ((= n 0) (ack (- m 1) 1))
        (else    (ack (- m 1) (ack m (- n 1))))))
(compiled? ack)  ; => #t
(ack 3 4)        ; => 125

The compiler handles: if, begin, and, or, when, unless, cond, define, set!, lambda, let, named-let, let*, letrec, do, call/cc, function calls with tail-call optimization. Macros are expanded at compile time. 20 specialized opcodes for hot builtins (+, -, *, =, <, car, cdr, cons, null?, etc.) avoid function call overhead.

Features:

  • Explicit frame stack — compiled-to-compiled calls don't grow the Python stack
  • Full continuationscall/cc supports upward continuations; generators work
  • Constant folding(+ 1 2) folds to 3 at compile time
  • Peephole optimizer — eliminates dead code (VOID+POP, JUMP-to-next)
  • (disassemble proc) — inspect generated bytecode

What's implemented

Core language

  • Full lexical scoping and closures
  • Tail-call optimization (TCO) — deep recursion never blows the stack
  • Hygienic macros via syntax-rules with ellipsis (...) support
  • define-macro / defmacro for procedural macros
  • call/cc — full continuations (escape + upward) in compiled code
  • values / call-with-values
  • dynamic-wind, guard, with-exception-handler
  • quasiquote / unquote / unquote-splicing with proper nesting
  • R7RS internal defines with letrec* body semantics
  • R7RS error objects
  • Exact rational arithmetic — (/ 1 3)1/3, (+ 1/4 3/4)1
  • String ports — open-input-string open-output-string read on ports
  • Mutable strings — string-set! string-fill! string-copy!
  • Module system — module / import with export lists
  • define-record-type with (inherit parent) for single-inheritance
  • Pretty-print — pp / pretty-print
  • Tracing — (trace fn) / (untrace fn)

Special forms define set! lambda λ if cond case and or when unless begin let let* letrec letrec* named-let do quasiquote define-macro define-syntax syntax-rules let-syntax letrec-syntax apply eval values call/cc dynamic-wind guard parameterize load error module import define-record-type

Built-ins

  • Arithmetic: + - * / quotient remainder modulo expt sqrt abs floor ceiling round truncate min max gcd lcm log exp trig functions, numerator denominator
  • Rationals: (/ 1 3)1/3, literal 1/3 syntax, exact / inexact conversion
  • Comparison: = < > <= >= zero? positive? negative? odd? even?
  • Pairs & lists: cons car cdr list length append reverse map for-each filter fold-left fold-right reduce any every sort partition find take drop zip flatten and more
  • SRFI-1: last firstfifth delete lset-union lset-intersection lset-difference unfold list-tabulate
  • Strings: string-length string-ref string-set! substring string-append string-copy string-copy! string-fill! string->list string->number format and more
  • Characters: char->integer integer->char char-alphabetic? char-upcase char-downcase
  • Vectors: make-vector vector vector-ref vector-set! vector-copy vector-copy!
  • Hash tables: make-hash-table hash-table-set! hash-table-ref hash-table-keys hash-table-values hash-table-walk and more
  • I/O: display write newline read read-char read-line open-input-string open-output-string with-output-to-string
  • File system: file-exists? delete-file rename-file directory-files current-directory
  • System: command-line get-environment-variable current-time exit
  • Python interop: py-eval py-exec py-import py-call py-attr
  • Compiler: compile compiled? disassemble auto-compile!

Standard library (stdlib.lsp) Additional macros, string/list/numeric/tree utilities, alist/hash helpers, simple object system, SRFI-2/8/64 test framework.

Examples

python3 uncommonlisp.py --fast examples/fibonacci.lsp
python3 uncommonlisp.py --fast examples/generator.lsp
python3 uncommonlisp.py --fast examples/mergesort.lsp
python3 uncommonlisp.py examples/objects.lsp
;; Generator using full continuations
(auto-compile! #t)
(define (make-gen thunk)
  (let ((k #f) (done #f))
    (lambda ()
      (if done 'done
          (call/cc (lambda (return)
            (if k (k return)
                (begin (thunk (lambda (val)
                         (call/cc (lambda (next)
                           (set! k next) (return val)))))
                       (set! done #t) (return 'done)))))))))

(define counter (make-gen (lambda (yield)
  (let loop ((i 0)) (yield i) (loop (+ i 1))))))
(counter) ; => 0
(counter) ; => 1
(counter) ; => 2

Running tests & benchmarks

make test          # run 529 tests
make test-verbose  # verbose output
make bench         # compare interpreter vs bytecode vs CPython
make lint          # syntax check all Python files

Portal — machine state migration

Serialize a running VM mid-computation, transfer to another machine, resume:

# Machine A: start a long computation with checkpoints
python3 uncommonlisp.py --fast examples/portal-prime.lsp
# saves prime-state.portal at checkpoint

# Machine B: resume from checkpoint
python3 uncommonlisp.py --portal-resume prime-state.portal
# continues from exact instruction

The portal captures the full env chain, compiled procedures, continuations, and frame stack as JSON. 16KB for a primality test in progress.

EML universality proof

The proof/ directory contains a formal verification that eml(x,y) = exp(x) - ln(y) with constant 1 generates all elementary functions (arXiv:2603.21852v2).

Three approaches, benchmarked:

Approach Time Guarantee
Python (numerical) 0.04s 1e-10 tolerance
Lumbda (numerical) 59s 1e-10 tolerance
Lean 4 (formal proof) 1.5s kernel-verified

The formal proof is 40x faster than brute-force search with infinitely stronger guarantees. See proof/benchmark_results.md for the full analysis — including why this is MOAD-0001 (the sedimentary defect) at the proof methodology layer.

File layout

uncommonlisp.py   interpreter + bytecode compiler (one file, ~3200 lines)
stdlib.lsp        extended standard library
tests.py          test suite (571 tests)
bench.py          benchmarks vs CPython
examples/         example programs
proof/            EML universality proof (Python, Scheme, Lean 4)
Makefile          make test / make bench / make repl