lumbda/Makefile
russell@unturf.com db2cd77c62 Add shared functional test suite: 114 tests, both implementations pass
tests/functional.lsp — single .lsp file, runs identically in Python and C.
Covers: arithmetic, comparison, booleans, pairs, lists, strings, characters,
vectors, hash tables, control flow, let/lambda/closures, do loops, define,
recursion, TCO (100k depth), quasiquote, macros, type predicates, call/cc,
error handling, mergesort, higher-order programs.

Fixed C call/cc: proper escape continuations via setjmp/longjmp.

make test-all runs: Python unit (571) + C unit (58) + shared functional (114).
2026-04-14 15:21:17 -04:00

147 lines
5.9 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
@echo "── C functional tests (shared .lsp suite) ──"
./c/uncommonlisp tests/functional.lsp
c-bench: c-build
$(MAKE) -C c bench
c-repl: c-build
./c/uncommonlisp
c-clean:
$(MAKE) -C c clean
# ─── Both implementations ────────────────────────────────────────
functional-test: c-build
@echo "═══ Shared functional tests (114 tests) ═══"
@echo "── Python ──"
@python3 uncommonlisp.py --fast tests/functional.lsp | tail -3
@echo "── C ──"
@./c/uncommonlisp tests/functional.lsp | tail -3
test-all: test c-test functional-test
@echo "════════════════════════════════════"
@echo "All tests passed (Python + C + shared functional)"
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