lumbda/Makefile
russell@unturf.com fc9eb5350c Add C implementation: 7,429 lines, 58 tests, identical output
Complete C port of the Scheme interpreter. Same .lsp files run in
both Python and C with identical output.

Architecture:
- NaN-boxed 64-bit values (zero-alloc numbers)
- Hash-map environments with parent chain + global shortcut
- Interned symbols
- TCO via explicit loop (eval) and TAIL_CALL/SELF_TAIL_CALL (VM)
- Bytecode compiler with all opcodes including superinstructions
- 58 unit + integration tests

Makefile targets:
  make test-all    run Python (571) + C (58) tests
  make examples    run examples in both, compare output
  make friction    benchmark same .lsp in Python vs C
  make c-build     build C interpreter
  make c-test      run C tests
  make c-repl      C REPL
2026-04-14 14:55:17 -04:00

138 lines
5.5 KiB
Makefile

# ═══════════════════════════════════════════════════════════════════
# uncommonlisp — Python + C implementations
# ═══════════════════════════════════════════════════════════════════
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 uncommonlisp.py
lint:
python3 -m py_compile uncommonlisp.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
c-bench: c-build
$(MAKE) -C c bench
c-repl: c-build
./c/uncommonlisp
c-clean:
$(MAKE) -C c clean
# ─── Both implementations ────────────────────────────────────────
test-all: test c-test
@echo "════════════════════════════════════"
@echo "All tests passed (Python + C)"
bench-all: bench c-bench
# ─── Examples (run in both, compare output) ──────────────────────
examples: c-build
@echo "═══ fibonacci.lsp ═══"
@echo "--- Python ---"
@python3 uncommonlisp.py --fast examples/fibonacci.lsp
@echo "--- C ---"
@./c/uncommonlisp examples/fibonacci.lsp
@echo
@echo "═══ mergesort.lsp ═══"
@echo "--- Python ---"
@python3 uncommonlisp.py --fast examples/mergesort.lsp
@echo "--- C ---"
@./c/uncommonlisp examples/mergesort.lsp
@echo
@echo "═══ objects.lsp ═══"
@echo "--- Python ---"
@python3 uncommonlisp.py examples/objects.lsp
@echo "--- C ---"
@./c/uncommonlisp examples/objects.lsp
# ─── Friction benchmark (same .lsp, both runtimes) ──────────────
friction: c-build
@echo "═══════════════════════════════════════════════════════"
@echo "Friction benchmark: Python vs C on identical .lsp files"
@echo "═══════════════════════════════════════════════════════"
@echo
@echo ">>> fib(35) iterative"
@printf " Python: " && python3 -c "\
import time; from uncommonlisp import *; \
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('(define (fib n) (let loop ((a 0) (b 1) (i 0)) (if (= i n) a (loop b (+ a b) (+ i 1)))))')]; \
t=time.perf_counter(); r=[leval(e,g) for e in read_all('(fib 35)')][-1]; \
print(f'{(time.perf_counter()-t)*1000:.2f}ms result={r}')"
@printf " 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))))) (fib 35)' 2>&1
@echo
@echo ">>> ackermann(3,4)"
@printf " Python: " && python3 -c "\
import time; from uncommonlisp import *; \
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('(define (ack m n) (cond ((= m 0) (+ n 1)) ((= n 0) (ack (- m 1) 1)) (else (ack (- m 1) (ack m (- n 1))))))')];\
t=time.perf_counter(); r=[leval(e,g) for e in read_all('(ack 3 4)')][-1]; \
print(f'{(time.perf_counter()-t)*1000:.2f}ms result={r}')"
@printf " 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)))))) (ack 3 4)' 2>&1
# ═══════════════════════════════════════════════════════════════════
# Whitepaper
# ═══════════════════════════════════════════════════════════════════
VENV := whitepaper/.venv
RST := whitepaper/uncommonlisp-whitepaper.rst
PDF := whitepaper/uncommonlisp-whitepaper.pdf
STYLE := whitepaper/whitepaper.style
$(VENV)/bin/rst2pdf:
python3 -m venv $(VENV)
$(VENV)/bin/pip install --upgrade pip
$(VENV)/bin/pip install rst2pdf
whitepaper: $(PDF)
$(PDF): $(RST) $(STYLE) $(VENV)/bin/rst2pdf
cd whitepaper && ../$(<D)/.venv/bin/rst2pdf \
-s whitepaper.style \
--fit-background-mode=scale \
uncommonlisp-whitepaper.rst \
-o uncommonlisp-whitepaper.pdf
@ln -sf uncommonlisp-whitepaper.pdf whitepaper/WHITEPAPER.pdf
@echo "Built: $(PDF)"
clean:
rm -rf __pycache__ *.pyc
clean-whitepaper:
rm -rf $(VENV) $(PDF) whitepaper/WHITEPAPER.pdf
clean-all: clean clean-whitepaper c-clean
.PHONY: all test test-verbose bench bench-verbose repl lint \
c-build c-test c-bench c-repl c-clean \
test-all bench-all examples friction \
whitepaper clean clean-whitepaper clean-all