Pure functional code. Imperative performance.
Mo is a strict functional language where you write clean, compositional code and the compiler generates efficient imperative output. No ownership annotations. No garbage collector.
On five non-pipeline benchmarks, Mo runs at roughly Zig-comparable time (~1x) with lower measured peak RSS.
| Benchmark | Pattern | vs Zig (Time) | vs Zig (Memory) | Note |
|---|---|---|---|---|
| Edit Distance | 2D dynamic programming | ~1x | 0.97x | Same 2-row algorithm both sides |
| Graph BFS | Visited set, queue | ~1x | 0.82x | Zig baseline being strengthened |
| Red-Black Tree | Balanced tree, rebalancing | ~1x | 0.90x | Mo delegates to a native runtime tree |
| LRU Cache | HashMap + linked list | ~1x | 0.92x | Same delegation; eviction semantics differ slightly |
| Regex NFA | State machine simulation | — | — | Under repair: current Mo matcher lacks epsilon closure |
These aren't pipelines. They're graph traversals, dynamic programming, pointer-heavy trees, coordinated data structures, and state machines --- the cases that have historically been hard for functional languages.
Caveats we're actively addressing: the two sides currently use different allocators (malloc vs Zig's GPA), Mo-emitted code does not yet free memory (which flatters peak RSS for short-lived processes), and the benchmark runner does not yet assert output equality. See docs/guide/generalization_benchmarks.md for methodology. The strongest measured result is Mo-vs-Mo: the compiler's swap-buffer and hoisting passes automatically reduce per-iteration allocation by up to 752x on naively written DP folds.
Prerequisites: OCaml (for the compiler), Zig 0.15+ (for the runtime)
# Build the compiler
./src/compiler/build.sh
# Compile and run an example
./src/compiler/moc examples/fib.mo
zig run examples/fib.zig-- Fibonacci
letrec fib = \n ->
if lt n 2 then n
else add (fib (sub n 1)) (fib (sub n 2))
in fib 35-- Pipeline fusion: compiles to a single loop, zero intermediate arrays
let sum_doubled = \xs ->
fold (\acc x -> add acc x) 0 (map (\x -> mul x 2) xs)
in
sum_doubled (collect (range 0 10))-- O(log n) red-black tree with pure functional semantics
let tree = treemap_put tree key value in
let (tree, result) = treemap_get tree key in-- Edit distance: compiler detects swap-buffer pattern,
-- allocates two buffers upfront instead of per-iteration
let result = fold (\(prev_row, curr_row) i ->
let new_row = compute_dp_row prev_row curr_row i in
(curr_row, new_row)
) (row0, row1) (range 0 num_rows)Three mechanisms close the gap between functional semantics and imperative efficiency:
1. Linearity inference. The compiler infers when values are used exactly once, enabling in-place mutation --- without user-written ownership annotations. Unlike Rust, where developers explicitly manage lifetimes, Mo infers linearity from usage. The current analysis has known soundness gaps that are being closed; a runtime uniqueness check with copy fallback is planned as the safety net.
2. Stateful pattern fusion. Common patterns (swap-buffer, buffer hoisting, prefix slices) are detected and optimized automatically. The compiler extends fusion beyond pipelines to stateful folds.
3. Opaque linear handles. When algorithmic complexity matters (O(log n) trees, O(1) caches), handles provide efficient mutable data structures with pure functional semantics.
Pure Functional Code
fold, map, filter, update_inplace, treemap_*, lru_*, ...
|
v
OCaml Compiler
Analysis + Optimization Engine
(linearity inference, pattern fusion, stream fusion;
type checking currently via the Zig backend)
|
v
Generated Zig Code
In-place mutation, efficient data structures, zero-copy
mo/
src/
compiler/ # OCaml compiler (lexer, parser, analysis, optimizer, codegen)
runtime/ # Zig runtime (allocators, arrays, streams)
lib/
std/ # Standard library
examples/ # Example programs (.mo files)
docs/
paper/ # Research paper (LaTeX + PDF)
guide/ # Language guide, spec, optimization docs
| Document | What it covers |
|---|---|
| Paper (PDF) | Research paper with benchmarks and design |
| Language Guide | Syntax, semantics, and practical reference |
| Language Spec | Full specification |
| Opaque Linear Handles | HashMap, TreeMap, LRU, Deque APIs |
| Stateful Pattern Fusion | Compiler optimization passes |
| Benchmarks | Methodology and results |
Mo is an early-stage research prototype exploring whether pure functional code can achieve systems-level performance. The compiler runs and the code is here to try; the benchmark suite and the linearity analysis are under active repair, and claims above should be read with the stated caveats.
What exists:
- Working compiler (OCaml) targeting Zig, fast happy-path builds
- Stream fusion, linearity heuristics, stateful pattern fusion (swap-buffer and hoisting passes)
- Opaque linear handles (HashMap, TreeMap, LRU, Deque) backed by native runtime implementations
- Examples and a small standard library
What's next (in order):
- Benchmark suite repair (regex epsilon closure, stronger Zig baselines, matched allocators, output-equality checks)
- A sound, gated linearity analysis with a runtime uniqueness fallback
- A real type checker and name resolution in the Mo frontend
- Formalization of the rolling-buffer inference (the core research contribution)
- Code (compiler, runtime, standard library, examples): MIT — No Way Labs
- Paper (
docs/paper/): CC BY 4.0
Mo: where functional programming meets systems performance.