Commit 3a14ffb
Mini Lisp interpreter in OMC + display_frame_name for trace stability
A working Scheme dialect implemented entirely in OMC. ~430 lines.
Demonstrates pattern matching under load (every Lisp form is a
match arm in lisp_eval) and stress-tests every recent feature.
Forms: define, lambda, if, let, quote (and `'`), begin
Builtins: + - * / = < > <= >=, car cdr cons list, null? pair?,
not, display, newline.
11 sample programs run to completion in the demo, including:
- higher-order map written in the Lisp itself
- fact(10) = 3628800 via real recursion
- real lexical closures: ((lambda (n) (lambda (x) (+ x n))) 5)
- quoted lists, nested let, multi-form programs with comments
- try/catch around lisp_run catching "undefined: ghost"
Architectural notes from writing it:
* OMC dicts pass by value, so an env passed as a parameter can't
be mutated by the callee. The fix that worked: env is a closure
PAIR [lookup_fn, define_fn] capturing a shared dict by Rc<RefCell>
through the closure environment. All env ops go through the
closures; mutations stick across function boundaries. This is
the same trick the log_analyzer counter table used at smaller
scale, now load-bearing.
* `break` works inside match arms: tokenizer's nested-loop sentinel
workarounds vanished once I remembered OMC has it. Worth a
README mention.
Bonus: display_frame_name() in interpreter.rs collapses internal
auto-generated lambda identifiers (`__rt_lambda_N` from tree-walk,
`__lambda_N` from compiler) to "<lambda>" in stack traces. Without
this the tree-walk and VM produced cosmetically-different traces
(different counter values) on identical Lisp programs. Used by both
invoke_user_function (tree-walk) and run_function (VM).
42/42 functional examples produce identical output under tree-walk
and VM. 92/92 unit tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 2eb2c0c commit 3a14ffb
3 files changed
Lines changed: 635 additions & 3 deletions
0 commit comments