/Users/alexjokela/projects/lattice/src/ast.c
Line | Count | Source |
1 | | #include "ast.h" |
2 | | #include <stdlib.h> |
3 | | #include <string.h> |
4 | | #include <stdio.h> |
5 | | |
6 | | /* ── Expression constructors ── */ |
7 | | |
8 | 162k | static Expr *expr_alloc(ExprTag tag) { |
9 | 162k | Expr *e = calloc(1, sizeof(Expr)); |
10 | 162k | e->tag = tag; |
11 | 162k | return e; |
12 | 162k | } |
13 | | |
14 | 10.2k | Expr *expr_int_lit(int64_t val) { |
15 | 10.2k | Expr *e = expr_alloc(EXPR_INT_LIT); |
16 | 10.2k | e->as.int_val = val; |
17 | 10.2k | return e; |
18 | 10.2k | } |
19 | | |
20 | 324 | Expr *expr_float_lit(double val) { |
21 | 324 | Expr *e = expr_alloc(EXPR_FLOAT_LIT); |
22 | 324 | e->as.float_val = val; |
23 | 324 | return e; |
24 | 324 | } |
25 | | |
26 | 17.8k | Expr *expr_string_lit(char *val) { |
27 | 17.8k | Expr *e = expr_alloc(EXPR_STRING_LIT); |
28 | 17.8k | e->as.str_val = val; |
29 | 17.8k | return e; |
30 | 17.8k | } |
31 | | |
32 | 2.36k | Expr *expr_bool_lit(bool val) { |
33 | 2.36k | Expr *e = expr_alloc(EXPR_BOOL_LIT); |
34 | 2.36k | e->as.bool_val = val; |
35 | 2.36k | return e; |
36 | 2.36k | } |
37 | | |
38 | 1.01k | Expr *expr_nil_lit(void) { |
39 | 1.01k | return expr_alloc(EXPR_NIL_LIT); |
40 | 1.01k | } |
41 | | |
42 | 66.6k | Expr *expr_ident(char *name) { |
43 | 66.6k | Expr *e = expr_alloc(EXPR_IDENT); |
44 | 66.6k | e->as.str_val = name; |
45 | 66.6k | return e; |
46 | 66.6k | } |
47 | | |
48 | 9.68k | Expr *expr_binop(BinOpKind op, Expr *left, Expr *right) { |
49 | 9.68k | Expr *e = expr_alloc(EXPR_BINOP); |
50 | 9.68k | e->as.binop.op = op; |
51 | 9.68k | e->as.binop.left = left; |
52 | 9.68k | e->as.binop.right = right; |
53 | 9.68k | return e; |
54 | 9.68k | } |
55 | | |
56 | 618 | Expr *expr_unaryop(UnaryOpKind op, Expr *operand) { |
57 | 618 | Expr *e = expr_alloc(EXPR_UNARYOP); |
58 | 618 | e->as.unaryop.op = op; |
59 | 618 | e->as.unaryop.operand = operand; |
60 | 618 | return e; |
61 | 618 | } |
62 | | |
63 | 16.0k | Expr *expr_call(Expr *func, Expr **args, size_t arg_count) { |
64 | 16.0k | Expr *e = expr_alloc(EXPR_CALL); |
65 | 16.0k | e->as.call.func = func; |
66 | 16.0k | e->as.call.args = args; |
67 | 16.0k | e->as.call.arg_count = arg_count; |
68 | 16.0k | return e; |
69 | 16.0k | } |
70 | | |
71 | 15.6k | Expr *expr_method_call(Expr *object, char *method, Expr **args, size_t arg_count) { |
72 | 15.6k | Expr *e = expr_alloc(EXPR_METHOD_CALL); |
73 | 15.6k | e->as.method_call.object = object; |
74 | 15.6k | e->as.method_call.method = method; |
75 | 15.6k | e->as.method_call.args = args; |
76 | 15.6k | e->as.method_call.arg_count = arg_count; |
77 | 15.6k | return e; |
78 | 15.6k | } |
79 | | |
80 | 270 | Expr *expr_field_access(Expr *object, char *field) { |
81 | 270 | Expr *e = expr_alloc(EXPR_FIELD_ACCESS); |
82 | 270 | e->as.field_access.object = object; |
83 | 270 | e->as.field_access.field = field; |
84 | 270 | return e; |
85 | 270 | } |
86 | | |
87 | 3.04k | Expr *expr_index(Expr *object, Expr *index) { |
88 | 3.04k | Expr *e = expr_alloc(EXPR_INDEX); |
89 | 3.04k | e->as.index.object = object; |
90 | 3.04k | e->as.index.index = index; |
91 | 3.04k | return e; |
92 | 3.04k | } |
93 | | |
94 | 1.90k | Expr *expr_array(Expr **elems, size_t count) { |
95 | 1.90k | Expr *e = expr_alloc(EXPR_ARRAY); |
96 | 1.90k | e->as.array.elems = elems; |
97 | 1.90k | e->as.array.count = count; |
98 | 1.90k | return e; |
99 | 1.90k | } |
100 | | |
101 | 138 | Expr *expr_struct_lit(char *name, FieldInit *fields, size_t field_count) { |
102 | 138 | Expr *e = expr_alloc(EXPR_STRUCT_LIT); |
103 | 138 | e->as.struct_lit.name = name; |
104 | 138 | e->as.struct_lit.fields = fields; |
105 | 138 | e->as.struct_lit.field_count = field_count; |
106 | 138 | return e; |
107 | 138 | } |
108 | | |
109 | 255 | Expr *expr_freeze(Expr *inner, Expr *contract) { |
110 | 255 | Expr *e = expr_alloc(EXPR_FREEZE); |
111 | 255 | e->as.freeze.expr = inner; |
112 | 255 | e->as.freeze.contract = contract; |
113 | 255 | e->as.freeze.except_fields = NULL; |
114 | 255 | e->as.freeze.except_count = 0; |
115 | 255 | return e; |
116 | 255 | } |
117 | | |
118 | 9 | Expr *expr_freeze_except(Expr *inner, Expr *contract, Expr **except_fields, size_t except_count) { |
119 | 9 | Expr *e = expr_alloc(EXPR_FREEZE); |
120 | 9 | e->as.freeze.expr = inner; |
121 | 9 | e->as.freeze.contract = contract; |
122 | 9 | e->as.freeze.except_fields = except_fields; |
123 | 9 | e->as.freeze.except_count = except_count; |
124 | 9 | return e; |
125 | 9 | } |
126 | | |
127 | 57 | Expr *expr_thaw(Expr *inner) { |
128 | 57 | Expr *e = expr_alloc(EXPR_THAW); |
129 | 57 | e->as.freeze_expr = inner; |
130 | 57 | return e; |
131 | 57 | } |
132 | | |
133 | 9 | Expr *expr_clone(Expr *inner) { |
134 | 9 | Expr *e = expr_alloc(EXPR_CLONE); |
135 | 9 | e->as.freeze_expr = inner; |
136 | 9 | return e; |
137 | 9 | } |
138 | | |
139 | 21 | Expr *expr_anneal(Expr *target, Expr *closure) { |
140 | 21 | Expr *e = expr_alloc(EXPR_ANNEAL); |
141 | 21 | e->as.anneal.expr = target; |
142 | 21 | e->as.anneal.closure = closure; |
143 | 21 | return e; |
144 | 21 | } |
145 | | |
146 | 12 | Expr *expr_crystallize(Expr *expr, Stmt **body, size_t body_count) { |
147 | 12 | Expr *e = expr_alloc(EXPR_CRYSTALLIZE); |
148 | 12 | e->as.crystallize.expr = expr; |
149 | 12 | e->as.crystallize.body = body; |
150 | 12 | e->as.crystallize.body_count = body_count; |
151 | 12 | return e; |
152 | 12 | } |
153 | | |
154 | 15 | Expr *expr_sublimate(Expr *inner) { |
155 | 15 | Expr *e = expr_alloc(EXPR_SUBLIMATE); |
156 | 15 | e->as.freeze_expr = inner; |
157 | 15 | return e; |
158 | 15 | } |
159 | | |
160 | 27 | Expr *expr_spread(Expr *inner) { |
161 | 27 | Expr *e = expr_alloc(EXPR_SPREAD); |
162 | 27 | e->as.spread_expr = inner; |
163 | 27 | return e; |
164 | 27 | } |
165 | | |
166 | 18 | Expr *expr_try_propagate(Expr *inner) { |
167 | 18 | Expr *e = expr_alloc(EXPR_TRY_PROPAGATE); |
168 | 18 | e->as.try_propagate_expr = inner; |
169 | 18 | return e; |
170 | 18 | } |
171 | | |
172 | 15 | Expr *expr_select(SelectArm *arms, size_t arm_count) { |
173 | 15 | Expr *e = expr_alloc(EXPR_SELECT); |
174 | 15 | e->as.select_expr.arms = arms; |
175 | 15 | e->as.select_expr.arm_count = arm_count; |
176 | 15 | return e; |
177 | 15 | } |
178 | | |
179 | 33 | Expr *expr_tuple(Expr **elems, size_t count) { |
180 | 33 | Expr *e = expr_alloc(EXPR_TUPLE); |
181 | 33 | e->as.tuple.elems = elems; |
182 | 33 | e->as.tuple.count = count; |
183 | 33 | return e; |
184 | 33 | } |
185 | | |
186 | 3 | Expr *expr_forge(Stmt **stmts, size_t count) { |
187 | 3 | Expr *e = expr_alloc(EXPR_FORGE); |
188 | 3 | e->as.block.stmts = stmts; |
189 | 3 | e->as.block.count = count; |
190 | 3 | return e; |
191 | 3 | } |
192 | | |
193 | 7.27k | Expr *expr_if(Expr *cond, Stmt **then_s, size_t then_n, Stmt **else_s, size_t else_n) { |
194 | 7.27k | Expr *e = expr_alloc(EXPR_IF); |
195 | 7.27k | e->as.if_expr.cond = cond; |
196 | 7.27k | e->as.if_expr.then_stmts = then_s; |
197 | 7.27k | e->as.if_expr.then_count = then_n; |
198 | 7.27k | e->as.if_expr.else_stmts = else_s; |
199 | 7.27k | e->as.if_expr.else_count = else_n; |
200 | 7.27k | return e; |
201 | 7.27k | } |
202 | | |
203 | 1.85k | Expr *expr_block(Stmt **stmts, size_t count) { |
204 | 1.85k | Expr *e = expr_alloc(EXPR_BLOCK); |
205 | 1.85k | e->as.block.stmts = stmts; |
206 | 1.85k | e->as.block.count = count; |
207 | 1.85k | return e; |
208 | 1.85k | } |
209 | | |
210 | | Expr *expr_closure(char **params, size_t param_count, Expr *body, |
211 | 1.92k | Expr **default_values, bool has_variadic) { |
212 | 1.92k | Expr *e = expr_alloc(EXPR_CLOSURE); |
213 | 1.92k | e->as.closure.params = params; |
214 | 1.92k | e->as.closure.param_count = param_count; |
215 | 1.92k | e->as.closure.body = body; |
216 | 1.92k | e->as.closure.default_values = default_values; |
217 | 1.92k | e->as.closure.has_variadic = has_variadic; |
218 | 1.92k | return e; |
219 | 1.92k | } |
220 | | |
221 | 42 | Expr *expr_range(Expr *start, Expr *end) { |
222 | 42 | Expr *e = expr_alloc(EXPR_RANGE); |
223 | 42 | e->as.range.start = start; |
224 | 42 | e->as.range.end = end; |
225 | 42 | return e; |
226 | 42 | } |
227 | | |
228 | 3.27k | Expr *expr_print(Expr **args, size_t arg_count) { |
229 | 3.27k | Expr *e = expr_alloc(EXPR_PRINT); |
230 | 3.27k | e->as.print.args = args; |
231 | 3.27k | e->as.print.arg_count = arg_count; |
232 | 3.27k | return e; |
233 | 3.27k | } |
234 | | |
235 | 12 | Expr *expr_spawn(Stmt **stmts, size_t count) { |
236 | 12 | Expr *e = expr_alloc(EXPR_SPAWN); |
237 | 12 | e->as.block.stmts = stmts; |
238 | 12 | e->as.block.count = count; |
239 | 12 | return e; |
240 | 12 | } |
241 | | |
242 | 9 | Expr *expr_scope(Stmt **stmts, size_t count) { |
243 | 9 | Expr *e = expr_alloc(EXPR_SCOPE); |
244 | 9 | e->as.block.stmts = stmts; |
245 | 9 | e->as.block.count = count; |
246 | 9 | return e; |
247 | 9 | } |
248 | | |
249 | | Expr *expr_try_catch(Stmt **try_stmts, size_t try_count, char *catch_var, |
250 | 315 | Stmt **catch_stmts, size_t catch_count) { |
251 | 315 | Expr *e = expr_alloc(EXPR_TRY_CATCH); |
252 | 315 | e->as.try_catch.try_stmts = try_stmts; |
253 | 315 | e->as.try_catch.try_count = try_count; |
254 | 315 | e->as.try_catch.catch_var = catch_var; |
255 | 315 | e->as.try_catch.catch_stmts = catch_stmts; |
256 | 315 | e->as.try_catch.catch_count = catch_count; |
257 | 315 | return e; |
258 | 315 | } |
259 | | |
260 | 48 | Expr *expr_interp_string(char **parts, Expr **exprs, size_t count) { |
261 | 48 | Expr *e = expr_alloc(EXPR_INTERP_STRING); |
262 | 48 | e->as.interp.parts = parts; |
263 | 48 | e->as.interp.exprs = exprs; |
264 | 48 | e->as.interp.count = count; |
265 | 48 | return e; |
266 | 48 | } |
267 | | |
268 | 45 | Expr *expr_match(Expr *scrutinee, MatchArm *arms, size_t arm_count) { |
269 | 45 | Expr *e = expr_alloc(EXPR_MATCH); |
270 | 45 | e->as.match_expr.scrutinee = scrutinee; |
271 | 45 | e->as.match_expr.arms = arms; |
272 | 45 | e->as.match_expr.arm_count = arm_count; |
273 | 45 | return e; |
274 | 45 | } |
275 | | |
276 | 1.64k | Expr *expr_enum_variant(char *enum_name, char *variant_name, Expr **args, size_t arg_count) { |
277 | 1.64k | Expr *e = expr_alloc(EXPR_ENUM_VARIANT); |
278 | 1.64k | e->as.enum_variant.enum_name = enum_name; |
279 | 1.64k | e->as.enum_variant.variant_name = variant_name; |
280 | 1.64k | e->as.enum_variant.args = args; |
281 | 1.64k | e->as.enum_variant.arg_count = arg_count; |
282 | 1.64k | return e; |
283 | 1.64k | } |
284 | | |
285 | 27 | Pattern *pattern_literal(Expr *lit) { |
286 | 27 | Pattern *p = calloc(1, sizeof(Pattern)); |
287 | 27 | p->tag = PAT_LITERAL; |
288 | 27 | p->phase_qualifier = PHASE_UNSPECIFIED; |
289 | 27 | p->as.literal = lit; |
290 | 27 | return p; |
291 | 27 | } |
292 | | |
293 | 54 | Pattern *pattern_wildcard(void) { |
294 | 54 | Pattern *p = calloc(1, sizeof(Pattern)); |
295 | 54 | p->tag = PAT_WILDCARD; |
296 | 54 | p->phase_qualifier = PHASE_UNSPECIFIED; |
297 | 54 | return p; |
298 | 54 | } |
299 | | |
300 | 15 | Pattern *pattern_binding(char *name) { |
301 | 15 | Pattern *p = calloc(1, sizeof(Pattern)); |
302 | 15 | p->tag = PAT_BINDING; |
303 | 15 | p->phase_qualifier = PHASE_UNSPECIFIED; |
304 | 15 | p->as.binding_name = name; |
305 | 15 | return p; |
306 | 15 | } |
307 | | |
308 | 6 | Pattern *pattern_range(Expr *start, Expr *end) { |
309 | 6 | Pattern *p = calloc(1, sizeof(Pattern)); |
310 | 6 | p->tag = PAT_RANGE; |
311 | 6 | p->phase_qualifier = PHASE_UNSPECIFIED; |
312 | 6 | p->as.range.start = start; |
313 | 6 | p->as.range.end = end; |
314 | 6 | return p; |
315 | 6 | } |
316 | | |
317 | 102 | void pattern_free(Pattern *p) { |
318 | 102 | if (!p) return; |
319 | 102 | switch (p->tag) { |
320 | 27 | case PAT_LITERAL: |
321 | 27 | expr_free(p->as.literal); |
322 | 27 | break; |
323 | 54 | case PAT_WILDCARD: |
324 | 54 | break; |
325 | 15 | case PAT_BINDING: |
326 | 15 | free(p->as.binding_name); |
327 | 15 | break; |
328 | 6 | case PAT_RANGE: |
329 | 6 | expr_free(p->as.range.start); |
330 | 6 | expr_free(p->as.range.end); |
331 | 6 | break; |
332 | 102 | } |
333 | 102 | free(p); |
334 | 102 | } |
335 | | |
336 | | /* ── Clone (for lvalue AST expressions in desugaring) ── */ |
337 | | |
338 | 90 | Expr *expr_clone_ast(const Expr *e) { |
339 | 90 | if (!e) return NULL; |
340 | 90 | switch (e->tag) { |
341 | 81 | case EXPR_IDENT: |
342 | 81 | return expr_ident(strdup(e->as.str_val)); |
343 | 3 | case EXPR_FIELD_ACCESS: { |
344 | 3 | Expr *obj = expr_clone_ast(e->as.field_access.object); |
345 | 3 | return expr_field_access(obj, strdup(e->as.field_access.field)); |
346 | 0 | } |
347 | 3 | case EXPR_INDEX: { |
348 | 3 | Expr *obj = expr_clone_ast(e->as.index.object); |
349 | 3 | Expr *idx = expr_clone_ast(e->as.index.index); |
350 | 3 | return expr_index(obj, idx); |
351 | 0 | } |
352 | 3 | case EXPR_INT_LIT: |
353 | 3 | return expr_int_lit(e->as.int_val); |
354 | 0 | default: |
355 | 0 | return NULL; |
356 | 90 | } |
357 | 90 | } |
358 | | |
359 | | /* ── Statement constructors ── */ |
360 | | |
361 | 45.9k | static Stmt *stmt_alloc(StmtTag tag) { |
362 | 45.9k | Stmt *s = calloc(1, sizeof(Stmt)); |
363 | 45.9k | s->tag = tag; |
364 | 45.9k | return s; |
365 | 45.9k | } |
366 | | |
367 | 13.3k | Stmt *stmt_binding(AstPhase phase, char *name, TypeExpr *ty, Expr *value) { |
368 | 13.3k | Stmt *s = stmt_alloc(STMT_BINDING); |
369 | 13.3k | s->as.binding.phase = phase; |
370 | 13.3k | s->as.binding.name = name; |
371 | 13.3k | s->as.binding.ty = ty; |
372 | 13.3k | s->as.binding.value = value; |
373 | 13.3k | return s; |
374 | 13.3k | } |
375 | | |
376 | 2.76k | Stmt *stmt_assign(Expr *target, Expr *value) { |
377 | 2.76k | Stmt *s = stmt_alloc(STMT_ASSIGN); |
378 | 2.76k | s->as.assign.target = target; |
379 | 2.76k | s->as.assign.value = value; |
380 | 2.76k | return s; |
381 | 2.76k | } |
382 | | |
383 | 18.3k | Stmt *stmt_expr(Expr *expr) { |
384 | 18.3k | Stmt *s = stmt_alloc(STMT_EXPR); |
385 | 18.3k | s->as.expr = expr; |
386 | 18.3k | return s; |
387 | 18.3k | } |
388 | | |
389 | 9.08k | Stmt *stmt_return(Expr *expr) { |
390 | 9.08k | Stmt *s = stmt_alloc(STMT_RETURN); |
391 | 9.08k | s->as.return_expr = expr; |
392 | 9.08k | return s; |
393 | 9.08k | } |
394 | | |
395 | 858 | Stmt *stmt_for(char *var, Expr *iter, Stmt **body, size_t count) { |
396 | 858 | Stmt *s = stmt_alloc(STMT_FOR); |
397 | 858 | s->as.for_loop.var = var; |
398 | 858 | s->as.for_loop.iter = iter; |
399 | 858 | s->as.for_loop.body = body; |
400 | 858 | s->as.for_loop.body_count = count; |
401 | 858 | return s; |
402 | 858 | } |
403 | | |
404 | 366 | Stmt *stmt_while(Expr *cond, Stmt **body, size_t count) { |
405 | 366 | Stmt *s = stmt_alloc(STMT_WHILE); |
406 | 366 | s->as.while_loop.cond = cond; |
407 | 366 | s->as.while_loop.body = body; |
408 | 366 | s->as.while_loop.body_count = count; |
409 | 366 | return s; |
410 | 366 | } |
411 | | |
412 | 348 | Stmt *stmt_loop(Stmt **body, size_t count) { |
413 | 348 | Stmt *s = stmt_alloc(STMT_LOOP); |
414 | 348 | s->as.loop.body = body; |
415 | 348 | s->as.loop.body_count = count; |
416 | 348 | return s; |
417 | 348 | } |
418 | | |
419 | 294 | Stmt *stmt_break(void) { return stmt_alloc(STMT_BREAK); } |
420 | 123 | Stmt *stmt_continue(void) { return stmt_alloc(STMT_CONTINUE); } |
421 | | |
422 | | Stmt *stmt_destructure(AstPhase phase, DestructKind kind, char **names, size_t name_count, |
423 | 24 | char *rest_name, Expr *value) { |
424 | 24 | Stmt *s = stmt_alloc(STMT_DESTRUCTURE); |
425 | 24 | s->as.destructure.phase = phase; |
426 | 24 | s->as.destructure.kind = kind; |
427 | 24 | s->as.destructure.names = names; |
428 | 24 | s->as.destructure.name_count = name_count; |
429 | 24 | s->as.destructure.rest_name = rest_name; |
430 | 24 | s->as.destructure.value = value; |
431 | 24 | return s; |
432 | 24 | } |
433 | | |
434 | 282 | Stmt *stmt_import(char *path, char *alias, char **selective, size_t count) { |
435 | 282 | Stmt *s = stmt_alloc(STMT_IMPORT); |
436 | 282 | s->as.import.module_path = path; |
437 | 282 | s->as.import.alias = alias; |
438 | 282 | s->as.import.selective_names = selective; |
439 | 282 | s->as.import.selective_count = count; |
440 | 282 | return s; |
441 | 282 | } |
442 | | |
443 | 18 | Stmt *stmt_defer(Stmt **body, size_t count) { |
444 | 18 | Stmt *s = stmt_alloc(STMT_DEFER); |
445 | 18 | s->as.defer.body = body; |
446 | 18 | s->as.defer.body_count = count; |
447 | 18 | return s; |
448 | 18 | } |
449 | | |
450 | | /* ── Destructors ── */ |
451 | | |
452 | 9.21k | void type_expr_free(TypeExpr *t) { |
453 | 9.21k | if (!t) return; |
454 | 9.21k | free(t->name); |
455 | 9.21k | if (t->inner) { |
456 | 6 | type_expr_free(t->inner); |
457 | 6 | free(t->inner); |
458 | 6 | } |
459 | 9.21k | } |
460 | | |
461 | 118k | void expr_free(Expr *e) { |
462 | 118k | if (!e) return; |
463 | 118k | switch (e->tag) { |
464 | 8.34k | case EXPR_INT_LIT: |
465 | 8.64k | case EXPR_FLOAT_LIT: |
466 | 10.2k | case EXPR_BOOL_LIT: |
467 | 10.9k | case EXPR_NIL_LIT: |
468 | 10.9k | break; |
469 | 13.0k | case EXPR_STRING_LIT: |
470 | 60.2k | case EXPR_IDENT: |
471 | 60.2k | free(e->as.str_val); |
472 | 60.2k | break; |
473 | 6.87k | case EXPR_BINOP: |
474 | 6.87k | expr_free(e->as.binop.left); |
475 | 6.87k | expr_free(e->as.binop.right); |
476 | 6.87k | break; |
477 | 436 | case EXPR_UNARYOP: |
478 | 436 | expr_free(e->as.unaryop.operand); |
479 | 436 | break; |
480 | 11.6k | case EXPR_CALL: |
481 | 11.6k | expr_free(e->as.call.func); |
482 | 27.2k | for (size_t i = 0; i < e->as.call.arg_count; i++) |
483 | 15.5k | expr_free(e->as.call.args[i]); |
484 | 11.6k | free(e->as.call.args); |
485 | 11.6k | break; |
486 | 11.1k | case EXPR_METHOD_CALL: |
487 | 11.1k | expr_free(e->as.method_call.object); |
488 | 11.1k | free(e->as.method_call.method); |
489 | 23.9k | for (size_t i = 0; i < e->as.method_call.arg_count; i++) |
490 | 12.8k | expr_free(e->as.method_call.args[i]); |
491 | 11.1k | free(e->as.method_call.args); |
492 | 11.1k | break; |
493 | 270 | case EXPR_FIELD_ACCESS: |
494 | 270 | expr_free(e->as.field_access.object); |
495 | 270 | free(e->as.field_access.field); |
496 | 270 | break; |
497 | 2.22k | case EXPR_INDEX: |
498 | 2.22k | expr_free(e->as.index.object); |
499 | 2.22k | expr_free(e->as.index.index); |
500 | 2.22k | break; |
501 | 1.45k | case EXPR_ARRAY: |
502 | 4.18k | for (size_t i = 0; i < e->as.array.count; i++) |
503 | 2.73k | expr_free(e->as.array.elems[i]); |
504 | 1.45k | free(e->as.array.elems); |
505 | 1.45k | break; |
506 | 136 | case EXPR_STRUCT_LIT: |
507 | 136 | free(e->as.struct_lit.name); |
508 | 396 | for (size_t i = 0; i < e->as.struct_lit.field_count; i++) { |
509 | 260 | free(e->as.struct_lit.fields[i].name); |
510 | 260 | expr_free(e->as.struct_lit.fields[i].value); |
511 | 260 | } |
512 | 136 | free(e->as.struct_lit.fields); |
513 | 136 | break; |
514 | 264 | case EXPR_FREEZE: |
515 | 264 | expr_free(e->as.freeze.expr); |
516 | 264 | if (e->as.freeze.contract) expr_free(e->as.freeze.contract); |
517 | 273 | for (size_t i = 0; i < e->as.freeze.except_count; i++) |
518 | 9 | expr_free(e->as.freeze.except_fields[i]); |
519 | 264 | free(e->as.freeze.except_fields); |
520 | 264 | break; |
521 | 57 | case EXPR_THAW: |
522 | 66 | case EXPR_CLONE: |
523 | 81 | case EXPR_SUBLIMATE: |
524 | 81 | expr_free(e->as.freeze_expr); |
525 | 81 | break; |
526 | 12 | case EXPR_CRYSTALLIZE: |
527 | 12 | expr_free(e->as.crystallize.expr); |
528 | 30 | for (size_t i = 0; i < e->as.crystallize.body_count; i++) |
529 | 18 | stmt_free(e->as.crystallize.body[i]); |
530 | 12 | free(e->as.crystallize.body); |
531 | 12 | break; |
532 | 21 | case EXPR_ANNEAL: |
533 | 21 | expr_free(e->as.anneal.expr); |
534 | 21 | expr_free(e->as.anneal.closure); |
535 | 21 | break; |
536 | 3 | case EXPR_FORGE: |
537 | 1.33k | case EXPR_BLOCK: |
538 | 1.35k | case EXPR_SPAWN: |
539 | 1.35k | case EXPR_SCOPE: |
540 | 4.52k | for (size_t i = 0; i < e->as.block.count; i++) |
541 | 3.16k | stmt_free(e->as.block.stmts[i]); |
542 | 1.35k | free(e->as.block.stmts); |
543 | 1.35k | break; |
544 | 4.89k | case EXPR_IF: |
545 | 4.89k | expr_free(e->as.if_expr.cond); |
546 | 12.0k | for (size_t i = 0; i < e->as.if_expr.then_count; i++) |
547 | 7.19k | stmt_free(e->as.if_expr.then_stmts[i]); |
548 | 4.89k | free(e->as.if_expr.then_stmts); |
549 | 6.01k | for (size_t i = 0; i < e->as.if_expr.else_count; i++) |
550 | 1.12k | stmt_free(e->as.if_expr.else_stmts[i]); |
551 | 4.89k | free(e->as.if_expr.else_stmts); |
552 | 4.89k | break; |
553 | 1.40k | case EXPR_CLOSURE: |
554 | 2.96k | for (size_t i = 0; i < e->as.closure.param_count; i++) |
555 | 1.56k | free(e->as.closure.params[i]); |
556 | 1.40k | free(e->as.closure.params); |
557 | 1.40k | if (e->as.closure.default_values) { |
558 | 423 | for (size_t i = 0; i < e->as.closure.param_count; i++) |
559 | 222 | if (e->as.closure.default_values[i]) |
560 | 21 | expr_free(e->as.closure.default_values[i]); |
561 | 201 | free(e->as.closure.default_values); |
562 | 201 | } |
563 | 1.40k | expr_free(e->as.closure.body); |
564 | 1.40k | break; |
565 | 42 | case EXPR_RANGE: |
566 | 42 | expr_free(e->as.range.start); |
567 | 42 | expr_free(e->as.range.end); |
568 | 42 | break; |
569 | 3.19k | case EXPR_PRINT: |
570 | 6.38k | for (size_t i = 0; i < e->as.print.arg_count; i++) |
571 | 3.19k | expr_free(e->as.print.args[i]); |
572 | 3.19k | free(e->as.print.args); |
573 | 3.19k | break; |
574 | 231 | case EXPR_TRY_CATCH: |
575 | 529 | for (size_t i = 0; i < e->as.try_catch.try_count; i++) |
576 | 298 | stmt_free(e->as.try_catch.try_stmts[i]); |
577 | 231 | free(e->as.try_catch.try_stmts); |
578 | 231 | free(e->as.try_catch.catch_var); |
579 | 462 | for (size_t i = 0; i < e->as.try_catch.catch_count; i++) |
580 | 231 | stmt_free(e->as.try_catch.catch_stmts[i]); |
581 | 231 | free(e->as.try_catch.catch_stmts); |
582 | 231 | break; |
583 | 48 | case EXPR_INTERP_STRING: |
584 | 174 | for (size_t i = 0; i <= e->as.interp.count; i++) |
585 | 126 | free(e->as.interp.parts[i]); |
586 | 48 | free(e->as.interp.parts); |
587 | 126 | for (size_t i = 0; i < e->as.interp.count; i++) |
588 | 78 | expr_free(e->as.interp.exprs[i]); |
589 | 48 | free(e->as.interp.exprs); |
590 | 48 | break; |
591 | 45 | case EXPR_MATCH: |
592 | 45 | expr_free(e->as.match_expr.scrutinee); |
593 | 147 | for (size_t i = 0; i < e->as.match_expr.arm_count; i++) { |
594 | 102 | MatchArm *arm = &e->as.match_expr.arms[i]; |
595 | 102 | pattern_free(arm->pattern); |
596 | 102 | if (arm->guard) expr_free(arm->guard); |
597 | 207 | for (size_t j = 0; j < arm->body_count; j++) |
598 | 105 | stmt_free(arm->body[j]); |
599 | 102 | free(arm->body); |
600 | 102 | } |
601 | 45 | free(e->as.match_expr.arms); |
602 | 45 | break; |
603 | 1.24k | case EXPR_ENUM_VARIANT: |
604 | 1.24k | free(e->as.enum_variant.enum_name); |
605 | 1.24k | free(e->as.enum_variant.variant_name); |
606 | 1.39k | for (size_t i = 0; i < e->as.enum_variant.arg_count; i++) |
607 | 153 | expr_free(e->as.enum_variant.args[i]); |
608 | 1.24k | free(e->as.enum_variant.args); |
609 | 1.24k | break; |
610 | 27 | case EXPR_SPREAD: |
611 | 27 | expr_free(e->as.spread_expr); |
612 | 27 | break; |
613 | 33 | case EXPR_TUPLE: |
614 | 126 | for (size_t i = 0; i < e->as.tuple.count; i++) |
615 | 93 | expr_free(e->as.tuple.elems[i]); |
616 | 33 | free(e->as.tuple.elems); |
617 | 33 | break; |
618 | 18 | case EXPR_TRY_PROPAGATE: |
619 | 18 | expr_free(e->as.try_propagate_expr); |
620 | 18 | break; |
621 | 15 | case EXPR_SELECT: |
622 | 42 | for (size_t i = 0; i < e->as.select_expr.arm_count; i++) { |
623 | 27 | SelectArm *arm = &e->as.select_expr.arms[i]; |
624 | 27 | free(arm->binding_name); |
625 | 27 | if (arm->channel_expr) expr_free(arm->channel_expr); |
626 | 27 | if (arm->timeout_expr) expr_free(arm->timeout_expr); |
627 | 54 | for (size_t j = 0; j < arm->body_count; j++) |
628 | 27 | stmt_free(arm->body[j]); |
629 | 27 | free(arm->body); |
630 | 27 | } |
631 | 15 | free(e->as.select_expr.arms); |
632 | 15 | break; |
633 | 118k | } |
634 | 118k | free(e); |
635 | 118k | } |
636 | | |
637 | 33.5k | void stmt_free(Stmt *s) { |
638 | 33.5k | if (!s) return; |
639 | 33.5k | switch (s->tag) { |
640 | 9.80k | case STMT_BINDING: |
641 | 9.80k | free(s->as.binding.name); |
642 | 9.80k | if (s->as.binding.ty) { |
643 | 0 | type_expr_free(s->as.binding.ty); |
644 | 0 | free(s->as.binding.ty); |
645 | 0 | } |
646 | 9.80k | expr_free(s->as.binding.value); |
647 | 9.80k | break; |
648 | 1.94k | case STMT_ASSIGN: |
649 | 1.94k | expr_free(s->as.assign.target); |
650 | 1.94k | expr_free(s->as.assign.value); |
651 | 1.94k | break; |
652 | 13.9k | case STMT_EXPR: |
653 | 13.9k | expr_free(s->as.expr); |
654 | 13.9k | break; |
655 | 6.11k | case STMT_RETURN: |
656 | 6.11k | expr_free(s->as.return_expr); |
657 | 6.11k | break; |
658 | 591 | case STMT_FOR: |
659 | 591 | free(s->as.for_loop.var); |
660 | 591 | expr_free(s->as.for_loop.iter); |
661 | 1.91k | for (size_t i = 0; i < s->as.for_loop.body_count; i++) |
662 | 1.32k | stmt_free(s->as.for_loop.body[i]); |
663 | 591 | free(s->as.for_loop.body); |
664 | 591 | break; |
665 | 248 | case STMT_WHILE: |
666 | 248 | expr_free(s->as.while_loop.cond); |
667 | 1.05k | for (size_t i = 0; i < s->as.while_loop.body_count; i++) |
668 | 809 | stmt_free(s->as.while_loop.body[i]); |
669 | 248 | free(s->as.while_loop.body); |
670 | 248 | break; |
671 | 232 | case STMT_LOOP: |
672 | 1.16k | for (size_t i = 0; i < s->as.loop.body_count; i++) |
673 | 928 | stmt_free(s->as.loop.body[i]); |
674 | 232 | free(s->as.loop.body); |
675 | 232 | break; |
676 | 197 | case STMT_BREAK: |
677 | 280 | case STMT_CONTINUE: |
678 | 280 | break; |
679 | 24 | case STMT_DESTRUCTURE: |
680 | 72 | for (size_t i = 0; i < s->as.destructure.name_count; i++) |
681 | 48 | free(s->as.destructure.names[i]); |
682 | 24 | free(s->as.destructure.names); |
683 | 24 | free(s->as.destructure.rest_name); |
684 | 24 | expr_free(s->as.destructure.value); |
685 | 24 | break; |
686 | 282 | case STMT_IMPORT: |
687 | 282 | free(s->as.import.module_path); |
688 | 282 | free(s->as.import.alias); |
689 | 282 | if (s->as.import.selective_names) { |
690 | 111 | for (size_t i = 0; i < s->as.import.selective_count; i++) |
691 | 60 | free(s->as.import.selective_names[i]); |
692 | 51 | free(s->as.import.selective_names); |
693 | 51 | } |
694 | 282 | break; |
695 | 18 | case STMT_DEFER: |
696 | 36 | for (size_t i = 0; i < s->as.defer.body_count; i++) |
697 | 18 | stmt_free(s->as.defer.body[i]); |
698 | 18 | free(s->as.defer.body); |
699 | 18 | break; |
700 | 33.5k | } |
701 | 33.5k | free(s); |
702 | 33.5k | } |
703 | | |
704 | 6.21k | void fn_decl_free(FnDecl *f) { |
705 | 6.21k | free(f->name); |
706 | 11.9k | for (size_t i = 0; i < f->param_count; i++) { |
707 | 5.76k | free(f->params[i].name); |
708 | 5.76k | type_expr_free(&f->params[i].ty); |
709 | 5.76k | if (f->params[i].default_value) |
710 | 67 | expr_free(f->params[i].default_value); |
711 | 5.76k | } |
712 | 6.21k | free(f->params); |
713 | 6.21k | if (f->return_type) { |
714 | 3.12k | type_expr_free(f->return_type); |
715 | 3.12k | free(f->return_type); |
716 | 3.12k | } |
717 | 6.21k | if (f->contracts) { |
718 | 42 | for (size_t i = 0; i < f->contract_count; i++) { |
719 | 24 | expr_free(f->contracts[i].condition); |
720 | 24 | free(f->contracts[i].message); |
721 | 24 | } |
722 | 18 | free(f->contracts); |
723 | 18 | } |
724 | 23.6k | for (size_t i = 0; i < f->body_count; i++) |
725 | 17.4k | stmt_free(f->body[i]); |
726 | 6.21k | free(f->body); |
727 | 6.21k | f->next_overload = NULL; |
728 | 6.21k | } |
729 | | |
730 | 140 | void struct_decl_free(StructDecl *s) { |
731 | 140 | free(s->name); |
732 | 406 | for (size_t i = 0; i < s->field_count; i++) { |
733 | 266 | free(s->fields[i].name); |
734 | 266 | type_expr_free(&s->fields[i].ty); |
735 | 266 | } |
736 | 140 | free(s->fields); |
737 | 140 | } |
738 | | |
739 | 6 | void test_decl_free(TestDecl *t) { |
740 | 6 | free(t->name); |
741 | 12 | for (size_t i = 0; i < t->body_count; i++) |
742 | 6 | stmt_free(t->body[i]); |
743 | 6 | free(t->body); |
744 | 6 | } |
745 | | |
746 | 27 | void enum_decl_free(EnumDecl *e) { |
747 | 27 | free(e->name); |
748 | 99 | for (size_t i = 0; i < e->variant_count; i++) { |
749 | 72 | free(e->variants[i].name); |
750 | 72 | if (e->variants[i].param_types) { |
751 | 30 | for (size_t j = 0; j < e->variants[i].param_count; j++) |
752 | 18 | type_expr_free(&e->variants[i].param_types[j]); |
753 | 12 | free(e->variants[i].param_types); |
754 | 12 | } |
755 | 72 | } |
756 | 27 | free(e->variants); |
757 | 27 | } |
758 | | |
759 | 12 | void trait_decl_free(TraitDecl *t) { |
760 | 12 | free(t->name); |
761 | 27 | for (size_t i = 0; i < t->method_count; i++) { |
762 | 15 | free(t->methods[i].name); |
763 | 33 | for (size_t j = 0; j < t->methods[i].param_count; j++) { |
764 | 18 | free(t->methods[i].params[j].name); |
765 | 18 | type_expr_free(&t->methods[i].params[j].ty); |
766 | 18 | if (t->methods[i].params[j].default_value) |
767 | 0 | expr_free(t->methods[i].params[j].default_value); |
768 | 18 | } |
769 | 15 | free(t->methods[i].params); |
770 | 15 | if (t->methods[i].return_type) { |
771 | 15 | type_expr_free(t->methods[i].return_type); |
772 | 15 | free(t->methods[i].return_type); |
773 | 15 | } |
774 | 15 | } |
775 | 12 | free(t->methods); |
776 | 12 | } |
777 | | |
778 | 15 | void impl_block_free(ImplBlock *ib) { |
779 | 15 | free(ib->trait_name); |
780 | 15 | free(ib->type_name); |
781 | 33 | for (size_t i = 0; i < ib->method_count; i++) { |
782 | 18 | fn_decl_free(&ib->methods[i]); |
783 | 18 | } |
784 | 15 | free(ib->methods); |
785 | 15 | } |
786 | | |
787 | 7.18k | void item_free(Item *item) { |
788 | 7.18k | switch (item->tag) { |
789 | 6.20k | case ITEM_FUNCTION: |
790 | 6.20k | fn_decl_free(&item->as.fn_decl); |
791 | 6.20k | break; |
792 | 140 | case ITEM_STRUCT: |
793 | 140 | struct_decl_free(&item->as.struct_decl); |
794 | 140 | break; |
795 | 780 | case ITEM_STMT: |
796 | 780 | stmt_free(item->as.stmt); |
797 | 780 | break; |
798 | 6 | case ITEM_TEST: |
799 | 6 | test_decl_free(&item->as.test_decl); |
800 | 6 | break; |
801 | 27 | case ITEM_ENUM: |
802 | 27 | enum_decl_free(&item->as.enum_decl); |
803 | 27 | break; |
804 | 12 | case ITEM_TRAIT: |
805 | 12 | trait_decl_free(&item->as.trait_decl); |
806 | 12 | break; |
807 | 15 | case ITEM_IMPL: |
808 | 15 | impl_block_free(&item->as.impl_block); |
809 | 15 | break; |
810 | 7.18k | } |
811 | 7.18k | } |
812 | | |
813 | 2.77k | void program_free(Program *p) { |
814 | 9.95k | for (size_t i = 0; i < p->item_count; i++) { |
815 | 7.18k | item_free(&p->items[i]); |
816 | 7.18k | } |
817 | 2.77k | free(p->items); |
818 | 2.77k | if (p->export_names) { |
819 | 36 | for (size_t i = 0; i < p->export_count; i++) |
820 | 24 | free(p->export_names[i]); |
821 | 12 | free(p->export_names); |
822 | 12 | } |
823 | 2.77k | } |
824 | | |
825 | | bool module_should_export(const char *name, const char **export_names, |
826 | 5.31k | size_t export_count, bool has_exports) { |
827 | | /* Always skip internal metadata */ |
828 | 5.31k | if ((name[0] == '_' && name[1] == '_') || strchr(name, ':')) |
829 | 4 | return false; |
830 | | /* Legacy mode: no export keywords → export everything */ |
831 | 5.31k | if (!has_exports) |
832 | 5.24k | return true; |
833 | | /* Explicit mode: only export listed names */ |
834 | 141 | for (size_t i = 0; i < export_count; i++) |
835 | 111 | if (strcmp(export_names[i], name) == 0) return true; |
836 | 30 | return false; |
837 | 63 | } |