1use 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;
23pub type ScopeMap = Vec<Vec<String>>;
25
26pub struct Ast {
30 pub exprs: Arena<Expression>,
31}
32
33pub 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 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}