#interpreter #repl #lava #mumu #language-interpreter

bin+lib core-mumu

MuMu/Lava core interpreter and REPL (engine + optional host features)

15 releases

0.9.0-rc.5 Oct 13, 2025
0.9.0-rc.3 Sep 27, 2025
0.1.6 Jul 31, 2025

#455 in Parser implementations


Used in 29 crates

MIT/Apache

625KB
12K SLoC

Lava / MuMu — Core Interpreter

MuMu doesn’t embed into apps, apps embed into MuMu.
The language is the platform; plugins are compiled software that adopt MuMu’s rules and interoperate by construction.

Repository: https://gitlab.com/tofo/core-mumu · Homepage: https://lava.nu11.uk
License: MIT OR Apache-2.0


Lava vs MuMu ?

MuMu is the host runtime and Lava is the language. Both are contained in core-mumu

  • Lexer + precedence parser with template strings and regex literals
  • Interpreter with Value/FunctionValue and first‑class functions
  • Typed data: ints/longs/floats/bools/strings; arrays & 2D matrices; keyed maps; iterators; streams; regex; MixedArray
  • Semantics:
    • const‑by‑default; ^ for scoped mutables; #name = array deep‑freezes content
    • TypeName @ expr casts (right‑associative); assignment is an expression
    • partial application by default + _ placeholders
  • REPL with history/autocomplete; cooperative pollers keep it responsive
  • Plugin system (extend("ns")) with namespace reservation and dynamic registry safety

Produces one binary: lava (CLI + REPL)


Philosophy — “software embeds into MuMu”

MuMu is a small core. Everything else is software that compiles into the runtime as a plugin and adopts MuMu’s calling & typing rules.

+---------------------+     +------------------------------+
|  Lava CLI / REPL    |     |  Guests (compiled plugins)   |
|  include(), extend()|---->|  array:, math:, flow:, av:,  |
|  history/autocomplete     |  sqlite:,|
+---------------------+     |  register_all + Cargo_lock   |
             |              +------------------------------+
             v
   +--------------------------+
   |  Core Runtime            |
   |  - Value/FunctionValue   |
   |  - namespace reservation |
   |  - dynamic registry      |
   |  - parser/interpreter    |
   +--------------------------+

Why this is unique in practice

  • Guests are compiled (Rust crates) → clear ABI; no ad‑hoc FFI bridging at call sites
  • All guests share one call model (partials, _), one value space (typed arrays, keyed maps), one error shape (KeyedError)
  • Plugins compose across namespaces without glue code

The Bridge Contract (for all plugins)

  1. Register functions as dynamics and bind a same‑name variable:
    interp.register_dynamic_function("array:map", func);
    interp.set_variable("array:map",
      Value::Function(Box::new(FunctionValue::Named("array:map".into()))));
    
  2. Host entry‐point for extend(""):
    #[no_mangle]
    pub unsafe extern "C" fn Cargo_lock(interp: *mut c_void, _extra: *const c_void) -> i32 {
        register_all(&mut *(interp as *mut Interpreter)); 0
    }
    
  3. Adopt MuMu semantics:
    • partials + _ where natural; data‑last ergonomics for transforms
    • typed results (IntArray / Float2DArray / …); MixedArray when heterogeneous
    • errors are strings or KeyedError; truthiness matches core rules
  4. Namespace hygiene: extend("ns") reserves ns:*; don’t overwrite other dynamics

Follow this and your software becomes part of the language — not an add‑on.


6) Language surface (core)

  • Lambdas (x,y)=> with capture; partials by default; _ placeholders anywhere
  • Casts Type @ expr (right‑associative): scalar/array/matrix/mixed/regex/undefined
  • Arrays auto‑upcast numeric only when needed; negative indexing; growth on assign
  • Literals: backtick templates ${} (nested OK); regex //imsx
  • Operators: arithmetic, comparisons, logical, bitwise (&|^<<>>), NAND ~, ternary ?:, prefix/postfix ++/--
  • Assignment is an expression (right‑assoc), including compound forms
  • Variables: const‑by‑default; ^ to declare scoped mutables; #name = array deep‑freezes content

7) Host vs Web

  • Host (default feature host): REPL + dynamic loading + host helpers (flow:h*)
  • WASM (feature wasm): same language/runtime; host‑only surfaces return “unavailable”

Environment knobs:

  • LAVA_VERBOSE=1 — verbose bridges/REPL
  • LAVA_TIMING_VERBOSE=1 — poll/await/drop timing
  • LAVA_AWAIT_MAX_MS=<ms> — cap idle‑await loop
  • LAVA_UNLOAD_PLUGINS=1 — dlclose plugins at shutdown (default is leak‑on‑exit to avoid buggy dtors)

8) File layout (selected)

src/
  main.rs, lib.rs
  parser/
    lexer.rs, ast.rs, core/{precedence,primary,stmt,driver}.rs
    interpreter/
      core.rs (scopes, dyn registry, namespace reservation)
      eval/{expr,statement,regex,indexing}.rs
      apply.rs, lambda.rs, partial.rs, array_runtime.rs, numeric.rs, utils.rs
  modules/
    compose.rs, type.rs, slog.rs, sput.rs, step.rs, include.rs, try.rs, flow_host.rs
  modules/repl/
    core/{parse,helpers,print,main_loop}.rs, input.rs, autocomplete.rs, render.rs
examples/   tests/

9) Why this scales

One language → many compiled guests → zero impedance mismatch.
Batch jobs, REPL sessions, streaming pipelines (flow:), audio (av:), databases (sqlite:) — all share MuMu’s values, partials, and errors, so they compose like built‑ins.


10) Credits & license

  • Author & Maintainer: Tom Fotheringham (@tofo)
  • Thanks: the MuMu community across core-mumu, array-mumu, math-mumu, flow-mumu, av-mumu, sqlite-mumu

Dual‑licensed under MIT OR Apache‑2.0
SPDX-License-Identifier: MIT OR Apache-2.0

Dependencies

~2.7–4.5MB
~72K SLoC