1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! AXON Algebraic Effects Runtime — Fase 23.f
//! ============================================
//!
//! Native Rust runtime for AXON algebraic effects (paper §1-§6,
//! `docs/algebraic_effects_streaming.md`). Implements Plotkin/Pretnar
//! handlers + one-shot delimited continuations as a deterministic FSM
//! interpreter that consumes the JSON IR emitted by the Python frontend
//! (Fase 23.b/c/d).
//!
//! # Decisions materialised here
//!
//! * **D1** — Operation polymorphism. Operation type parameters survive
//! into the IR and are honoured at perform-site dispatch (the runtime
//! is type-erased — values are tagged dynamically; the typechecker
//! already proved soundness statically).
//! * **D2** — One-shot continuations. Each `Resume` consumes the
//! captured continuation exactly once. Multi-resume is rejected
//! statically by the typechecker (D10) so the runtime can assume the
//! property and skip clone/allocation in the hot path.
//! * **D3** — Delimited handler scope. The handler stack is per-flow,
//! pushed on `HandleEntry`, popped on exit.
//! * **D6** — Rust-only runtime. Python frontend emits IR, this crate
//! executes. There is no Python runtime.
//! * **D9** — Compile-time exhaustiveness. The runtime trusts the
//! typechecker and panics on violations (those would be impossible
//! in well-typed programs and indicate a bug in the compiler).
//! * **D11** — Effect row polymorphism. Open vs closed rows are a
//! compile-time concept; at runtime every effect is dispatched by
//! name regardless of how the row was inferred.
//! * **D12** — `Forward` propagates to the outer handler frame —
//! `find_handler` walks the stack from the innermost frame outward,
//! skipping the source frame for forward instructions.
//!
//! # Architecture
//!
//! ```text
//! Python frontend Rust runtime (this crate)
//! ──────────────── ────────────────────────
//! parser \ ┌──────────────────────┐
//! typechecker \ │ effects::ir │
//! ir_generator (CPS) \──> JSON ──▶ Deserialize structs │
//! │ (mirror of Python │
//! │ IRPerform / etc.) │
//! ├──────────────────────┤
//! │ effects::runtime │
//! │ • EffectRuntime │
//! │ • FSM dispatch loop │
//! │ • handler stack │
//! │ • Value env │
//! └──────────────────────┘
//! ```
//!
//! The interpreter is direct-style — the Rust call stack mirrors the
//! handler stack, and a `Resume` is implemented by returning a value
//! from a recursive call. Captured continuations are *not* boxed
//! closures; they are just the remaining instruction list at the
//! perform site, which the dispatch loop walks through.
//!
//! This is the FSM canonical shape promised by paper §5: the
//! `(flow_name, state_id)` coordinate the Python compiler emits is
//! exactly what the Rust runtime indexes by. A future Fase 24 may
//! lower this further to native `jmp` instructions via codegen; the
//! interpreter shipped here is the operational ground truth.
pub use ;
pub use ;
pub use Value;