Skip to main content

yulang_native/
cps_ir.rs

1use yulang_typed_ir as typed_ir;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct CpsModule {
5    pub functions: Vec<CpsFunction>,
6    pub roots: Vec<CpsFunction>,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct CpsFunction {
11    pub name: String,
12    pub params: Vec<CpsValueId>,
13    pub entry: CpsContinuationId,
14    pub continuations: Vec<CpsContinuation>,
15    pub handlers: Vec<CpsHandler>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct CpsContinuation {
20    pub id: CpsContinuationId,
21    pub params: Vec<CpsValueId>,
22    pub captures: Vec<CpsValueId>,
23    pub shot_kind: CpsShotKind,
24    pub stmts: Vec<CpsStmt>,
25    pub terminator: CpsTerminator,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum CpsShotKind {
30    OneShot,
31    MultiShot,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub enum CpsStmt {
36    Literal {
37        dest: CpsValueId,
38        literal: CpsLiteral,
39    },
40    FreshGuard {
41        dest: CpsValueId,
42        var: yulang_runtime::EffectIdVar,
43    },
44    PeekGuard {
45        dest: CpsValueId,
46    },
47    FindGuard {
48        dest: CpsValueId,
49        guard: CpsValueId,
50    },
51    MakeThunk {
52        dest: CpsValueId,
53        entry: CpsContinuationId,
54    },
55    AddThunkBoundary {
56        dest: CpsValueId,
57        thunk: CpsValueId,
58        guard: CpsValueId,
59        allowed: typed_ir::Type,
60        active: bool,
61    },
62    MakeClosure {
63        dest: CpsValueId,
64        entry: CpsContinuationId,
65    },
66    MakeRecursiveClosure {
67        dest: CpsValueId,
68        entry: CpsContinuationId,
69    },
70    ForceThunk {
71        dest: CpsValueId,
72        thunk: CpsValueId,
73    },
74    Tuple {
75        dest: CpsValueId,
76        items: Vec<CpsValueId>,
77    },
78    Record {
79        dest: CpsValueId,
80        base: Option<CpsValueId>,
81        fields: Vec<CpsRecordField>,
82    },
83    RecordWithoutFields {
84        dest: CpsValueId,
85        base: CpsValueId,
86        fields: Vec<typed_ir::Name>,
87    },
88    Variant {
89        dest: CpsValueId,
90        tag: typed_ir::Name,
91        value: Option<CpsValueId>,
92    },
93    Select {
94        dest: CpsValueId,
95        base: CpsValueId,
96        field: typed_ir::Name,
97    },
98    SelectWithDefault {
99        dest: CpsValueId,
100        base: CpsValueId,
101        field: typed_ir::Name,
102        default: CpsValueId,
103    },
104    RecordHasField {
105        dest: CpsValueId,
106        base: CpsValueId,
107        field: typed_ir::Name,
108    },
109    TupleGet {
110        dest: CpsValueId,
111        tuple: CpsValueId,
112        index: usize,
113    },
114    VariantTagEq {
115        dest: CpsValueId,
116        variant: CpsValueId,
117        tag: typed_ir::Name,
118    },
119    VariantPayload {
120        dest: CpsValueId,
121        variant: CpsValueId,
122    },
123    Primitive {
124        dest: CpsValueId,
125        op: typed_ir::PrimitiveOp,
126        args: Vec<CpsValueId>,
127    },
128    DirectCall {
129        dest: CpsValueId,
130        target: String,
131        args: Vec<CpsValueId>,
132    },
133    ApplyClosure {
134        dest: CpsValueId,
135        closure: CpsValueId,
136        arg: CpsValueId,
137    },
138    CloneContinuation {
139        dest: CpsValueId,
140        source: CpsValueId,
141    },
142    Resume {
143        dest: CpsValueId,
144        resumption: CpsValueId,
145        arg: CpsValueId,
146    },
147    ResumeWithHandler {
148        dest: CpsValueId,
149        resumption: CpsValueId,
150        arg: CpsValueId,
151        handler: CpsHandlerId,
152        envs: Vec<CpsHandlerEnv>,
153    },
154    InstallHandler {
155        handler: CpsHandlerId,
156        envs: Vec<CpsHandlerEnv>,
157        /// Continuation that applies the handler's value arm when the body
158        /// completes naturally. Runtime installs this as a prompt-exit frame
159        /// so shallow resumptions can capture the raw body continuation
160        /// without capturing the value arm.
161        value: CpsContinuationId,
162        /// The continuation reached when the handler scope completes —
163        /// either because the body returned normally or a non-resuming
164        /// arm fell through. ScopeReturn-style abort uses this as the
165        /// jump target after popping the handler frame, so handler
166        /// scopes can return values without bubbling past the catch.
167        escape: CpsContinuationId,
168    },
169    UninstallHandler {
170        handler: CpsHandlerId,
171    },
172}
173
174#[derive(Debug, Clone, PartialEq, Eq)]
175pub struct CpsRecordField {
176    pub name: typed_ir::Name,
177    pub value: CpsValueId,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct CpsHandlerEnv {
182    pub entry: CpsContinuationId,
183    /// Value ids read at the install / reentry site.
184    pub values: Vec<CpsValueId>,
185    /// Value ids written into the handler arm's captured environment.
186    /// Empty means `targets == values`, which keeps ordinary same-function
187    /// handler installs compact.
188    pub targets: Vec<CpsValueId>,
189}
190
191#[derive(Debug, Clone, PartialEq, Eq)]
192pub enum CpsTerminator {
193    Return(CpsValueId),
194    Continue {
195        target: CpsContinuationId,
196        args: Vec<CpsValueId>,
197    },
198    Branch {
199        cond: CpsValueId,
200        then_cont: CpsContinuationId,
201        else_cont: CpsContinuationId,
202    },
203    Perform {
204        effect: typed_ir::Path,
205        payload: CpsValueId,
206        resume: CpsContinuationId,
207        handler: CpsHandlerId,
208        blocked: Option<CpsValueId>,
209    },
210    /// Effectful direct function call. Used inside handler scopes when the
211    /// callee may perform effects. The resume continuation receives the return
212    /// value; the call site's post-call computation is captured as a return
213    /// frame so Perform inside the callee can include it in the resumption.
214    EffectfulCall {
215        target: String,
216        args: Vec<CpsValueId>,
217        resume: CpsContinuationId,
218    },
219    /// Effectful closure application. Same semantics as EffectfulCall but for
220    /// first-class closures / resumptions.
221    EffectfulApply {
222        closure: CpsValueId,
223        arg: CpsValueId,
224        resume: CpsContinuationId,
225    },
226    /// Effectful thunk force. Used when an EffectfulCall's result is a Thunk
227    /// that needs to be forced inside the handler scope — the force needs to
228    /// be a terminator so its Perform captures the post-force continuation
229    /// in the resumption.
230    EffectfulForce {
231        thunk: CpsValueId,
232        resume: CpsContinuationId,
233    },
234}
235
236#[derive(Debug, Clone, PartialEq, Eq)]
237pub struct CpsHandler {
238    pub id: CpsHandlerId,
239    pub arms: Vec<CpsHandlerArm>,
240}
241
242#[derive(Debug, Clone, PartialEq, Eq)]
243pub struct CpsHandlerArm {
244    pub effect: typed_ir::Path,
245    pub entry: CpsContinuationId,
246}
247
248#[derive(Debug, Clone, PartialEq, Eq)]
249pub enum CpsLiteral {
250    Int(String),
251    Float(String),
252    String(String),
253    Bool(bool),
254    Unit,
255}
256
257#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
258pub struct CpsValueId(pub usize);
259
260#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
261pub struct CpsContinuationId(pub usize);
262
263#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
264pub struct CpsHandlerId(pub usize);
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
267pub struct CpsHandlerContextId(pub usize);