Lumbda
@@ -839,8 +864,6 @@ table.align-right {Lumbda
A Lisp/Scheme-derived, just-in-time lambda language. Four implementation tiers with MOAD defect isolation. Workloads migrate across basic UNIX systems.
Feedback is all you need: continuations within a process, portals across processes, S-expressions across implementations, sockets across machines.
russell@unturf, TimeHexOn, foxhop
@@ -848,7 +871,7 @@ table.align-right {April 2026
Abstract
+Abstract
License: AGPL-3.0-only · This implementation, its bytecode VM, & all associated code carry the GNU Affero General Public License v3.0 (only). You may use, modify, & distribute under those terms. No proprietary relicensing exists.
Lumbda is a Lisp/Scheme-derived language designed around one primitive and one discipline: feedback (a function that receives its own continuation composes every control-flow pattern) and MOAD defect isolation (every implementation audited against the five canonical Mother-of-all-Defects patterns, with every defect confined to its own implementation tier rather than propagating through shared infrastructure — see §12). The rest of the design follows: one primitive becomes universal when a function receives its own continuation. A continuation lets a program loop, branch, yield, checkpoint, resume, & migrate. Every control flow pattern reduces to a continuation captured & invoked. Extend feedback across time (portals) & across implementations (source-as-wire-format) and you recover the full scope of computation without new primitives.
Lumbda ships in four implementation tiers — each independently built, each MOAD-isolated, each able to run every test in the shared functional suite byte-identically:
@@ -867,13 +890,13 @@ table.align-right {Feedback is the primitive. Continuations are its mechanism in time. Portals are its mechanism across time. S-expressions are its mechanism across implementations. Sockets are its mechanism across machines. One file is the proof — by three translations.
1. The Problem: Interpreters That Cannot Feed Back
+1. The Problem: Interpreters That Cannot Feed Back
Most language implementations treat control flow as a tree of special cases. if branches. while loops. return exits. try/catch unwinds. Each form carries its own implementation, its own edge cases, its own interaction with the call stack. When you need a pattern that crosses these boundaries (a generator that yields mid-loop, a coroutine that resumes from a checkpoint, a computation that migrates between machines), the tower of special cases collapses.
The insight: every control flow pattern is a special case of feedback. A loop feeds the tail position back to the head. A generator feeds a value out & a resumption point in. An exception feeds control to the nearest handler. A checkpoint feeds the entire machine state to storage. If the language exposes feedback as a first-class primitive, all these patterns compose without special cases.
Scheme discovered this in 1975 with call-with-current-continuation. But most Scheme implementations compromise: they limit continuations to escape-only, implement them via setjmp/longjmp on the C stack, or require CPS transformation that obscures the source. Lumbda takes a different path: an explicit frame stack that makes continuations a data structure, not a stack manipulation trick.
2. Architecture: One File, Two Evaluators
+2. Architecture: One File, Two Evaluators
Bytecode compiler + VM (_bc + _vm_loop): Enabled with --fast or (auto-compile! #t). Compiles Scheme expressions to a stack-based bytecode, then executes on a virtual machine with an explicit frame stack. Achieves 7--19x speedups on recursive & iterative workloads.
Both evaluators share the same type system, environment model, & built-in function library. The bytecode compiler handles: if, begin, and, or, when, unless, cond, define, set!, lambda, let, named-let, let*, letrec, do, call/cc, & function calls with tail-call optimization. Macros expand at compile time. Forms the compiler cannot handle fall back to the interpreter via OP_EVAL.
2.1 Type System
+2.1 Type System
Core types stay minimal:
Symbol: Interned strings with identity comparison (Symbol._t cache)
@@ -900,7 +923,7 @@ table.align-right {
Exact rational arithmetic uses Python's Fraction type. (/ 1 3) evaluates to 1/3, not 0.333.... Literal 1/3 syntax parses directly to rationals.
2.2 The Bytecode
+2.2 The Bytecode
The compiler emits instructions as (opcode, operand) tuples into a CodeObj:
Core opcodes (20):
OP_CONST push a constant value @@ -934,7 +957,7 @@ OP_VEC_REF OP_VEC_SET
3. The Explicit Frame Stack
+3. The Explicit Frame Stack
This is the architectural decision that makes everything else possible.
Instead of using Python's call stack for Scheme function calls, the VM maintains its own frame stack:
frames = [] # Each frame: (instrs, ip, env, stack)@@ -957,7 +980,7 @@ OP_VEC_REF OP_VEC_SET
Why this matters: Python's default recursion limit is 1,000 frames. A Scheme that uses the Python stack for Scheme calls inherits this limit. The explicit frame stack removes it. Lumbda can recurse 50,000 deep without difficulty, limited only by available memory.
4. Continuations: Feedback as a Data Structure
+4. Continuations: Feedback as a Data Structure
With an explicit frame stack, capturing a continuation becomes copying a data structure:
class FullCont:
frames # deep-copied list of (instrs, ip, env, stack)
@@ -984,7 +1007,7 @@ OP_VEC_REF OP_VEC_SET
Multi-shot continuations: Because the state is deep-copied at capture time, a continuation can be invoked multiple times. Each invocation restores an independent copy of the machine state. This enables generators, coroutines, & backtracking search.
4.1 Generators from Continuations
+4.1 Generators from Continuations
A generator in Lumbda uses call/cc to yield values & resume later:
(auto-compile! #t) (define (make-gen thunk) @@ -1006,7 +1029,7 @@ OP_VEC_REF OP_VEC_SET
No special generator syntax. No coroutine framework. The same call/cc that handles escape continuations also handles cooperative multitasking, because feedback is feedback.
4.2 Why "Feedback Is All You Need"
+4.2 Why "Feedback Is All You Need"
Every control flow pattern reduces to a continuation operation:
Loop: tail-call feeds the function back to itself
@@ -1020,7 +1043,7 @@ OP_VEC_REF OP_VEC_SET
One primitive. Every pattern.
4.3 Four Scopes of Feedback
+4.3 Four Scopes of Feedback
The single word "feedback" covers four nested scopes, each giving rise to one of our core abstractions:
Times measured on a 4-binding workload (int + list + string + fib(30) result) excluding process startup. "k" = continuation.
7.1 S-Expression Portal — the Portable One
+7.1 S-Expression Portal — the Portable One
The most boring format is the most portable. An S-expression portal is a sequence of define forms:
;; Lumbda portable state (define my-int 42) @@ -1648,7 +1671,7 @@ KBProducer side: assemble the file with (display ...) & (write ...) to an output port. Consumer side: (load "file.sexp"). Both sides exist in every implementation, giving us a 3×3 matrix of valid exchanges.