Skip to main content

sema_vm/
core_expr.rs

1use sema_core::{Spur, Value};
2
3/// How a variable reference was resolved by the resolver pass.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum VarResolution {
6    /// Local variable in the current function frame.
7    Local { slot: u16 },
8    /// Captured variable from an enclosing function scope.
9    Upvalue { index: u16 },
10    /// Module-level / global binding.
11    Global { spur: Spur },
12}
13
14/// A resolved variable reference (name preserved for debugging).
15#[derive(Debug, Clone, Copy)]
16pub struct VarRef {
17    pub name: Spur,
18    pub resolution: VarResolution,
19}
20
21/// Desugared core language. Variables referenced by name (Spur).
22/// The variable resolver replaces names with slot indices in a later pass.
23#[derive(Debug, Clone)]
24pub enum CoreExpr {
25    /// Literal constant
26    Const(Value),
27    /// Variable reference
28    Var(Spur),
29    /// if-then-else
30    If {
31        test: Box<CoreExpr>,
32        then: Box<CoreExpr>,
33        else_: Box<CoreExpr>,
34    },
35    /// Sequence of expressions
36    Begin(Vec<CoreExpr>),
37    /// Variable mutation (set!)
38    Set(Spur, Box<CoreExpr>),
39    /// Closure creation
40    Lambda(LambdaDef),
41    /// Function call (tail flag for TCO)
42    Call {
43        func: Box<CoreExpr>,
44        args: Vec<CoreExpr>,
45        tail: bool,
46    },
47    /// Variable definition (define)
48    Define(Spur, Box<CoreExpr>),
49    /// Parallel binding
50    Let {
51        bindings: Vec<(Spur, CoreExpr)>,
52        body: Vec<CoreExpr>,
53    },
54    /// Sequential binding
55    LetStar {
56        bindings: Vec<(Spur, CoreExpr)>,
57        body: Vec<CoreExpr>,
58    },
59    /// Recursive binding
60    Letrec {
61        bindings: Vec<(Spur, CoreExpr)>,
62        body: Vec<CoreExpr>,
63    },
64    /// Named let (loop construct)
65    NamedLet {
66        name: Spur,
67        bindings: Vec<(Spur, CoreExpr)>,
68        body: Vec<CoreExpr>,
69    },
70    /// Do loop
71    Do(DoLoop),
72    /// Try/catch
73    Try {
74        body: Vec<CoreExpr>,
75        catch_var: Spur,
76        handler: Vec<CoreExpr>,
77    },
78    /// Throw exception
79    Throw(Box<CoreExpr>),
80    /// Short-circuit and
81    And(Vec<CoreExpr>),
82    /// Short-circuit or
83    Or(Vec<CoreExpr>),
84    /// Quoted value (no evaluation)
85    Quote(Value),
86    /// List constructor (evaluate elements)
87    MakeList(Vec<CoreExpr>),
88    /// Vector constructor (evaluate elements)
89    MakeVector(Vec<CoreExpr>),
90    /// Map constructor (evaluate key-value pairs)
91    MakeMap(Vec<(CoreExpr, CoreExpr)>),
92    /// Macro definition (runtime)
93    Defmacro {
94        name: Spur,
95        params: Vec<Spur>,
96        rest: Option<Spur>,
97        body: Vec<CoreExpr>,
98    },
99    /// Record type definition
100    DefineRecordType {
101        type_name: Spur,
102        ctor_name: Spur,
103        pred_name: Spur,
104        field_names: Vec<Spur>,
105        field_specs: Vec<(Spur, Spur)>,
106    },
107    /// Module declaration
108    Module {
109        name: Spur,
110        exports: Vec<Spur>,
111        body: Vec<CoreExpr>,
112    },
113    /// Import a module
114    Import {
115        path: Box<CoreExpr>,
116        selective: Vec<Spur>,
117    },
118    /// Load a file in current env
119    Load(Box<CoreExpr>),
120    /// Dynamic eval
121    Eval(Box<CoreExpr>),
122    /// Prompt (LLM data constructor)
123    Prompt(Vec<PromptEntry>),
124    /// Message (LLM data constructor)
125    Message {
126        role: Box<CoreExpr>,
127        parts: Vec<CoreExpr>,
128    },
129    /// Tool definition (LLM)
130    Deftool {
131        name: Spur,
132        description: Box<CoreExpr>,
133        parameters: Box<CoreExpr>,
134        handler: Box<CoreExpr>,
135    },
136    /// Agent definition (LLM)
137    Defagent { name: Spur, options: Box<CoreExpr> },
138    /// Delay (create thunk)
139    Delay(Box<CoreExpr>),
140    /// Force (evaluate thunk)
141    Force(Box<CoreExpr>),
142    /// Macroexpand
143    Macroexpand(Box<CoreExpr>),
144}
145
146/// A prompt entry: either a role-content form or an expression.
147#[derive(Debug, Clone)]
148pub enum PromptEntry {
149    RoleContent { role: String, parts: Vec<CoreExpr> },
150    Expr(CoreExpr),
151}
152
153#[derive(Debug, Clone)]
154pub struct LambdaDef {
155    pub name: Option<Spur>,
156    pub params: Vec<Spur>,
157    pub rest: Option<Spur>,
158    pub body: Vec<CoreExpr>,
159}
160
161#[derive(Debug, Clone)]
162pub struct DoLoop {
163    pub vars: Vec<DoVar>,
164    pub test: Box<CoreExpr>,
165    pub result: Vec<CoreExpr>,
166    pub body: Vec<CoreExpr>,
167}
168
169#[derive(Debug, Clone)]
170pub struct DoVar {
171    pub name: Spur,
172    pub init: CoreExpr,
173    pub step: Option<CoreExpr>,
174}
175
176// --- Resolved IR (output of variable resolution pass) ---
177
178/// Resolved expression: like CoreExpr but variables are resolved to slots/upvalues/globals.
179#[derive(Debug, Clone)]
180pub enum ResolvedExpr {
181    Const(Value),
182    Var(VarRef),
183    If {
184        test: Box<ResolvedExpr>,
185        then: Box<ResolvedExpr>,
186        else_: Box<ResolvedExpr>,
187    },
188    Begin(Vec<ResolvedExpr>),
189    Set(VarRef, Box<ResolvedExpr>),
190    Lambda(ResolvedLambda),
191    Call {
192        func: Box<ResolvedExpr>,
193        args: Vec<ResolvedExpr>,
194        tail: bool,
195    },
196    Define(Spur, Box<ResolvedExpr>),
197    Let {
198        bindings: Vec<(VarRef, ResolvedExpr)>,
199        body: Vec<ResolvedExpr>,
200    },
201    LetStar {
202        bindings: Vec<(VarRef, ResolvedExpr)>,
203        body: Vec<ResolvedExpr>,
204    },
205    Letrec {
206        bindings: Vec<(VarRef, ResolvedExpr)>,
207        body: Vec<ResolvedExpr>,
208    },
209    NamedLet {
210        name: VarRef,
211        bindings: Vec<(VarRef, ResolvedExpr)>,
212        body: Vec<ResolvedExpr>,
213    },
214    Do(ResolvedDoLoop),
215    Try {
216        body: Vec<ResolvedExpr>,
217        catch_var: VarRef,
218        handler: Vec<ResolvedExpr>,
219    },
220    Throw(Box<ResolvedExpr>),
221    And(Vec<ResolvedExpr>),
222    Or(Vec<ResolvedExpr>),
223    Quote(Value),
224    MakeList(Vec<ResolvedExpr>),
225    MakeVector(Vec<ResolvedExpr>),
226    MakeMap(Vec<(ResolvedExpr, ResolvedExpr)>),
227    Defmacro {
228        name: Spur,
229        params: Vec<Spur>,
230        rest: Option<Spur>,
231        body: Vec<ResolvedExpr>,
232    },
233    DefineRecordType {
234        type_name: Spur,
235        ctor_name: Spur,
236        pred_name: Spur,
237        field_names: Vec<Spur>,
238        field_specs: Vec<(Spur, Spur)>,
239    },
240    Module {
241        name: Spur,
242        exports: Vec<Spur>,
243        body: Vec<ResolvedExpr>,
244    },
245    Import {
246        path: Box<ResolvedExpr>,
247        selective: Vec<Spur>,
248    },
249    Load(Box<ResolvedExpr>),
250    Eval(Box<ResolvedExpr>),
251    Prompt(Vec<ResolvedPromptEntry>),
252    Message {
253        role: Box<ResolvedExpr>,
254        parts: Vec<ResolvedExpr>,
255    },
256    Deftool {
257        name: Spur,
258        description: Box<ResolvedExpr>,
259        parameters: Box<ResolvedExpr>,
260        handler: Box<ResolvedExpr>,
261    },
262    Defagent {
263        name: Spur,
264        options: Box<ResolvedExpr>,
265    },
266    Delay(Box<ResolvedExpr>),
267    Force(Box<ResolvedExpr>),
268    Macroexpand(Box<ResolvedExpr>),
269}
270
271#[derive(Debug, Clone)]
272pub enum ResolvedPromptEntry {
273    RoleContent {
274        role: String,
275        parts: Vec<ResolvedExpr>,
276    },
277    Expr(ResolvedExpr),
278}
279
280#[derive(Debug, Clone)]
281pub struct ResolvedLambda {
282    pub name: Option<Spur>,
283    pub params: Vec<Spur>,
284    pub rest: Option<Spur>,
285    pub body: Vec<ResolvedExpr>,
286    pub upvalues: Vec<UpvalueDesc>,
287    pub n_locals: u16,
288}
289
290// Re-export UpvalueDesc from chunk.rs — used by both ResolvedLambda and Function.
291pub use crate::chunk::UpvalueDesc;
292
293#[derive(Debug, Clone)]
294pub struct ResolvedDoLoop {
295    pub vars: Vec<ResolvedDoVar>,
296    pub test: Box<ResolvedExpr>,
297    pub result: Vec<ResolvedExpr>,
298    pub body: Vec<ResolvedExpr>,
299}
300
301#[derive(Debug, Clone)]
302pub struct ResolvedDoVar {
303    pub name: VarRef,
304    pub init: ResolvedExpr,
305    pub step: Option<ResolvedExpr>,
306}