Commit graph

9 commits

Author SHA1 Message Date
6b832d5154 Add portal: serialize and resume VM state across machines
Portal saves the full machine state — env chain, compiled procedures,
continuations, frame stack — to a JSON file. Another interpreter
instance loads it and resumes execution from the exact instruction.

Demo: start a primality test on machine A, checkpoint mid-computation,
resume on machine B. 1000000007 prime check: machine B picks up from
i=30000 and finishes in 6% of the original time.

Implementation:
- PortalSerializer: graph-aware with identity tracking for shared env
  references. Handles cycles (closures referencing their own env).
- portal-checkpoint!: triggers mid-execution save from within VM loop.
  Hooks into TAIL_CALL (loop back-edge) for compiled code.
- --portal-resume CLI flag: load .portal file and resume continuation.
- portal-save / portal-resume Scheme builtins.

571 tests green (7 new portal tests: unit + integration + functional).
2026-04-13 19:00:11 -04:00
74c23cc677 Add source maps, multi-shot continuations, inline caching, bytecode serialization
Source maps: tokenizer tracks line numbers, parser attaches to Pair nodes,
compiler records in CodeObj.source_map, errors display source line.

Multi-shot continuations: FullCont snapshots env at capture time via
deep copy. Each invocation gets a fresh env copy. Generators and
multi-shot patterns both work correctly.

Inline caching: VM caches global env lookups per instruction site.
Local shadow check (arg not in env.b) prevents stale cache hits.
Compiler tracks compile-time scopes to suppress specialization/folding
when builtins are locally shadowed.

Bytecode serialization: JSON-based .lspc format. save-compiled/load-compiled
builtins. --compile CLI flag precompiles .lsp files. Round-trip tested for
all operand types including nested closures and quoted data.

564 tests green (35 new: unit + integration + functional for each feature).
2026-04-13 17:57:29 -04:00
f89d3bce6f Add specialized opcodes, mutable strings, --fast flag
- 20 specialized opcodes: ADD, SUB, MUL, NEG, ADD1, SUB1, NUM_EQ, LT, GT,
  LE, GE, CAR, CDR, CONS, NULL?, PAIR?, NOT, ZERO?, VEC_REF, VEC_SET.
  Compiler pattern-matches (+ x 1) → ADD1, (- x 1) → SUB1.
- MutableString class: string-set!, string-fill!, string-copy! now work.
  make-string and string-copy return mutable strings.
- --fast / -f flag: auto-compile mode from command line.
- 529 tests green.
2026-04-13 16:19:27 -04:00
e091accd56 Add full continuations, explicit frame stack, env shortcut, constant folding
- Full call/cc: upward continuations via explicit VM frame stack + trampoline.
  Generators now work: (make-gen (lambda (yield) (yield 1) (yield 2)))
- Explicit frame stack: compiled→compiled CALL no longer grows Python stack.
  Non-tail calls use frames list instead of recursive vm_exec.
- Env global shortcut: lookup checks local then global before walking chain,
  O(1) for builtins instead of O(depth).
- Constant folding: arithmetic on literals folded at compile time.
- Auto-compile covers inline lambdas (not just define).
- 522 tests green, 7-19x speedup over interpreter.
2026-04-13 15:14:55 -04:00
f584ad76f2 Add auto-compile, VM optimization, disassemble, call/cc compilation
- auto-compile! parameter: compile defines on the fly for zero-effort speedup
- VM optimization: local aliases, inlined truthiness checks (~15% faster)
- disassemble builtin: human-readable bytecode listing
- call/cc compiled natively in VM (escape-only, no longer falls back to eval)
- Makefile: add lint, bench-verbose, clean targets
- 518 tests green
2026-04-13 14:49:32 -04:00
a7ca8e9f89 Add bytecode compiler and stack-based VM with 3-25x speedup
Stack-based VM with 17 opcodes, TCO via in-place frame reset,
compile-time macro expansion, and seamless interop between
compiled and interpreted code. 514 tests green.
2026-04-13 14:39:15 -04:00
52d14a2f59 Add parameterize fix, let-values, case=>, arithmetic, FS/system builtins, tracing, SRFI-64
Correctness:
- Fix parameterize: was restoring current value instead of saved old value
- Add let-values and let*-values special forms (R7RS multi-value binding)
- Update case macro to handle (datum... => proc) clauses

Numeric tower:
- truncate-quotient, truncate-remainder, floor-quotient, floor-remainder
- square, exact-integer?

Vectors:
- vector-copy now accepts optional start/end bounds
- vector-copy! for destination-vector mutation

File system and system interface:
- file-exists?, delete-file, rename-file, current-directory,
  set-current-directory!, directory-files, make-directory,
  file-size, file-directory?, file-regular?
- command-line, get-environment-variable, current-time,
  current-jiffy, jiffies-per-second, flush-output-port

Debuggability:
- Call stack tracing: _call_stack captured in LispErr.call_stack
  _call() pushes/pops frames; REPL prints last 5 frames on error
- trace/untrace macros + make-traced/untrace-proc builtins
  (set! f (make-traced f 'f)) wraps f to print args and return values

stdlib.lsp:
- SRFI-64 lightweight test framework: test-begin, test-end,
  test-assert, test-equal, test-error macros

Tests: 455 → 491 (+36 new tests)
2026-04-13 13:32:11 -04:00
66977049f1 Add string ports, error objects, rationals, modules, record inheritance, pretty-print
Core additions:
- StringInputPort / StringOutputPort — open-input-string, open-output-string,
  get-output-string, read/read-char/peek-char/read-line on ports
- R7RS ErrorObject class — error-object?, error-object-message,
  error-object-irritants; guard and with-exception-handler now receive
  ErrorObject instances instead of raw strings
- Exact rational arithmetic via Fraction — (/ 1 3) => 1/3, literal 1/3
  syntax, numerator/denominator, exact/inexact conversions
- Module system — (module name (export ...) body...) and (import name) /
  (import (name sym ...)) for selective import
- define-record-type now a Python special form supporting (inherit parent)
  for single-inheritance with subtype predicates
- Pretty-printer — pp/pretty-print with configurable line width

Correctness:
- R7RS letrec* body semantics for internal defines — names pre-declared
  before any initializer runs, enabling mutual recursion in let bodies
- string->number detects #x/#b/#o/#d and 0x/0b/0o prefixes
- show() guarantees decimal point in float output
- number->string rounds through show() for consistent float representation

Performance:
- _body_env fast path: skip scan when first body form is not define/begin
- Proc.has_defs flag: skip _body_env entirely for procs without internal defines
- Single-form body optimization: skip begin wrapper, set expr directly

Tests: 396 → 455 (+59 new tests covering all new features)
2026-04-13 12:27:06 -04:00
f72190d2dc Initial implementation of uncommonlisp
Single-file Scheme-like Lisp interpreter in Python with:
- TCO via explicit while loop (no Python stack overflow at any depth)
- syntax-rules with ellipsis for hygienic macros
- define-macro for procedural macros
- Full numeric tower, strings, chars, vectors, hash tables
- SRFI-1 list library
- call/cc (escape continuations), values, dynamic-wind, guard
- Python interop (py-eval, py-import, py-call, py-attr)
- 396 passing unit/integration/functional tests
- stdlib.lsp with 60+ utility functions
- Benchmark suite vs CPython baseline
2026-04-13 11:01:04 -04:00