Skip to content

Interpreter Backend

Accepted

Accepted for the V1 shared IR interpreter model; complete runtime interpreter coverage remains staged.

Catalyst has a shared IR interpreter engine that executes verified IR directly. It is useful for fast execution tests, compiler validation, and demand-driven or forced comptime execution.

Backend Role

The interpreter is an IR execution engine, not a separate language evaluator.

flowchart LR
  %% Node categories are colored by the site stylesheet for light/dark mode.
  classDef phase stroke-width:1.5px
  classDef backend stroke-width:1.5px
  classDef deferred stroke-width:1.5px

  Source[source]:::phase --> Tokens[tokens]:::phase
  Tokens --> AST[AST]:::phase
  AST --> SIR[SIR]:::phase
  SIR --> IR[IR]:::phase
  IR --> Interpreter[interpreter]:::backend
  IR --> CBackend[C backend]:::backend
  IR --> LLVMBackend[LLVM backend later]:::deferred

Backend boundary

The interpreter must not inspect AST or SIR directly. If interpretation needs information that is missing from IR, the fix belongs in SIR-to-IR lowering or the IR schema.

The same engine can run in different modes:

comptime mode
Runs during compilation with deterministic compiler context, sandboxing, resource limits, and compiler-provided intrinsics such as Type, reflection, Compiler.err, attribute setters, module(...), and include(...).
runtime mode
Runs verified IR for execution tests or a future complete interpreted backend.

These modes differ by allowed capabilities, host access, and resource policy. They do not define different Catalyst language semantics.

Interpreter Uses

The interpreter can support:

  • deterministic execution tests without invoking a C compiler
  • quick validation of IR semantics
  • constant evaluation
  • demand-driven and forced comptime execution
  • diagnostics for unsupported runtime behavior in checked contexts

Comptime

comptime is powered by the same semantic model as normal compiled code. The IR interpreter gives Catalyst one execution path for compile-time evaluation instead of inventing a separate evaluator with different behavior. Compiler-owned semantic values are represented as opaque comptime handles with explicit intrinsic handlers, as documented in Comptime Bootstrapping and Compiler Objects.

Comptime interpretation must be:

  • deterministic
  • sandboxed
  • resource-limited
  • cacheable
  • independent of host-global mutable state

Comptime interpretation uses target semantics, not host semantics. Pointer-sized integer behavior, layout queries, alignment, ABI checks, and checked safety behavior are evaluated for the selected compilation target and safety mode. See Target and Safety Modes.

Comptime code may use ordinary language constructs once they lower to verified IR, including locals, aggregate values, address-taking, pointer parameters, loads, stores, and slices. The comptime boundary restricts host effects and nondeterminism, not ordinary memory semantics.

Backend Contract

The interpreter should obey the same backend-facing IR contract as C and future LLVM emission:

  • consume verified IR only
  • reject malformed or unsupported IR deterministically
  • avoid source-level name resolution
  • avoid backend-specific semantic rules
  • produce deterministic results and diagnostics

Checked safety failures trap in a deterministic panic-like way outside ordinary error returns. Interpreter trap reports must include a stable trap kind and should include a source span when IR carries one. Trap output must not depend on host formatting, pointer addresses, or nondeterministic ordering.

Implementation Coverage

V1 requires the interpreter model to support real IR execution with an abstract memory model. Any accepted source that demands comptime evaluation must lower to verified IR and execute through this interpreter. Missing support for an IR operation used by accepted demanded comptime code is an implementation gap, not a separate language mode.

Interpreter implementation work naturally follows the IR feature set:

  • scalar values, constants, locals, function calls, binary operations, returns, blocks, branches, and traps;
  • aggregate values, address-taking, pointer parameters, loads, stores, and slices;
  • compiler-approved comptime intrinsics for Type, reflection, diagnostics, attributes, and module/include evaluation.

Runtime IO, arbitrary host calls, external function execution, hidden host-global mutable state, broad allocation effects, realtime restrictions, and complete runtime interpreter coverage are not required for the Core Compiler Pipeline acceptance item.