Commit graph

5 commits

Author SHA1 Message Date
88c4b05032
c: enable Boehm GC by default, GC_INIT, file ops, regression test
Three coupled changes that unblock the ecdsa quantum-circuit
simulator's run on the C tier from neoblanka.

1. c/Makefile autodetects libgc-dev — if /usr/include/gc.h is
   present, the build links Boehm and defines USE_BOEHM_GC. Without
   GC, ul_free is a no-op (lumbda.h:35) and every allocation leaks;
   small REPL snippets work but workloads with thousands of envs
   OOM the process. Override with USE_GC=0 to force the malloc-only
   path for diagnostics.

2. c/main.c calls GC_INIT before init_symbols, then GC_disable.
   GC_INIT registers the stack base for conservative scan — without
   it some Linux configs miss roots. GC_disable is a deliberate
   stopgap: lumbda Values are NaN-boxed pointers that conservative
   Boehm cannot recognize as pointers, so live targets get reclaimed
   (env binding symbol payloads, SymbolEntry strings) and lookups
   fail with "undefined: <sym>". Reproducing this without GC_disable
   on the GC build: any sim.lsp call chain triggers the corruption
   after ~100 named-let iterations. Until tracing is precise,
   growing the heap is safer than wrong results. Long-running
   workloads run under ulimit -v.

3. c/builtins.c gains rename-file and delete-file matching the
   Python tier (lumbda.py:3468). sim.lsp's write-portal! pattern
   (write to .tmp, rename) needs rename-file to land cross-tier
   identical results.

4. tests/regression-named-let-leak.lsp + .sh pin four shapes that
   blew up ecdsa: the c/TODO-named-let-bytecode.md repro, the F1
   shape from foxhop.net's lumbda-c-tier-leak-SP.md (12-line
   minimum), a 200-iter scaled variant, and a sim.lsp run-ops!
   mirror. Wired into root Makefile as regression-named-let-leak;
   added to test-all. Wrapper caps memory at 256 MB virt and 15s
   per tier so a leak regression fails the run instead of consuming
   host RAM.

Known limits:
- --fast JIT still has the named-let + inner user-fn call hang
  (separate TODO; tree-walker handles this fine).
- GC_disable means the heap grows; workloads must bound their work
  budget. ecdsa's sim runs comfortably in 5 MB.

Verified inside a 2G/2vCPU QEMU guest (foxhop.net ecdsa/vm-runner.sh):
- test-c (tree-walker) — 35/35 PASS
- bench-c (tree-walker) — score 18 matches Python tier byte-identical
- F1 probe (tree-walker) — all four steps PASS
2026-06-04 00:55:31 -04:00
f7352b51b0 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.
2026-04-19 10:20:11 -04:00
610c93e8c8 C: add full continuations, portal save/resume, 7 new tests
Full continuations: FullCont captures frames/stack/env with deep copy.
VM trampoline via setjmp/longjmp. Multi-shot safe via deep_copy_env.

Portal (new c/portal.c): serialize env + continuation to JSON,
resume on another machine. portal-checkpoint! triggers mid-VM save.

83/83 C unit tests + 181/181 functional tests pass.
2026-04-15 20:07:09 -04:00
c80eabac47 x86_64 JIT: 12-21x faster than CPython, 230x faster than interpreter
Real native machine code via mmap(PROT_EXEC). No exec(). No strings.
Raw x86_64 bytes: mov, add, sub, imul, cmp, je, jne, call, ret, jmp.

ack(3,4):    0.12ms JIT vs 1.5ms CPython vs 28ms interpreter
fib-rec(20): 0.16ms JIT vs 3.4ms CPython vs 40ms interpreter

Added cond support to JIT (cascaded comparisons → conditional jumps).
Fixed JIT cache: sentinel value prevents retry on unjittable functions.
System V AMD64 ABI: args in rdi/rsi/rdx, callee-saved r12-r15.
Tail calls use jmp (true TCO at machine code level).

691 lines of jit.c. 114 functional tests pass. All C tests pass.
2026-04-14 19:58:26 -04:00
fc9eb5350c Add C implementation: 7,429 lines, 58 tests, identical output
Complete C port of the Scheme interpreter. Same .lsp files run in
both Python and C with identical output.

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

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