rename: uncommonlisp -> lumbda throughout the repo

Historical internal name "uncommonlisp" retired in favor of the
public name "lumbda" ahead of lumbda.com going live. Scope of
this commit:

Source files renamed:
  uncommonlisp.py                     -> lumbda.py
  asm/uncommonlisp.s                  -> asm/lumbda.s
  c/uncommonlisp.h                    -> c/lumbda.h
  whitepaper/uncommonlisp-whitepaper  -> whitepaper/lumbda-whitepaper (.rst + .pdf)

Binaries renamed (tracked ones; c/ was always gitignored):
  asm/uncommonlisp, asm/uncommonlisp-gc, asm/uncommonlisp.o,
  asm/uncommonlisp-gc.o                -> asm/lumbda(-gc)(.o)
  c/.gitignore                          -> ignores lumbda

Internal string updates (sed pass ordered longest-first):
  asm/uncommonlisp -> asm/lumbda
  c/uncommonlisp   -> c/lumbda
  uncommonlisp.py  -> lumbda.py
  UNCOMMONLISP_BIN -> LUMBDA_BIN (asm/test.sh env var)
  "uncommonlisp> " -> "lumbda> " (asm REPL prompt baked into binary)
  UNCOMMONLISP     -> LUMBDA (macros, comments)
  uncommonlisp     -> lumbda (prose)

Binary portal magic updated:
  "ULPORTAL" -> "LUMBDAB1"   # "Lumbda Binary v1"
Old portal files are not backward-compatible — this is a deliberate
break since it's the rename moment. S-expression portals already
carry their own ";; lumbda-portal v1" header and remain cleanly
versioned.

WHITEPAPER.pdf / WHITEPAPER.rst symlinks repointed to the renamed
files. Makefile's whitepaper target targets lumbda-whitepaper.pdf.

Not changed (intentional, separate phases):
  - Filesystem directory /home/fox/git/uncommonlisp itself
    (fox renames locally and the gitlab repo URL in a follow-up)
  - tests.py hardcoded cwd=/home/fox/git/uncommonlisp
    (matches the current on-disk location; will flip when the
    directory rename ships)
  - Git history (immutable; old commits still say uncommonlisp,
    which is correct — that's what they were)

Verified:
  137 asm no-GC + 137 asm GC + 571 Python + 83 C + 189 shared
  functional tests all pass under the new names.
  bench-gc-http (2000 req): all 4 cells behave as expected
  (cells 1/2 flat, 3 leaks, 4 bounded at 1 chunk).
  Python REPL, C REPL, asm REPL all start cleanly.
This commit is contained in:
russell@unturf.com 2026-04-19 10:20:11 -04:00
parent 9e54c7aaf1
commit f7352b51b0
77 changed files with 383 additions and 383 deletions

View file

@ -1,6 +1,6 @@
# Agent Blackops — Lumbda repo # Agent Blackops — Lumbda repo
This repo is operated by **agent blackops** — ml agent for fox/timehexon on the unsandbox/unturf/permacomputer platform. **Lumbda** is the language (home: lumbda.com); the repo directory and binaries still use the historical name `uncommonlisp` until the filesystem rename ships in a later phase. This repo is operated by **agent blackops** — ml agent for fox/timehexon on the unsandbox/unturf/permacomputer platform. **Lumbda** is the language (home: lumbda.com); the repo directory and binaries still use the historical name `lumbda` until the filesystem rename ships in a later phase.
## Identity ## Identity
@ -39,7 +39,7 @@ Then ask fox what the mission is.
| Impl | Path | Build | Test | REPL | | Impl | Path | Build | Test | REPL |
|------|------|-------|------|------| |------|------|-------|------|------|
| Python | `uncommonlisp.py` | — | `make test` | `make repl` | | Python | `lumbda.py` | — | `make test` | `make repl` |
| C | `c/` | `make c-build` | `make c-test` | `make c-repl` | | C | `c/` | `make c-build` | `make c-test` | `make c-repl` |
| Assembly | `asm/` | `make asm-build` | `make asm-test` | `make asm-repl` | | Assembly | `asm/` | `make asm-build` | `make asm-test` | `make asm-repl` |
| All | — | — | `make test-all` | — | | All | — | — | `make test-all` | — |
@ -75,22 +75,22 @@ crash is not just "my problem" — it takes their state down too.
The rules below are belt, suspenders, AND a parachute so that even The rules below are belt, suspenders, AND a parachute so that even
if two safeguards fail, the kernel itself backstops. if two safeguards fail, the kernel itself backstops.
**MANDATORY pattern — every asm/uncommonlisp test in a shell block:** **MANDATORY pattern — every asm/lumbda test in a shell block:**
```bash ```bash
set -e # (1) fail-fast set -e # (1) fail-fast
ulimit -v 524288 # (2) KERNEL CAP: 512 MB virt ulimit -v 524288 # (2) KERNEL CAP: 512 MB virt
# process gets SIGKILL at cap, no matter what # process gets SIGKILL at cap, no matter what
trap 'pkill -9 -u "$USER" -f "examples/http-server|asm/uncommonlisp" 2>/dev/null || true' \ trap 'pkill -9 -u "$USER" -f "examples/http-server|asm/lumbda" 2>/dev/null || true' \
EXIT INT TERM # (3) cleanup always fires EXIT INT TERM # (3) cleanup always fires
timeout 30 asm/uncommonlisp < server.lsp & # (4) wall-clock ceiling timeout 30 asm/lumbda < server.lsp & # (4) wall-clock ceiling
SPID=$! SPID=$!
# ... do the work (curl requests, measurements, etc.) ... # ... do the work (curl requests, measurements, etc.) ...
kill -9 $SPID 2>/dev/null; wait $SPID 2>/dev/null # (5) explicit cleanup kill -9 $SPID 2>/dev/null; wait $SPID 2>/dev/null # (5) explicit cleanup
# (6) VERIFY the block is clean before moving on # (6) VERIFY the block is clean before moving on
pgrep -u "$USER" -f 'asm/uncommonlisp|examples/http-server' \ pgrep -u "$USER" -f 'asm/lumbda|examples/http-server' \
&& { echo "STRAGGLER"; exit 1; } || true && { echo "STRAGGLER"; exit 1; } || true
``` ```
@ -108,12 +108,12 @@ Additional rules:
in `examples/http-server.lsp`). Never raise for long-running tests. in `examples/http-server.lsp`). Never raise for long-running tests.
- Use `pkill -u "$USER" -f <pattern>` not `pkill` alone — others may - Use `pkill -u "$USER" -f <pattern>` not `pkill` alone — others may
have their own processes on this machine. have their own processes on this machine.
- Prefer FOREGROUND runs when possible: `timeout 10 asm/uncommonlisp - Prefer FOREGROUND runs when possible: `timeout 10 asm/lumbda
< test.lsp` with the `.lsp` exiting on its own beats backgrounding. < test.lsp` with the `.lsp` exiting on its own beats backgrounding.
- C has Boehm GC via `GC_MALLOC`. Python has Python's GC. Asm has - C has Boehm GC via `GC_MALLOC`. Python has Python's GC. Asm has
neither. Risk scales with how long the asm process lives. neither. Risk scales with how long the asm process lives.
- If `ulimit` is unavailable (some container setups), use - If `ulimit` is unavailable (some container setups), use
`systemd-run --user --scope -p MemoryMax=512M -- asm/uncommonlisp ...` `systemd-run --user --scope -p MemoryMax=512M -- asm/lumbda ...`
as the equivalent cgroup-based cap. as the equivalent cgroup-based cap.
## MOAD Scanner ## MOAD Scanner
@ -122,10 +122,10 @@ Additional rules:
```bash ```bash
cd ~/git/unmoadner && make all cd ~/git/unmoadner && make all
./unmoad ~/git/uncommonlisp/ # scan entire repo ./unmoad ~/git/lumbda/ # scan entire repo
./unmoad ~/git/uncommonlisp/asm/ # scan assembly only ./unmoad ~/git/lumbda/asm/ # scan assembly only
./unmoad ~/git/uncommonlisp/c/ # scan C only ./unmoad ~/git/lumbda/c/ # scan C only
./unmoad ~/git/uncommonlisp/*.py # scan Python only ./unmoad ~/git/lumbda/*.py # scan Python only
``` ```
**MANDATORY before committing new code:** run `unmoad` on changed files. **MANDATORY before committing new code:** run `unmoad` on changed files.

View file

@ -1,11 +1,11 @@
# ═══════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════
# uncommonlisp — Python + C + Assembly implementations # lumbda — Python + C + Assembly implementations
# ═══════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════
# #
# Implementations: # Implementations:
# Python uncommonlisp.py bytecode VM, full continuations, portal # Python lumbda.py bytecode VM, full continuations, portal
# C c/uncommonlisp tree-walker + bytecode VM + x86_64 JIT # C c/lumbda tree-walker + bytecode VM + x86_64 JIT
# Assembly asm/uncommonlisp pure x86_64, no libc, 13KB binary # Assembly asm/lumbda pure x86_64, no libc, 13KB binary
# #
# Test suites: # Test suites:
# make test Python unit/integration (571 tests) # make test Python unit/integration (571 tests)
@ -50,10 +50,10 @@ bench-verbose:
python3 bench.py -v python3 bench.py -v
repl: repl:
python3 uncommonlisp.py python3 lumbda.py
lint: lint:
python3 -m py_compile uncommonlisp.py python3 -m py_compile lumbda.py
python3 -m py_compile tests.py python3 -m py_compile tests.py
python3 -m py_compile bench.py python3 -m py_compile bench.py
@ -65,13 +65,13 @@ c-build:
c-test: c-build c-test: c-build
$(MAKE) -C c test $(MAKE) -C c test
@echo "── C functional tests (shared .lsp suite) ──" @echo "── C functional tests (shared .lsp suite) ──"
./c/uncommonlisp tests/functional.lsp ./c/lumbda tests/functional.lsp
c-bench: c-build c-bench: c-build
$(MAKE) -C c bench $(MAKE) -C c bench
c-repl: c-build c-repl: c-build
./c/uncommonlisp ./c/lumbda
c-clean: c-clean:
$(MAKE) -C c clean $(MAKE) -C c clean
@ -85,7 +85,7 @@ asm-test: asm-build
$(MAKE) -C asm test $(MAKE) -C asm test
asm-repl: asm-build asm-repl: asm-build
./asm/uncommonlisp ./asm/lumbda
asm-clean: asm-clean:
$(MAKE) -C asm clean $(MAKE) -C asm clean
@ -95,9 +95,9 @@ asm-clean:
functional-test: c-build functional-test: c-build
@echo "═══ Shared functional tests (114 tests) ═══" @echo "═══ Shared functional tests (114 tests) ═══"
@echo "── Python ──" @echo "── Python ──"
@python3 uncommonlisp.py --fast tests/functional.lsp | tail -3 @python3 lumbda.py --fast tests/functional.lsp | tail -3
@echo "── C ──" @echo "── C ──"
@./c/uncommonlisp tests/functional.lsp | tail -3 @./c/lumbda tests/functional.lsp | tail -3
test-all: test c-test asm-test functional-test test-all: test c-test asm-test functional-test
@echo "════════════════════════════════════════════════════" @echo "════════════════════════════════════════════════════"
@ -147,16 +147,16 @@ bench-all: bench c-bench bench-3way bench-portal bench-portal-cross bench-web be
examples: c-build examples: c-build
@echo "═══ fibonacci.lsp ═══" @echo "═══ fibonacci.lsp ═══"
@echo "--- Python ---" && python3 uncommonlisp.py --fast examples/fibonacci.lsp @echo "--- Python ---" && python3 lumbda.py --fast examples/fibonacci.lsp
@echo "--- C ---" && ./c/uncommonlisp examples/fibonacci.lsp @echo "--- C ---" && ./c/lumbda examples/fibonacci.lsp
@echo @echo
@echo "═══ mergesort.lsp ═══" @echo "═══ mergesort.lsp ═══"
@echo "--- Python ---" && python3 uncommonlisp.py --fast examples/mergesort.lsp @echo "--- Python ---" && python3 lumbda.py --fast examples/mergesort.lsp
@echo "--- C ---" && ./c/uncommonlisp examples/mergesort.lsp @echo "--- C ---" && ./c/lumbda examples/mergesort.lsp
@echo @echo
@echo "═══ objects.lsp ═══" @echo "═══ objects.lsp ═══"
@echo "--- Python ---" && python3 uncommonlisp.py examples/objects.lsp @echo "--- Python ---" && python3 lumbda.py examples/objects.lsp
@echo "--- C ---" && ./c/uncommonlisp examples/objects.lsp @echo "--- C ---" && ./c/lumbda examples/objects.lsp
# ─── Friction benchmark ────────────────────────────────────────── # ─── Friction benchmark ──────────────────────────────────────────
@ -176,8 +176,8 @@ docs/%.png: docs/%.dot
# ─── Whitepaper ─────────────────────────────────────────────────── # ─── Whitepaper ───────────────────────────────────────────────────
VENV := whitepaper/.venv VENV := whitepaper/.venv
RST := whitepaper/uncommonlisp-whitepaper.rst RST := whitepaper/lumbda-whitepaper.rst
PDF := whitepaper/uncommonlisp-whitepaper.pdf PDF := whitepaper/lumbda-whitepaper.pdf
STYLE := whitepaper/whitepaper.style STYLE := whitepaper/whitepaper.style
$(VENV)/bin/rst2pdf: $(VENV)/bin/rst2pdf:
@ -191,9 +191,9 @@ $(PDF): $(RST) $(STYLE) $(VENV)/bin/rst2pdf
cd whitepaper && ../$(<D)/.venv/bin/rst2pdf \ cd whitepaper && ../$(<D)/.venv/bin/rst2pdf \
-s whitepaper.style \ -s whitepaper.style \
--fit-background-mode=scale \ --fit-background-mode=scale \
uncommonlisp-whitepaper.rst \ lumbda-whitepaper.rst \
-o uncommonlisp-whitepaper.pdf -o lumbda-whitepaper.pdf
@ln -sf uncommonlisp-whitepaper.pdf whitepaper/WHITEPAPER.pdf @ln -sf lumbda-whitepaper.pdf whitepaper/WHITEPAPER.pdf
@echo "Built: $(PDF)" @echo "Built: $(PDF)"
# ─── Clean ──────────────────────────────────────────────────────── # ─── Clean ────────────────────────────────────────────────────────

View file

@ -24,10 +24,10 @@ Home: [lumbda.com](https://lumbda.com)
## Usage ## Usage
```bash ```bash
python3 uncommonlisp.py # interactive REPL python3 lumbda.py # interactive REPL
python3 uncommonlisp.py script.lsp # run a file python3 lumbda.py script.lsp # run a file
python3 uncommonlisp.py -e '(+ 1 2)' # eval an expression python3 lumbda.py -e '(+ 1 2)' # eval an expression
python3 uncommonlisp.py --fast script.lsp # auto-compile (7-19x faster) python3 lumbda.py --fast script.lsp # auto-compile (7-19x faster)
``` ```
## Bytecode compiler ## Bytecode compiler
@ -35,7 +35,7 @@ python3 uncommonlisp.py --fast script.lsp # auto-compile (7-19x faster)
Lumbda includes a stack-based bytecode compiler and VM. Enable it with `--fast` or `(auto-compile! #t)`: Lumbda includes a stack-based bytecode compiler and VM. Enable it with `--fast` or `(auto-compile! #t)`:
```bash ```bash
python3 uncommonlisp.py --fast examples/fibonacci.lsp python3 lumbda.py --fast examples/fibonacci.lsp
``` ```
```scheme ```scheme
@ -108,10 +108,10 @@ Additional macros, string/list/numeric/tree utilities, alist/hash helpers, simpl
## Examples ## Examples
```bash ```bash
python3 uncommonlisp.py --fast examples/fibonacci.lsp python3 lumbda.py --fast examples/fibonacci.lsp
python3 uncommonlisp.py --fast examples/generator.lsp python3 lumbda.py --fast examples/generator.lsp
python3 uncommonlisp.py --fast examples/mergesort.lsp python3 lumbda.py --fast examples/mergesort.lsp
python3 uncommonlisp.py examples/objects.lsp python3 lumbda.py examples/objects.lsp
``` ```
```scheme ```scheme
@ -150,11 +150,11 @@ Serialize a running VM mid-computation, transfer to another machine, resume:
```bash ```bash
# Machine A: start a long computation with checkpoints # Machine A: start a long computation with checkpoints
python3 uncommonlisp.py --fast examples/portal-prime.lsp python3 lumbda.py --fast examples/portal-prime.lsp
# saves prime-state.portal at checkpoint # saves prime-state.portal at checkpoint
# Machine B: resume from checkpoint # Machine B: resume from checkpoint
python3 uncommonlisp.py --portal-resume prime-state.portal python3 lumbda.py --portal-resume prime-state.portal
# continues from exact instruction # continues from exact instruction
``` ```
@ -181,7 +181,7 @@ why this is MOAD-0001 (the sedimentary defect) at the proof methodology layer.
## File layout ## File layout
``` ```
uncommonlisp.py interpreter + bytecode compiler (one file, ~3200 lines) lumbda.py interpreter + bytecode compiler (one file, ~3200 lines)
stdlib.lsp extended standard library stdlib.lsp extended standard library
tests.py test suite (571 tests) tests.py test suite (571 tests)
bench.py benchmarks vs CPython bench.py benchmarks vs CPython

View file

@ -1,20 +1,20 @@
all: uncommonlisp uncommonlisp-gc all: lumbda lumbda-gc
uncommonlisp: uncommonlisp.s lumbda: lumbda.s
as --64 -o uncommonlisp.o uncommonlisp.s as --64 -o lumbda.o lumbda.s
ld -o uncommonlisp uncommonlisp.o ld -o lumbda lumbda.o
uncommonlisp-gc: uncommonlisp.s lumbda-gc: lumbda.s
as --64 --defsym GC_NAIVE=1 -o uncommonlisp-gc.o uncommonlisp.s as --64 --defsym GC_NAIVE=1 -o lumbda-gc.o lumbda.s
ld -o uncommonlisp-gc uncommonlisp-gc.o ld -o lumbda-gc lumbda-gc.o
test: uncommonlisp test: lumbda
@bash test.sh @bash test.sh
test-gc: uncommonlisp-gc test-gc: lumbda-gc
@UNCOMMONLISP_BIN=./uncommonlisp-gc bash test.sh @LUMBDA_BIN=./lumbda-gc bash test.sh
clean: clean:
rm -f uncommonlisp.o uncommonlisp uncommonlisp-gc.o uncommonlisp-gc rm -f lumbda.o lumbda lumbda-gc.o lumbda-gc
.PHONY: all test test-gc clean .PHONY: all test test-gc clean

BIN
asm/lumbda Executable file

Binary file not shown.

BIN
asm/lumbda-gc Executable file

Binary file not shown.

BIN
asm/lumbda.o Normal file

Binary file not shown.

View file

@ -1,4 +1,4 @@
# uncommonlisp.s — A Scheme interpreter in pure x86_64 assembly # lumbda.s — A Scheme interpreter in pure x86_64 assembly
# No C. No libc. Just Linux syscalls and machine instructions. # No C. No libc. Just Linux syscalls and machine instructions.
# #
# Value representation (tag in low 3 bits): # Value representation (tag in low 3 bits):
@ -207,7 +207,7 @@
.data .data
# ============================================================ # ============================================================
prompt_str: .ascii "uncommonlisp> " prompt_str: .ascii "lumbda> "
.equ prompt_len, . - prompt_str .equ prompt_len, . - prompt_str
newline_ch: .byte 10 newline_ch: .byte 10
@ -351,7 +351,7 @@ s_hashset: .ascii "#<hash-set>"
err_ht_miss: .ascii "Error: hash-table-ref: missing key\n" err_ht_miss: .ascii "Error: hash-table-ref: missing key\n"
.equ err_ht_miss_len, . - err_ht_miss .equ err_ht_miss_len, . - err_ht_miss
portal_magic: .ascii "ULPORTAL" portal_magic: .ascii "LUMBDAB1"
.equ PORTAL_MAGIC_LEN, 8 .equ PORTAL_MAGIC_LEN, 8
.equ PORTAL_HDR_SIZE, 48 # magic(8) + heap_size(8) + heap_base(8) + r14(8) + r15(8) + reserved(8) .equ PORTAL_HDR_SIZE, 48 # magic(8) + heap_size(8) + heap_base(8) + r14(8) + r15(8) + reserved(8)

View file

@ -10,7 +10,7 @@ cd "$(dirname "$0")"
PASS=0 PASS=0
FAIL=0 FAIL=0
UL="${UNCOMMONLISP_BIN:-./uncommonlisp}" UL="${LUMBDA_BIN:-./lumbda}"
check() { check() {
local name="$1" input="$2" expected="$3" local name="$1" input="$2" expected="$3"
@ -28,7 +28,7 @@ check() {
} }
echo "═══════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════"
echo "asm/uncommonlisp test suite" echo "asm/lumbda test suite"
echo "═══════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════"
# ─── UNIT TESTS: individual primitives ──────────────────── # ─── UNIT TESTS: individual primitives ────────────────────
@ -205,7 +205,7 @@ EOF
check "load-proc" "(load \"$LOAD_TMP/b.lsp\") (square 9)" "81" check "load-proc" "(load \"$LOAD_TMP/b.lsp\") (square 9)" "81"
echo "[unit] load — missing file returns #f" echo "[unit] load — missing file returns #f"
check "load-missing" "(load \"/tmp/__nope_uncommonlisp_$$\")" "#f" check "load-missing" "(load \"/tmp/__nope_lumbda_$$\")" "#f"
echo "[unit] load — empty file is void" echo "[unit] load — empty file is void"
: > "$LOAD_TMP/empty.lsp" : > "$LOAD_TMP/empty.lsp"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,13 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
bench.py — benchmarks for uncommonlisp. bench.py — benchmarks for lumbda.
Compares interpreter time against equivalent CPython. Compares interpreter time against equivalent CPython.
Usage: python3 bench.py [-v] Usage: python3 bench.py [-v]
""" """
import sys, time, math import sys, time, math
sys.setrecursionlimit(10000) sys.setrecursionlimit(10000)
from uncommonlisp import make_global_env, read_all, leval, PRELUDE, show, bc_compile_proc, Proc from lumbda import make_global_env, read_all, leval, PRELUDE, show, bc_compile_proc, Proc
VERBOSE = '-v' in sys.argv VERBOSE = '-v' in sys.argv
@ -56,7 +56,7 @@ def bench(name, lisp_src, python_fn, iters=3):
return lisp_best, py_best return lisp_best, py_best
print('uncommonlisp benchmarks') print('lumbda benchmarks')
print('=' * 75) print('=' * 75)
# ── 1. Fibonacci (iterative, named let) ────────────────────────────────────── # ── 1. Fibonacci (iterative, named let) ──────────────────────────────────────
@ -388,7 +388,7 @@ print()
print('AUTO-COMPILE mode (auto-compile! #t)') print('AUTO-COMPILE mode (auto-compile! #t)')
print('=' * 75) print('=' * 75)
from uncommonlisp import _auto_compile from lumbda import _auto_compile
def bench_auto(name, lisp_src, python_fn, iters=3): def bench_auto(name, lisp_src, python_fn, iters=3):
"""Time auto-compiled lisp vs python. Defines + runs in one pass.""" """Time auto-compiled lisp vs python. Defines + runs in one pass."""

2
c/.gitignore vendored
View file

@ -1,5 +1,5 @@
*.o *.o
uncommonlisp lumbda
test_runner test_runner
test_runner_dbg test_runner_dbg
bench_runner bench_runner

View file

@ -1,4 +1,4 @@
# Makefile for uncommonlisp C interpreter # Makefile for lumbda C interpreter
# Targets: all, test, bench, clean # Targets: all, test, bench, clean
CC = gcc CC = gcc
@ -15,9 +15,9 @@ OBJS = $(SRCS:.c=.o)
.PHONY: all clean test bench .PHONY: all clean test bench
all: uncommonlisp all: lumbda
uncommonlisp: main.o $(OBJS) lumbda: main.o $(OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
test: test_runner test: test_runner
@ -26,14 +26,14 @@ test: test_runner
test_runner: test.c $(OBJS) test_runner: test.c $(OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
bench: bench_runner uncommonlisp bench: bench_runner lumbda
ulimit -s 65536 && ./bench_runner ulimit -s 65536 && ./bench_runner
bench_runner: bench.c $(OBJS) bench_runner: bench.c $(OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
%.o: %.c uncommonlisp.h %.o: %.c lumbda.h
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
clean: clean:
rm -f *.o uncommonlisp test_runner bench_runner rm -f *.o lumbda test_runner bench_runner

View file

@ -13,8 +13,8 @@
Expected output: `4` Expected output: `4`
Actual with `c/uncommonlisp --fast`: hangs or segfaults. Actual with `c/lumbda --fast`: hangs or segfaults.
Tree-walker (`c/uncommonlisp` default) works correctly. Tree-walker (`c/lumbda` default) works correctly.
Python `--fast` and asm tree-walker both work correctly. Python `--fast` and asm tree-walker both work correctly.
## What's special ## What's special

View file

@ -1,7 +1,7 @@
/* /*
* bench.c — Benchmarks: interpreted vs compiled vs JIT * bench.c — Benchmarks: interpreted vs compiled vs JIT
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
#include "jit.h" #include "jit.h"
static double bench_time(void) { static double bench_time(void) {
@ -184,7 +184,7 @@ int main(void) {
return 1; return 1;
} }
printf("uncommonlisp C benchmarks — interpreted vs compiled vs JIT\n"); printf("lumbda C benchmarks — interpreted vs compiled vs JIT\n");
printf("═════════════════════════════════════════════════════════════════\n"); printf("═════════════════════════════════════════════════════════════════\n");
const char *modes[] = { "interp", "compiled", "jit", NULL }; const char *modes[] = { "interp", "compiled", "jit", NULL };

View file

@ -1,7 +1,7 @@
/* /*
* builtins.c — All built-in functions for the Scheme interpreter * builtins.c — All built-in functions for the Scheme interpreter
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
* Helper macros * Helper macros
@ -1926,7 +1926,7 @@ Env *make_global_env(void) {
env_define(g, intern("else"), VAL_TRUE); env_define(g, intern("else"), VAL_TRUE);
env_define(g, intern("..."), intern("...")); env_define(g, intern("..."), intern("..."));
env_define(g, intern("*version*"), make_string_from_cstr("1.0.0")); env_define(g, intern("*version*"), make_string_from_cstr("1.0.0"));
env_define(g, intern("*name*"), make_string_from_cstr("uncommonlisp")); env_define(g, intern("*name*"), make_string_from_cstr("lumbda"));
/* Portal builtins */ /* Portal builtins */
register_portal_builtins(g); register_portal_builtins(g);

View file

@ -3,7 +3,7 @@
* *
* Port of the Python leval() function with full special form support. * Port of the Python leval() function with full special form support.
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
#include "jit.h" #include "jit.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════

View file

@ -1,5 +1,5 @@
/* /*
* jit.c — x86_64 native code JIT compiler for uncommonlisp * jit.c — x86_64 native code JIT compiler for lumbda
* *
* Emits real machine code bytes into mmap'd executable memory. * Emits real machine code bytes into mmap'd executable memory.
* Handles: integer arithmetic (+, -, *), comparisons (=, <, >, <=, >=), * Handles: integer arithmetic (+, -, *), comparisons (=, <, >, <=, >=),
@ -9,7 +9,7 @@
* *
* Code outlasts authors. * Code outlasts authors.
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
#include "jit.h" #include "jit.h"
#include <sys/mman.h> #include <sys/mman.h>

View file

@ -1,5 +1,5 @@
/* /*
* jit.h — x86_64 JIT compiler for uncommonlisp * jit.h — x86_64 JIT compiler for lumbda
* *
* Compiles Scheme procedures to native machine code. * Compiles Scheme procedures to native machine code.
* Uses mmap(PROT_READ|PROT_WRITE|PROT_EXEC) for executable memory. * Uses mmap(PROT_READ|PROT_WRITE|PROT_EXEC) for executable memory.
@ -9,7 +9,7 @@
#ifndef JIT_H #ifndef JIT_H
#define JIT_H #define JIT_H
#include "uncommonlisp.h" #include "lumbda.h"
/* A JIT-compiled function takes NaN-boxed Value args and returns a Value. /* A JIT-compiled function takes NaN-boxed Value args and returns a Value.
* System V AMD64 ABI: args in rdi, rsi, rdx, rcx, r8, r9 */ * System V AMD64 ABI: args in rdi, rsi, rdx, rcx, r8, r9 */

View file

@ -1,11 +1,11 @@
/* /*
* uncommonlisp.h — A Scheme interpreter in C (NaN-boxed values, Boehm-style GC) * lumbda.h — A Scheme interpreter in C (NaN-boxed values, Boehm-style GC)
* *
* Complete port of uncommonlisp.py. * Complete port of lumbda.py.
* Part of the permacomputer platform — code outlasts authors. * Part of the permacomputer platform — code outlasts authors.
*/ */
#ifndef UNCOMMONLISP_H #ifndef LUMBDA_H
#define UNCOMMONLISP_H #define LUMBDA_H
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -763,4 +763,4 @@ typedef struct Module {
extern Module *g_modules; extern Module *g_modules;
#endif /* UNCOMMONLISP_H */ #endif /* LUMBDA_H */

View file

@ -1,7 +1,7 @@
/* /*
* main.c — REPL, script mode, -e mode * main.c — REPL, script mode, -e mode
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
#include "jit.h" #include "jit.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
@ -16,7 +16,7 @@ static char *find_stdlib(const char *argv0) {
ssize_t n = readlink("/proc/self/exe", path, sizeof(path) - 1); ssize_t n = readlink("/proc/self/exe", path, sizeof(path) - 1);
if (n > 0) { if (n > 0) {
path[n] = '\0'; path[n] = '\0';
/* Go up one directory (from c/uncommonlisp to uncommonlisp/) */ /* Go up one directory (from c/lumbda to lumbda/) */
char *slash = strrchr(path, '/'); char *slash = strrchr(path, '/');
if (slash) { if (slash) {
*slash = '\0'; *slash = '\0';
@ -51,7 +51,7 @@ static char *find_stdlib(const char *argv0) {
static void repl(Env *env) { static void repl(Env *env) {
char *version_str = show(env_lookup(env, intern("*version*")), true); char *version_str = show(env_lookup(env, intern("*version*")), true);
printf("uncommonlisp %s (C) — (exit) to quit, (load \"file.lsp\") to load\n", version_str); printf("lumbda %s (C) — (exit) to quit, (load \"file.lsp\") to load\n", version_str);
ul_free(version_str); ul_free(version_str);
char buf[16384]; char buf[16384];
@ -161,10 +161,10 @@ int main(int argc, char **argv) {
} }
if (help) { if (help) {
printf("uncommonlisp — a Scheme interpreter in C\n\n" printf("lumbda — a Scheme interpreter in C\n\n"
"Usage: uncommonlisp [options] [script.lsp] [args...]\n" "Usage: lumbda [options] [script.lsp] [args...]\n"
" uncommonlisp -e '(+ 1 2)'\n" " lumbda -e '(+ 1 2)'\n"
" uncommonlisp (interactive REPL)\n\n" " lumbda (interactive REPL)\n\n"
"Options:\n" "Options:\n"
" -e EXPR evaluate expression and print result\n" " -e EXPR evaluate expression and print result\n"
" -f, --fast auto-compile all defines (bytecode VM;\n" " -f, --fast auto-compile all defines (bytecode VM;\n"
@ -178,7 +178,7 @@ int main(int argc, char **argv) {
} }
if (version) { if (version) {
printf("uncommonlisp 1.0.0 (C)\n"); printf("lumbda 1.0.0 (C)\n");
return 0; return 0;
} }

View file

@ -4,7 +4,7 @@
* Port of the Python portal_save/portal_resume system. * Port of the Python portal_save/portal_resume system.
* Serializes environment bindings and full continuations. * Serializes environment bindings and full continuations.
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
* Portal checkpoint — thread-local signal for mid-execution save * Portal checkpoint — thread-local signal for mid-execution save
@ -188,7 +188,7 @@ void portal_save(Env *env, const char *path, FullCont *continuation) {
return; return;
} }
fputs("{\"format\":\"uncommonlisp-portal-v1\",\n", fp); fputs("{\"format\":\"lumbda-portal-v1\",\n", fp);
/* Environment bindings (user-defined only from global) */ /* Environment bindings (user-defined only from global) */
fputs("\"env\":", fp); fputs("\"env\":", fp);
@ -620,7 +620,7 @@ bool portal_resume(const char *path, Env *base_env, Env **out_env, FullCont **ou
/* Check format */ /* Check format */
const char *fmt = json_str(json_obj_get(root, "format")); const char *fmt = json_str(json_obj_get(root, "format"));
if (!fmt || strcmp(fmt, "uncommonlisp-portal-v1") != 0) { if (!fmt || strcmp(fmt, "lumbda-portal-v1") != 0) {
json_free(root); json_free(root);
return false; return false;
} }

View file

@ -1,7 +1,7 @@
/* /*
* printer.c — show/display/write for Scheme values * printer.c — show/display/write for Scheme values
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
/* Dynamic string builder */ /* Dynamic string builder */
typedef struct { typedef struct {

View file

@ -1,7 +1,7 @@
/* /*
* reader.c — Tokenizer + parser for Scheme source * reader.c — Tokenizer + parser for Scheme source
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
* Tokenizer * Tokenizer

View file

@ -1,7 +1,7 @@
/* /*
* test.c — Unit + integration tests for the C Scheme interpreter * test.c — Unit + integration tests for the C Scheme interpreter
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
#include "jit.h" #include "jit.h"
static int tests_run = 0; static int tests_run = 0;
@ -876,7 +876,7 @@ TEST(portal_checkpoint_builtin) {
int main(void) { int main(void) {
init_symbols(); init_symbols();
printf("Running uncommonlisp C tests...\n\n"); printf("Running lumbda C tests...\n\n");
printf("[types]\n"); printf("[types]\n");
run_test_nan_boxing_int(); run_test_nan_boxing_int();
run_test_nan_boxing_double(); run_test_nan_boxing_double();

View file

@ -1,7 +1,7 @@
/* /*
* types.c — Value types, NaN-boxing, symbol interning, Env, Pair, etc. * types.c — Value types, NaN-boxing, symbol interning, Env, Pair, etc.
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
* Error context (thread-local) * Error context (thread-local)

4
c/vm.c
View file

@ -1,7 +1,7 @@
/* /*
* vm.c — Bytecode compiler + stack-based VM * vm.c — Bytecode compiler + stack-based VM
*/ */
#include "uncommonlisp.h" #include "lumbda.h"
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
* CodeObj * CodeObj
@ -625,7 +625,7 @@ void bc_compile(Value expr, CodeObj *code, Env *env, bool tail) {
ul_free(call_args); ul_free(call_args);
} }
/* syntax_transform_value is declared in uncommonlisp.h, implemented in eval.c */ /* syntax_transform_value is declared in lumbda.h, implemented in eval.c */
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
* Compile a Proc into a CompiledProc * Compile a Proc into a CompiledProc

View file

@ -1,10 +1,10 @@
# uncommonlisp Architecture Documentation # lumbda Architecture Documentation
> "A diagram is worth 10,000 words." — russell@unturf.com > "A diagram is worth 10,000 words." — russell@unturf.com
Three implementations of the same Scheme language, sharing the same .lsp test files. Three implementations of the same Scheme language, sharing the same .lsp test files.
## Python Implementation (uncommonlisp.py) ## Python Implementation (lumbda.py)
3,324 lines. Bytecode compiler + stack VM + full continuations + portal. 3,324 lines. Bytecode compiler + stack VM + full continuations + portal.
@ -118,5 +118,5 @@ make test-all
Total: 943 assertions Total: 943 assertions
``` ```
The language is **R7RS Scheme**. uncommonlisp is the project name — a play on The language is **R7RS Scheme**. lumbda is the project name — a play on
Common Lisp, since this is decidedly uncommon. Common Lisp, since this is decidedly uncommon.

View file

@ -21,7 +21,7 @@ digraph c_arch {
} }
subgraph cluster_types { subgraph cluster_types {
label="Types (types.c, uncommonlisp.h)" label="Types (types.c, lumbda.h)"
style=rounded style=rounded
color="#666666" color="#666666"
nanbox [label="NaN-Boxing\n64-bit doubles\ntype tags in NaN payload\nzero-alloc numbers" fillcolor="#e2d5f1"] nanbox [label="NaN-Boxing\n64-bit doubles\ntype tags in NaN payload\nzero-alloc numbers" fillcolor="#e2d5f1"]

View file

@ -3,7 +3,7 @@
;;; ASM-ONLY: exercises the native hash-set-* primitives introduced ;;; ASM-ONLY: exercises the native hash-set-* primitives introduced
;;; alongside the portable-lib equivalent. C and Python tiers do not ;;; alongside the portable-lib equivalent. C and Python tiers do not
;;; carry hash-set builtins (they have hash-table), so this file is ;;; carry hash-set builtins (they have hash-table), so this file is
;;; driven from tests/bench-hashset.sh against asm/uncommonlisp only. ;;; driven from tests/bench-hashset.sh against asm/lumbda only.
;;; ;;;
;;; Phases: insert-N, hit-lookup-N, miss-lookup-N. ;;; Phases: insert-N, hit-lookup-N, miss-lookup-N.
;;; Output: ms per phase + speedup (portable/native). ;;; Output: ms per phase + speedup (portable/native).

View file

@ -1,5 +1,5 @@
;;; fibonacci.lsp — iterative and recursive Fibonacci ;;; fibonacci.lsp — iterative and recursive Fibonacci
;;; Run: python3 uncommonlisp.py --fast examples/fibonacci.lsp ;;; Run: python3 lumbda.py --fast examples/fibonacci.lsp
(define (fib-iter n) (define (fib-iter n)
(let loop ((a 0) (b 1) (i 0)) (let loop ((a 0) (b 1) (i 0))

View file

@ -1,5 +1,5 @@
;;; generator.lsp — coroutine-style generators using full continuations ;;; generator.lsp — coroutine-style generators using full continuations
;;; Run: python3 uncommonlisp.py --fast examples/generator.lsp ;;; Run: python3 lumbda.py --fast examples/generator.lsp
(define (make-generator thunk) (define (make-generator thunk)
(let ((k #f) (done #f)) (let ((k #f) (done #f))

View file

@ -10,9 +10,9 @@
;;; server throughput shows up. ;;; server throughput shows up.
;;; ;;;
;;; Usage: ;;; Usage:
;;; python3 uncommonlisp.py --fast examples/http-client-bench.lsp ;;; python3 lumbda.py --fast examples/http-client-bench.lsp
;;; ./c/uncommonlisp examples/http-client-bench.lsp ;;; ./c/lumbda examples/http-client-bench.lsp
;;; ./asm/uncommonlisp < examples/http-client-bench.lsp ;;; ./asm/lumbda < examples/http-client-bench.lsp
;;; ;;;
;;; Override N or PORT by pre-setting *n-requests* / *port* before load. ;;; Override N or PORT by pre-setting *n-requests* / *port* before load.

View file

@ -56,7 +56,7 @@
(cond (cond
((string=? path "/") ((string=? path "/")
(http-response "200 OK" "text/html" (http-response "200 OK" "text/html"
"<!doctype html><title>uncommonlisp</title><h1>feedback is all you need</h1>")) "<!doctype html><title>lumbda</title><h1>feedback is all you need</h1>"))
((string=? path "/bench") ((string=? path "/bench")
(http-response "200 OK" "text/plain" *bench-body*)) (http-response "200 OK" "text/plain" *bench-body*))
(else (else

View file

@ -3,9 +3,9 @@
;;; Runs identically in Python, C, and asm. The only primitives used are ;;; Runs identically in Python, C, and asm. The only primitives used are
;;; the six socket builtins + display/string-append/substring. ;;; the six socket builtins + display/string-append/substring.
;;; ;;;
;;; python3 uncommonlisp.py --fast examples/http-server.lsp ;;; python3 lumbda.py --fast examples/http-server.lsp
;;; ./c/uncommonlisp examples/http-server.lsp ;;; ./c/lumbda examples/http-server.lsp
;;; ./asm/uncommonlisp < examples/http-server.lsp ;;; ./asm/lumbda < examples/http-server.lsp
;;; ;;;
;;; Default port 8080. First-line dispatch: GET / → greeting page. ;;; Default port 8080. First-line dispatch: GET / → greeting page.
;;; GET /bench → 1 KB body for throughput benchmarks. ;;; GET /bench → 1 KB body for throughput benchmarks.
@ -76,7 +76,7 @@
(cond (cond
((string=? path "/") ((string=? path "/")
(http-response "200 OK" "text/html" (http-response "200 OK" "text/html"
"<!doctype html><title>uncommonlisp</title><h1>feedback is all you need</h1><p>portable HTTP in Scheme.</p>")) "<!doctype html><title>lumbda</title><h1>feedback is all you need</h1><p>portable HTTP in Scheme.</p>"))
((string=? path "/bench") ((string=? path "/bench")
(http-response "200 OK" "text/plain" *bench-body*)) (http-response "200 OK" "text/plain" *bench-body*))
((string=? path "/hello") ((string=? path "/hello")
@ -110,7 +110,7 @@
(server-loop (+ n 1) snap)))) (server-loop (+ n 1) snap))))
(define (serve) (define (serve)
(display "uncommonlisp http server on :") (display *port*) (display "lumbda http server on :") (display *port*)
(display " (max ") (display *max-requests*) (display " requests)") (newline) (display " (max ") (display *max-requests*) (display " requests)") (newline)
(server-loop 0 (heap-snapshot))) (server-loop 0 (heap-snapshot)))

View file

@ -1,5 +1,5 @@
;;; mergesort.lsp — functional merge sort ;;; mergesort.lsp — functional merge sort
;;; Run: python3 uncommonlisp.py --fast examples/mergesort.lsp ;;; Run: python3 lumbda.py --fast examples/mergesort.lsp
(define (merge a b) (define (merge a b)
(cond ((null? a) b) (cond ((null? a) b)

View file

@ -1,5 +1,5 @@
;;; objects.lsp — record types, closures as objects, hash tables ;;; objects.lsp — record types, closures as objects, hash tables
;;; Run: python3 uncommonlisp.py examples/objects.lsp ;;; Run: python3 lumbda.py examples/objects.lsp
;; Record types with inheritance ;; Record types with inheritance
(define-record-type <point> (define-record-type <point>
@ -42,7 +42,7 @@
;; Hash table ;; Hash table
(define ht (make-hash-table)) (define ht (make-hash-table))
(hash-table-set! ht 'name "uncommonlisp") (hash-table-set! ht 'name "lumbda")
(hash-table-set! ht 'version "1.0.0") (hash-table-set! ht 'version "1.0.0")
(hash-table-set! ht 'features '(bytecode continuations macros)) (hash-table-set! ht 'features '(bytecode continuations macros))
(display "Name: ") (display (hash-table-ref ht 'name)) (newline) (display "Name: ") (display (hash-table-ref ht 'name)) (newline)

View file

@ -7,9 +7,9 @@
;;; lines of string-munging plus (read-from-string) + (eval). ;;; lines of string-munging plus (read-from-string) + (eval).
;;; ;;;
;;; Usage (server must be running first — see portal-http-server.lsp): ;;; Usage (server must be running first — see portal-http-server.lsp):
;;; python3 uncommonlisp.py --fast examples/portal-http-client.lsp ;;; python3 lumbda.py --fast examples/portal-http-client.lsp
;;; ./c/uncommonlisp examples/portal-http-client.lsp ;;; ./c/lumbda examples/portal-http-client.lsp
;;; ./asm/uncommonlisp < examples/portal-http-client.lsp ;;; ./asm/lumbda < examples/portal-http-client.lsp
(define *host* "127.0.0.1") (define *host* "127.0.0.1")
(define *port* 9085) (define *port* 9085)

View file

@ -10,9 +10,9 @@
;;; sockets, using the language itself as the wire format. ;;; sockets, using the language itself as the wire format.
;;; ;;;
;;; Runs byte-identically in Python, C, and asm: ;;; Runs byte-identically in Python, C, and asm:
;;; python3 uncommonlisp.py --fast examples/portal-http-server.lsp ;;; python3 lumbda.py --fast examples/portal-http-server.lsp
;;; ./c/uncommonlisp examples/portal-http-server.lsp ;;; ./c/lumbda examples/portal-http-server.lsp
;;; ./asm/uncommonlisp < examples/portal-http-server.lsp ;;; ./asm/lumbda < examples/portal-http-server.lsp
;;; ;;;
;;; Default port 9085. ;;; Default port 9085.
@ -53,7 +53,7 @@
(define (portal-body) (define (portal-body)
;; Produce the S-expression portal as a single string. ;; Produce the S-expression portal as a single string.
(string-append (string-append
";; uncommonlisp portable portal\n" ";; lumbda portable portal\n"
"(define counter " (number->string counter) ")\n" "(define counter " (number->string counter) ")\n"
"(define my-int " (number->string my-int) ")\n" "(define my-int " (number->string my-int) ")\n"
"(define my-list '(" (list->string my-list) "))\n" "(define my-list '(" (list->string my-list) "))\n"
@ -91,7 +91,7 @@
(http-response "200 OK" "application/scheme" (portal-body))) (http-response "200 OK" "application/scheme" (portal-body)))
((string=? path "/") ((string=? path "/")
(http-response "200 OK" "text/html" (http-response "200 OK" "text/html"
"<!doctype html><title>portal-http</title><h1>uncommonlisp portal-http</h1><p>GET /portal returns the S-expression portal.</p>")) "<!doctype html><title>portal-http</title><h1>lumbda portal-http</h1><p>GET /portal returns the S-expression portal.</p>"))
(else (else
(http-response "404 Not Found" "text/plain" (http-response "404 Not Found" "text/plain"
(string-append "not found: " path "\n")))))) (string-append "not found: " path "\n"))))))

View file

@ -1,9 +1,9 @@
;;; portal-prime.lsp — portal a primality test between machines ;;; portal-prime.lsp — portal a primality test between machines
;;; ;;;
;;; Machine A: python3 uncommonlisp.py --fast examples/portal-prime.lsp ;;; Machine A: python3 lumbda.py --fast examples/portal-prime.lsp
;;; (starts computing, saves checkpoint to prime-state.portal) ;;; (starts computing, saves checkpoint to prime-state.portal)
;;; ;;;
;;; Machine B: python3 uncommonlisp.py --portal-resume prime-state.portal ;;; Machine B: python3 lumbda.py --portal-resume prime-state.portal
;;; (resumes from checkpoint, finishes the computation) ;;; (resumes from checkpoint, finishes the computation)
(define (prime? n) (define (prime? n)

View file

@ -13,9 +13,9 @@
;;; until both hold the union of what either knew. ;;; until both hold the union of what either knew.
;;; ;;;
;;; Usage (start the server first): ;;; Usage (start the server first):
;;; python3 uncommonlisp.py --fast examples/proof-netspace-client.lsp ;;; python3 lumbda.py --fast examples/proof-netspace-client.lsp
;;; ./c/uncommonlisp examples/proof-netspace-client.lsp ;;; ./c/lumbda examples/proof-netspace-client.lsp
;;; ./asm/uncommonlisp < examples/proof-netspace-client.lsp ;;; ./asm/lumbda < examples/proof-netspace-client.lsp
(define *host* "127.0.0.1") (define *host* "127.0.0.1")
(define *port* 9086) (define *port* 9086)

View file

@ -12,9 +12,9 @@
;;; ;;;
;;; Portable across Python, C, and asm. Example: ;;; Portable across Python, C, and asm. Example:
;;; ;;;
;;; python3 uncommonlisp.py --fast examples/proof-netspace-server.lsp ;;; python3 lumbda.py --fast examples/proof-netspace-server.lsp
;;; ./c/uncommonlisp --fast examples/proof-netspace-server.lsp ;;; ./c/lumbda --fast examples/proof-netspace-server.lsp
;;; ./asm/uncommonlisp < examples/proof-netspace-server.lsp ;;; ./asm/lumbda < examples/proof-netspace-server.lsp
;;; ;;;
;;; For multi-node demos see proof-netspace-node-{a,b}.lsp. ;;; For multi-node demos see proof-netspace-node-{a,b}.lsp.

View file

@ -11,9 +11,9 @@
;;; because both sides already have a reader and an evaluator. ;;; because both sides already have a reader and an evaluator.
;;; ;;;
;;; Usage: ;;; Usage:
;;; python3 uncommonlisp.py --fast examples/repl-server.lsp ;;; python3 lumbda.py --fast examples/repl-server.lsp
;;; ./c/uncommonlisp examples/repl-server.lsp ;;; ./c/lumbda examples/repl-server.lsp
;;; ./asm/uncommonlisp < examples/repl-server.lsp ;;; ./asm/lumbda < examples/repl-server.lsp
;;; ;;;
;;; Then from a client: ;;; Then from a client:
;;; (define x 42) ; server mutates its global env ;;; (define x 42) ; server mutates its global env

View file

@ -5,9 +5,9 @@
;;; because they agree on S-expression framing. ;;; because they agree on S-expression framing.
;;; ;;;
;;; Usage: ;;; Usage:
;;; python3 uncommonlisp.py --fast examples/rpc-client.lsp ;;; python3 lumbda.py --fast examples/rpc-client.lsp
;;; ./c/uncommonlisp examples/rpc-client.lsp ;;; ./c/lumbda examples/rpc-client.lsp
;;; ./asm/uncommonlisp < examples/rpc-client.lsp ;;; ./asm/lumbda < examples/rpc-client.lsp
;;; ;;;
;;; Override *target-port* before loading to hit either rpc-server (9080) ;;; Override *target-port* before loading to hit either rpc-server (9080)
;;; or repl-server (9081). ;;; or repl-server (9081).

View file

@ -6,9 +6,9 @@
;;; asm backend, where the same .lsp runs at every hop and the wire ;;; asm backend, where the same .lsp runs at every hop and the wire
;;; format (Scheme source) needs no translation. ;;; format (Scheme source) needs no translation.
;;; ;;;
;;; python3 uncommonlisp.py --fast examples/rpc-relay.lsp ;;; python3 lumbda.py --fast examples/rpc-relay.lsp
;;; ./c/uncommonlisp examples/rpc-relay.lsp ;;; ./c/lumbda examples/rpc-relay.lsp
;;; ./asm/uncommonlisp < examples/rpc-relay.lsp ;;; ./asm/lumbda < examples/rpc-relay.lsp
;;; ;;;
;;; Override *listen-port* / *backend-port* by pre-defining before load ;;; Override *listen-port* / *backend-port* by pre-defining before load
;;; (or edit here for a one-off demo). ;;; (or edit here for a one-off demo).

View file

@ -5,9 +5,9 @@
;;; the parser on each side is already the right tool. ;;; the parser on each side is already the right tool.
;;; ;;;
;;; Runs byte-identically in Python, C, and asm: ;;; Runs byte-identically in Python, C, and asm:
;;; python3 uncommonlisp.py --fast examples/rpc-server.lsp ;;; python3 lumbda.py --fast examples/rpc-server.lsp
;;; ./c/uncommonlisp examples/rpc-server.lsp ;;; ./c/lumbda examples/rpc-server.lsp
;;; ./asm/uncommonlisp < examples/rpc-server.lsp ;;; ./asm/lumbda < examples/rpc-server.lsp
;;; ;;;
;;; Request examples (send as plain text, one per connection): ;;; Request examples (send as plain text, one per connection):
;;; (ping) -> pong ;;; (ping) -> pong

View file

@ -12,7 +12,7 @@
;;; direction. N nodes in a mesh converge after N-1 spiral passes. ;;; direction. N nodes in a mesh converge after N-1 spiral passes.
;;; ;;;
;;; Usage (start both nodes first): ;;; Usage (start both nodes first):
;;; python3 uncommonlisp.py --fast examples/spiral-client.lsp ;;; python3 lumbda.py --fast examples/spiral-client.lsp
(define *host* "127.0.0.1") (define *host* "127.0.0.1")
(define *port-a* 9086) (define *port-a* 9086)

View file

@ -19,9 +19,9 @@ trap 'pkill -9 -u "$USER" -f "proof-netspace-node|spiral-client" 2>/dev/null ||
IMPL="${1:-python}" IMPL="${1:-python}"
case "$IMPL" in case "$IMPL" in
python) BIN="python3 uncommonlisp.py --fast" ;; python) BIN="python3 lumbda.py --fast" ;;
c) BIN="./c/uncommonlisp --fast" ;; c) BIN="./c/lumbda --fast" ;;
asm) BIN="asm/uncommonlisp" ;; asm) BIN="asm/lumbda" ;;
*) echo "unknown impl: $IMPL (expected python|c|asm)"; exit 1 ;; *) echo "unknown impl: $IMPL (expected python|c|asm)"; exit 1 ;;
esac esac

View file

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# friction.sh — Head-to-head benchmark: CPython vs uncommonlisp-Python vs uncommonlisp-C # friction.sh — Head-to-head benchmark: CPython vs lumbda-Python vs lumbda-C
# #
# Usage: bash friction.sh # Usage: bash friction.sh
@ -7,7 +7,7 @@ set -e
cd "$(dirname "$0")" cd "$(dirname "$0")"
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"
echo "Friction Benchmark: CPython vs uncommonlisp-Python vs uncommonlisp-C" echo "Friction Benchmark: CPython vs lumbda-Python vs lumbda-C"
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"
echo echo
@ -27,9 +27,9 @@ def fib(n):
t=time.perf_counter(); r=fib(35); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') t=time.perf_counter(); r=fib(35); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-Python: " printf " lumbda-Python: "
python3 -c " python3 -c "
import time; from uncommonlisp import * import time; from lumbda import *
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)] g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
[leval(e,g) for e in read_all('(auto-compile! #t)')] [leval(e,g) for e in read_all('(auto-compile! #t)')]
[leval(e,g) for e in read_all('(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1)))))')] [leval(e,g) for e in read_all('(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1)))))')]
@ -37,8 +37,8 @@ t=time.perf_counter(); r=[leval(e,g) for e in read_all('(fib 35)')][-1]
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-C: " printf " lumbda-C: "
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1))))) (display (fib 35)) (newline)' 2>&1 /usr/bin/time -f "%e s" ./c/lumbda -e '(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1))))) (display (fib 35)) (newline)' 2>&1
echo echo
@ -54,9 +54,9 @@ def fib(n):
t=time.perf_counter(); r=fib(20); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') t=time.perf_counter(); r=fib(20); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-Python: " printf " lumbda-Python: "
python3 -c " python3 -c "
import time,sys; sys.setrecursionlimit(50000); from uncommonlisp import * import time,sys; sys.setrecursionlimit(50000); from lumbda import *
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)] g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
[leval(e,g) for e in read_all('(auto-compile! #t)')] [leval(e,g) for e in read_all('(auto-compile! #t)')]
[leval(e,g) for e in read_all('(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2)))))')] [leval(e,g) for e in read_all('(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2)))))')]
@ -64,8 +64,8 @@ t=time.perf_counter(); r=[leval(e,g) for e in read_all('(fib 20)')][-1]
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-C: " printf " lumbda-C: "
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))) (display (fib 20)) (newline)' 2>&1 /usr/bin/time -f "%e s" ./c/lumbda -e '(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))) (display (fib 20)) (newline)' 2>&1
echo echo
@ -82,9 +82,9 @@ def ack(m,n):
t=time.perf_counter(); r=ack(3,4); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') t=time.perf_counter(); r=ack(3,4); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-Python: " printf " lumbda-Python: "
python3 -c " python3 -c "
import time,sys; sys.setrecursionlimit(50000); from uncommonlisp import * import time,sys; sys.setrecursionlimit(50000); from lumbda import *
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)] g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
[leval(e,g) for e in read_all('(auto-compile! #t)')] [leval(e,g) for e in read_all('(auto-compile! #t)')]
[leval(e,g) for e in read_all('(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1))))))')] [leval(e,g) for e in read_all('(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1))))))')]
@ -92,8 +92,8 @@ t=time.perf_counter(); r=[leval(e,g) for e in read_all('(ack 3 4)')][-1]
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-C: " printf " lumbda-C: "
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1)))))) (display (ack 3 4)) (newline)' 2>&1 /usr/bin/time -f "%e s" ./c/lumbda -e '(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1)))))) (display (ack 3 4)) (newline)' 2>&1
echo echo
@ -110,9 +110,9 @@ def s(n):
t=time.perf_counter(); r=s(50000); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') t=time.perf_counter(); r=s(50000); print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-Python: " printf " lumbda-Python: "
python3 -c " python3 -c "
import time; from uncommonlisp import * import time; from lumbda import *
g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)] g=make_global_env(); [leval(e,g) for e in read_all(PRELUDE)]
[leval(e,g) for e in read_all('(auto-compile! #t)')] [leval(e,g) for e in read_all('(auto-compile! #t)')]
[leval(e,g) for e in read_all('(define (sum-to n) (let loop ((i n) (acc 0)) (if (= i 0) acc (loop (- i 1) (+ acc i)))))')] [leval(e,g) for e in read_all('(define (sum-to n) (let loop ((i n) (acc 0)) (if (= i 0) acc (loop (- i 1) (+ acc i)))))')]
@ -120,8 +120,8 @@ t=time.perf_counter(); r=[leval(e,g) for e in read_all('(sum-to 50000)')][-1]
print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}') print(f'{(time.perf_counter()-t)*1000:.3f}ms result={r}')
" "
printf " uncommonlisp-C: " printf " lumbda-C: "
/usr/bin/time -f "%e s" ./c/uncommonlisp -e '(define (sum-to n) (let loop ((i n) (acc 0)) (if (= i 0) acc (loop (- i 1) (+ acc i))))) (display (sum-to 50000)) (newline)' 2>&1 /usr/bin/time -f "%e s" ./c/lumbda -e '(define (sum-to n) (let loop ((i n) (acc 0)) (if (= i 0) acc (loop (- i 1) (+ acc i))))) (display (sum-to 50000)) (newline)' 2>&1
echo echo
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"

View file

@ -1,9 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
uncommonlisp — a Lisp in one Python file. lumbda — a Lisp in one Python file.
Usage: python3 uncommonlisp.py [script.lsp] # run a file Usage: python3 lumbda.py [script.lsp] # run a file
python3 uncommonlisp.py # interactive REPL python3 lumbda.py # interactive REPL
python3 uncommonlisp.py -e '(+ 1 2)' # eval expression python3 lumbda.py -e '(+ 1 2)' # eval expression
""" """
import sys, re, math, itertools, os as _os import sys, re, math, itertools, os as _os
from fractions import Fraction from fractions import Fraction
@ -2217,7 +2217,7 @@ def portal_save(env, path, continuation=None):
"""Save machine state to a .portal file.""" """Save machine state to a .portal file."""
ser = _PortalSerializer() ser = _PortalSerializer()
state = { state = {
'format': 'uncommonlisp-portal-v1', 'format': 'lumbda-portal-v1',
'env': ser.serialize_env(env), 'env': ser.serialize_env(env),
'continuation': ser.serialize_continuation(continuation) if continuation else None, 'continuation': ser.serialize_continuation(continuation) if continuation else None,
'auto_compile': _auto_compile[0], 'auto_compile': _auto_compile[0],
@ -2231,7 +2231,7 @@ def portal_resume(path, base_env=None):
"""Resume machine state from a .portal file. Returns (env, continuation_or_None).""" """Resume machine state from a .portal file. Returns (env, continuation_or_None)."""
with open(path) as f: with open(path) as f:
state = _json.load(f) state = _json.load(f)
if state.get('format') != 'uncommonlisp-portal-v1': if state.get('format') != 'lumbda-portal-v1':
raise LispErr(f'portal: unsupported format: {state.get("format")}') raise LispErr(f'portal: unsupported format: {state.get("format")}')
if base_env is None: if base_env is None:
base_env = make_global_env() base_env = make_global_env()
@ -3488,7 +3488,7 @@ def make_global_env():
d(S('else'), True) d(S('else'), True)
d(S('...'), S('...')) d(S('...'), S('...'))
d(S('*version*'), '1.0.0') d(S('*version*'), '1.0.0')
d(S('*name*'), 'uncommonlisp') d(S('*name*'), 'lumbda')
return g return g
@ -3621,7 +3621,7 @@ PRELUDE = r"""
def repl(env, prompt='λ> ', quiet=False): def repl(env, prompt='λ> ', quiet=False):
if not quiet: if not quiet:
print(f'uncommonlisp {env.lookup(S("*version*"))} ' print(f'lumbda {env.lookup(S("*version*"))} '
f'— (exit) to quit, (load "file.lsp") to load') f'— (exit) to quit, (load "file.lsp") to load')
buf = '' buf = ''
while True: while True:
@ -3674,11 +3674,11 @@ def main():
# --help / -h # --help / -h
if '--help' in args or '-h' in args: if '--help' in args or '-h' in args:
print('''uncommonlisp — a Scheme in one Python file print('''lumbda — a Scheme in one Python file
Usage: uncommonlisp [options] [script.lsp] [args...] Usage: lumbda [options] [script.lsp] [args...]
uncommonlisp -e '(+ 1 2)' lumbda -e '(+ 1 2)'
uncommonlisp (interactive REPL) lumbda (interactive REPL)
Options: Options:
-e EXPR evaluate expression and print result -e EXPR evaluate expression and print result
@ -3692,7 +3692,7 @@ Features: R7RS core, bytecode compiler, full continuations, macros,
# --version / -v # --version / -v
if '--version' in args or '-v' in args: if '--version' in args or '-v' in args:
print(f'uncommonlisp 1.0.0'); return print(f'lumbda 1.0.0'); return
# --fast / -f: enable auto-compile # --fast / -f: enable auto-compile
if '--fast' in args or '-f' in args: if '--fast' in args or '-f' in args:
@ -3703,7 +3703,7 @@ Features: R7RS core, bytecode compiler, full continuations, macros,
if '--compile' in args: if '--compile' in args:
args = [a for a in args if a != '--compile'] args = [a for a in args if a != '--compile']
if not args: if not args:
print('usage: uncommonlisp --compile file.lsp', file=sys.stderr); sys.exit(1) print('usage: lumbda --compile file.lsp', file=sys.stderr); sys.exit(1)
path = args[0]; out = path.rsplit('.', 1)[0] + '.lspc' path = args[0]; out = path.rsplit('.', 1)[0] + '.lspc'
_auto_compile[0] = True _auto_compile[0] = True
_load(path, g) _load(path, g)
@ -3721,7 +3721,7 @@ Features: R7RS core, bytecode compiler, full continuations, macros,
if '--portal-resume' in args: if '--portal-resume' in args:
args = [a for a in args if a != '--portal-resume'] args = [a for a in args if a != '--portal-resume']
if not args: if not args:
print('usage: uncommonlisp --portal-resume state.portal', file=sys.stderr); sys.exit(1) print('usage: lumbda --portal-resume state.portal', file=sys.stderr); sys.exit(1)
path = args[0] path = args[0]
env, cont = portal_resume(path, g) env, cont = portal_resume(path, g)
if cont is not None: if cont is not None:
@ -3739,7 +3739,7 @@ Features: R7RS core, bytecode compiler, full continuations, macros,
# -e 'expr' mode # -e 'expr' mode
if args and args[0] == '-e': if args and args[0] == '-e':
if len(args) < 2: if len(args) < 2:
print('usage: uncommonlisp -e <expression>', file=sys.stderr) print('usage: lumbda -e <expression>', file=sys.stderr)
sys.exit(1) sys.exit(1)
for expr in read_all(args[1]): for expr in read_all(args[1]):
result = leval(expr, g) result = leval(expr, g)

View file

@ -1,10 +1,10 @@
#!/bin/bash #!/bin/bash
# benchmark.sh — Run EML proof in both Python and uncommonlisp, compare times # benchmark.sh — Run EML proof in both Python and lumbda, compare times
# #
# Usage: cd proof && bash benchmark.sh # Usage: cd proof && bash benchmark.sh
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"
echo "EML Universality Proof — Benchmark: Python vs uncommonlisp" echo "EML Universality Proof — Benchmark: Python vs lumbda"
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"
echo echo
@ -13,9 +13,9 @@ echo "---"
time python3 eml_proof.py time python3 eml_proof.py
echo echo
echo ">>> uncommonlisp implementation (--fast = bytecode compiled)" echo ">>> lumbda implementation (--fast = bytecode compiled)"
echo "---" echo "---"
time python3 ../uncommonlisp.py --fast eml_proof.lsp time python3 ../lumbda.py --fast eml_proof.lsp
echo echo
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"

View file

@ -8,7 +8,7 @@ with constant 1 generates all elementary functions (arXiv:2603.21852v2).
| Approach | Time | Guarantee | Friction | | Approach | Time | Guarantee | Friction |
|----------|------|-----------|----------| |----------|------|-----------|----------|
| Python (numerical) | 0.04s | 1e-10 tolerance | Low | | Python (numerical) | 0.04s | 1e-10 tolerance | Low |
| uncommonlisp (numerical) | 59s | 1e-10 tolerance | High | | lumbda (numerical) | 59s | 1e-10 tolerance | High |
| Lean 4 (formal proof) | 1.5s | kernel-verified | Medium | | Lean 4 (formal proof) | 1.5s | kernel-verified | Medium |
## Analysis ## Analysis
@ -16,7 +16,7 @@ with constant 1 generates all elementary functions (arXiv:2603.21852v2).
**The formal proof is 40x faster than brute-force search and provides **The formal proof is 40x faster than brute-force search and provides
mathematical certainty instead of floating-point tolerance.** mathematical certainty instead of floating-point tolerance.**
The numerical approaches (Python and uncommonlisp) perform O(N²) pairwise The numerical approaches (Python and lumbda) perform O(N²) pairwise
enumeration of EML trees, evaluating at transcendental test points and enumeration of EML trees, evaluating at transcendental test points and
comparing against target functions. This is MOAD-0001 at the proof layer: comparing against target functions. This is MOAD-0001 at the proof layer:
quadratic search friction where algebraic reasoning suffices. quadratic search friction where algebraic reasoning suffices.

View file

@ -1,9 +1,9 @@
;;; eml_proof.lsp — Verify EML universality in uncommonlisp ;;; eml_proof.lsp — Verify EML universality in lumbda
;;; ;;;
;;; eml(x, y) = exp(x) - ln(y) generates all elementary functions. ;;; eml(x, y) = exp(x) - ln(y) generates all elementary functions.
;;; Reference: "All elementary functions from a single operator" (arXiv:2603.21852v2) ;;; Reference: "All elementary functions from a single operator" (arXiv:2603.21852v2)
;;; ;;;
;;; Run: python3 uncommonlisp.py --fast proof/eml_proof.lsp ;;; Run: python3 lumbda.py --fast proof/eml_proof.lsp
;;; ═══════════════════════════════════════════════════════════════════ ;;; ═══════════════════════════════════════════════════════════════════
;;; EML operator and test infrastructure ;;; EML operator and test infrastructure
@ -35,7 +35,7 @@
(define gamma 0.5772156649015329) (define gamma 0.5772156649015329)
(define apery 1.2020569031595943) (define apery 1.2020569031595943)
(display "EML Universality Proof — uncommonlisp") (newline) (display "EML Universality Proof — lumbda") (newline)
(display "eml(x, y) = exp(x) - ln(y)") (newline) (display "eml(x, y) = exp(x) - ln(y)") (newline)
(display "======================================================================") (newline) (display "======================================================================") (newline)
@ -118,7 +118,7 @@
(display "----------------------------------------------------------------------") (newline) (display "----------------------------------------------------------------------") (newline)
(display " Key insight: ln(negative) = ln(|neg|) + iπ") (newline) (display " Key insight: ln(negative) = ln(|neg|) + iπ") (newline)
(display " From -1, ln(-1) = iπ, giving access to complex plane.") (newline) (display " From -1, ln(-1) = iπ, giving access to complex plane.") (newline)
(display " uncommonlisp uses real arithmetic; verifying the chain:") (newline) (display " lumbda uses real arithmetic; verifying the chain:") (newline)
(newline) (newline)
;; Verify the real-arithmetic building blocks that WOULD give complex access: ;; Verify the real-arithmetic building blocks that WOULD give complex access:

View file

@ -12,9 +12,9 @@
;;; that checks it live in the same file. ;;; that checks it live in the same file.
;;; ;;;
;;; Runs byte-identically in Python, C, and asm: ;;; Runs byte-identically in Python, C, and asm:
;;; python3 uncommonlisp.py --fast proof/eml_proof_in_lumbda.lsp ;;; python3 lumbda.py --fast proof/eml_proof_in_lumbda.lsp
;;; ./c/uncommonlisp proof/eml_proof_in_lumbda.lsp ;;; ./c/lumbda proof/eml_proof_in_lumbda.lsp
;;; ./asm/uncommonlisp < proof/eml_proof_in_lumbda.lsp ;;; ./asm/lumbda < proof/eml_proof_in_lumbda.lsp
;;; ═══════════════════════════════════════════════════════════════ ;;; ═══════════════════════════════════════════════════════════════
;;; Term-rewriting engine ;;; Term-rewriting engine

View file

@ -1,6 +1,6 @@
;;; stdlib.lsp — standard library for uncommonlisp ;;; stdlib.lsp — standard library for lumbda
;;; Load with: (load "stdlib.lsp") ;;; Load with: (load "stdlib.lsp")
;;; Automatically loaded by the interpreter if found next to uncommonlisp.py. ;;; Automatically loaded by the interpreter if found next to lumbda.py.
;;;; ── Syntax-rules versions of core macros ──────────────────────────────── ;;;; ── Syntax-rules versions of core macros ────────────────────────────────

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
tests.py — unit, integration, and functional tests for uncommonlisp. tests.py — unit, integration, and functional tests for lumbda.
Run: python3 tests.py [-v] Run: python3 tests.py [-v]
""" """
@ -8,7 +8,7 @@ import sys, io, unittest, math, textwrap
sys.setrecursionlimit(200) # intentionally low — proves TCO works sys.setrecursionlimit(200) # intentionally low — proves TCO works
# ── import the interpreter ──────────────────────────────────────────────────── # ── import the interpreter ────────────────────────────────────────────────────
from uncommonlisp import ( from lumbda import (
Symbol, S, NIL, Pair, Proc, Macro, VOID, EOF, LispErr, Symbol, S, NIL, Pair, Proc, Macro, VOID, EOF, LispErr,
show, _tokenize, _tokenize_lines, read_all, _L, _P, _truthy, _formals, _equal, show, _tokenize, _tokenize_lines, read_all, _L, _P, _truthy, _formals, _equal,
Env, _qq, leval, _call, make_global_env, PRELUDE, Env, _qq, leval, _call, make_global_env, PRELUDE,
@ -67,7 +67,7 @@ class TestSymbol(unittest.TestCase):
class TestNil(unittest.TestCase): class TestNil(unittest.TestCase):
def test_singleton(self): def test_singleton(self):
from uncommonlisp import _Nil from lumbda import _Nil
assert _Nil() is NIL assert _Nil() is NIL
def test_falsy(self): def test_falsy(self):
@ -1509,7 +1509,7 @@ class TestCommandLine(unittest.TestCase):
def _run(self, *args, input_text=None): def _run(self, *args, input_text=None):
import subprocess import subprocess
result = subprocess.run( result = subprocess.run(
[sys.executable, 'uncommonlisp.py'] + list(args), [sys.executable, 'lumbda.py'] + list(args),
capture_output=True, text=True, input=input_text, capture_output=True, text=True, input=input_text,
cwd='/home/fox/git/uncommonlisp' cwd='/home/fox/git/uncommonlisp'
) )
@ -1670,7 +1670,7 @@ class TestStringPorts(unittest.TestCase):
def test_open_input_string_eof(self): def test_open_input_string_eof(self):
r = run('(let ((p (open-input-string ""))) (read p))', self.g) r = run('(let ((p (open-input-string ""))) (read p))', self.g)
from uncommonlisp import EOF from lumbda import EOF
assert r is EOF assert r is EOF
def test_open_input_string_read_char(self): def test_open_input_string_read_char(self):
@ -1728,7 +1728,7 @@ class TestErrorObjects(unittest.TestCase):
def test_error_object_irritants_empty(self): def test_error_object_irritants_empty(self):
r = run('(guard (e (#t (error-object-irritants e))) (error "no-irritants"))', self.g) r = run('(guard (e (#t (error-object-irritants e))) (error "no-irritants"))', self.g)
from uncommonlisp import NIL from lumbda import NIL
assert r is NIL assert r is NIL
def test_with_exception_handler_gets_error_object(self): def test_with_exception_handler_gets_error_object(self):
@ -2717,7 +2717,7 @@ class TestSourceMaps(unittest.TestCase):
f.write('(define x 1)\n(define y 2)\n(+ x y)') f.write('(define x 1)\n(define y 2)\n(+ x y)')
path = f.name path = f.name
try: try:
from uncommonlisp import _load from lumbda import _load
env = fresh() env = fresh()
_load(path, env) _load(path, env)
assert env.lookup(S('x')) == 1 assert env.lookup(S('x')) == 1
@ -3029,7 +3029,7 @@ class TestBytecodeSerialization(unittest.TestCase):
lspc = path.rsplit('.', 1)[0] + '.lspc' lspc = path.rsplit('.', 1)[0] + '.lspc'
try: try:
result = subprocess.run( result = subprocess.run(
['python3', 'uncommonlisp.py', '--compile', path], ['python3', 'lumbda.py', '--compile', path],
capture_output=True, text=True, timeout=30) capture_output=True, text=True, timeout=30)
assert result.returncode == 0 assert result.returncode == 0
assert os.path.exists(lspc) assert os.path.exists(lspc)
@ -3177,7 +3177,7 @@ class TestPortal(unittest.TestCase):
try: try:
portal_save(self.g, path) portal_save(self.g, path)
result = subprocess.run( result = subprocess.run(
['python3', 'uncommonlisp.py', '--portal-resume', path, ['python3', 'lumbda.py', '--portal-resume', path,
'-e', '(display answer)'], '-e', '(display answer)'],
capture_output=True, text=True, timeout=30) capture_output=True, text=True, timeout=30)
# portal-resume loads state, then -e isn't processed (portal-resume returns) # portal-resume loads state, then -e isn't processed (portal-resume returns)
@ -3195,7 +3195,7 @@ class TestPortal(unittest.TestCase):
portal_save(self.g, path) portal_save(self.g, path)
with open(path) as f: with open(path) as f:
data = json.load(f) data = json.load(f)
assert data['format'] == 'uncommonlisp-portal-v1' assert data['format'] == 'lumbda-portal-v1'
assert 'objects' in data assert 'objects' in data
assert 'env' in data assert 'env' in data
finally: finally:

View file

@ -60,15 +60,15 @@ best_of_two() {
} }
echo "── Python (--fast) ──" echo "── Python (--fast) ──"
best_of_two "python3 uncommonlisp.py --fast /tmp/bench-3way.lsp" best_of_two "python3 lumbda.py --fast /tmp/bench-3way.lsp"
echo echo
echo "── C (--fast) ──" echo "── C (--fast) ──"
best_of_two "c/uncommonlisp --fast /tmp/bench-3way.lsp" best_of_two "c/lumbda --fast /tmp/bench-3way.lsp"
echo echo
echo "── asm ──" echo "── asm ──"
best_of_two "asm/uncommonlisp < /tmp/bench-3way.lsp" best_of_two "asm/lumbda < /tmp/bench-3way.lsp"
echo echo
rm -f /tmp/bench-3way.lsp rm -f /tmp/bench-3way.lsp

View file

@ -6,7 +6,7 @@ set -e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
ulimit -v 524288 ulimit -v 524288
trap 'pkill -9 -u "$USER" -f "asm/uncommonlisp" 2>/dev/null || true' EXIT trap 'pkill -9 -u "$USER" -f "asm/lumbda" 2>/dev/null || true' EXIT
make -s -C asm all make -s -C asm all
@ -20,7 +20,7 @@ run_phase() {
echo "(define *workload* $workload)" echo "(define *workload* $workload)"
echo "(define *mode* $mode)" echo "(define *mode* $mode)"
cat examples/bench-gc-adaptive.lsp cat examples/bench-gc-adaptive.lsp
} | timeout 60 ./asm/uncommonlisp-gc } | timeout 60 ./asm/lumbda-gc
echo "" echo ""
} }
@ -31,7 +31,7 @@ run_phase "hostile" 1 1 "adaptive"
run_phase "mixed" 2 0 "greedy" run_phase "mixed" 2 0 "greedy"
run_phase "mixed" 2 1 "adaptive" run_phase "mixed" 2 1 "adaptive"
if pgrep -u "$USER" -f 'asm/uncommonlisp' > /dev/null; then if pgrep -u "$USER" -f 'asm/lumbda' > /dev/null; then
echo "STRAGGLER" >&2 echo "STRAGGLER" >&2
exit 1 exit 1
fi fi

View file

@ -7,12 +7,12 @@ set -e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
ulimit -v 524288 ulimit -v 524288
trap 'pkill -9 -u "$USER" -f "asm/uncommonlisp" 2>/dev/null || true' EXIT trap 'pkill -9 -u "$USER" -f "asm/lumbda" 2>/dev/null || true' EXIT
make -s -C asm all make -s -C asm all
echo "== asm (naive GC, with arena as meta fast path) ==" echo "== asm (naive GC, with arena as meta fast path) =="
./asm/uncommonlisp-gc < examples/bench-gc-arena.lsp & ./asm/lumbda-gc < examples/bench-gc-arena.lsp &
pid=$! pid=$!
peak=0 peak=0
while kill -0 "$pid" 2>/dev/null; do while kill -0 "$pid" 2>/dev/null; do
@ -24,7 +24,7 @@ wait "$pid" || true
echo "" echo ""
echo "peak_rss_kb=$peak" echo "peak_rss_kb=$peak"
if pgrep -u "$USER" -f 'asm/uncommonlisp' > /dev/null; then if pgrep -u "$USER" -f 'asm/lumbda' > /dev/null; then
echo "STRAGGLER" >&2 echo "STRAGGLER" >&2
exit 1 exit 1
fi fi

View file

@ -96,9 +96,9 @@ run_case() {
# to completion rather than OOM'd. # to completion rather than OOM'd.
VCAP=${VCAP:-524288} VCAP=${VCAP:-524288}
run_case "asm no-GC + snapshot loop" "./asm/uncommonlisp" "examples/http-server.lsp" "$VCAP" || true run_case "asm no-GC + snapshot loop" "./asm/lumbda" "examples/http-server.lsp" "$VCAP" || true
run_case "asm GC + snapshot loop" "./asm/uncommonlisp-gc" "examples/http-server.lsp" "$VCAP" || true run_case "asm GC + snapshot loop" "./asm/lumbda-gc" "examples/http-server.lsp" "$VCAP" || true
run_case "asm no-GC + no snapshot" "./asm/uncommonlisp" "examples/http-server-noarena.lsp" "$VCAP" || true run_case "asm no-GC + no snapshot" "./asm/lumbda" "examples/http-server-noarena.lsp" "$VCAP" || true
run_case "asm GC + no snapshot" "./asm/uncommonlisp-gc" "examples/http-server-noarena.lsp" "$VCAP" || true run_case "asm GC + no snapshot" "./asm/lumbda-gc" "examples/http-server-noarena.lsp" "$VCAP" || true
printf "\n" printf "\n"

View file

@ -7,7 +7,7 @@ set -e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
ulimit -v 524288 ulimit -v 524288
trap 'pkill -9 -u "$USER" -f "asm/uncommonlisp" 2>/dev/null || true' EXIT trap 'pkill -9 -u "$USER" -f "asm/lumbda" 2>/dev/null || true' EXIT
make -s -C asm all make -s -C asm all
@ -35,12 +35,12 @@ run_with_sampling() {
echo "" echo ""
} }
run_with_sampling ./asm/uncommonlisp "asm (no GC, 64 MB chunks)" run_with_sampling ./asm/lumbda "asm (no GC, 64 MB chunks)"
run_with_sampling ./asm/uncommonlisp-gc "asm (naive GC, 1 MB chunks)" run_with_sampling ./asm/lumbda-gc "asm (naive GC, 1 MB chunks)"
rm -f /tmp/gc-bench.out rm -f /tmp/gc-bench.out
if pgrep -u "$USER" -f 'asm/uncommonlisp' > /dev/null; then if pgrep -u "$USER" -f 'asm/lumbda' > /dev/null; then
echo "STRAGGLER detected" >&2 echo "STRAGGLER detected" >&2
exit 1 exit 1
fi fi

View file

@ -5,26 +5,26 @@ set +e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
ulimit -v 524288 ulimit -v 524288
trap 'pkill -9 -u "$USER" -f "asm/uncommonlisp" 2>/dev/null || true' EXIT trap 'pkill -9 -u "$USER" -f "asm/lumbda" 2>/dev/null || true' EXIT
# Build if needed # Build if needed
if [ ! -x asm/uncommonlisp ] || [ asm/uncommonlisp.s -nt asm/uncommonlisp ]; then if [ ! -x asm/lumbda ] || [ asm/lumbda.s -nt asm/lumbda ]; then
make -s asm-build make -s asm-build
fi fi
echo "── asm no-GC ──" echo "── asm no-GC ──"
timeout 60 ./asm/uncommonlisp < examples/bench-hashset.lsp timeout 60 ./asm/lumbda < examples/bench-hashset.lsp
echo "" echo ""
echo "── asm GC (GC_NAIVE build) ──" echo "── asm GC (GC_NAIVE build) ──"
# Under GC_NAIVE the heap is 1 MB per chunk; build-list(K=500) runs # Under GC_NAIVE the heap is 1 MB per chunk; build-list(K=500) runs
# into the bump threshold and triggers implicit GC. That's the # into the bump threshold and triggers implicit GC. That's the
# intended comparison — same primitives, different allocator. # intended comparison — same primitives, different allocator.
timeout 60 ./asm/uncommonlisp-gc < examples/bench-hashset.lsp timeout 60 ./asm/lumbda-gc < examples/bench-hashset.lsp
# Verify cleanup. pgrep with -x matches the exact command basename # Verify cleanup. pgrep with -x matches the exact command basename
# so it doesn't false-positive on the parent shell. # so it doesn't false-positive on the parent shell.
if pgrep -u "$USER" -x uncommonlisp > /dev/null || \ if pgrep -u "$USER" -x lumbda > /dev/null || \
pgrep -u "$USER" -x uncommonlisp-gc > /dev/null; then pgrep -u "$USER" -x lumbda-gc > /dev/null; then
echo "STRAGGLER asm binary detected" >&2 echo "STRAGGLER asm binary detected" >&2
exit 1 exit 1
fi fi

View file

@ -52,17 +52,17 @@ echo "════════════════════════
printf " %-38s %s\n" "Lumbda tier" "cold cached" printf " %-38s %s\n" "Lumbda tier" "cold cached"
printf " %-38s %s\n" "─────────────────────────────────────" "───────────────" printf " %-38s %s\n" "─────────────────────────────────────" "───────────────"
printf " %-38s %4s ms %4s ms\n" "Python --fast" \ printf " %-38s %4s ms %4s ms\n" "Python --fast" \
"$(bestof_cold 'python3 uncommonlisp.py --fast proof/eml_proof_in_lumbda.lsp')" \ "$(bestof_cold 'python3 lumbda.py --fast proof/eml_proof_in_lumbda.lsp')" \
"$(bestof_cached 'python3 uncommonlisp.py --fast proof/eml_proof_in_lumbda.lsp')" "$(bestof_cached 'python3 lumbda.py --fast proof/eml_proof_in_lumbda.lsp')"
printf " %-38s %4s ms %4s ms\n" "C (tree-walker)" \ printf " %-38s %4s ms %4s ms\n" "C (tree-walker)" \
"$(bestof_cold 'c/uncommonlisp proof/eml_proof_in_lumbda.lsp')" \ "$(bestof_cold 'c/lumbda proof/eml_proof_in_lumbda.lsp')" \
"$(bestof_cached 'c/uncommonlisp proof/eml_proof_in_lumbda.lsp')" "$(bestof_cached 'c/lumbda proof/eml_proof_in_lumbda.lsp')"
printf " %-38s %4s ms %4s ms\n" "C --fast (bytecode VM)" \ printf " %-38s %4s ms %4s ms\n" "C --fast (bytecode VM)" \
"$(bestof_cold 'timeout 15 c/uncommonlisp --fast proof/eml_proof_in_lumbda.lsp')" \ "$(bestof_cold 'timeout 15 c/lumbda --fast proof/eml_proof_in_lumbda.lsp')" \
"$(bestof_cached 'timeout 15 c/uncommonlisp --fast proof/eml_proof_in_lumbda.lsp')" "$(bestof_cached 'timeout 15 c/lumbda --fast proof/eml_proof_in_lumbda.lsp')"
printf " %-38s %4s ms %4s ms\n" "asm" \ printf " %-38s %4s ms %4s ms\n" "asm" \
"$(bestof_cold 'asm/uncommonlisp < proof/eml_proof_in_lumbda.lsp')" \ "$(bestof_cold 'asm/lumbda < proof/eml_proof_in_lumbda.lsp')" \
"$(bestof_cached 'asm/uncommonlisp < proof/eml_proof_in_lumbda.lsp')" "$(bestof_cached 'asm/lumbda < proof/eml_proof_in_lumbda.lsp')"
echo "" echo ""
echo " Lean 4 comparison:" echo " Lean 4 comparison:"

View file

@ -1,8 +1,8 @@
;;; functional.lsp — Shared functional test suite ;;; functional.lsp — Shared functional test suite
;;; Runs identically in both Python and C implementations. ;;; Runs identically in both Python and C implementations.
;;; ;;;
;;; Python: python3 uncommonlisp.py --fast tests/functional.lsp ;;; Python: python3 lumbda.py --fast tests/functional.lsp
;;; C: ./c/uncommonlisp tests/functional.lsp ;;; C: ./c/lumbda tests/functional.lsp
;;; ;;;
;;; Output: lines of "PASS: name" or "FAIL: name got=X expected=Y" ;;; Output: lines of "PASS: name" or "FAIL: name got=X expected=Y"
;;; Exit: displays summary at end ;;; Exit: displays summary at end
@ -595,11 +595,11 @@
;;; File I/O: write-file / file->string round-trip ;;; File I/O: write-file / file->string round-trip
;;; ═══════════════════════════════════════════════════════════════ ;;; ═══════════════════════════════════════════════════════════════
(define *tmp-path* "/tmp/uncommonlisp-functional-fio.txt") (define *tmp-path* "/tmp/lumbda-functional-fio.txt")
(assert-true "write-file basic" (write-file *tmp-path* "hello\n")) (assert-true "write-file basic" (write-file *tmp-path* "hello\n"))
(assert-equal "file->string round-trip" (file->string *tmp-path*) "hello\n") (assert-equal "file->string round-trip" (file->string *tmp-path*) "hello\n")
(assert-false "file->string missing" (file->string "/tmp/__nope_uncommonlisp_fio__")) (assert-false "file->string missing" (file->string "/tmp/__nope_lumbda_fio__"))
(assert-true "write-file overwrite" (assert-true "write-file overwrite"
(begin (write-file *tmp-path* "second") (string=? (file->string *tmp-path*) "second"))) (begin (write-file *tmp-path* "second") (string=? (file->string *tmp-path*) "second")))
@ -608,7 +608,7 @@
;;; Cross-impl state exchange using only string primitives ;;; Cross-impl state exchange using only string primitives
;;; ═══════════════════════════════════════════════════════════════ ;;; ═══════════════════════════════════════════════════════════════
(define *portal-path* "/tmp/uncommonlisp-functional-portal.sexp") (define *portal-path* "/tmp/lumbda-functional-portal.sexp")
(write-file *portal-path* (write-file *portal-path*
"(define portal-x 111)\n(define portal-y 222)\n(define portal-z 333)\n") "(define portal-x 111)\n(define portal-y 222)\n(define portal-z 333)\n")

View file

@ -11,9 +11,9 @@
set -u set -u
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
PY="python3 uncommonlisp.py --fast" PY="python3 lumbda.py --fast"
C="./c/uncommonlisp" C="./c/lumbda"
ASM="./asm/uncommonlisp" ASM="./asm/lumbda"
N=50 N=50
pad() { printf " %-42s " "$1"; } pad() { printf " %-42s " "$1"; }

View file

@ -13,9 +13,9 @@
set -e set -e
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
PY="python3 uncommonlisp.py --fast" PY="python3 lumbda.py --fast"
C="./c/uncommonlisp" C="./c/lumbda"
ASM="./asm/uncommonlisp" ASM="./asm/lumbda"
SEXP=/tmp/portal-xtest.sexp SEXP=/tmp/portal-xtest.sexp
PASS=0 PASS=0

View file

@ -16,7 +16,7 @@
;; Write all user-defined bindings as (define name value) forms ;; Write all user-defined bindings as (define name value) forms
;; that any Scheme can evaluate to restore state ;; that any Scheme can evaluate to restore state
(let ((port (open-output-file filename))) (let ((port (open-output-file filename)))
(display ";; uncommonlisp portable state" port) (display ";; lumbda portable state" port)
(newline port) (newline port)
(display ";; generated by portal-save-sexp" port) (display ";; generated by portal-save-sexp" port)
(newline port) (newline port)

View file

@ -4,9 +4,9 @@
;;; 2. JSON (Python + C) ;;; 2. JSON (Python + C)
;;; 3. Binary heap dump (assembly only, fastest) ;;; 3. Binary heap dump (assembly only, fastest)
;;; ;;;
;;; Run in Python: python3 uncommonlisp.py --fast tests/portal-formats.lsp ;;; Run in Python: python3 lumbda.py --fast tests/portal-formats.lsp
;;; Run in C: ./c/uncommonlisp tests/portal-formats.lsp ;;; Run in C: ./c/lumbda tests/portal-formats.lsp
;;; Asm: asm/uncommonlisp < tests/portal-cross-load.lsp (no `load` builtin) ;;; Asm: asm/lumbda < tests/portal-cross-load.lsp (no `load` builtin)
;;; ;;;
;;; ── Observed results (2026-04-16, same laptop) ───────────────── ;;; ── Observed results (2026-04-16, same laptop) ─────────────────
;;; ;;;
@ -47,7 +47,7 @@
(define (write-sexp-portal filename) (define (write-sexp-portal filename)
(let ((port (open-output-file filename))) (let ((port (open-output-file filename)))
;; Header ;; Header
(display ";; uncommonlisp portable state (S-expression format)" port) (display ";; lumbda portable state (S-expression format)" port)
(newline port) (newline port)
(display ";; resume: (load \"" port) (display ";; resume: (load \"" port)
(display filename port) (display filename port)

View file

@ -24,7 +24,7 @@ SPAWNED=()
cleanup() { cleanup() {
for pid in "${SPAWNED[@]}"; do kill -9 "$pid" 2>/dev/null; done for pid in "${SPAWNED[@]}"; do kill -9 "$pid" 2>/dev/null; done
sleep 0.2 sleep 0.2
pkill -9 -u "$USER" -f 'uncommonlisp.*(rpc|repl)-(server|relay|chain-bench)\.lsp' 2>/dev/null || true pkill -9 -u "$USER" -f 'lumbda.*(rpc|repl)-(server|relay|chain-bench)\.lsp' 2>/dev/null || true
} }
trap cleanup EXIT INT TERM trap cleanup EXIT INT TERM
@ -61,17 +61,17 @@ stop_bg() {
verify_clean() { verify_clean() {
local strays local strays
strays=$(pgrep -u "$USER" -f 'uncommonlisp.*(rpc|repl)-(server|relay|chain-bench)\.lsp' 2>/dev/null || true) strays=$(pgrep -u "$USER" -f 'lumbda.*(rpc|repl)-(server|relay|chain-bench)\.lsp' 2>/dev/null || true)
if [ -n "$strays" ]; then if [ -n "$strays" ]; then
echo "!! STRAYS: $strays" >&2 echo "!! STRAYS: $strays" >&2
pkill -9 -u "$USER" -f 'uncommonlisp.*(rpc|repl)-(server|relay|chain-bench)\.lsp' 2>/dev/null || true pkill -9 -u "$USER" -f 'lumbda.*(rpc|repl)-(server|relay|chain-bench)\.lsp' 2>/dev/null || true
return 1 return 1
fi fi
} }
PY="python3 uncommonlisp.py --fast" PY="python3 lumbda.py --fast"
C="./c/uncommonlisp" C="./c/lumbda"
ASM="./asm/uncommonlisp" ASM="./asm/lumbda"
# Always use Python client to drive (identical across benches). # Always use Python client to drive (identical across benches).
# We sed the hardcoded port in-place because asm's top-level # We sed the hardcoded port in-place because asm's top-level

View file

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# web-benchmark.sh — race the three uncommonlisp HTTP servers # web-benchmark.sh — race the three lumbda HTTP servers
# against Python http.server and busybox httpd. # against Python http.server and busybox httpd.
# #
# No wrk/ab/nginx dependency — we use xargs+curl for concurrency. # No wrk/ab/nginx dependency — we use xargs+curl for concurrency.
@ -12,10 +12,10 @@ cd "$(dirname "$0")/.."
REQUESTS=${REQUESTS:-500} REQUESTS=${REQUESTS:-500}
CONCURRENCY=${CONCURRENCY:-10} CONCURRENCY=${CONCURRENCY:-10}
PY="python3 uncommonlisp.py --fast" PY="python3 lumbda.py --fast"
C="./c/uncommonlisp" C="./c/lumbda"
ASM="./asm/uncommonlisp" ASM="./asm/lumbda"
ASM_GC="./asm/uncommonlisp-gc" ASM_GC="./asm/lumbda-gc"
# Track every server PID we spawn; the EXIT trap kills them all. # Track every server PID we spawn; the EXIT trap kills them all.
# Asm has no GC — a leaked server leaks 64 MB per heap growth # Asm has no GC — a leaked server leaks 64 MB per heap growth
@ -34,7 +34,7 @@ cleanup() {
rm -rf "${STATIC_DIR:-/nonexistent/xyz}" rm -rf "${STATIC_DIR:-/nonexistent/xyz}"
# Final sanity: any stray servers from examples/http-server? # Final sanity: any stray servers from examples/http-server?
# Narrow to processes actually serving the HTTP example, not the # Narrow to processes actually serving the HTTP example, not the
# shell running this script or tmux sessions with "uncommonlisp" # shell running this script or tmux sessions with "lumbda"
# in their name. # in their name.
local strays local strays
strays=$(pgrep -u "$USER" -f 'examples/http-server\.lsp|http\.server 8080' | wc -l) strays=$(pgrep -u "$USER" -f 'examples/http-server\.lsp|http\.server 8080' | wc -l)
@ -106,25 +106,25 @@ stop_server() {
sleep 0.2 sleep 0.2
} }
# ── uncommonlisp Python ── # ── lumbda Python ──
PID=$(start_server "$PY examples/http-server.lsp" 8080) PID=$(start_server "$PY examples/http-server.lsp" 8080)
bench_one "uncommonlisp Python (/bench, 1 KB)" 8080 /bench bench_one "lumbda Python (/bench, 1 KB)" 8080 /bench
stop_server "$PID" stop_server "$PID"
# ── uncommonlisp C ── # ── lumbda C ──
PID=$(start_server "$C examples/http-server.lsp" 8080) PID=$(start_server "$C examples/http-server.lsp" 8080)
bench_one "uncommonlisp C (/bench, 1 KB)" 8080 /bench bench_one "lumbda C (/bench, 1 KB)" 8080 /bench
stop_server "$PID" stop_server "$PID"
# ── uncommonlisp asm (bump-only) ── # ── lumbda asm (bump-only) ──
PID=$(start_server "$ASM < examples/http-server.lsp" 8080) PID=$(start_server "$ASM < examples/http-server.lsp" 8080)
bench_one "uncommonlisp asm (/bench, 1 KB)" 8080 /bench bench_one "lumbda asm (/bench, 1 KB)" 8080 /bench
stop_server "$PID" stop_server "$PID"
# ── uncommonlisp asm-gc (naive mark-sweep + meta-GC build) ── # ── lumbda asm-gc (naive mark-sweep + meta-GC build) ──
if [ -x "$ASM_GC" ]; then if [ -x "$ASM_GC" ]; then
PID=$(start_server "$ASM_GC < examples/http-server.lsp" 8080) PID=$(start_server "$ASM_GC < examples/http-server.lsp" 8080)
bench_one "uncommonlisp asm-gc (/bench, 1 KB)" 8080 /bench bench_one "lumbda asm-gc (/bench, 1 KB)" 8080 /bench
stop_server "$PID" stop_server "$PID"
fi fi
@ -148,9 +148,9 @@ echo
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"
echo "Binary sizes" echo "Binary sizes"
echo "═══════════════════════════════════════════════════════════════" echo "═══════════════════════════════════════════════════════════════"
printf " uncommonlisp asm: %s\n" "$(du -b asm/uncommonlisp | cut -f1) bytes" printf " lumbda asm: %s\n" "$(du -b asm/lumbda | cut -f1) bytes"
[ -x asm/uncommonlisp-gc ] && \ [ -x asm/lumbda-gc ] && \
printf " uncommonlisp asm-gc: %s\n" "$(du -b asm/uncommonlisp-gc | cut -f1) bytes (GC_NAIVE build)" printf " lumbda asm-gc: %s\n" "$(du -b asm/lumbda-gc | cut -f1) bytes (GC_NAIVE build)"
printf " uncommonlisp C: %s\n" "$(du -b c/uncommonlisp | cut -f1) bytes" printf " lumbda C: %s\n" "$(du -b c/lumbda | cut -f1) bytes"
printf " busybox httpd: %s\n" "$(du -b /usr/bin/busybox | cut -f1) bytes (multi-call)" printf " busybox httpd: %s\n" "$(du -b /usr/bin/busybox | cut -f1) bytes (multi-call)"
printf " python3: %s bytes (interpreter binary)\n" "$(du -bL $(which python3) | cut -f1)" printf " python3: %s bytes (interpreter binary)\n" "$(du -bL $(which python3) | cut -f1)"

View file

@ -1 +1 @@
uncommonlisp-whitepaper.pdf lumbda-whitepaper.pdf

View file

@ -1 +1 @@
uncommonlisp-whitepaper.rst lumbda-whitepaper.rst

View file

@ -584,7 +584,7 @@ endobj
endobj endobj
69 0 obj 69 0 obj
<< <<
/Author () /CreationDate (D:20260419094254-04'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260419094254-04'00') /Producer (ReportLab PDF Library - \(opensource\)) /Author () /CreationDate (D:20260419101758-04'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260419101758-04'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (\(unspecified\)) /Title () /Trapped /False /Subject (\(unspecified\)) /Title () /Trapped /False
>> >>
endobj endobj
@ -875,7 +875,7 @@ endobj
endobj endobj
125 0 obj 125 0 obj
<< <<
/Dest [ 57 0 R /XYZ 57.02362 265.0236 0 ] /Next 126 0 R /Parent 123 0 R /Prev 124 0 R /Title (12.2 MOAD-0002: The Intertangle in Our Own Design) /Dest [ 57 0 R /XYZ 57.02362 277.0236 0 ] /Next 126 0 R /Parent 123 0 R /Prev 124 0 R /Title (12.2 MOAD-0002: The Intertangle in Our Own Design)
>> >>
endobj endobj
126 0 obj 126 0 obj
@ -4473,7 +4473,7 @@ endstream
endobj endobj
143 0 obj 143 0 obj
<< <<
/Length 8523 /Length 8511
>> >>
stream stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@ -4492,7 +4492,7 @@ n -6 -6 480.0283 31.2 re B*
Q Q
q q
0 0 0 rg 0 0 0 rg
BT 1 0 0 1 0 11.2 Tm /F5 8 Tf 9.6 TL (as --64 --defsym GC_NAIVE=1 uncommonlisp.s # collecting build) Tj T* (as --64 uncommonlisp.s # default, bump-only) Tj T* ET BT 1 0 0 1 0 11.2 Tm /F5 8 Tf 9.6 TL (as --64 --defsym GC_NAIVE=1 lumbda.s # collecting build) Tj T* (as --64 lumbda.s # default, bump-only) Tj T* ET
Q Q
Q Q
Q Q
@ -6477,7 +6477,7 @@ endstream
endobj endobj
148 0 obj 148 0 obj
<< <<
/Length 10633 /Length 10627
>> >>
stream stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@ -6920,7 +6920,7 @@ n -6 -6 480.0283 21.6 re B*
Q Q
q q
0 0 0 rg 0 0 0 rg
BT 1 0 0 1 0 1.6 Tm /F5 8 Tf 9.6 TL (python3 uncommonlisp.py --portal-resume state.portal) Tj T* ET BT 1 0 0 1 0 1.6 Tm /F5 8 Tf 9.6 TL (python3 lumbda.py --portal-resume state.portal) Tj T* ET
Q Q
Q Q
Q Q
@ -7905,7 +7905,7 @@ endstream
endobj endobj
152 0 obj 152 0 obj
<< <<
/Length 10223 /Length 10217
>> >>
stream stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@ -8206,7 +8206,7 @@ Q
q q
1 0 0 1 23 -3 cm 1 0 0 1 23 -3 cm
q q
BT 1 0 0 1 0 26 Tm .886835 Tw 12 TL /F3 10 Tf 0 0 0 rg (Self-hosted verification) Tj /F1 10 Tf ( \() Tj /F5 10 Tf (proof/eml_proof.lsp) Tj /F1 10 Tf (\): The same proof runs in Lumbda's bytecode VM) Tj T* 0 Tw 2.063543 Tw (\() Tj /F5 10 Tf (python3) Tj ( ) Tj (uncommonlisp.py) Tj ( ) Tj (--fast) Tj ( ) Tj (proof/eml_proof.lsp) Tj /F1 10 Tf (\). The language verifies its own) Tj T* 0 Tw (mathematical foundations.) Tj T* ET BT 1 0 0 1 0 26 Tm .886835 Tw 12 TL /F3 10 Tf 0 0 0 rg (Self-hosted verification) Tj /F1 10 Tf ( \() Tj /F5 10 Tf (proof/eml_proof.lsp) Tj /F1 10 Tf (\): The same proof runs in Lumbda's bytecode VM) Tj T* 0 Tw 6.563543 Tw (\() Tj /F5 10 Tf (python3) Tj ( ) Tj (lumbda.py) Tj ( ) Tj (--fast) Tj ( ) Tj (proof/eml_proof.lsp) Tj /F1 10 Tf (\). The language verifies its own) Tj T* 0 Tw (mathematical foundations.) Tj T* ET
Q Q
Q Q
q q
@ -9374,7 +9374,7 @@ endstream
endobj endobj
157 0 obj 157 0 obj
<< <<
/Length 16605 /Length 16587
>> >>
stream stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@ -10123,7 +10123,7 @@ q
n -6 -6 480.0283 40.8 re B* n -6 -6 480.0283 40.8 re B*
Q Q
q q
BT 1 0 0 1 0 20.8 Tm 9.6 TL /F5 8 Tf 0 0 0 rg (python3 uncommonlisp.py --fast examples/http-server.lsp) Tj T* (./c/uncommonlisp examples/http-server.lsp) Tj T* (./asm/uncommonlisp ) Tj (<) Tj ( examples/http-server.lsp) Tj T* ET BT 1 0 0 1 0 20.8 Tm 9.6 TL /F5 8 Tf 0 0 0 rg (python3 lumbda.py --fast examples/http-server.lsp) Tj T* (./c/lumbda examples/http-server.lsp) Tj T* (./asm/lumbda ) Tj (<) Tj ( examples/http-server.lsp) Tj T* ET
Q Q
Q Q
Q Q
@ -10975,7 +10975,7 @@ endstream
endobj endobj
161 0 obj 161 0 obj
<< <<
/Length 8009 /Length 7971
>> >>
stream stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@ -11091,7 +11091,7 @@ Q
q q
1 0 0 1 23 -3 cm 1 0 0 1 23 -3 cm
q q
BT 1 0 0 1 0 26 Tm .908543 Tw 12 TL /F5 10 Tf 0 0 0 rg (uncommonlisp.py) Tj /F1 10 Tf ('s ) Tj /F5 10 Tf (_tokenize_lines) Tj /F1 10 Tf ( called ) Tj /F5 10 Tf (src.count\('\\n',) Tj ( ) Tj (0,) Tj ( ) Tj (m.start\(\)\)) Tj /F1 10 Tf ( per token to) Tj T* 0 Tw 1.140596 Tw (compute line numbers. O\(N\267M\). Replaced with a single pass that builds a ) Tj /F5 10 Tf (line_starts) Tj /F1 10 Tf ( array, then) Tj T* 0 Tw (bisects per token. O\(M + N log M\).) Tj T* ET BT 1 0 0 1 0 26 Tm .237594 Tw 12 TL /F5 10 Tf 0 0 0 rg (lumbda.py) Tj /F1 10 Tf ('s ) Tj /F5 10 Tf (_tokenize_lines) Tj /F1 10 Tf ( called ) Tj /F5 10 Tf (src.count\('\\n',) Tj ( ) Tj (0,) Tj ( ) Tj (m.start\(\)\)) Tj /F1 10 Tf ( per token to compute) Tj T* 0 Tw .39789 Tw (line numbers. O\(N\267M\). Replaced with a single pass that builds a ) Tj /F5 10 Tf (line_starts) Tj /F1 10 Tf ( array, then bisects per) Tj T* 0 Tw (token. O\(M + N log M\).) Tj T* ET
Q Q
Q Q
q q
@ -11102,39 +11102,39 @@ q
1 0 0 1 57.02362 387.0236 cm 1 0 0 1 57.02362 387.0236 cm
Q Q
q q
1 0 0 1 57.02362 297.0236 cm 1 0 0 1 57.02362 309.0236 cm
q q
BT 1 0 0 1 0 74 Tm 4.926213 Tw 12 TL /F1 10 Tf 0 0 0 rg (A third correctness fix landed after the portal-over-HTTP demo exposed it: ) Tj /F5 10 Tf (uncommonlisp.py) Tj /F1 10 Tf ('s) Tj T* 0 Tw .515223 Tw /F5 10 Tf (Env.lookup) Tj /F1 10 Tf ( used to short-cut from the local frame directly to the global frame before walking intermediate) Tj T* 0 Tw 1.47713 Tw (parents. That was fast but wrong \227 a let-loop parameter named the same as a global builtin \() Tj /F5 10 Tf (count) Tj /F1 10 Tf (, a) Tj T* 0 Tw .409897 Tw (SRFI-1 procedure\) got shadowed in reverse, the shortcut returned the global builtin instead of walking up to) Tj T* 0 Tw .07402 Tw (the loop's parameter frame. Fix: walk ) Tj /F5 10 Tf (self) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (self.p) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (...) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (global) Tj /F1 10 Tf ( in order, without any shortcut.) Tj T* 0 Tw 1.17189 Tw (The inline cache at ) Tj /F5 10 Tf (OP_LOOKUP) Tj /F1 10 Tf ( was correspondingly tightened to validate the full chain before firing. 980) Tj T* 0 Tw (tests remained green.) Tj T* ET BT 1 0 0 1 0 62 Tm .226796 Tw 12 TL /F1 10 Tf 0 0 0 rg (A third correctness fix landed after the portal-over-HTTP demo exposed it: ) Tj /F5 10 Tf (lumbda.py) Tj /F1 10 Tf ('s ) Tj /F5 10 Tf (Env.lookup) Tj /F1 10 Tf ( used) Tj T* 0 Tw .794272 Tw (to short-cut from the local frame directly to the global frame before walking intermediate parents. That was) Tj T* 0 Tw .366019 Tw (fast but wrong \227 a let-loop parameter named the same as a global builtin \() Tj /F5 10 Tf (count) Tj /F1 10 Tf (, a SRFI-1 procedure\) got) Tj T* 0 Tw .949897 Tw (shadowed in reverse, the shortcut returned the global builtin instead of walking up to the loop's parameter) Tj T* 0 Tw .453797 Tw (frame. Fix: walk ) Tj /F5 10 Tf (self) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (self.p) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (...) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (global) Tj /F1 10 Tf ( in order, without any shortcut. The inline cache at) Tj T* 0 Tw /F5 10 Tf (OP_LOOKUP) Tj /F1 10 Tf ( was correspondingly tightened to validate the full chain before firing. 980 tests remained green.) Tj T* ET
Q Q
Q Q
q q
1 0 0 1 57.02362 279.0236 cm 1 0 0 1 57.02362 291.0236 cm
q q
0 0 0 rg 0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Every release audit surfaces more. Writing new code is writing new sediment, unless the audit runs.) Tj T* ET BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Every release audit surfaces more. Writing new code is writing new sediment, unless the audit runs.) Tj T* ET
Q Q
Q Q
q q
1 0 0 1 57.02362 253.0236 cm 1 0 0 1 57.02362 265.0236 cm
q q
BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf .133333 .133333 .133333 rg (12.2 MOAD-0002: The Intertangle in Our Own Design) Tj T* ET BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf .133333 .133333 .133333 rg (12.2 MOAD-0002: The Intertangle in Our Own Design) Tj T* ET
Q Q
Q Q
q q
1 0 0 1 57.02362 235.0236 cm 1 0 0 1 57.02362 247.0236 cm
q q
0 0 0 rg 0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (All three implementations share mutable global state between subsystems:) Tj T* ET BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (All three implementations share mutable global state between subsystems:) Tj T* ET
Q Q
Q Q
q q
1 0 0 1 57.02362 229.0236 cm 1 0 0 1 57.02362 241.0236 cm
Q Q
q q
1 0 0 1 57.02362 229.0236 cm 1 0 0 1 57.02362 241.0236 cm
Q Q
q q
1 0 0 1 57.02362 181.0236 cm 1 0 0 1 57.02362 193.0236 cm
q q
0 0 0 rg 0 0 0 rg
BT /F1 10 Tf 12 TL ET BT /F1 10 Tf 12 TL ET
@ -11156,10 +11156,10 @@ Q
Q Q
Q Q
q q
1 0 0 1 57.02362 175.0236 cm 1 0 0 1 57.02362 187.0236 cm
Q Q
q q
1 0 0 1 57.02362 139.0236 cm 1 0 0 1 57.02362 151.0236 cm
q q
0 0 0 rg 0 0 0 rg
BT /F1 10 Tf 12 TL ET BT /F1 10 Tf 12 TL ET
@ -11181,10 +11181,10 @@ Q
Q Q
Q Q
q q
1 0 0 1 57.02362 133.0236 cm 1 0 0 1 57.02362 145.0236 cm
Q Q
q q
1 0 0 1 57.02362 97.02362 cm 1 0 0 1 57.02362 109.0236 cm
q q
0 0 0 rg 0 0 0 rg
BT /F1 10 Tf 12 TL ET BT /F1 10 Tf 12 TL ET
@ -11206,7 +11206,7 @@ Q
Q Q
Q Q
q q
1 0 0 1 57.02362 79.02362 cm 1 0 0 1 57.02362 91.02362 cm
Q Q
endstream endstream
@ -12146,66 +12146,66 @@ xref
0002447433 00000 n 0002447433 00000 n
0002457549 00000 n 0002457549 00000 n
0002466915 00000 n 0002466915 00000 n
0002475491 00000 n 0002475479 00000 n
0002486442 00000 n 0002486430 00000 n
0002498945 00000 n 0002498933 00000 n
0002509558 00000 n 0002509546 00000 n
0002518581 00000 n 0002518569 00000 n
0002529268 00000 n 0002529250 00000 n
0002536885 00000 n 0002536867 00000 n
0002546473 00000 n 0002546455 00000 n
0002554309 00000 n 0002554291 00000 n
0002564586 00000 n 0002564562 00000 n
0002574527 00000 n 0002574503 00000 n
0002581044 00000 n 0002581020 00000 n
0002582879 00000 n 0002582855 00000 n
0002596335 00000 n 0002596311 00000 n
0002612994 00000 n 0002612952 00000 n
0002623502 00000 n 0002623460 00000 n
0002630961 00000 n 0002630919 00000 n
0002637635 00000 n 0002637593 00000 n
0002645697 00000 n 0002645617 00000 n
0002653633 00000 n 0002653553 00000 n
0002660101 00000 n 0002660021 00000 n
0002662257 00000 n 0002662177 00000 n
0002663335 00000 n 0002663255 00000 n
0002663739 00000 n 0002663659 00000 n
0002663774 00000 n 0002663694 00000 n
0002663809 00000 n 0002663729 00000 n
0002663844 00000 n 0002663764 00000 n
0002663879 00000 n 0002663799 00000 n
0002663914 00000 n 0002663834 00000 n
0002663949 00000 n 0002663869 00000 n
0002663984 00000 n 0002663904 00000 n
0002664019 00000 n 0002663939 00000 n
0002664054 00000 n 0002663974 00000 n
0002664090 00000 n 0002664010 00000 n
0002664126 00000 n 0002664046 00000 n
0002664162 00000 n 0002664082 00000 n
0002664198 00000 n 0002664118 00000 n
0002664234 00000 n 0002664154 00000 n
0002664270 00000 n 0002664190 00000 n
0002664306 00000 n 0002664226 00000 n
0002664342 00000 n 0002664262 00000 n
0002664378 00000 n 0002664298 00000 n
0002664414 00000 n 0002664334 00000 n
0002664450 00000 n 0002664370 00000 n
0002664486 00000 n 0002664406 00000 n
0002664522 00000 n 0002664442 00000 n
0002664558 00000 n 0002664478 00000 n
0002664594 00000 n 0002664514 00000 n
0002664630 00000 n 0002664550 00000 n
0002664666 00000 n 0002664586 00000 n
0002664702 00000 n 0002664622 00000 n
0002664738 00000 n 0002664658 00000 n
0002664774 00000 n 0002664694 00000 n
0002664810 00000 n 0002664730 00000 n
0002664846 00000 n 0002664766 00000 n
0002664882 00000 n 0002664802 00000 n
trailer trailer
<< <<
/ID /ID
[<1d446ae1004a02d6f40b0a19c1f8b013><1d446ae1004a02d6f40b0a19c1f8b013>] [<256838ea1d698f91db2ad0c26a223907><256838ea1d698f91db2ad0c26a223907>]
% ReportLab generated PDF document -- digest (opensource) % ReportLab generated PDF document -- digest (opensource)
/Info 69 0 R /Info 69 0 R
@ -12213,5 +12213,5 @@ trailer
/Size 200 /Size 200
>> >>
startxref startxref
2664918 2664838
%%EOF %%EOF

View file

@ -482,8 +482,8 @@ To measure what a collector would actually cost, we built a second asm binary be
.. code-block:: .. code-block::
as --64 --defsym GC_NAIVE=1 uncommonlisp.s # collecting build as --64 --defsym GC_NAIVE=1 lumbda.s # collecting build
as --64 uncommonlisp.s # default, bump-only as --64 lumbda.s # default, bump-only
Same source, same tests (137/137 pass on both). The GC build adds an 8-byte ``(size << 1 | mark)`` header on every heap block, a stop-the-world mark-sweep triggered by bump overflow, and a free-list allocator that first-fits reclaimed space. Same source, same tests (137/137 pass on both). The GC build adds an 8-byte ``(size << 1 | mark)`` header on every heap block, a stop-the-world mark-sweep triggered by bump overflow, and a free-list allocator that first-fits reclaimed space.
@ -746,7 +746,7 @@ During VM execution, ``portal-checkpoint!`` triggers at ``OP_JUMP`` & ``OP_TAIL_
:: ::
python3 uncommonlisp.py --portal-resume state.portal python3 lumbda.py --portal-resume state.portal
The computation does not need to restart from the beginning. The computation does not need to restart from the beginning.
@ -954,7 +954,7 @@ The proof has been verified at six distinct levels. Times are best-of-3 on the i
1. **Numerical verification** (``proof/eml_proof.py``): Python script using ``cmath`` at high precision. Verifies every derivation step with tolerance ``1e-10``. Includes brute-force tree search at depth ≤ 4 confirming that eml compositions reach the expected targets. 1. **Numerical verification** (``proof/eml_proof.py``): Python script using ``cmath`` at high precision. Verifies every derivation step with tolerance ``1e-10``. Includes brute-force tree search at depth ≤ 4 confirming that eml compositions reach the expected targets.
2. **Self-hosted verification** (``proof/eml_proof.lsp``): The same proof runs in Lumbda's bytecode VM (``python3 uncommonlisp.py --fast proof/eml_proof.lsp``). The language verifies its own mathematical foundations. 2. **Self-hosted verification** (``proof/eml_proof.lsp``): The same proof runs in Lumbda's bytecode VM (``python3 lumbda.py --fast proof/eml_proof.lsp``). The language verifies its own mathematical foundations.
3. **Formal proof** (``proof/lean/EmlProof/Basic.lean``): Lean 4 proof with zero ``sorry``. Five theorems: 3. **Formal proof** (``proof/lean/EmlProof/Basic.lean``): Lean 4 proof with zero ``sorry``. Five theorems:
@ -1143,9 +1143,9 @@ Sockets share the same port representation as files — in asm the fd is packed
:: ::
python3 uncommonlisp.py --fast examples/http-server.lsp python3 lumbda.py --fast examples/http-server.lsp
./c/uncommonlisp examples/http-server.lsp ./c/lumbda examples/http-server.lsp
./asm/uncommonlisp < examples/http-server.lsp ./asm/lumbda < examples/http-server.lsp
The companion ``examples/http-client-bench.lsp`` is a 45-line load generator using only the six ``tcp-*`` primitives plus ``current-time-ms``. In-process client eliminates the ~2 ms/request fork overhead that curl-based benchmarks suffer, so real server throughput shows through. **Reproduce:** ``make bench-web`` (source: ``tests/web-benchmark.sh``). The companion ``examples/http-client-bench.lsp`` is a 45-line load generator using only the six ``tcp-*`` primitives plus ``current-time-ms``. In-process client eliminates the ~2 ms/request fork overhead that curl-based benchmarks suffer, so real server throughput shows through. **Reproduce:** ``make bench-web`` (source: ``tests/web-benchmark.sh``).
@ -1314,9 +1314,9 @@ The Python implementation had a similar defect: ``_define_record_type`` used ``l
**Two more MOAD-0001 defects surfaced during the HTTP server work and were fixed in the same pass:** **Two more MOAD-0001 defects surfaced during the HTTP server work and were fixed in the same pass:**
- ``c/builtins.c``'s ``bi_string_replace`` scanned the source byte-by-byte, calling ``strncmp(src, from, from_len)`` at every position. O(N·k). Replaced with ``strstr`` (libc-tuned, typically Boyer-Moore-Horspool) called in a loop that skips to the next match. O(N + matches·k). - ``c/builtins.c``'s ``bi_string_replace`` scanned the source byte-by-byte, calling ``strncmp(src, from, from_len)`` at every position. O(N·k). Replaced with ``strstr`` (libc-tuned, typically Boyer-Moore-Horspool) called in a loop that skips to the next match. O(N + matches·k).
- ``uncommonlisp.py``'s ``_tokenize_lines`` called ``src.count('\\n', 0, m.start())`` per token to compute line numbers. O(N·M). Replaced with a single pass that builds a ``line_starts`` array, then bisects per token. O(M + N log M). - ``lumbda.py``'s ``_tokenize_lines`` called ``src.count('\\n', 0, m.start())`` per token to compute line numbers. O(N·M). Replaced with a single pass that builds a ``line_starts`` array, then bisects per token. O(M + N log M).
A third correctness fix landed after the portal-over-HTTP demo exposed it: ``uncommonlisp.py``'s ``Env.lookup`` used to short-cut from the local frame directly to the global frame before walking intermediate parents. That was fast but wrong — a let-loop parameter named the same as a global builtin (``count``, a SRFI-1 procedure) got shadowed in reverse, the shortcut returned the global builtin instead of walking up to the loop's parameter frame. Fix: walk ``self → self.p → ... → global`` in order, without any shortcut. The inline cache at ``OP_LOOKUP`` was correspondingly tightened to validate the full chain before firing. 980 tests remained green. A third correctness fix landed after the portal-over-HTTP demo exposed it: ``lumbda.py``'s ``Env.lookup`` used to short-cut from the local frame directly to the global frame before walking intermediate parents. That was fast but wrong — a let-loop parameter named the same as a global builtin (``count``, a SRFI-1 procedure) got shadowed in reverse, the shortcut returned the global builtin instead of walking up to the loop's parameter frame. Fix: walk ``self → self.p → ... → global`` in order, without any shortcut. The inline cache at ``OP_LOOKUP`` was correspondingly tightened to validate the full chain before firing. 980 tests remained green.
Every release audit surfaces more. Writing new code is writing new sediment, unless the audit runs. Every release audit surfaces more. Writing new code is writing new sediment, unless the audit runs.