Skip to content

no-way-labs/mo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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


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

# 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

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

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

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 — No Way Labs
  • Paper (docs/paper/): CC BY 4.0

Mo: where functional programming meets systems performance.

About

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.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors