rl_lang/ast/statements.rs
1//! Statement AST nodes, type annotations, and parameter definitions.
2//!
3//! A [`Statement`] is any construct that does not directly produce a value
4//! (declarations, control flow, imports). Every node carries the source [`Span`]
5//! it was parsed from.
6//!
7//! # Resolved variants
8//! The [`Resolver`] pass rewrites name-based declaration and loop variants into
9//! their `Resolved*` counterparts, adding a `slot: usize` field that gives the
10//! variable's index in its environment frame. This eliminates all runtime
11//! HashMap lookups in the evaluator.
12//!
13//! # Type annotations
14//! [`TypeAnnotation`] distinguishes mutable (`dec`) and constant (`const`)
15//! bindings at the type level via separate variants (`Int` vs `CInt`, etc.).
16//!
17//! [`Resolver`]: crate::resolver
18use std::rc::Rc;
19
20use crate::ast::ExprId;
21use crate::utils::span::Span;
22
23/// A statement paired with its source span.
24#[derive(Debug, Clone, PartialEq)]
25pub struct Statement {
26 pub kind: StatementKind,
27 pub span: Span,
28}
29
30impl Statement {
31 pub fn new(kind: StatementKind, span: Span) -> Self {
32 Self { kind, span }
33 }
34}
35
36#[derive(Debug, Clone, PartialEq)]
37pub enum StatementKind {
38 /// A mutable variable declaration: `dec T name = value`.
39 VariableDeclaration {
40 name: String,
41 type_annotation: TypeAnnotation,
42 value: ExprId,
43 },
44 /// Resolver-annotated mutable variable declaration. `slot` is the index
45 /// in the current environment frame.
46 ResolvedVariableDeclaration {
47 name: String,
48 slot: usize,
49 type_annotation: TypeAnnotation,
50 value: ExprId,
51 },
52 /// An immutable constant declaration: `const T NAME = value`.
53 ConstantDeclaration {
54 name: String,
55 type_annotation: TypeAnnotation,
56 value: ExprId,
57 },
58 /// Resolver-annotated constant declaration.
59 ResolvedConstantDeclaration {
60 name: String,
61 slot: usize,
62 type_annotation: TypeAnnotation,
63 value: ExprId,
64 },
65 /// A mutable array declaration with an inline literal: `dec array[T] name = [items]`.
66 Array {
67 name: String,
68 type_annotation: TypeAnnotation,
69 value: Vec<ExprId>,
70 },
71 /// An immutable array declaration with an inline literal: `const array[T] NAME = [items]`.
72 ConstantArray {
73 name: String,
74 type_annotation: TypeAnnotation,
75 value: Vec<ExprId>,
76 },
77 /// Resolver-annotated mutable array declaration. `value` is the
78 /// initialiser expression (may be an [`ExpressionKind::ArrayLiteral`]).
79 ///
80 /// [`ExpressionKind::ArrayLiteral`]: crate::ast::nodes::ExpressionKind::ArrayLiteral
81 ResolvedArray {
82 name: String,
83 slot: usize,
84 type_annotation: TypeAnnotation,
85 value: ExprId,
86 },
87 /// Resolver-annotated constant array declaration.
88 ResolvedConstantArray {
89 name: String,
90 slot: usize,
91 type_annotation: TypeAnnotation,
92 value: ExprId,
93 },
94
95 Map {
96 name: String,
97 type_annotation: TypeAnnotation,
98 entries: Vec<(ExprId, ExprId)>,
99 },
100 ConstantMap {
101 name: String,
102 type_annotation: TypeAnnotation,
103 entries: Vec<(ExprId, ExprId)>,
104 },
105 ResolvedMap {
106 name: String,
107 slot: usize,
108 type_annotation: TypeAnnotation,
109 value: ExprId,
110 },
111 ResolvedConstantMap {
112 name: String,
113 slot: usize,
114 type_annotation: TypeAnnotation,
115 value: ExprId,
116 },
117
118 Set {
119 name: String,
120 type_annotation: TypeAnnotation,
121 items: Vec<ExprId>,
122 },
123 ConstantSet {
124 name: String,
125 type_annotation: TypeAnnotation,
126 items: Vec<ExprId>,
127 },
128 ResolvedSet {
129 name: String,
130 slot: usize,
131 type_annotation: TypeAnnotation,
132 value: ExprId,
133 },
134 ResolvedConstantSet {
135 name: String,
136 slot: usize,
137 type_annotation: TypeAnnotation,
138 value: ExprId,
139 },
140 /// A bare expression used as a statement (e.g. a function call whose
141 /// return value is discarded, or a newline placeholder).
142 Expression(ExprId),
143 /// A `while condition { body }` loop.
144 While {
145 condition: ExprId,
146 body: Vec<Statement>,
147 },
148 /// A C-style `for [init, cond, incr] { body }` loop.
149 For {
150 initializer: Box<Statement>,
151 condition: ExprId,
152 increment: ExprId,
153 body: Vec<Statement>,
154 },
155 /// Resolver-annotated C-style for loop.
156 ResolvedFor {
157 initializer: Box<Statement>,
158 condition: ExprId,
159 increment: ExprId,
160 body: Vec<Statement>,
161 },
162 /// A range-based `for x in N..M { body }` loop. The range is pre-evaluated
163 /// at parse time into a [`Range`] statement.
164 ForRange {
165 variable: String,
166 range: Box<Statement>,
167 body: Vec<Statement>,
168 },
169 /// Resolver-annotated range-based for loop. `slot` is the loop variable's
170 /// environment index.
171 ResolvedForRange {
172 slot: usize,
173 variable: String,
174 range: Box<Statement>,
175 body: Vec<Statement>,
176 },
177 /// A foreach `for item in iterable { body }` loop over an array expression.
178 ForEach {
179 variable: String,
180 iterable: ExprId,
181 body: Vec<Statement>,
182 },
183 /// Resolver-annotated foreach loop.
184 ResolvedForEach {
185 slot: usize,
186 variable: String,
187 iterable: ExprId,
188 body: Vec<Statement>,
189 },
190 /// A pre-evaluated integer range produced by the parser for `for x in N..M`.
191 Range(Vec<i64>),
192 /// A single branch of a conditional: either `if condition { body }` (`condition`
193 /// is `Some`) or `else { body }` (`condition` is `None`).
194 ConditionalBranch {
195 condition: Option<ExprId>,
196 body: Vec<Statement>,
197 /// Precomputed by the resolver
198 /// true if `body` declares any local variable/constant
199 /// and therefore needs its own scope frame
200 needs_scope: bool,
201 },
202 /// A full if / else-if / else chain.
203 Conditional {
204 if_branch: Box<Statement>,
205 else_branch: Option<Box<Statement>>,
206 },
207 /// A named function declaration.
208 FunctionDeclaration {
209 name: String,
210 params: Vec<Param>,
211 return_type: TypeAnnotation,
212 body: Vec<Statement>,
213 /// `true` when the function is marked with `!#[entry]`.
214 attribute: Option<FunctionAttribute>,
215 },
216 /// Resolver-annotated function declaration. `slot` is the function's
217 /// index in the current environment frame.
218 ResolvedFunctionDeclaration {
219 name: String,
220 slot: usize,
221 params: Vec<Param>,
222 return_type: TypeAnnotation,
223 body: Vec<Statement>,
224 attribute: Option<FunctionAttribute>,
225 },
226 /// A `return expr` or bare `return` statement.
227 Return(Option<ExprId>),
228 /// Breaks out of the nearest enclosing loop.
229 Break,
230 /// Skips to the next iteration of the nearest enclosing loop.
231 Continue,
232 /// A stdlib import: `get std::ns::fn` or `get fn from std::ns`.
233 Import {
234 /// names of the imported functions
235 names: Vec<String>,
236 /// module path (e.g. `["std", "math"]`)
237 path: Vec<String>,
238 },
239 /// A file module import: `get mymodule` or `get mymodule::sub`.
240 ImportFile { path: Vec<String> },
241 /// A resolved file import - the imported file's statements are inlined here.
242 ResolvedImportFile {
243 path: Vec<String>,
244 body: Vec<Statement>,
245 },
246 /// A named file import: `get fn, fn from mymodule::sub`.
247 ImportFileNamed {
248 path: Vec<String>,
249 names: Vec<String>,
250 },
251
252 DestructureDeclaration {
253 bindings: Vec<(TypeAnnotation, String)>,
254 value: ExprId,
255 },
256 ResolvedDestructureDeclaration {
257 bindings: Vec<(TypeAnnotation, String)>,
258 slots: Vec<usize>,
259 value: ExprId,
260 },
261
262 Match {
263 value: ExprId,
264 arms: Vec<(MatchPattern, Vec<Statement>)>,
265 },
266
267 /// A record (struct) type declaration: `record Name { int a, string b }`.
268 RecordDeclaration {
269 name: String,
270 fields: Vec<(String, TypeAnnotation)>,
271 },
272
273 /// A tag (enum) type declaration: `tag Name { VariantA, VariantB }`.
274 TagDeclaration { name: String, variants: Vec<String> },
275}
276
277#[derive(Debug, PartialEq, Clone)]
278pub enum MatchPattern {
279 Literal(ExprId),
280 Wildcard,
281}
282
283#[derive(Debug, Clone, PartialEq)]
284pub enum FunctionAttribute {
285 Entry,
286 Init,
287 Final,
288 Test,
289}
290
291/// The type of a variable, constant, or parameter binding.
292///
293/// Mutable variants (`Int`, `Float`, etc.) are produced by `dec` declarations.
294/// Constant variants (`CInt`, `CFloat`, etc.) are produced by `const` declarations.
295/// `Array(T)` / `CArray(T)` are the mutable / constant array forms.
296#[derive(Debug, Clone, PartialEq)]
297pub enum TypeAnnotation {
298 /// Mutable 64-bit signed integer.
299 Int,
300 /// Mutable 64-bit float.
301 Float,
302 /// Mutable boolean.
303 Bool,
304 /// Mutable string.
305 String,
306 /// Mutable byte (`u8`).
307 Byte,
308 /// Mutable character.
309 Char,
310 /// Mutable array with a typed element.
311 Array(Box<TypeAnnotation>),
312 Map(Box<TypeAnnotation>, Box<TypeAnnotation>),
313 Set(Box<TypeAnnotation>),
314 /// Constant 64-bit signed integer.
315 CInt,
316 /// Constant 64-bit float.
317 CFloat,
318 /// Constant boolean.
319 CBool,
320 /// Constant string.
321 CString,
322 /// Constant byte.
323 CByte,
324 /// Constant character.
325 CChar,
326 /// Constant array with a typed element.
327 CArray(Box<TypeAnnotation>),
328 CMap(Box<TypeAnnotation>, Box<TypeAnnotation>),
329 CSet(Box<TypeAnnotation>),
330 /// A function value (used for `fn`-typed parameters and variables).
331 Fn,
332 /// Absence of a type - used as the default return type when none is annotated.
333 Null,
334
335 Tuple(Rc<Vec<TypeAnnotation>>),
336 CTuple(Rc<Vec<TypeAnnotation>>),
337
338 Error,
339 CError,
340
341 Result(Box<TypeAnnotation>),
342 CResult(Box<TypeAnnotation>),
343
344 /// A named record (struct) type, mutable binding.
345 Record(String),
346 /// A named record (struct) type, constant binding.
347 CRecord(String),
348
349 /// A named tag (enum) type, mutable binding.
350 Enum(String),
351 /// A named tag (enum) type, constant binding.
352 CEnum(String),
353}
354
355/// A single function or lambda parameter: a name and its type annotation.
356#[derive(Debug, Clone, PartialEq)]
357pub struct Param {
358 pub param_name: String,
359 pub param_type: TypeAnnotation,
360}