A Flow-first, Typestate-Oriented system programming language
Interpreter + LLVM 18 Codegen Dual Backend · Z3 Formal Verification · Sparse Flow State Machines · Linear Resources · Actor Model · Session Types · Component Boundary
Mimi is a Flow-first, Typestate-Oriented system programming language. Its core insight: replace lifetime annotations and &mut self with business-logic state machines (Flow). Every resource's lifecycle is bound to a business state — the compiler guarantees safety through state transitions, not borrow checking.
Mimi answers five questions from source code and types alone:
- What state is this business object in?
- What events are allowed in the current state?
- How do resources and ownership transfer on state change?
- Is this failure a local return, a state Fault, or a concurrent PeerFault?
- Which errors can be rejected before the program runs?
flow Order {
state Pending
state Paid
state Shipped
transition pay(Pending, payment: Payment) -> Paid { ... }
transition ship(Paid, tracking: Tracking) -> Shipped { ... }
}
Sparse, not dense. You don't declare pay(Paid) or ship(Pending). These combinations aren't missing matrix cells that auto-fill to Fault — they don't exist at the type level. Calling ship on a Pending order is a compile error, not a runtime fallback. Dynamic boundaries (network, FFI, deserialization) produce typed UnexpectedEvent errors, not fake business edges.
| Construct | Sole Responsibility |
|---|---|
func |
Stateless synchronous computation and composition |
flow |
Business state across time and its legal transitions |
actor |
Mailbox, scheduling, isolation, supervision; business state lives in Flow |
protocol |
Static state-topology projection of a Flow |
session |
Message ordering between two linear endpoints |
Result<T, E> |
Synchronous, recoverable failure |
Fault |
Flow invariant violation or unrecoverable state failure |
view / mutate / consume |
Read-only, in-place modification, and ownership transfer permissions |
requires / ensures |
Dynamically checked or statically proven contracts |
component / foreign |
Cross-language boundary with typed ownership, errors, and effects |
Mimi is the production compilation backend. Intent-level design lives in MimiSpec (.mms), which promotes to Mimi via mimi promote.
The Architecture Amendment (2026-07-25) established 10 irreversible invariants after nine rounds of external blind review:
| # | Invariant | Meaning |
|---|---|---|
| 1 | Sparse is irreversible | No dense mode. Undeclared (state, event) pairs are compile errors. |
| 2 | No nested Flow | Flow payload holds plain data only — handles, primitives, shared/weak refs. Never another Flow instance. |
| 3 | No WAL | The compiler does not generate transaction logs. Consistency is business logic. |
| 4 | Recover = in-place reuse | Recover preserves memory handles (XPU tensor reallocation is a disaster). Not transaction rollback. |
| 5 | Generation by escape analysis | No explicit syntax. Local handles: zero overhead. Cross-boundary handles: compiler packs generation automatically. |
| 6 | View/Mutate is a 1.0 requirement | view/mutate borrowing for pure function parameters. Not nice-to-have. |
| 7 | Multi-target is a 1.0 requirement | transition parse(Pending) -> Connected | Rejected with nominal state tags. |
| 8 | FFI failure = Fault | Cross-FFI failure must enter Fault, never Rejected. Cannot undo C's side effects. |
| 9 | No linear consumption before ? |
Checker statically rejects consuming linear resources before a fallible operation. |
| 10 | No synchronous pinned timeout | Hanging C functions go to ForeignTask (async). No synchronous watchdog. |
Full amendment: 13 clauses + 10 invariants. Supersedes the white paper (
devdocs/Mimi语言特性设计研究.md) where they conflict.
| Feature | Status |
|---|---|
flow / state / transition declarations, state payloads, transfer dispatch |
✅ |
Sparse transition graph — undeclared (state, event) = compile error (@sparse) |
✅ |
Typed Fault — per-flow fault ErrorType declaration |
✅ |
return S{} terminal — unique transition terminal (become/stay removed per ADR-001) |
✅ |
fails E rollback path — ? returns Err((source, error)), source generation restored |
✅ |
| Reset / Recover system verbs (user-overridable) | ✅ |
SystemTrace provenance (last_state, unexpected_event, snapshot) |
✅ |
Progressive mode — script main() via implicit flow Main { state Single } shell (genuine semantic desugaring, spec §3.13) |
✅ |
Multi-target transition (-> A | B with state tags) |
✅ (stable tagged-union ABI, 0.34.15-16, ADR-002) |
| Feature | Status |
|---|---|
| Flow state use-after-move rejection (E0423) | ✅ |
| Alias chain, closure capture, collection/tuple insertion rejection (E0427) | ✅ |
CFG-level linearity — is_linear() for Flow states in dataflow analysis |
✅ |
| Session endpoint linearity — scope exit (E0425), use-after-alias (E0426) | ✅ |
| Shared/weak wrapping of linear resources rejected | ✅ |
| View/mutate borrowing (pure function parameter passing) | ✅ (0.34.13-14 closure + 0.34.25c place-grammar fail-closed, E0434/E0435) |
| Cross-turn exactly-once resource tracking | ✅ |
| Channel/Mutex/Atomic type-level linearity | 📋 (known limitation: builtin integer handles) |
| Feature | Status |
|---|---|
actor Name runs FlowName — Actor business state carried by Flow |
✅ (interp; codegen pending) |
Session types: session / dual / end, compile-time residual checking |
✅ |
| Protocol interface abstraction (conservative projection subtyping) | ✅ |
| PeerFault cross-Actor propagation | ✅ |
| Mailbox backpressure auto-governance | ✅ |
Spawn quota control (@max_children(N)) |
✅ |
Polymorphic broadcast (Vec<Protocol>) |
✅ |
| Feature | Status |
|---|---|
requires: / ensures: / invariant: in function bodies |
✅ |
Z3 SMT solver integration (mimi verify) |
✅ |
Runtime contract assertions (mimi build --verify-contracts) |
✅ |
| Feature | Status |
|---|---|
| Bytecode VM interpreter (sole interpreter since 0.1.3) + LLVM 18 codegen (native binary) — L1 equivalence tested | ✅ |
| Hindley-Milner type inference (undo trail + TypeScheme + zonk) | ✅ |
Generics <T: Bound>, recursive types |
✅ |
Enums / records / tuples, match exhaustiveness, while let |
✅ |
Option<T> / Result<T, E> / ? operator |
✅ |
| Feature | Status |
|---|---|
extern "C", repr(C), multi-language bindgen (C/C++/Rust/Go/Node.js/Java/Python) |
✅ |
comptime func + quote! AST generation |
✅ |
| LSP: completion, hover, goto-definition, contract lens | ✅ |
Package manager: mimi.toml, registry, git deps, dependency tree |
✅ |
Cross-compilation: --target flag, shared library .so output |
✅ |
| Component IR + Native ABI + Wire Schema | ✅ (0.1.1 Phase C; SDK conformance green) |
git clone https://github.com/ontonous/mimi
cd mimi
bash scripts/setup-llvm-wrapper.sh
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo build --releaseflow Counter {
state Zero { count: i32 }
state Positive { count: i32 }
transition inc(Zero) -> Positive {
return Positive { count: self.count + 1 }
}
transition inc(Positive) -> Positive {
return Positive { count: self.count + 1 }
}
transition reset(Positive) -> Zero {
return Zero { count: 0 }
}
}
func main() -> i32 {
let s0 = Zero { count: 0 }
let s1 = Counter::inc(s0)
let s2 = Counter::inc(s1)
println(s2.count) // 2
let s3 = Counter::reset(s2)
println(s3.count) // 0
0
}
./target/release/mimi run counter.mimi
# => 2
# => 0Counter::inc(s0) consumes s0 — using s0 after the transition is a compile error (E0423). Each transition produces a new generation of the state.
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo testAll backends (interpreter, LLVM codegen, Z3 verifier) consume a single source of truth: CheckedProgram. No backend re-parses AST or re-guesses types.
Source → Lexer → Parser → AST
→ HM Inference → Type Checker → CheckedProgram
→ Typed Resolved IR (canonical signatures, catalogs, materialized types)
→ CFG (per-callable control flow graph)
→ Resource Analysis (linear resource actions)
↓
┌───────────┼───────────┐
Interpreter Codegen Verifier
(from_checked) (compile_checked) (verify_checked)
Iron rule: backends cannot fall back to raw AST. Declaration layer (signatures, Flow transitions, Actor/Session, ownership, CFG) is fully installed from CheckedProgram; function bodies compile via per-function dispatch (resolved native emitter with an explicit, observable legacy arm). CheckedProgram::raw_ast() is crate-internal and limited to 3 permanent consumers (codegen pass 5 / interpreter / Z3 verifier).
Span/Origin → HM → CFG/ownership → CheckedProgram/Resolved IR
→ Flow generation/turn → Actor/Session/resource → semantic trace
→ Verified Core
→ Component IR → Native ABI → Wire → Rust SDK / XPU FFI
| Abstraction | Location | Role |
|---|---|---|
| CheckedProgram | src/core/checker/ |
Single semantic hub: canonical signatures, catalogs, materialized types |
| Typed Resolved IR | src/core/resolved/ |
ResolvedFunction / ResolvedFlow / ResolvedTransition / ResolvedActor |
| HM Unification | src/core/unification.rs |
Undo trail + TypeScheme + zonk; generic call fresh instantiation |
| TypeFolder | src/core/type_folder.rs |
Binder-aware type folding (SurfaceTy / InferTy / ZonkedTy / BackendTy) |
| CFG | src/core/cfg/ |
Per-callable control flow graph, stable-ID CallableCfg |
| Resource Analysis | src/core/ownership.rs |
Linear resource ledger (Introduce / Move / Drop / Return + borrow) with canonical action kinds |
| AstNodeMeta | src/span.rs |
SourceId + Span + AstOrigin; NodeIdBuilder stable identity |
The compiler itself is built on the Flow paradigm — each front-end module is a state machine with fn transition(self, event) -> Self. Five rules: no &mut self, no Arc<Mutex<T>>, no unsafe, no transmute/lifetime annotations, no bare panic!/unwrap(). Parser, Lexer, Loader, LSP, Verifier: strict Flow. Interpreter, Core Checker: relaxed Flow. Codegen, Runtime, FFI: non-Flow (LLVM API / C-style / text generation).
| Module | Description |
|---|---|
prelude |
identity, clamp, lerp, compose, pipe, fail, assert_msg |
io |
print_line, input_line, print_format, IoOps trait |
fs |
read, write, exists, read_lines, write_lines, file_size |
strings |
split, join, replace_all, capitalize, reverse, truncate, pad |
collections |
sort, map, filter, reduce, partition, group_by, chunks, dedup |
maps |
get, set, merge, pick, omit, has_key, from_list, filter_keys |
set |
contains, insert, remove, to_list, is_empty |
json |
to_json, from_json, get_int, get_bool, get_string, JsonExt trait |
net |
TCP socket, HTTP fetch/fetch_post, Result<T, NetError> |
csv |
parse_csv, serialize_csv |
crypto |
sha256, base64_encode/decode, hex_encode/decode |
template |
render_template |
time / datetime |
timestamp, sleep_ms, duration, days_from_now, time_since |
env |
get_var, cli_args, has_var, get_int, get_float |
mymath |
gcd, lcm, factorial, fibonacci, is_prime, is_power_of_two |
array |
fill, slice, rotate, binary_search |
iter |
range, zip, enumerate, take, drop, chain |
random |
random_int, random_float, random_range |
text |
slugify, indent, wrap |
result |
unwrap, map, map_err, and_then, or_else |
testing |
assert_eq_int, assert_true, assert_approx_eq_float |
effects |
Stdlib effect annotations (purity constraints for type checker) |
errors |
Typed error enums (FsError, JsonError, CollectionError) + From protocol |
Built-in regex (always available): regex_match, regex_find, regex_replace.
Built-in concurrency primitives (always available): Mutex<T>, AtomicI32/AtomicI64/AtomicBool, Channel<T>, broadcast.
| Command | Description |
|---|---|
mimi check <path> |
Type-check with full error reporting |
mimi run <path> |
Run (interpret) with optional --verify-contracts / --profile / --watch |
mimi test <path> |
Run test_* functions with --filter and --verbose |
mimi build <path> |
Compile to native binary (LLVM). --emit-ir, --shared, --target, --verify-contracts |
mimi fmt <files> |
Format code (--check for CI) |
mimi lint <files> |
Static analysis (--fail-on-warnings) |
mimi verify <path> |
Z3 formal verification |
mimi lsp |
Start LSP server (stdin/stdout) |
mimi init [name] |
Initialize mimi.toml |
mimi add <name> |
Add dependency (--version, --git, --path) |
mimi remove <name> |
Remove dependency |
mimi install |
Install dependencies (--frozen, --offline) |
mimi update |
Update dependencies |
mimi list |
List dependencies |
mimi tree |
Show dependency tree |
mimi publish |
Publish to local registry |
mimi search <query> |
Search packages |
mimi doc <path> |
Generate documentation |
mimi promote <path> |
Upgrade .mms → .mimi |
mimi mms <files> |
Process MimiSpec files |
mimi stats <path> |
Usage statistics |
mimi stat <path> |
Directory analysis |
mimi bindgen <path> |
Generate multi-language FFI bindings |
mimi emit-*-bindings |
Language-specific FFI binding generation (C/C++/Rust/Go/Node.js/Java/Python) |
mimi/
├── src/ # Rust compiler (366 files, ~305k LOC)
│ ├── main.rs # CLI entry point (clap derive)
│ ├── lib.rs # Library entry point
│ ├── ast.rs # AST: FlowDef, StateDef, TransitionDef, ProtocolDef, ...
│ ├── span.rs # SourceId / Span / AstNodeMeta — stable node identity
│ ├── flow_matrix.rs # Transition matrix + Fault injection
│ ├── session.rs # Session type duality + sequencing check
│ ├── progressive.rs # Script → implicit flow Main { state Single }
│ ├── trace.rs # Canonical semantic trace (Transition / Fault / OwnershipTransfer)
│ ├── path_safety.rs # Unified path validation
│ ├── source_scan.rs # Shared SourceScanner (fmt/lint)
│ ├── parser/ # Flow parser (strict Flow state machine)
│ ├── lexer/ # Flow lexer (strict Flow state machine)
│ ├── core/ # Type inference & checking → CheckedProgram
│ │ ├── checker/ # Type checker → CheckedProgram semantic hub
│ │ ├── resolved/ # Typed Resolved IR (canonical declarations)
│ │ ├── unification.rs # HM unification (undo trail + TypeScheme)
│ │ ├── type_folder.rs # Binder-aware type folding
│ │ ├── cfg/ # Per-callable control flow graph
│ │ ├── ownership.rs # Linear resource analysis (canonical actions)
│ │ └── infer/ # HM type inference + contract derivation
│ ├── interp/ # Bytecode VM (sole interpreter since 0.1.3)
│ │ └── bytecode/ # Bytecode compiler + VM + builtin registry
│ ├── codegen/ # LLVM 18 codegen (compile_checked)
│ │ └── builtins/ # Builtin function codegen (io, string, json, ...)
│ ├── verifier/ # Z3 contract verifier (verify_checked)
│ ├── ffi/ # Multi-language binding generation (7 langs)
│ ├── lsp/ # LSP server (strict Flow)
│ ├── loader/ # Module loader (strict Flow)
│ ├── runtime/ # Rust runtime + actor mailbox + profiler
│ ├── fmt.rs # Code formatter
│ ├── lint.rs # Static linter
│ ├── main/ # CLI subcommand implementations (24 commands)
│ ├── diagnostic/ # Error codes & formatting
│ └── tests/ # 4500+ tests
├── std/ # Standard library (24 modules)
├── examples/ # Example programs (28)
├── demos/ # Demo programs (23)
├── tests/real_world/ # MCDD real-world dual-backend suite (69 programs)
├── devdocs/ # Design docs, blind reviews, amendment, roadmap
├── scripts/ # Build & CI scripts
├── Cargo.toml
└── CHANGELOG.md
- Rust 1.75+
- LLVM 18 (auto-configure via
scripts/setup-llvm-wrapper.sh) - libffi (FFI support)
- Z3 (contract verification; handled by
cargo build)
| Tier | Test | Meaning |
|---|---|---|
| L1 | cargo test dual_ |
Dual-backend equivalence (interp == codegen) |
| L2 | cargo test typecheck:: |
Type system soundness (bad code rejected) |
| L3 | cargo test e2e_asan -- --ignored |
Memory safety (Valgrind/ASan/Miri) |
# Full test suite
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo test
# Dual-backend equivalence (L1)
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo test dual_
# Type system soundness (L2)
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo test "typecheck::"
# Real-world MCDD test suite
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo test real_world
# Clippy (zero-warnings gate)
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo clippy --all-targets -- -D warnings
# Format
LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo fmtTest note: after the test-performance work, the normal full gate is
ulimit -v 20000000 && LLVM_SYS_181_PREFIX=/tmp/llvm-wrapper cargo test -- --test-threads=4(about 42 seconds). Keep Z3 verification subsets single-threaded; extremely memory-constrained systems may fall back to--test-threads=1. Debug builds can still use about 12 GB RAM. See AGENTS.md for details.
Current: 0.1.5-dev. 0.1.4 shipped (syntax freeze, semantic rulings, architecture freeze Phase G, O1 default). 0.1.5 focuses on performance (trap-cost reduction) with DX quality as secondary line — see devdocs/v0.35/README.md.
| Document | Role |
|---|---|
devdocs/v0.35/README.md |
0.1.5 roadmap: performance mainline + DX quality secondary (authoritative for 0.1.5) |
devdocs/v0.34/golden-document.md |
0.1.4 golden document: semantic rulings + sprint plan (authoritative for 0.1.4) |
devdocs/v0.31/README.md |
Authoritative roadmap (31 requirements, exit conditions) |
devdocs/v0.31/architecture-amendment-1.0.md |
Architecture Amendment: 13 clauses + 10 invariants (supersedes white paper) |
devdocs/pre-0.1/ |
Pre-0.1 design contract: core goals, Flow-first model, error algebra, Verified Core, Component Boundary |
devdocs/debt-report-2026-07-25.md |
Debt panorama: 9 architecture + 10 engineering debts + 9-round blind review corrections |
docs/language-spec.md |
Normative language specification (single entry point) |
Nine rounds of external blind review covered: Z3 verification, FFI/ABI, concurrency, Flow semantics, type system, runtime, interpreter/comptime, stdlib/error handling, and codegen. Results drove the Architecture Amendment and the debt report. Review files: devdocs/blind-review-*-2026-07-25.md.
| Version | Highlight |
|---|---|
| 0.1.5-dev | Current. Performance mainline: trap-cost reduction (O1 default baseline), resolved dispatch coverage extension (strings/collections module bodies, contract guard emission), O1 correctness slices. Quality secondary: resolve→zonk migration (31 sites), parser panic audit, LSP Span/Origin migration, trivia-ization of desc:/rule:/mms{}, actor runs_flow three-layer integration, flow_order fails-transition SIGSEGV fix. See devdocs/v0.35/README.md. |
| 0.1.4 | Shipped (2026-08-08). Syntax freeze + semantic rulings + language self-consistency (golden document): become/stay removal (ADR-001, sole terminal return State {}), multi-target stable tagged-union ABI (ADR-002), 'a removal (ADR-004), do wrapper removal (keywords 81→80), and/or/not soft keywords, if-let/for-destructuring, ieee_float {}, single-direction numeric coercion, View/Mutate closure. Doc-sync campaign closed the four verdicts across spec/pre-0.1/support/syntax-reference; trivia-ization of desc:/rule:/mms{} registered for 0.1.5. Phase G (architecture freeze): ADR-005~008, dispatch gate (fallback 0.3027, eligible 3783), contracts + stdlib module bodies on resolved slice, view/mutate borrow ABI, verifier engine isolation (E0439), ABI layout freeze (native-abi-1 §7/§8), pre-0.1 rename, 0.minor=major strategy, O1 default optimization. RC gates green (5287 lib). |
| 0.1.3 | Bytecode VM becomes the sole interpreter: tree-walker (24,976 LOC) + ResolvedInterpreter (4,375 lines) deleted, --legacy removed, FFI/Actor/quote fully on bytecode. |
| 0.1.2 | Codegen full migration: raw_ast() privatized (3 permanent consumers), gap filling, performance baseline. |
| 0.1.1 | 51-sprint roadmap: Flow core closure, foundation repair, Runtime Efficiency, Soundness, language freeze, Component boundary, tooling, RC. Architecture Amendment (13 clauses). Nine blind reviews. Codegen per-function dispatch active. |
| 0.1.0 | Baseline stability: CheckedProgram semantic hub, Typed Resolved IR, HM unification, CFG/ownership analysis, runtime/resolved split, semver switch, 4063 tests green |
| v0.30.0 | Hemostasis: zero new features — 15 architecture debts cleared (sprintf→snprintf, path safety, malloc checks, fmt tokenization) |
| v0.29.0–41 | Flow paradigm: compiler internal Flow replacement (7 modules) + language-level Flow semantics + 38 white paper capabilities |
| v0.28.0–37 | Use-driven: 7-lang FFI, profiler, bindgen, package manager; Feature Bugs zero |
| v0.27 | Safety audit: P0–P3 (arena, FFI, JSON, runtime) |
| v0.20–24 | Structured concurrency, Future/Waker/Executor codegen |
| v0.15 | C runtime → Rust runtime rewrite |
| v0.7 | Z3 verification + FFI codegen |
Full changelog: CHANGELOG.md. Pre-0.1.0 history: 1863 commits, 66
mimi-v*tags, archived indevdocs/archive/.
Copyright © 2026 ontonous