An open API service indexing awesome lists of open source software.

https://github.com/no-way-labs/mo

Mo is a strict functional language whose OCaml compiler generates efficient imperative Zig — no ownership annotations, no garbage collector. Linearity inference, stateful pattern fusion, and opaque linear handles let pure functional code match or beat hand-written Zig on memory across 5 benchmarks.
https://github.com/no-way-labs/mo

compiler compiler-optimization functional-programming language-design linear-types ocaml programming-language stream-fusion systems-programming zig

Last synced: about 8 hours ago
JSON representation

Mo is a strict functional language whose OCaml compiler generates efficient imperative Zig — no ownership annotations, no garbage collector. Linearity inference, stateful pattern fusion, and opaque linear handles let pure functional code match or beat hand-written Zig on memory across 5 benchmarks.

Awesome Lists containing this project

README

          

# Mo

**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.

> **Paper:** [Mo: Pure Functional Code, Imperative Performance](docs/paper/mo_abstract.pdf)

---

## The result

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](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.

---

## Quick start

**Prerequisites:** OCaml (for the compiler), Zig 0.15+ (for the runtime)

```bash
# Build the compiler
./src/compiler/build.sh

# Compile and run an example
./src/compiler/moc examples/fib.mo
zig run examples/fib.zig
```

---

## What it looks like

```ml
-- Fibonacci
letrec fib = \n ->
if lt n 2 then n
else add (fib (sub n 1)) (fib (sub n 2))
in fib 35
```

```ml
-- 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))
```

```ml
-- 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
```

```ml
-- 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)
```

---

## How it works

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
```

---

## Project structure

```
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
```

---

## Documentation

| Document | What it covers |
|----------|----------------|
| [Paper (PDF)](docs/paper/mo_abstract.pdf) | Research paper with benchmarks and design |
| [Language Guide](docs/guide/language_guide.md) | Syntax, semantics, and practical reference |
| [Language Spec](docs/guide/spec.md) | Full specification |
| [Opaque Linear Handles](docs/guide/opaque_linear_handles.md) | HashMap, TreeMap, LRU, Deque APIs |
| [Stateful Pattern Fusion](docs/guide/stateful_pattern_fusion.md) | Compiler optimization passes |
| [Benchmarks](docs/guide/generalization_benchmarks.md) | Methodology and results |

---

## Status

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)

---

## License

- Code (compiler, runtime, standard library, examples): [MIT](LICENSE) — No Way Labs
- Paper (`docs/paper/`): [CC BY 4.0](docs/paper/LICENSE)

---

*Mo: where functional programming meets systems performance.*