runmat-ignition 0.2.7

Baseline interpreter for RunMat enabling instant startup and execution
Documentation

RunMat Ignition (Interpreter)

Ignition is RunMat's reference interpreter. It compiles the high-level IR (HIR) emitted by runmat-hir into a compact bytecode and executes it on a fast, non-allocating stack virtual machine. The design goal is full MATLAB grammar/semantic compatibility with clear, testable semantics and a codebase that is easy to extend.

Sibling docs for deep dives:

  • INSTR_SET.md - opcode semantics, stack effects, failure modes
  • COMPILER_PIPELINE.md - HIR → bytecode lowering strategy
  • INDEXING_AND_SLICING.md - column-major rules, end arithmetic, N-D gather/scatter, expansion
  • ERROR_MODEL.md - MException and mex identifier normalization
  • OOP_SEMANTICS.md - objects, properties/methods, subsref/subsasgn, operator overloading

Module structure

  • instr.rs: Instruction set enum Instr (bytecode opcodes)
  • functions.rs: UserFunction, frames, and ExecutionContext
  • compiler.rs: exhaustive lowering for HirStmt/HirExprKind
  • bytecode.rs: compile, compile_with_functions
  • vm.rs: Interpreter loop and semantics (execute)
  • gc_roots.rs: RAII GC roots for stack/locals/globals

Public API

  • compile(&HirProgram) -> Bytecode
  • compile_with_functions(&HirProgram, &HashMap<String, UserFunction>) -> Bytecode
  • interpret(&Bytecode) -> Result<Vec<Value>, String>
  • interpret_with_vars(&Bytecode, &mut [Value]) -> Result<Vec<Value>, String>
  • execute(&HirProgram) -> Result<Vec<Value>, String>

Execution model

  • Each function compiles to bytecode + constants. Calls create frames holding PC, locals, return arity, and a base stack pointer.
  • The VM uses a single operand stack of Value. Locals are a separate array per frame. Both are GC roots.
  • Column-major semantics are global invariants. All indexing, reshape, broadcast and assignment follow MATLAB order.

Compatibility surface

  • Expressions: numbers/strings/identifiers/constants; unary (+, -, transpose, non-conjugate transpose .'), logical not (~); arithmetic (+, -, , /, ^), elementwise (., ./, .^); comparisons; ranges (start[:step]:end).
  • Tensors/Cells: 2-D literals, transpose, indexing, stores.
  • Indexing: scalar/vector/range/logical/colon/end; N-D gather via IndexSlice; 1-D/2-D fast-paths preserved.
  • Slice assignment: N-D scatter via StoreSlice with broadcast/shape checks.
  • Control flow: if/elseif/else, while, for (±/0 step), break/continue, switch/case/otherwise.
  • Try/catch: nested via EnterTry/PopTry; catch variable bound to Value::MException.
  • Functions/Recursion: fixed arity + varargs; nargin/nargout accounted; multi-assign via CallFunctionMulti.
  • Handles/Closures: captures and feval supported.
  • OOP: properties/methods (instance/static), access checks, class refs/metaclass, overloaded indexing routed to subsref/subsasgn.

Compiler principles

  • Evaluation order is preserved (left-to-right) to match MATLAB side-effects.
  • Control flow uses structured blocks with patched jumps.
  • Multi-assign lowers to CallFunctionMulti with explicit arity then sequential stores.
  • Indexing lowers to 2-D fast paths where safe, otherwise IndexSlice. Stores mirror via StoreSlice.

Indexing and slicing (summary)

  • Column-major gather: cartesian enumeration in column-major with shape normalization (2-D (I,scalar)[|I|,1], (scalar,J)[1,|J|]).
  • end arithmetic per dimension; logical masks are validated and expanded to indices.
  • Slice assignment enforces exact shape/broadcast rules; scalar broadcasts along selected extents.
  • Cells and function returns expand in argument lists and (when applicable) into slice targets.

Error model (mex)

  • All interpreter errors are normalized: mex(id, message) returns "<ID>: <message>".
  • Identifiers include: MATLAB:UndefinedFunction, MATLAB:UndefinedVariable, MATLAB:NotEnoughInputs, MATLAB:TooManyInputs, MATLAB:TooManyOutputs, MATLAB:VarargoutMismatch, MATLAB:SliceNonTensor, MATLAB:IndexOutOfBounds, MATLAB:CellIndexType, MATLAB:CellSubscriptOutOfBounds, MATLAB:ExpandError, MATLAB:MissingSubsref, MATLAB:MissingSubsasgn.

OOP semantics (summary)

  • Instance: LoadMember/StoreMember, LoadMethod/CallMethod with access checks.
  • Static: LoadStaticProperty/CallStaticMethod when base is a class reference.
  • Overloaded indexing: the VM constructs selector cells and routes to subsref/subsasgn. Missing hooks surface mex identifiers above.
  • Operator overloading: delegated through runtime dispatch (e.g., plus, mtimes), with numeric fallbacks normalized.

Testing strategy

  • Unit/property tests cover:
    • Gather/scatter round-trip invariants, column-major mapping, broadcast laws.
    • Negative paths: invalid indices, arity/output errors, expansion/type mismatches, OOP dispatch failures.
    • Parser+compiler+VM end-to-end for command-form, metaclass postfix, imports.
  • Tests assert mex identifiers to prevent semantic drift.

Performance

  • Correctness-first generic paths, plus 2-D fast paths for A(:, j) and A(i, :) with strict shape checks and column-major writes.
  • Unhandled opcodes in JIT (Turbine) explicitly fall back to the interpreter.

Remaining edges

  • Error model sweep: confirm all remaining failure paths surface normalized mex identifiers (indexing, arity, OOP dispatch). Most paths covered; add a couple more targeted tests.
  • OOP negative strictness: once the runtime registry guarantees absence of subsref/subsasgn, tighten tests to expect MATLAB:MissingSubsref/MATLAB:MissingSubsasgn only.
  • Expansion into slice targets: core implemented; add a few degenerate/empty seeds when encountered.

Contributing

  • Add builtins in runmat-runtime; wire special handling in the VM only if semantics require.
  • Prefer centralizing MATLAB rules in IndexSlice/StoreSlice rather than scattering logic.
  • When adding opcodes, document in INSTR_SET.md and ensure mex errors are uniform.