Skip to main content

rl_lang/ast/
mod.rs

1//! Abstract Syntax Tree (AST) node definitions.
2//!
3//! # Pipeline position
4//! ```text
5//! source -> Lexer -> [Token] -> Parser -> [Statement] -> Checker -> Evaluator
6//! ```
7//!
8//! # Module layout
9//! - [`nodes`] - [`Expression`] and [`ExpressionKind`]: the expression AST
10//! - [`statements`] - [`Statement`], [`StatementKind`], [`TypeAnnotation`], [`Param`]
11//!
12//! [`Expression`]: nodes::Expression
13//! [`Statement`]: statements::Statement
14use crate::ast::{
15    arena::{Arena, Id},
16    nodes::{Expression, ExpressionKind},
17    statements::{Statement, StatementKind},
18};
19
20pub mod arena;
21pub mod nodes;
22pub mod statements;
23// pub mod variables;
24pub type ScopeMap = Vec<Vec<String>>;
25
26/// Owns every `Expression` allocated during a single parse/resolve/eval
27/// session. `Statement` stays `Box`-owned for now - this migrates the
28/// leaf/expression side first, on its own, before statements follow.
29pub struct Ast {
30    pub exprs: Arena<Expression>,
31}
32
33/// Handle to an `Expression` living in `Ast::exprs`.
34pub type ExprId = Id<Expression>;
35
36impl Default for Ast {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl Ast {
43    pub fn new() -> Self {
44        Self {
45            exprs: Arena::new(),
46        }
47    }
48
49    pub fn alloc_expr(&mut self, kind: ExpressionKind, span: crate::utils::span::Span) -> ExprId {
50        self.exprs.alloc(Expression { kind, span })
51    }
52
53    /// Merges `other`'s expression arena into `self`, and rewrites every
54    /// `ExprId` in `statements` - both ids referenced directly from a
55    /// `StatementKind` field, and ids nested *inside* the moved expressions
56    /// themselves (e.g. `Binary`'s `left`/`right`) - to point into `self`
57    /// under its numbering instead of `other`'s.
58    pub fn merge_statements(
59        &mut self,
60        mut other: Ast,
61        mut statements: Vec<Statement>,
62    ) -> Vec<Statement> {
63        let offset = self.exprs.raw_parts_mut().1.len() as u32;
64        let target_arena_id = self.exprs.raw_parts_mut().0;
65
66        let (_, other_items) = other.exprs.raw_parts_mut();
67        for expr in other_items.iter_mut() {
68            remap_expr_kind(&mut expr.kind, offset, target_arena_id);
69        }
70        let other_items = std::mem::take(other_items);
71
72        self.exprs.raw_parts_mut().1.extend(other_items);
73
74        for stmt in &mut statements {
75            remap_stmt_kind(&mut stmt.kind, offset, target_arena_id);
76        }
77        statements
78    }
79}
80
81fn remap_id<T>(id: &mut Id<T>, offset: u32, target_arena_id: u32) {
82    *id = id.rebase(offset, target_arena_id);
83}
84
85fn remap_expr_kind(kind: &mut ExpressionKind, offset: u32, target_arena_id: u32) {
86    use ExpressionKind::*;
87    match kind {
88        Null
89        | Integer(_)
90        | Byte(_)
91        | String(_)
92        | Bool(_)
93        | Float(_)
94        | Character(_)
95        | Identifier(_)
96        | ResolvedIdentifier { .. } => {}
97
98        Binary { left, right, .. } => {
99            remap_id(left, offset, target_arena_id);
100            remap_id(right, offset, target_arena_id);
101        }
102        Unary { operand, .. } => remap_id(operand, offset, target_arena_id),
103        Grouping(id) | ErrorLiteral(id) | OkLiteral(id) | ErrLiteral(id) | Propagate(id) => {
104            remap_id(id, offset, target_arena_id)
105        }
106        ArrayLiteral(items) | TupleLiteral(items) => {
107            for id in items {
108                remap_id(id, offset, target_arena_id);
109            }
110        }
111        MapLiteral(entries) => {
112            for (k, v) in entries {
113                remap_id(k, offset, target_arena_id);
114                remap_id(v, offset, target_arena_id);
115            }
116        }
117        SetLiteral(items) => {
118            for id in items {
119                remap_id(id, offset, target_arena_id);
120            }
121        }
122        Assign { value, .. } | ResolvedAssign { value, .. } => {
123            remap_id(value, offset, target_arena_id)
124        }
125        Call { args, .. } => {
126            for id in args {
127                remap_id(id, offset, target_arena_id);
128            }
129        }
130        MethodCall { caller, args, .. } => {
131            remap_id(caller, offset, target_arena_id);
132            for id in args {
133                remap_id(id, offset, target_arena_id);
134            }
135        }
136        Index { target, index } => {
137            remap_id(target, offset, target_arena_id);
138            remap_id(index, offset, target_arena_id);
139        }
140        IndexAssign {
141            target,
142            index,
143            value,
144        } => {
145            remap_id(target, offset, target_arena_id);
146            remap_id(index, offset, target_arena_id);
147            remap_id(value, offset, target_arena_id);
148        }
149        CallExpr { callee, args } => {
150            remap_id(callee, offset, target_arena_id);
151            for id in args {
152                remap_id(id, offset, target_arena_id);
153            }
154        }
155        Cast { value, .. } => remap_id(value, offset, target_arena_id),
156        Lambda { body, .. } | ResolvedLambda { body, .. } => {
157            for stmt in body {
158                remap_stmt_kind(&mut stmt.kind, offset, target_arena_id);
159            }
160        }
161
162        StructLiteral { fields, .. } => {
163            for (_, id) in fields {
164                remap_id(id, offset, target_arena_id);
165            }
166        }
167        EnumVariant { .. } => {}
168        FieldAccess { target, .. } => remap_id(target, offset, target_arena_id),
169        FieldAssign { target, value, .. } => {
170            remap_id(target, offset, target_arena_id);
171            remap_id(value, offset, target_arena_id);
172        }
173    }
174}
175
176fn remap_stmt_kind(kind: &mut StatementKind, offset: u32, target_arena_id: u32) {
177    use StatementKind::*;
178    match kind {
179        Break
180        | Continue
181        | Range(_)
182        | Import { .. }
183        | ImportFile { .. }
184        | ImportFileNamed { .. }
185        | RecordDeclaration { .. }
186        | TagDeclaration { .. } => {}
187
188        VariableDeclaration { value, .. }
189        | ResolvedVariableDeclaration { value, .. }
190        | ConstantDeclaration { value, .. }
191        | ResolvedConstantDeclaration { value, .. }
192        | ResolvedArray { value, .. }
193        | ResolvedMap { value, .. }
194        | ResolvedConstantMap { value, .. }
195        | ResolvedConstantArray { value, .. }
196        | ResolvedSet { value, .. }
197        | ResolvedConstantSet { value, .. }
198        | Expression(value)
199        | ResolvedDestructureDeclaration { value, .. }
200        | DestructureDeclaration { value, .. } => remap_id(value, offset, target_arena_id),
201
202        Array { value, .. } | ConstantArray { value, .. } => {
203            for id in value {
204                remap_id(id, offset, target_arena_id);
205            }
206        }
207
208        Return(expr) => {
209            if let Some(id) = expr {
210                remap_id(id, offset, target_arena_id);
211            }
212        }
213
214        While { condition, body } => {
215            remap_id(condition, offset, target_arena_id);
216            remap_stmts(body, offset, target_arena_id);
217        }
218        For {
219            initializer,
220            condition,
221            increment,
222            body,
223        }
224        | ResolvedFor {
225            initializer,
226            condition,
227            increment,
228            body,
229        } => {
230            remap_stmt_kind(&mut initializer.kind, offset, target_arena_id);
231            remap_id(condition, offset, target_arena_id);
232            remap_id(increment, offset, target_arena_id);
233            remap_stmts(body, offset, target_arena_id);
234        }
235        ForRange { range, body, .. } | ResolvedForRange { range, body, .. } => {
236            remap_stmt_kind(&mut range.kind, offset, target_arena_id);
237            remap_stmts(body, offset, target_arena_id);
238        }
239        ForEach { iterable, body, .. } | ResolvedForEach { iterable, body, .. } => {
240            remap_id(iterable, offset, target_arena_id);
241            remap_stmts(body, offset, target_arena_id);
242        }
243
244        ConditionalBranch {
245            condition, body, ..
246        } => {
247            if let Some(id) = condition {
248                remap_id(id, offset, target_arena_id);
249            }
250            remap_stmts(body, offset, target_arena_id);
251        }
252        Conditional {
253            if_branch,
254            else_branch,
255        } => {
256            remap_stmt_kind(&mut if_branch.kind, offset, target_arena_id);
257            if let Some(branch) = else_branch {
258                remap_stmt_kind(&mut branch.kind, offset, target_arena_id);
259            }
260        }
261
262        FunctionDeclaration { body, .. }
263        | ResolvedFunctionDeclaration { body, .. }
264        | ResolvedImportFile { body, .. } => {
265            remap_stmts(body, offset, target_arena_id);
266        }
267
268        Match { value, arms } => {
269            remap_id(value, offset, target_arena_id);
270            for (pattern, body) in arms {
271                if let crate::ast::statements::MatchPattern::Literal(id) = pattern {
272                    remap_id(id, offset, target_arena_id);
273                }
274                remap_stmts(body, offset, target_arena_id);
275            }
276        }
277
278        Map { entries, .. } | ConstantMap { entries, .. } => {
279            for (k, v) in entries {
280                remap_id(k, offset, target_arena_id);
281                remap_id(v, offset, target_arena_id);
282            }
283        }
284
285        Set { items, .. } | ConstantSet { items, .. } => {
286            for id in items {
287                remap_id(id, offset, target_arena_id);
288            }
289        }
290    }
291}
292
293fn remap_stmts(body: &mut [Statement], offset: u32, target_arena_id: u32) {
294    for stmt in body {
295        remap_stmt_kind(&mut stmt.kind, offset, target_arena_id);
296    }
297}