This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.
Interpreter
import std/interpreterKoru Interpreter Standard Library
interpreter.kz · 6 tors · ~[runtime]
Koru Interpreter Standard Library · 21 more lines
Phantom lifecycles
Derived from the phantom labels in the declarations below — state! issues an
obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.
string 1 state allocated!// VALUE SERIALIZATION - Convert interpreter Value to JSON
~[retain] pub tor value.stringify { value: Value } -> string<std.io:allocated!>~part args koru_std/interpreter.args.kz
Koru Standard Library: the `args` part of interpreter.kz — the arg judgment: field membership and bound references, one walk over the flow before it runs. Joined via `~part args` in interpreter.kz; merged into the interpreter module at load. The walk itself moved to the `flowchecks` part — the field-membership and bound-reference rationale moved with it.
~part argref koru_std/interpreter.argref.kz
Koru Standard Library: the `argref` part of interpreter.kz — the bare-reference judgment used by the arg check: which raw arg values are references to bound names. Joined via `~part argref` in interpreter.kz; merged into the interpreter module at load. `std` arrives at module scope from the other parts — a local import here would shadow it. The name a bare arg value references, or null when the value is a literal. A quoted value is a string literal; `true`/`false`/`null` are literals. Text that is not a lone identifier is expression text — `wireExprRefName` names the first unbound ident inside it.
~part arith koru_std/interpreter.arith.kz
Koru Standard Library: the `arith` part of interpreter.kz — the numeric binary-op kernels behind evaluateExpression's arithmetic. Joined via `~part arith` in interpreter.kz; merged into the interpreter module at load. `ExprValue`/`ExprArithOp`/`ExprEvalError` arrive at module scope from the root file.
~part arms koru_std/interpreter.arms.kz
Koru Standard Library: the `arms` part of interpreter.kz — the arm judgment: which siblings can ever fire. Joined via `~part arms` in interpreter.kz; merged into the interpreter module at load. ARM REACHABILITY — a second unguarded handler for a branch an earlier sibling already answers is dead text Selection is first-match (the `select` part): on an outcome the first unguarded arm naming it fires, and every later same-name sibling can never run — dead text a writer believes executed. Compiled flows refuse the shape as SHAPE002 (branch_checker's `firstDuplicateSibling` is the single source of truth this mirrors); an interpreted flow now meets the same judge. `when` narrows rather than duplicates, `!` links compose (every link fires during the tor), `|?` is the fallback — none of them shadow. A transformed subtree's synthesized children are exempt — the same carve-out the compiled checkers take. The message teaches the spelling the writer usually meant: an arm that follows a STEP is indented under that step's line — flat `|` lines are siblings of the head call.
~part checks koru_std/interpreter.checks.kz
Koru Standard Library: the `checks` part of interpreter — the flow-check internals. Joined via `~part checks` in interpreter.kz; merged into the interpreter module at load. checkInvocationArgs moved to the `invargs` part — the argument-vocabulary walk beside the seed helpers below. `name` enters the bound set unless an outer scope already bound it — then it stays bound (and the duplicate is the shadowing check's call).
~part contracts koru_std/interpreter.contracts.kz
Koru Standard Library: the `contracts` part of interpreter — the dispatcher and obligation-spec type surface. Joined via `~part contracts` in interpreter.kz; merged into the interpreter module at load. Everything here is declaration-level types: the host-dispatch contract (HostView / HostDispatchFn / the dispatch-detail channel), the fn-ptr vocabulary the runtime generates dispatchers against, and the obligation CreateSpec/DischargeSpec specs. DISPATCHER TYPE - Function signature for scope dispatchers
~part define koru_std/interpreter.define.kz
Koru Standard Library: the `define` part of interpreter.kz. Joined via `~part define` in interpreter.kz; merged into the interpreter module at load. The REPL define: install a subflow declaration into the session's defined-flows table, making it a verb callable on subsequent runs. A definition is `tor name { args }` followed by the impl flow `name = <body>`. The body is stored as SOURCE (durable) and re-parsed per dispatch; every call it makes runs through the same possession machinery, so a defined flow can never reach beyond what the session holds. The definition-time analyses (declared obligations must match the body's real behavior; every call must be within the session's scopes) are the richer guarantee and are rungs of the stance, not this slice; call-time possession enforcement is the floor and is already structural.
// Koru Standard Library: the `define` part of interpreter.kz.
// Joined via `~part define` in interpreter.kz; merged into the interpreter
// module at load.
// The REPL define: install a subflow declaration into the session's
// defined-flows table, making it a verb callable on subsequent runs.
// A definition is `tor name { args }` followed by the impl flow
// `name = <body>`. The body is stored as SOURCE (durable) and re-parsed per
// dispatch; every call it makes runs through the same possession machinery,
// so a defined flow can never reach beyond what the session holds.
//
// The definition-time analyses (declared obligations must match the body's
// real behavior; every call must be within the session's scopes) are the
// richer guarantee and are rungs of the stance, not this slice; call-time
// possession enforcement is the floor and is already structural.
~[retain] pub tor define { source: string, defined: *DefinedFlows }
| defined string
| parse-error { message: string, line: u32, column: u32 }~part expr koru_std/interpreter.expr.kz
Koru Standard Library: the `expr` part of interpreter — the runtime expression evaluator: ExprValue and its comparison/arithmetic ops (guards evaluate through this, distinct from the dispatch Value union) plus evaluateExpr, the env-facing entry the `eval` verb calls. Joined via `~part expr` in interpreter.kz; merged into the interpreter module at load. EXPRESSION VALUE - For runtime expression evaluation (different from Value)
~part fieldvalue koru_std/interpreter.fieldvalue.kz
Koru Standard Library: the `fieldvalue` part of interpreter.kz — the composite FieldValue helpers. Joined via `~part fieldvalue` in interpreter.kz; merged into the interpreter module at load. FieldValue's first composite is `string_array`: these are its three verbs — JSON render (Value serialization + interpolation), JSON render for expr bindings, and the deep copy that carries a []const []const u8 out of a dispatcher frame into interpreter/session memory. Scalars need none of this; the array pays the composite tax here, once. JSON-escape one string into a writer — shared by string_val and the per-element render of string_array.
~part guards koru_std/interpreter.guards.kz
Koru Standard Library: the `guards` part of interpreter.kz — `when` clauses on dispatch arms. Joined via `~part guards` in interpreter.kz; merged into the interpreter module at load. Compiled emission lowers same-branch armed continuations into an if/else-if/else chain: arms try in source order, the first truthy guard wins, an unguarded arm is the else. The interpreter mirrors that — a guard is an expression over the arm's OWN binding, which does not exist until selection, so `armGuardPasses` evaluates against a scratch scope provisionally holding the payload. A false guard moves selection to the next name-matching candidate; it never fires the arm anyway. A guard that cannot be judged (won't parse, names nothing bound) is GuardUnjudgable — surfaced as a dispatch-error, never silently true or silently false. (440_024; kopium bridge-mirror 2026-09-13-arm-when-guards)
~part interp koru_std/interpreter.interp.kz
Koru Standard Library: the `interp` part of interpreter — `{{ name }}` / `{{ name.field }}` splicing inside wire string literals, resolved against the session's bindings. Joined via `~part interp` in interpreter.kz; merged into the interpreter module at load. `{{ name }}` / `{{ name.field }}` inside a wire string splices a bound value into the text — the composition channel that lets one reply carry a call's result into prose ("booked {{ b.reservation_id }}") instead of spending a second turn to quote it. A reference that resolves substitutes; a name nobody bound refuses loudly (an empty placeholder shipped as data is the dishonest version of that error). `{{` that does not open a dotted identifier stays literal, so prose may carry braces.
~part names koru_std/interpreter.names.kz
Koru Standard Library: the `names` part of interpreter.kz — name identity across the authored/mangled boundary. Joined via `~part names`. Koru names compare in normalized space: `-` and `_` are the same character (ast_mangle folds both to `_` at parse). Interpreter-parsed source keeps the author's spelling (`| bad-amount`), while a dispatch outcome or registry spec carries the mangled form (`bad_amount`) — raw eql can never join them, and every comparison across that boundary owes this fold.
~part parse koru_std/interpreter.parse.kz
Koru Standard Library: the `parse` part of interpreter.kz. Joined via `~part parse` in interpreter.kz; merged into the interpreter module at load. Parse WITHOUT executing — the other half of `eval`. Interpreter source is pure Koru: it has no file, so it has no host half and no ``. That is why this takes no file name. The full compiler parser derives its host/pure mode from the filename extension (`src/parser.zig:707`), so handing it a synthetic name silently answers a question interpreted source does not have; `flow_parser` has no such notion and is the only correct parser here. The returned Flow and every slice it points at are allocated from `allocator` — the caller owns the AST and may `eval` it as many times as it likes.
// Koru Standard Library: the `parse` part of interpreter.kz.
// Joined via `~part parse` in interpreter.kz; merged into the interpreter
// module at load.
// Parse WITHOUT executing — the other half of `eval`.
//
// Interpreter source is pure Koru: it has no file, so it has no host half and
// no ``. That is why this takes no file name. The full compiler parser
// derives its host/pure mode from the filename extension
// (`src/parser.zig:707`), so handing it a synthetic name silently answers a
// question interpreted source does not have; `flow_parser` has no such notion
// and is the only correct parser here.
//
// The returned Flow and every slice it points at are allocated from
// `allocator` — the caller owns the AST and may `eval` it as many times as it
// likes.
~[retain] pub tor parse { source: string, allocator: std.mem.Allocator }
| flow *const ast.Flow
| parse-error { message: string, line: u32, column: u32 }~part pool koru_std/interpreter.pool.kz
Koru Standard Library: the `pool` part of interpreter.kz — the handle record. Joined via `~part pool` in interpreter.kz; merged into the interpreter module at load. HandlePool is the custody organ: every `acquire` mints, every discharge releases. When a world-mounted bridge installs `on_custody`, each of those events is witnessed into the world's holds.log — the record a successor session reads before it acts. Pool callbacks are null by default: a bare interpreter run records nothing, and nothing here knows a world exists. Handle, CustodyKind, custodySubject and renderHeldHandles moved to the `custody` part — the record types and witnesses beside the pool that mints them.
~part mint koru_std/interpreter.mint.kz
Koru Standard Library: the `mint` part of interpreter.kz — the opaque resource-token mint for HandlePool. Joined via `~part mint` in interpreter.kz; merged into the interpreter module at load. Split from the pool part under the line wall. The ruling (OPAQUE MINT — Lars 2026-09-07/08, the notes mint's rule carried to resource tokens 2026-10-20): token text must not be predictable, because a countable suffix lets a program spell custody it was never handed — `h:Res:1` used to be a resolvable guess. `h:Type:` stays for legibility; the suffix is seeded six-hex. Mint the token a `*T` return rides home on — opaque and pool-unique, carrying the resource's type name for legibility ("h:Connection:a3f9c2"). Called only from `HandlePool.mintResourceToken`. Token bytes live on the page allocator — the same never-freed tolerance __koru_own already documents — because a result field aliasing the token may still be rendered after its handle discharges.
~part run koru_std/interpreter.run.kz
Koru Standard Library: the `run` part of interpreter.kz — the main interpreter tors (run / run-cached / eval) and the flow-execution core. Joined via `~part run` in interpreter.kz; merged into the interpreter module at load. MAIN INTERPRETER EVENTS Parse and execute in one step - the main interpreter entry point Use get-scope to get the dispatcher first, then pass it here
// Koru Standard Library: the `run` part of interpreter.kz — the main
// interpreter tors (run / run-cached / eval) and the flow-execution core.
// Joined via `~part run` in interpreter.kz; merged into the interpreter
// module at load.
//
// MAIN INTERPRETER EVENTS
//
// Parse and execute in one step - the main interpreter entry point
// Use get-scope to get the dispatcher first, then pass it here
~[retain] pub tor run {
source: string,
dispatcher: DispatchFn,
cost_fn: ?CostFn,
creates_obligations_fn: ?ObligationsArrayFn,
discharges_obligations_fn: ?ObligationsArrayFn,
discharge_event_fn: ?DischargeEventFn,
creates_spec_fn: ?CreatesSpecFn,
discharges_spec_fn: ?DischargesSpecFn,
budget: ?u64,
handle_pool: ?*HandlePool,
fail_fast: bool,
scope_name: string,
auto_discharge: bool,
defined: ?*DefinedFlows,
input_fn: ?InputLookupFn,
branches_fn: ?BranchesLookupFn,
lenient: bool,
host_dispatch: ?HostDispatchFn,
session_env: ?*Environment,
session_bind_fn: ?SessionBindFn,
session_bind_env: ?*Environment,
session_bind_counter: ?*u64,
turn_env: ?*Environment
}
| result { value: Value, used: u64, handles: u32, bound: string, trace: string }
| unhandled-branch {
branch: string,
payload: string,
handles: string,
bound: string
}
| exhausted { used: u64, last_event: string, handles: u32 }
| parse-error { message: string, line: u32, column: u32 }
| validation-error string
| dispatch-error { event_name: string, message: string, trace: string }~part refuse koru_std/interpreter.refuse.kz
Koru Standard Library: the `refuse` part of interpreter.run — the post-parse gates that reject source which parsed but must never dispatch. Joined via `~part refuse` in interpreter.run.kz; merged into the run part at load. Two refusals share one position — after either parse path, before the scope lookup, before dispatch: prose-shaped invocation names (430_055) and `|*` residual arms (440_020). Both answer `parse-error` from `run` and `validation-error` from `eval`. Event-name prose check: an tor name must lex as identifier segments with `.`/`-`/`:` between them, never spaces. The fast parser already rejects prose, but the full-parser fallback re-accepts an English sentence whose first `(` makes it look like an invocation.
~part runcached koru_std/interpreter.runcached.kz
Koru Standard Library: the `runcached` part of interpreter — the cached fast path. Joined via `~part runcached` in interpreter.kz; merged into the interpreter module at load. `run-cached` reuses a parsed flow for identical source input — the same contract as `run`, minus the parse.
// Koru Standard Library: the `runcached` part of interpreter — the cached
// fast path. Joined via `~part runcached` in interpreter.kz; merged into
// the interpreter module at load.
//
// `run-cached` reuses a parsed flow for identical source input — the same
// contract as `run`, minus the parse.
~[retain] pub tor run-cached {
source: string,
dispatcher: DispatchFn,
cost_fn: ?CostFn,
creates_obligations_fn: ?ObligationsArrayFn,
discharges_obligations_fn: ?ObligationsArrayFn,
discharge_event_fn: ?DischargeEventFn,
creates_spec_fn: ?CreatesSpecFn,
discharges_spec_fn: ?DischargesSpecFn,
budget: ?u64,
handle_pool: ?*HandlePool,
fail_fast: bool,
scope_name: string,
auto_discharge: bool,
defined: ?*DefinedFlows,
input_fn: ?InputLookupFn,
branches_fn: ?BranchesLookupFn,
lenient: bool,
host_dispatch: ?HostDispatchFn,
session_env: ?*Environment,
session_bind_fn: ?SessionBindFn,
session_bind_env: ?*Environment,
session_bind_counter: ?*u64,
turn_env: ?*Environment
}
| result { value: Value, used: u64, handles: u32, bound: string, trace: string }
| unhandled-branch {
branch: string,
payload: string,
handles: string,
bound: string
}
| exhausted { used: u64, last_event: string, handles: u32 }
| parse-error { message: string, line: u32, column: u32 }
| validation-error string
| dispatch-error { event_name: string, message: string, trace: string }~part select koru_std/interpreter.select.kz
Koru Standard Library: the `select` part of interpreter.kz — picking the arm a dispatched outcome runs. Joined via `~part select` in interpreter.kz. There is no catch-all: an arm names a declared branch or the outcome goes unhandled. A same-branch `when` guard gates the arm and is judged in source order — the machinery lives in the `guards` part. (kopium bridge-mirror 2026-09-12-branch-arms, 2026-09-13-arm-when-guards)
~part literal koru_std/interpreter.literal.kz
Koru Standard Library: the `literal` part of interpreter.kz — literal materialization on the wire path: what the quoted text between the quotes MEANS when it becomes a value. Joined via `~part literal` in interpreter.kz; merged into the interpreter module at load. Unescape a string literal's inner text (between the quotes). The wire is line-oriented — an agent cannot put a raw newline inside a quoted arg, so escapes are the ONLY way to carry one; before this, `\n` in a wire string materialized as backslash-n (measured live: a model's multi-line edit() wrote literal "\n" into suite.k, kopium libs-workbench 2026-09-25). Codegen never sees this — its strings are re-emitted into Zig literals, which unescape downstream. Unknown escapes pass through untouched: \q stays backslash-q, not q.
~part validate koru_std/interpreter.validate.kz
Koru Standard Library: the `validate` part of interpreter.kz — pre-execution flow validation. Joined via `~part validate` in interpreter.kz; merged into the interpreter module at load. ValidationError and validateFlow moved to the `flowchecks` part — the pre-execution judgment sits beside the arg walk it calls; the recursive shadow walk it consults stays in the `checks` part.
~part trace koru_std/interpreter.trace.kz
Koru Standard Library: the `trace` part of interpreter.kz — the run's dispatch trace and the durable naming a failure report needs. Joined via `~part trace` in interpreter.kz; merged into the interpreter module at load. One dispatched call's outcome in a run's trace — a chain's middle is invisible to the model unless each link's issued value is named and shown. `bound` is the durable session name (rN) when the host supplied a binder; `arm` is the `|` arm's binding name when one armed it.
~part handles koru_std/interpreter.handles.kz
Koru Standard Library: the `handles` part of interpreter.kz — the handle-pool custody cluster: the discharge sweeps and the held-handles report. Joined via `~part handles` in interpreter.kz; merged into the interpreter module at load. renderHeldHandles moved to the `custody` part — the record's witnesses live beside Handle/CustodyKind now. assertHandlesHeld moved to the `mounted` part — the held gate consults the verb's owner, and owners are a scope-set question now.
~part flowsrc koru_std/interpreter.flowsrc.kz
Koru Standard Library: the `flowsrc` part of interpreter.kz — how a run gets a parsed Flow: the per-thread parse cache, and the full-parser fallback for source the fast path declines. Joined via `~part flowsrc` in interpreter.kz; merged into the interpreter module at load.
~part deftable koru_std/interpreter.deftable.kz
Koru Standard Library: the `deftable` part of interpreter.kz — the defined-flows table itself: the record, the durable map that owns it, and the install path `define` calls. Joined via `~part deftable` in interpreter.kz; merged into the interpreter module at load. A flow the session defined at runtime (std/runtime:define): its name, its signature parameters, its declared outcome contract, and its body SOURCE. The body is re-parsed per dispatch — cheap, and the definition stays durable text rather than a cloned AST that dies with the turn's arena. Every call the body makes runs through the same possession/obligation machinery as any other dispatch, so a defined flow can never reach beyond what the session holds.
~part defined koru_std/interpreter.defined.kz
Koru Standard Library: the `defined` part of interpreter.kz. Joined via `~part defined` in interpreter.kz; merged into the interpreter module at load. The defined-flow dispatch machinery — MAX_DEFINED_DEPTH, findDefinedFlow, dispatchDefinedFlow — moved to the `defflow` part; its recursion-cap rationale moved with it.
~part wireexpr koru_std/interpreter.wireexpr.kz
Koru Standard Library: the `wireexpr` part of interpreter.kz — the whole-expression fallback for arg values. Joined via `~part wireexpr` in interpreter.kz; merged into the interpreter module at load. evaluateExpr resolves quoted strings, bound names, and lone field paths first; what remains is judged here as one Koru expression — `2 + 3`, `n * 2`, `r3.total > 50` — evaluated against expr_bindings, the same scope `when` guards see. Text that is not an expression at all returns null so the caller keeps its verbatim fallback (non-wire callers feed evaluateExpr raw shapes the wire never admits); text that parses as an expression but cannot evaluate — a name nothing bound — refuses loudly.
~part resdispatch koru_std/interpreter.resdispatch.kz
Koru Standard Library: the `resdispatch` part of interpreter — the thread-local channels a generated dispatcher speaks through. Joined via `~part resdispatch` in interpreter.kz; merged into the interpreter module at load. A generated dispatcher lives in the user module and cannot reach InterpreterContext or the HandlePool — these slots are the channel: dispatch-detail carries the typed-arg failure it detects, dispatch-pool carries the pool that `*T` handle args resolve against and `*T` returns mint into. Dispatch-detail channel: a typed-arg failure the dispatcher detects (e.g. an i64 field handed 'abc') reports through this slot instead of degrading to a silent default. Cleared at the top of every run; read when a dispatch actually throws, folded into error_detail.
~part custody koru_std/interpreter.custody.kz
Koru Standard Library: the `custody` part of interpreter.kz — the handle record's types and witnesses. Joined via `~part custody` in interpreter.kz; merged into the interpreter module at load. The Handle is what a HandlePool mints and discharges; CustodyKind is what the custody log calls those acts; custodySubject renders WHAT the minting verb took, renderHeldHandles WHO still owes.
~part invargs koru_std/interpreter.invargs.kz
Koru Standard Library: the `invargs` part of interpreter — the argument-vocabulary walk. Joined via `~part invargs` in interpreter.kz; merged into the interpreter module at load. checkInvocationArgs judges each invocation's named fields against the verb's declared input vocabulary, and each arm word against its declared outcome vocabulary — the checks called by checkFlowArgs in the args part. Owner resolution (bound scope, then the run's mounted set) lives in the `mounted` part.
~part mounted koru_std/interpreter.mounted.kz
Koru Standard Library: the `mounted` part of interpreter — the runtime-installed scope lane. Joined via `~part mounted` in interpreter.kz; merged into the interpreter module at load. A scope mounted by `std/bridge:mount` is a `.dylib` whose `koru_module_init` handed the host a ScopeRuntime — the same vtable a register block emits at compile time. Every check a run performs on a verb then answers to the installed scope SET (bound first, then mounted), not the bound scope alone: this part holds the channel the set rides in on, the host-service ABI a module stores at init, the owner resolution every check consults, and the checks themselves — held-possession, the dispatch fallback, the arm-word walk, obligation bookkeeping, and the sweep's discharge-owner search — each moved here because each now resolves an owner the bound scope may not be.
~part flowchecks koru_std/interpreter.flowchecks.kz
Koru Standard Library: the `flowchecks` part of interpreter — the pre-execution judgment: field membership, bound references, shadowing, unreachable arms — one traversal before the flow runs. Joined via `~part flowchecks` in interpreter.kz; merged into the module at load. FIELD MEMBERSHIP — a named field the verb's signature does not declare is refused, never ignored at dispatch. The declared vocabulary comes from the scope's own `get_event_input` table — the check is derived from the same registry data the prompt and dispatcher are emitted from, so it cannot drift from what dispatch enforces. `input_fn` answers null for a name outside the scope: vocabulary membership is a different question (event-denied at dispatch), and an empty list is a real answer — a zero-field verb refuses any named field. A session-defined flow's params are its own surface and are not judged against the scope manifest; calls nested in its arms still are. BOUND REFERENCES — a bare identifier in arg position is a reference, never a literal. Unbound, it must not degrade to its own text (`append(handle: h)` dispatching `handle="h"` fails `HandleNotHeld`, which blames the handle instead of the missing binding). Bindings are per item along an arm path: `| ok h |>` scopes `h` to that arm's subtree and to every later item of the turn — a sibling arm still sees it unbound.
~part defflow koru_std/interpreter.defflow.kz
Koru Standard Library: the `defflow` part of interpreter.kz — the runtime-defined-flow dispatch machinery. Joined via `~part defflow` in interpreter.kz; merged into the interpreter module at load. Runtime-defined-flow DISPATCH — the call half of the REPL define (interpreter.define.kz is the install half). A defined flow's body is stored source, re-parsed and executed inline per dispatch; the table is a live namespace, so a body naming a defined flow — itself included — resolves to the CURRENT body. That makes self-referencing recursion; `run` forwards no budget, so depth is the only bound: MAX_DEFINED_DEPTH answers before nested frames kill the host stack. Pin: 440_042.
~part eval koru_std/interpreter.eval.kz
Koru Standard Library: the `eval` part of interpreter.kz — the fast-path tor: a pre-parsed flow, no parse step. Joined via `~part eval` in interpreter.kz; merged into the interpreter module at load. This is the fast path: no parsing overhead, just execution!
// Koru Standard Library: the `eval` part of interpreter.kz — the
// fast-path tor: a pre-parsed flow, no parse step. Joined via
// `~part eval` in interpreter.kz; merged into the interpreter module
// at load.
//
// This is the fast path: no parsing overhead, just execution!
~[retain] pub tor eval {
flow: *const ast.Flow,
dispatcher: DispatchFn,
cost_fn: ?CostFn,
creates_obligations_fn: ?ObligationsArrayFn,
discharges_obligations_fn: ?ObligationsArrayFn,
discharge_event_fn: ?DischargeEventFn,
creates_spec_fn: ?CreatesSpecFn,
discharges_spec_fn: ?DischargesSpecFn,
budget: ?u64,
handle_pool: ?*HandlePool,
scope_name: string,
auto_discharge: bool,
defined: ?*DefinedFlows,
input_fn: ?InputLookupFn,
branches_fn: ?BranchesLookupFn,
lenient: bool,
host_dispatch: ?HostDispatchFn,
session_env: ?*Environment,
session_bind_fn: ?SessionBindFn,
session_bind_env: ?*Environment,
session_bind_counter: ?*u64,
turn_env: ?*Environment
}
| result { value: Value, used: u64, handles: u32, bound: string, trace: string }
| unhandled-branch {
branch: string,
payload: string,
handles: string,
bound: string
}
| exhausted { used: u64, last_event: string, handles: u32 }
| validation-error string
| dispatch-error { event_name: string, message: string, trace: string }~part env koru_std/interpreter.env.kz
Koru Standard Library: the `env` part of interpreter.kz — the binding table and its seeding. Joined via `~part env` in interpreter.kz; merged into the interpreter module at load. ENVIRONMENT - Tracks bindings during interpretation