Skip to main content

rl_lang/resolver/
statements.rs

1//! Statement resolution - transforms declarations and control flow into
2//! slot-indexed variants and resolves import statements at compile time.
3//!
4//! Key behaviors:
5//!
6//! - Variable/constant/array declarations: resolve the initializer expression
7//!   first, *then* declare the name so the initializer cannot reference itself
8//! - Function declarations: declare the name in the outer scope first (enabling
9//!   recursion), then push a new scope for parameters and resolve the body
10//! - `ForEach`/`ForRange`: the loop variable is declared inside its own scope
11//!   so it does not leak into the surrounding scope after the loop ends
12//! - `ImportFile` / `ImportFileNamed`: reads the file from disk, lexes, parses,
13//!   and resolves it inline - the result replaces the import statement with
14//!   `ResolvedImportFile { body }` containing the fully resolved statements.
15//!   `ImportFileNamed` additionally filters to only the requested names before resolving.
16//!   Both silently return the original unresolved statement on any IO/parse failure
17
18use crate::{
19    ast::{
20        Ast,
21        nodes::ExpressionKind,
22        statements::{Statement, StatementKind},
23    },
24    lexer::tokenizer::Tokenizer,
25    parser::parser_logic::Parser,
26    resolver::Resolver,
27    utils::source::SourceFile,
28};
29
30impl Resolver {
31    pub fn resolve_program(&mut self, ast: Ast, statements: Vec<Statement>) -> Vec<Statement> {
32        let statements = self.ast_arena.merge_statements(ast, statements);
33        self.resolve_statements(statements)
34    }
35
36    pub fn resolve_statements(&mut self, statements: Vec<Statement>) -> Vec<Statement> {
37        statements
38            .into_iter()
39            .map(|statement| self.resolve_statement(statement))
40            .collect()
41    }
42
43    fn resolve_statement(&mut self, stmt: Statement) -> Statement {
44        let span = stmt.span;
45        let kind = match stmt.kind {
46            StatementKind::VariableDeclaration {
47                name,
48                type_annotation,
49                value,
50            } => {
51                let value = self.resolve_expression(value);
52                let slot = self.declare(name.clone());
53                StatementKind::ResolvedVariableDeclaration {
54                    name,
55                    slot,
56                    type_annotation,
57                    value,
58                }
59            }
60            StatementKind::ConstantDeclaration {
61                name,
62                type_annotation,
63                value,
64            } => {
65                let value = self.resolve_expression(value);
66                let slot = self.declare(name.clone());
67                StatementKind::ResolvedConstantDeclaration {
68                    name,
69                    slot,
70                    type_annotation,
71                    value,
72                }
73            }
74            // new arrays variant
75            StatementKind::Array {
76                name,
77                type_annotation,
78                value,
79            } => {
80                let value = value
81                    .into_iter()
82                    .map(|e| self.resolve_expression(e))
83                    .collect();
84                let slot = self.declare(name.clone());
85                let value = self
86                    .ast_arena
87                    .alloc_expr(ExpressionKind::ArrayLiteral(value), span);
88
89                StatementKind::ResolvedArray {
90                    name,
91                    slot,
92                    type_annotation,
93                    value,
94                }
95            }
96            StatementKind::ConstantArray {
97                name,
98                type_annotation,
99                value,
100            } => {
101                let value = value
102                    .into_iter()
103                    .map(|e| self.resolve_expression(e))
104                    .collect();
105                let slot = self.declare(name.clone());
106                let value = self
107                    .ast_arena
108                    .alloc_expr(ExpressionKind::ArrayLiteral(value), span);
109
110                StatementKind::ResolvedConstantArray {
111                    name,
112                    slot,
113                    type_annotation,
114                    value,
115                }
116            }
117
118            StatementKind::Set {
119                name,
120                type_annotation,
121                items,
122            } => {
123                let value = items
124                    .into_iter()
125                    .map(|e| self.resolve_expression(e))
126                    .collect();
127                let slot = self.declare(name.clone());
128                let value = self
129                    .ast_arena
130                    .alloc_expr(ExpressionKind::SetLiteral(value), span);
131
132                StatementKind::ResolvedSet {
133                    name,
134                    slot,
135                    type_annotation,
136                    value,
137                }
138            }
139            StatementKind::ConstantSet {
140                name,
141                type_annotation,
142                items,
143            } => {
144                let value = items
145                    .into_iter()
146                    .map(|e| self.resolve_expression(e))
147                    .collect();
148                let slot = self.declare(name.clone());
149                let value = self
150                    .ast_arena
151                    .alloc_expr(ExpressionKind::SetLiteral(value), span);
152
153                StatementKind::ResolvedConstantSet {
154                    name,
155                    slot,
156                    type_annotation,
157                    value,
158                }
159            }
160
161            StatementKind::Map {
162                name,
163                type_annotation,
164                entries,
165            } => {
166                let entries = entries
167                    .into_iter()
168                    .map(|(k, v)| (self.resolve_expression(k), self.resolve_expression(v)))
169                    .collect();
170                let slot = self.declare(name.clone());
171                let value = self
172                    .ast_arena
173                    .alloc_expr(ExpressionKind::MapLiteral(entries), span);
174
175                StatementKind::ResolvedMap {
176                    name,
177                    slot,
178                    type_annotation,
179                    value,
180                }
181            }
182            StatementKind::ConstantMap {
183                name,
184                type_annotation,
185                entries,
186            } => {
187                let entries = entries
188                    .into_iter()
189                    .map(|(k, v)| (self.resolve_expression(k), self.resolve_expression(v)))
190                    .collect();
191                let slot = self.declare(name.clone());
192                let value = self
193                    .ast_arena
194                    .alloc_expr(ExpressionKind::MapLiteral(entries), span);
195
196                StatementKind::ResolvedConstantMap {
197                    name,
198                    slot,
199                    type_annotation,
200                    value,
201                }
202            }
203
204            StatementKind::FunctionDeclaration {
205                name,
206                params,
207                return_type,
208                body,
209                attribute,
210            } => {
211                let slot = self.declare(name.clone());
212                self.push_scope();
213                for p in &params {
214                    self.declare(p.param_name.clone());
215                }
216                let body = self.resolve_statements(body);
217                self.pop_scope();
218                StatementKind::ResolvedFunctionDeclaration {
219                    name,
220                    slot,
221                    params,
222                    return_type,
223                    body,
224                    attribute,
225                }
226            }
227            StatementKind::ForEach {
228                variable,
229                iterable,
230                body,
231            } => {
232                let iterable = self.resolve_expression(iterable);
233                self.push_scope();
234                let slot = self.declare(variable.clone());
235                let body = self.resolve_statements(body);
236                self.pop_scope();
237                StatementKind::ResolvedForEach {
238                    variable,
239                    slot,
240                    iterable,
241                    body,
242                }
243            }
244            StatementKind::ForRange {
245                variable,
246                range,
247                body,
248            } => {
249                let range = Box::new(self.resolve_statement(*range));
250                self.push_scope();
251                let slot = self.declare(variable.clone());
252                let body = self.resolve_statements(body);
253                self.pop_scope();
254                StatementKind::ResolvedForRange {
255                    variable,
256                    slot,
257                    range,
258                    body,
259                }
260            }
261            StatementKind::For {
262                initializer,
263                condition,
264                increment,
265                body,
266            } => {
267                let initializer = Box::new(self.resolve_statement(*initializer));
268                let condition = self.resolve_expression(condition);
269                let increment = self.resolve_expression(increment);
270                let body = self.resolve_statements(body);
271                StatementKind::ResolvedFor {
272                    initializer,
273                    condition,
274                    increment,
275                    body,
276                }
277            }
278            StatementKind::While { condition, body } => {
279                let condition = self.resolve_expression(condition);
280                self.push_scope();
281                let body = self.resolve_statements(body);
282                self.pop_scope();
283                StatementKind::While { condition, body }
284            }
285            StatementKind::Conditional {
286                if_branch,
287                else_branch,
288            } => {
289                let if_branch = Box::new(self.resolve_statement(*if_branch));
290                let else_branch = else_branch.map(|e| Box::new(self.resolve_statement(*e)));
291                StatementKind::Conditional {
292                    if_branch,
293                    else_branch,
294                }
295            }
296
297            StatementKind::ConditionalBranch {
298                condition, body, ..
299            } => {
300                let condition = condition.map(|e| self.resolve_expression(e));
301                let needs_scope = body.iter().any(|s| {
302                    matches!(
303                        s.kind,
304                        StatementKind::VariableDeclaration { .. }
305                            | StatementKind::ConstantDeclaration { .. }
306                            | StatementKind::Array { .. }
307                            | StatementKind::ConstantArray { .. }
308                            | StatementKind::Map { .. }
309                            | StatementKind::ConstantMap { .. }
310                            | StatementKind::FunctionDeclaration { .. }
311                    )
312                });
313                if needs_scope {
314                    self.push_scope();
315                }
316                let body = self.resolve_statements(body);
317                if needs_scope {
318                    self.pop_scope();
319                }
320                StatementKind::ConditionalBranch {
321                    condition,
322                    body,
323                    needs_scope,
324                }
325            }
326
327            StatementKind::Return(expr) => {
328                StatementKind::Return(expr.map(|e| self.resolve_expression(e)))
329            }
330            StatementKind::Expression(expr) => {
331                StatementKind::Expression(self.resolve_expression(expr))
332            }
333
334            StatementKind::ImportFile { path } => {
335                let import_name = format!("{}.rl", path.join("/"));
336                let file_path = self.current_dir.join(&import_name);
337                let Ok(source_text) = std::fs::read_to_string(&file_path) else {
338                    return Statement::new(StatementKind::ImportFile { path }, span);
339                };
340                let source_file =
341                    SourceFile::new(file_path.to_string_lossy().as_ref(), source_text);
342                let Ok(tokens) = Tokenizer::lex(source_file.clone()) else {
343                    return Statement::new(StatementKind::ImportFile { path }, span);
344                };
345                let Ok((imported_ast, stmts)) = Parser::parse(tokens, source_file) else {
346                    return Statement::new(StatementKind::ImportFile { path }, span);
347                };
348
349                let stmts = self.ast_arena.merge_statements(imported_ast, stmts);
350
351                let imported_dir = file_path
352                    .parent()
353                    .unwrap_or(std::path::Path::new(""))
354                    .to_path_buf();
355                let prev_dir = std::mem::replace(&mut self.current_dir, imported_dir);
356                let resolved = self.resolve_statements(stmts);
357                self.current_dir = prev_dir;
358
359                StatementKind::ResolvedImportFile {
360                    path,
361                    body: resolved,
362                }
363            }
364
365            StatementKind::ImportFileNamed { path, names } => {
366                let import_name = format!("{}.rl", path.join("/"));
367                let file_path = self.current_dir.join(&import_name);
368                let Ok(source_text) = std::fs::read_to_string(&file_path) else {
369                    return Statement::new(StatementKind::ImportFileNamed { path, names }, span);
370                };
371                let source_file =
372                    SourceFile::new(file_path.to_string_lossy().as_ref(), source_text);
373                let Ok(tokens) = Tokenizer::lex(source_file.clone()) else {
374                    return Statement::new(StatementKind::ImportFileNamed { path, names }, span);
375                };
376                let Ok((imported_ast, stmts)) = Parser::parse(tokens, source_file) else {
377                    return Statement::new(StatementKind::ImportFileNamed { path, names }, span);
378                };
379                let stmts: Vec<_> = stmts
380                    .into_iter()
381                    .filter(|s| match &s.kind {
382                        StatementKind::FunctionDeclaration { name, .. }
383                        | StatementKind::VariableDeclaration { name, .. }
384                        | StatementKind::ConstantDeclaration { name, .. } => names.contains(name),
385                        StatementKind::Array { name, .. }
386                        | StatementKind::ConstantArray { name, .. } => names.contains(name),
387                        StatementKind::Map { name, .. }
388                        | StatementKind::ConstantMap { name, .. } => names.contains(name),
389                        _ => false,
390                    })
391                    .collect();
392
393                let stmts = self.ast_arena.merge_statements(imported_ast, stmts);
394
395                let imported_dir = file_path
396                    .parent()
397                    .unwrap_or(std::path::Path::new(""))
398                    .to_path_buf();
399                let prev_dir = std::mem::replace(&mut self.current_dir, imported_dir);
400                let body = self.resolve_statements(stmts);
401                self.current_dir = prev_dir;
402
403                StatementKind::ResolvedImportFile { path, body }
404            }
405
406            StatementKind::DestructureDeclaration { bindings, value } => {
407                let value = self.resolve_expression(value);
408                let slots = bindings
409                    .iter()
410                    .map(|(_, name)| self.declare(name.clone()))
411                    .collect();
412                StatementKind::ResolvedDestructureDeclaration {
413                    bindings,
414                    slots,
415                    value,
416                }
417            }
418
419            StatementKind::Match { value, arms } => {
420                let value = self.resolve_expression(value);
421                let arms = arms
422                    .into_iter()
423                    .map(|(pattern, body)| {
424                        self.push_scope();
425                        let body = self.resolve_statements(body);
426                        self.pop_scope();
427                        (pattern, body)
428                    })
429                    .collect();
430                StatementKind::Match { value, arms }
431            }
432
433            other => other,
434        };
435        Statement::new(kind, span)
436    }
437}