Coverage Report

Created: 2026-02-23 20:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}