Adds a parallel build of all three Lumbda implementations to WASM, a
single-page playground at www/playground/, and a verified test suite.
Tiers
- Python: Pyodide (CPython-in-WASM) hosting lumbda.py
- C: Emscripten build of c/ (tree-walker + bytecode VM; jit.c
stubbed, gc.c uses its existing no-Boehm fallback)
- Asm: hand-written asm/lumbda.wat — parallel impl to asm/lumbda.s.
Reader, eval (lambda/define/if/cond/let/and/or/quote/set!),
recursion across mutated top-level env, bump allocator with
memory.grow, 24 primitives. ~1200 lines of raw WAT.
SPA (wasm/app/, deployed to www/playground/)
- CodeMirror 6 editor (Scheme highlighting) on left, output on right
- Radios: 4 demos (Mandelbrot, Fib+Ack, Sieve, self-interp meta-eval)
x 4 tiers (Python | C | Asm | All three)
- All-three mode renders the three tier outputs side by side with
per-tier elapsed timing
Tests (38 verified assertions)
- 20 unit (Node): per-tier module loads, eval smoke
- 8 integration (Node): each demo on c+asm WASM byte-matches the
canonical native Python run
- 10 functional (Playwright headless Chromium): page mounts, every
demo runs on every tier, all-three renders
Makefile
- Root targets: wasm-build, wasm-test, wasm-test-fn, wasm-serve,
wasm-deploy, wasm-clean
- wasm/Makefile orchestrates the three tier builds; deploy copies
dist/ into www/playground/
Asm tier notes
- WAT linear symbol intern + linear env lookup is MOAD-0001 at scale;
documented in the asm/lumbda.wat header and in the SPA footer. The
demos hit ~30 globals so the linear walks are cheap enough.
- Bump allocator never frees (matches asm/lumbda.s heap discipline);
memory.grow expands by 1 MB chunks. Browser tab tears down at unload.
Toolchain (developer prerequisites)
- Emscripten 6.0.0 via emsdk at ~/git/emsdk
- wabt 1.0.36 at ~/git/wabt
- Playwright for functional tests (symlinked from ~/git/agnt)
371 lines
14 KiB
Makefile
371 lines
14 KiB
Makefile
# ═══════════════════════════════════════════════════════════════════
|
||
# lumbda — Python + C + Assembly implementations
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
#
|
||
# Implementations:
|
||
# Python lumbda.py bytecode VM, full continuations, portal
|
||
# C c/lumbda tree-walker + bytecode VM + x86_64 JIT
|
||
# Assembly asm/lumbda pure x86_64, no libc, 13KB binary
|
||
#
|
||
# Test suites:
|
||
# make test Python unit/integration (571 tests)
|
||
# make c-test C unit/integration + JIT (76 tests) + functional (114)
|
||
# make asm-test Assembly unit/integration/functional (75 tests)
|
||
# make functional-test Shared .lsp suite in Python + C (114 each)
|
||
# make test-all Everything (836 total)
|
||
#
|
||
# Benchmarks (each generates reproducible numbers referenced in the
|
||
# whitepaper; hardware-independent commands, safety envelope built in):
|
||
# make bench Python bench.py (tree-walker vs bytecode VM)
|
||
# make c-bench C unit-level microbenchmarks
|
||
# make bench-3way §6.4: Python vs C vs asm on sum-to/ack
|
||
# make bench-portal §7.5: S-exp/JSON/binary portal save+load timings
|
||
# make bench-portal-cross §7.2: 3x3 cross-impl portal save×load matrix
|
||
# make bench-web §11.3: HTTP benchmark vs busybox + python http.server
|
||
# make bench-rpc-chain §11.4: Py → C relay → asm backend chain timing
|
||
# make bench-proof §8.6: EML proof — Lean 4 vs Lumbda tiers
|
||
# make bench-all run every bench above back to back
|
||
# make friction head-to-head timing: Python vs C vs CPython
|
||
#
|
||
# Other:
|
||
# make examples Run examples in Python + C, compare output
|
||
# make docs Generate architecture diagrams
|
||
# make whitepaper Build PDF whitepaper
|
||
# make clean-all Clean everything
|
||
|
||
all: test
|
||
|
||
# ─── Python implementation ────────────────────────────────────────
|
||
|
||
test:
|
||
python3 tests.py
|
||
|
||
test-verbose:
|
||
python3 tests.py -v
|
||
|
||
bench:
|
||
python3 bench.py
|
||
|
||
bench-verbose:
|
||
python3 bench.py -v
|
||
|
||
repl:
|
||
python3 lumbda.py
|
||
|
||
lint:
|
||
python3 -m py_compile lumbda.py
|
||
python3 -m py_compile tests.py
|
||
python3 -m py_compile bench.py
|
||
|
||
# ─── C implementation ─────────────────────────────────────────────
|
||
|
||
c-build:
|
||
$(MAKE) -C c all
|
||
|
||
c-test: c-build
|
||
$(MAKE) -C c test
|
||
@echo "── C functional tests (shared .lsp suite) ──"
|
||
./c/lumbda tests/functional.lsp
|
||
|
||
c-bench: c-build
|
||
$(MAKE) -C c bench
|
||
|
||
c-repl: c-build
|
||
./c/lumbda
|
||
|
||
c-clean:
|
||
$(MAKE) -C c clean
|
||
|
||
# ─── Assembly implementation ──────────────────────────────────────
|
||
|
||
asm-build:
|
||
$(MAKE) -C asm all
|
||
|
||
asm-test: asm-build
|
||
$(MAKE) -C asm test
|
||
|
||
asm-repl: asm-build
|
||
./asm/lumbda
|
||
|
||
asm-clean:
|
||
$(MAKE) -C asm clean
|
||
|
||
# ─── All implementations ─────────────────────────────────────────
|
||
|
||
functional-test: c-build
|
||
@echo "═══ Shared functional tests (114 tests) ═══"
|
||
@echo "── Python ──"
|
||
@python3 lumbda.py --fast tests/functional.lsp | tail -3
|
||
@echo "── C ──"
|
||
@./c/lumbda tests/functional.lsp | tail -3
|
||
|
||
portal-rng-cross-test: c-build asm-build
|
||
@bash tests/portal-rng-cross-test.sh
|
||
|
||
zoe-favorites-test: c-build
|
||
@bash tests/zoe-favorites-test.sh
|
||
|
||
regression-named-let-leak: c-build
|
||
@bash tests/regression-named-let-leak.sh
|
||
|
||
# Fetches Zoë's source live from wedgewack.org, verifies the edits in
|
||
# examples/ursa.lisp.txt reduce to the documented six annotations, runs
|
||
# the suite across tiers, and spot-checks her exact source on asm-full
|
||
# with a 10-line stubs prelude. See tests/prove-ursa-runs.sh for the
|
||
# full chain. Needs a network connection; `make zoe-favorites-test`
|
||
# covers the offline case.
|
||
prove-ursa-runs: c-build
|
||
@bash tests/prove-ursa-runs.sh
|
||
|
||
test-all: test c-test asm-test functional-test portal-rng-cross-test zoe-favorites-test regression-named-let-leak
|
||
@echo "════════════════════════════════════════════════════"
|
||
@echo "All tests passed (Python + C + Assembly + functional + portal-rng-cross + zoe-favorites)"
|
||
|
||
# ─── Benchmarks (reproducible; referenced in whitepaper §6–§11) ───
|
||
|
||
bench-3way: c-build asm-build
|
||
@bash tests/bench-3way.sh
|
||
|
||
bench-portal: c-build asm-build
|
||
@bash tests/portal-benchmark.sh
|
||
|
||
bench-portal-cross: c-build asm-build
|
||
@bash tests/portal-cross-test.sh
|
||
|
||
bench-web: c-build asm-build
|
||
@bash tests/web-benchmark.sh
|
||
|
||
bench-rpc-chain: c-build asm-build
|
||
@bash tests/rpc-chain-bench.sh
|
||
|
||
bench-proof: c-build asm-build
|
||
@bash tests/bench-proof.sh
|
||
|
||
bench-hashset: asm-build
|
||
@bash tests/bench-hashset.sh
|
||
|
||
bench-gc: asm-build
|
||
@bash tests/bench-gc-memory.sh
|
||
|
||
bench-gc-arena: asm-build
|
||
@bash tests/bench-gc-arena.sh
|
||
|
||
bench-gc-adaptive: asm-build
|
||
@bash tests/bench-gc-adaptive.sh
|
||
|
||
bench-gc-http: asm-build
|
||
@bash tests/bench-gc-http.sh
|
||
|
||
bench-lumbda-www: asm-build
|
||
@bash tests/bench-lumbda-www.sh
|
||
|
||
bench-www-race: asm-build
|
||
@bash tests/bench-www-race.sh
|
||
bench-all: bench c-bench bench-3way bench-portal bench-portal-cross bench-web bench-rpc-chain bench-proof
|
||
@echo "═══════════════════════════════════════════════════════════"
|
||
@echo "All benchmarks complete. Numbers in the whitepaper §6.4,"
|
||
@echo "§7.2, §7.5, §11.3, §11.4 are reproducible from these targets."
|
||
|
||
# ─── Examples ─────────────────────────────────────────────────────
|
||
|
||
examples: c-build
|
||
@echo "═══ fibonacci.lsp ═══"
|
||
@echo "--- Python ---" && python3 lumbda.py --fast examples/fibonacci.lsp
|
||
@echo "--- C ---" && ./c/lumbda examples/fibonacci.lsp
|
||
@echo
|
||
@echo "═══ mergesort.lsp ═══"
|
||
@echo "--- Python ---" && python3 lumbda.py --fast examples/mergesort.lsp
|
||
@echo "--- C ---" && ./c/lumbda examples/mergesort.lsp
|
||
@echo
|
||
@echo "═══ objects.lsp ═══"
|
||
@echo "--- Python ---" && python3 lumbda.py examples/objects.lsp
|
||
@echo "--- C ---" && ./c/lumbda examples/objects.lsp
|
||
|
||
# ─── Friction benchmark ──────────────────────────────────────────
|
||
|
||
friction: c-build asm-build
|
||
bash friction.sh
|
||
|
||
# ─── GPU worker (bend primitive) ─────────────────────────────────
|
||
#
|
||
# Builds the cuda-fanout leaf binary & launches gpu-worker.lsp on
|
||
# port 8320 (override via PORT=NNNN). Client tier choice via
|
||
# LUMBDA=python|c|asm (default python). Once running, any tier can
|
||
# (bend …) to it from the same host or another LAN host.
|
||
#
|
||
# Port mnemonic — 8320 = BEND:
|
||
# 8 ~= B (implied infinity B flattened; bake a cake; baby & me)
|
||
# 3 ~= E (backward)
|
||
# 2 ~= N (pivoted 90 degrees)
|
||
# 0 ~= D (flattened)
|
||
|
||
GPU_WORKER_DIR := examples/cuda-fanout
|
||
PORT ?= 8320
|
||
LUMBDA ?= c
|
||
|
||
gpu-worker-bin:
|
||
$(MAKE) -C $(GPU_WORKER_DIR) shake256-fanout
|
||
|
||
gpu-worker: gpu-worker-bin
|
||
@echo "→ launching gpu-worker.lsp on port $(PORT) ($(LUMBDA) tier)"
|
||
@printf '(load "wire.lsp")\n(load "gpu-worker.lsp")\n(main)\n' > $(GPU_WORKER_DIR)/launch.lsp
|
||
ifeq ($(LUMBDA),c)
|
||
$(MAKE) c-build
|
||
cd $(GPU_WORKER_DIR) && ../../c/lumbda launch.lsp --port $(PORT)
|
||
else ifeq ($(LUMBDA),python)
|
||
cd $(GPU_WORKER_DIR) && python3 -u ../../lumbda.py launch.lsp --port $(PORT)
|
||
else ifeq ($(LUMBDA),asm)
|
||
$(MAKE) asm-build
|
||
cd $(GPU_WORKER_DIR) && ../../asm/lumbda-gc launch.lsp --port $(PORT)
|
||
else
|
||
@echo "LUMBDA=$(LUMBDA) — expected c | python | asm"; exit 2
|
||
endif
|
||
|
||
gpu-worker-test: gpu-worker-bin
|
||
$(MAKE) -C $(GPU_WORKER_DIR) test
|
||
|
||
# ─── Factory — bend at scale ──────────────────────────────────────
|
||
#
|
||
# Bounded-parallel emit + dispatch + autoscaling for lumbda research
|
||
# loops driving GPU bend backends. See factory/README.md & factory/CONTRACT.md.
|
||
# Originally built at foxhop for secp256k1 attack-surface research; shared
|
||
# upstream under AGPLv3.
|
||
#
|
||
# make factory-lint bash -n syntax check on factory/*.sh
|
||
# make test-integration integration tests (autoscaler V2 reducer + DLQ classifier)
|
||
# make sweep-doctrine TCRAUDT reducer gate (serial)
|
||
# make sweep-doctrine-parallel same, xargs -P fan-out (JOBS=N)
|
||
#
|
||
# Consumer wrapper pattern: domain repos export LUMBDA_* env then exec
|
||
# factory/bend-supervisor.sh. See factory/CONTRACT.md.
|
||
|
||
FACTORY_DIR := factory
|
||
TESTS_INTEGRATION_DIR := tests/integration
|
||
TESTS_SWEEP_DOCTRINE_DIR := tests/sweep-doctrine
|
||
|
||
factory-lint:
|
||
@bash $(TESTS_INTEGRATION_DIR)/test-bash-script-syntax.sh
|
||
|
||
test-integration:
|
||
@for t in $(TESTS_INTEGRATION_DIR)/test-*.sh; do \
|
||
echo "── $$t ──"; \
|
||
bash "$$t" || { rc=$$?; [ $$rc -eq 77 ] && echo "SKIP (factory script absent)" || exit $$rc; }; \
|
||
done
|
||
|
||
sweep-doctrine:
|
||
@bash $(TESTS_SWEEP_DOCTRINE_DIR)/run.sh
|
||
|
||
sweep-doctrine-parallel:
|
||
@bash $(TESTS_SWEEP_DOCTRINE_DIR)/run-parallel.sh
|
||
|
||
# ─── WebAssembly tiers (Python + C + asm to browser) ──────────────
|
||
#
|
||
# Three-tier Lumbda stack compiled to WASM for any modern browser.
|
||
# Python → Pyodide (CPython-in-WASM) loading lumbda.py
|
||
# C → Emscripten build of c/ (tree-walker + bytecode VM, no JIT)
|
||
# Asm → hand-written WebAssembly Text format (wasm/asm/lumbda.wat)
|
||
#
|
||
# Plus a single-page app at wasm/app/ (CodeMirror editor on left, output
|
||
# on right, tier radio: Python | C | Asm | All Three, demo radio:
|
||
# Mandelbrot | Fib+Ack | Sieve | Self-interp).
|
||
#
|
||
# make wasm-build all three tiers + SPA bundle in wasm/dist/
|
||
# make wasm-test unit + integration (node)
|
||
# make wasm-test-fn functional (headless browser via playwright)
|
||
# make wasm-serve local dev server at :8080
|
||
# make wasm-deploy copy bundle into www/playground/
|
||
# make wasm-clean
|
||
|
||
wasm-build:
|
||
$(MAKE) -C wasm build
|
||
|
||
wasm-test:
|
||
$(MAKE) -C wasm test
|
||
|
||
wasm-test-fn:
|
||
$(MAKE) -C wasm test-fn
|
||
|
||
wasm-serve:
|
||
$(MAKE) -C wasm serve
|
||
|
||
wasm-deploy:
|
||
$(MAKE) -C wasm deploy
|
||
|
||
wasm-clean:
|
||
$(MAKE) -C wasm clean
|
||
|
||
# ─── Documentation ────────────────────────────────────────────────
|
||
|
||
DOT_FILES := $(wildcard docs/*.dot)
|
||
DOT_PNGS := $(DOT_FILES:.dot=.png)
|
||
|
||
docs: $(DOT_PNGS)
|
||
|
||
docs/%.png: docs/%.dot
|
||
dot -Tpng $< -o $@
|
||
|
||
# ─── Whitepaper ───────────────────────────────────────────────────
|
||
|
||
VENV := whitepaper/.venv
|
||
RST := whitepaper/lumbda-whitepaper.rst
|
||
PDF := whitepaper/lumbda-whitepaper.pdf
|
||
HTML := whitepaper/lumbda-whitepaper.html
|
||
STYLE := whitepaper/whitepaper.style
|
||
|
||
$(VENV)/bin/rst2pdf:
|
||
python3 -m venv $(VENV)
|
||
$(VENV)/bin/pip install --upgrade pip
|
||
$(VENV)/bin/pip install rst2pdf docutils
|
||
|
||
whitepaper: $(PDF) $(HTML)
|
||
|
||
whitepaper-pdf: $(PDF)
|
||
whitepaper-html: $(HTML)
|
||
|
||
$(PDF): $(RST) $(STYLE) $(VENV)/bin/rst2pdf
|
||
cd whitepaper && ../$(<D)/.venv/bin/rst2pdf \
|
||
-s whitepaper.style \
|
||
--fit-background-mode=scale \
|
||
lumbda-whitepaper.rst \
|
||
-o lumbda-whitepaper.pdf
|
||
@ln -sf lumbda-whitepaper.pdf whitepaper/WHITEPAPER.pdf
|
||
@echo "Built: $(PDF)"
|
||
|
||
# HTML whitepaper: single self-contained file with embedded stylesheet
|
||
# plus an uncloseai.js module script (matches lumbda.com front door).
|
||
$(HTML): $(RST) $(VENV)/bin/rst2pdf
|
||
@DOCUTILS_CSS="$$(cd whitepaper/.venv/lib/python*/site-packages/docutils/writers/html5_polyglot && pwd)"; \
|
||
cd whitepaper && ../$(<D)/.venv/bin/rst2html5 \
|
||
--embed-stylesheet \
|
||
--stylesheet="$$DOCUTILS_CSS/minimal.css,$$DOCUTILS_CSS/responsive.css" \
|
||
lumbda-whitepaper.rst \
|
||
lumbda-whitepaper.html
|
||
@sed -i 's|</head>|<script src="https://uncloseai.com/uncloseai.js" type="module"></script>\n</head>|' $(HTML)
|
||
@sed -i 's|<title>lumbda-whitepaper.rst</title>|<title>Lumbda whitepaper — feedback as a primitive</title>|' $(HTML)
|
||
@python3 whitepaper/embed-images.py $(HTML)
|
||
@python3 whitepaper/inject-whitepaper-css.py $(HTML) \
|
||
www/fonts/chunkfive/chunkfive-regular-webfont.woff2
|
||
@echo "Built: $(HTML)"
|
||
|
||
# ─── Clean ────────────────────────────────────────────────────────
|
||
|
||
clean:
|
||
rm -rf __pycache__ *.pyc
|
||
|
||
clean-whitepaper:
|
||
rm -rf $(VENV) $(PDF) whitepaper/WHITEPAPER.pdf
|
||
|
||
clean-docs:
|
||
rm -f docs/*.png
|
||
|
||
clean-all: clean clean-whitepaper clean-docs c-clean asm-clean
|
||
|
||
.PHONY: all test test-verbose bench bench-verbose repl lint \
|
||
c-build c-test c-bench c-repl c-clean \
|
||
asm-build asm-test asm-repl asm-clean \
|
||
test-all bench-all examples friction functional-test portal-rng-cross-test \
|
||
bench-3way bench-portal bench-portal-cross bench-web bench-rpc-chain bench-proof \
|
||
gpu-worker gpu-worker-bin gpu-worker-test \
|
||
factory-lint test-integration sweep-doctrine sweep-doctrine-parallel \
|
||
wasm-build wasm-test wasm-test-fn wasm-serve wasm-deploy wasm-clean \
|
||
docs whitepaper clean clean-whitepaper clean-docs clean-all
|