Skip to main content

shape_ast/ast/
expr_helpers.rs

1//! Helper types for expressions in Shape AST
2
3use serde::{Deserialize, Serialize};
4
5use super::expressions::Expr;
6use super::functions::Annotation;
7use super::patterns::{DestructurePattern, Pattern};
8use super::program::VariableDecl;
9use super::span::Span;
10use super::types::TypeAnnotation;
11
12/// Block expression containing multiple statements
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct BlockExpr {
15    /// The statements in the block
16    pub items: Vec<BlockItem>,
17}
18
19/// An item in a block expression
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21pub enum BlockItem {
22    /// Variable declaration
23    VariableDecl(VariableDecl),
24    /// Assignment
25    Assignment(super::program::Assignment),
26    /// Statement
27    Statement(super::statements::Statement),
28    /// Expression (the last expression's value is the block's value)
29    Expression(Expr),
30}
31
32/// If expression that returns a value
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
34pub struct IfExpr {
35    pub condition: Box<Expr>,
36    pub then_branch: Box<Expr>,
37    pub else_branch: Option<Box<Expr>>, // Defaults to Unit if missing
38}
39
40/// While expression that returns a value
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
42pub struct WhileExpr {
43    pub condition: Box<Expr>,
44    pub body: Box<Expr>,
45}
46
47/// For expression that returns a value
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
49pub struct ForExpr {
50    pub pattern: Pattern,
51    pub iterable: Box<Expr>,
52    pub body: Box<Expr>,
53    /// Whether this is an async for-await: `for await x in stream { ... }`
54    pub is_async: bool,
55}
56
57/// List comprehension expression
58#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
59pub struct ListComprehension {
60    /// The expression to evaluate for each element
61    pub element: Box<Expr>,
62    /// The comprehension clauses (for loops and filters)
63    pub clauses: Vec<ComprehensionClause>,
64}
65
66/// A clause in a list comprehension
67#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
68pub struct ComprehensionClause {
69    /// The pattern to bind values to
70    pub pattern: DestructurePattern,
71    /// The iterable expression
72    pub iterable: Box<Expr>,
73    /// Optional filter expression (if clause)
74    pub filter: Option<Box<Expr>>,
75}
76
77/// Loop expression (infinite loop with break)
78#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub struct LoopExpr {
80    pub body: Box<Expr>,
81}
82
83/// Let binding expression
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85pub struct LetExpr {
86    pub pattern: Pattern,
87    pub type_annotation: Option<TypeAnnotation>,
88    pub value: Option<Box<Expr>>,
89    pub body: Box<Expr>, // The scope where the binding is valid
90}
91
92/// Assignment expression that returns the assigned value
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
94pub struct AssignExpr {
95    pub target: Box<Expr>, // Can be identifier, property access, index
96    pub value: Box<Expr>,
97}
98
99/// Match expression
100#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
101pub struct MatchExpr {
102    pub scrutinee: Box<Expr>,
103    pub arms: Vec<MatchArm>,
104}
105
106/// Match arm
107#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
108pub struct MatchArm {
109    pub pattern: Pattern,
110    pub guard: Option<Box<Expr>>,
111    pub body: Box<Expr>,
112    /// Span of the pattern portion (for error reporting)
113    pub pattern_span: Option<super::Span>,
114}
115
116/// LINQ-style from query expression
117/// Syntax: from var in source [clauses...] select expr
118#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
119pub struct FromQueryExpr {
120    /// Loop variable name (e.g., "t" in "from t in trades")
121    pub variable: String,
122    /// Source expression (e.g., "trades")
123    pub source: Box<Expr>,
124    /// Query clauses (where, order by, group by, join, let)
125    pub clauses: Vec<QueryClause>,
126    /// Final select expression
127    pub select: Box<Expr>,
128}
129
130/// Query clause in a from expression
131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
132pub enum QueryClause {
133    /// where condition
134    Where(Box<Expr>),
135
136    /// order by key asc/desc, key2 asc/desc, ...
137    OrderBy(Vec<OrderBySpec>),
138
139    /// group element by key into variable
140    GroupBy {
141        element: Box<Expr>,
142        key: Box<Expr>,
143        into_var: Option<String>,
144    },
145
146    /// join var in source on leftKey equals rightKey into var
147    Join {
148        variable: String,
149        source: Box<Expr>,
150        left_key: Box<Expr>,
151        right_key: Box<Expr>,
152        into_var: Option<String>,
153    },
154
155    /// let var = expr
156    Let { variable: String, value: Box<Expr> },
157}
158
159/// Order specification for order by clause
160#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
161pub struct OrderBySpec {
162    pub key: Box<Expr>,
163    pub descending: bool,
164}
165
166/// Join strategy for async join expressions
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
168pub enum JoinKind {
169    /// Wait for all branches to complete, return tuple of results
170    All = 0,
171    /// Return the first branch to complete, cancel the rest
172    Race = 1,
173    /// Return the first branch to succeed (non-error), cancel the rest
174    Any = 2,
175    /// Wait for all branches, preserve individual success/error results
176    Settle = 3,
177}
178
179/// A branch in a join expression
180#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
181pub struct JoinBranch {
182    /// Optional label for named branches: `prices: fetch_prices("AAPL")`
183    pub label: Option<String>,
184    /// The expression to evaluate in this branch
185    pub expr: Expr,
186    /// Per-branch annotations: `@node(find_node("us-east")) compute_a()`
187    pub annotations: Vec<Annotation>,
188}
189
190/// Async let expression: `async let name = expr`
191/// Spawns a task and binds a future handle to a local variable.
192#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
193pub struct AsyncLetExpr {
194    /// The variable name to bind the future handle to
195    pub name: String,
196    /// The expression to spawn as an async task
197    pub expr: Box<Expr>,
198    /// Span covering the entire async let expression
199    pub span: Span,
200}
201
202/// Join expression: `join all|race|any|settle { branch, ... }`
203#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub struct JoinExpr {
205    /// The join strategy
206    pub kind: JoinKind,
207    /// The branches to execute concurrently
208    pub branches: Vec<JoinBranch>,
209    /// Span covering the entire join expression
210    pub span: Span,
211}
212
213/// Compile-time for loop: `comptime for field in target.fields { ... }`
214/// Unrolled at compile time — each iteration generates code with the loop variable
215/// substituted for the concrete field descriptor.
216#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
217pub struct ComptimeForExpr {
218    /// Loop variable name (e.g., "field")
219    pub variable: String,
220    /// The iterable expression (e.g., `target.fields`)
221    pub iterable: Box<Expr>,
222    /// Body statements to unroll for each iteration
223    pub body: Vec<super::statements::Statement>,
224}