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:
parent
9e54c7aaf1
commit
f7352b51b0
77 changed files with 383 additions and 383 deletions
24
CLAUDE.md
24
CLAUDE.md
|
|
@ -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.
|
||||||
|
|
|
||||||
44
Makefile
44
Makefile
|
|
@ -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 ────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
24
README.md
24
README.md
|
|
@ -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
|
||||||
|
|
|
||||||
22
asm/Makefile
22
asm/Makefile
|
|
@ -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
BIN
asm/lumbda
Executable file
Binary file not shown.
BIN
asm/lumbda-gc
Executable file
BIN
asm/lumbda-gc
Executable file
Binary file not shown.
Binary file not shown.
BIN
asm/lumbda.o
Normal file
BIN
asm/lumbda.o
Normal file
Binary file not shown.
|
|
@ -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)
|
||||||
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
BIN
asm/uncommonlisp
BIN
asm/uncommonlisp
Binary file not shown.
Binary file not shown.
Binary file not shown.
8
bench.py
8
bench.py
|
|
@ -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
2
c/.gitignore
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
*.o
|
*.o
|
||||||
uncommonlisp
|
lumbda
|
||||||
test_runner
|
test_runner
|
||||||
test_runner_dbg
|
test_runner_dbg
|
||||||
bench_runner
|
bench_runner
|
||||||
|
|
|
||||||
12
c/Makefile
12
c/Makefile
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
2
c/eval.c
2
c/eval.c
|
|
@ -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"
|
||||||
|
|
||||||
/* ═══════════════════════════════════════════════════════════════════════════
|
/* ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
|
||||||
4
c/jit.c
4
c/jit.c
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
4
c/jit.h
4
c/jit.h
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
16
c/main.c
16
c/main.c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
4
c/test.c
4
c/test.c
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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
4
c/vm.c
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
|
||||||
|
|
@ -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).
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"))))))
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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).
|
||||||
|
|
|
||||||
|
|
@ -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).
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
36
friction.sh
36
friction.sh
|
|
@ -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 "═══════════════════════════════════════════════════════════════"
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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 "═══════════════════════════════════════════════════════════════"
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ────────────────────────────────
|
||||||
|
|
||||||
|
|
|
||||||
20
tests.py
20
tests.py
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:"
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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"; }
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
uncommonlisp-whitepaper.pdf
|
lumbda-whitepaper.pdf
|
||||||
|
|
@ -1 +1 @@
|
||||||
uncommonlisp-whitepaper.rst
|
lumbda-whitepaper.rst
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue