Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/gravity
Path: blob/master/src/compiler/gravity_ast.c
1214 views
1
//
2
// gravity_ast.c
3
// gravity
4
//
5
// Created by Marco Bambini on 02/09/14.
6
// Copyright (c) 2014 CreoLabs. All rights reserved.
7
//
8
9
#include "gravity_ast.h"
10
#include "gravity_utils.h"
11
#include "gravity_visitor.h"
12
#include "gravity_symboltable.h"
13
14
#define SETBASE(node, tagv, _tok) node->base.tag = tagv; \
15
node->base.token = _tok;
16
#define CHECK_REFCOUNT(_node) if (_node->base.refcount > 0) {--_node->base.refcount; return;}
17
18
// MARK: -
19
20
void_r *void_array_create (void) {
21
void_r *r = mem_alloc(sizeof(void_r));
22
marray_init(*r);
23
return r;
24
}
25
26
cstring_r *cstring_array_create (void) {
27
cstring_r *r = mem_alloc(sizeof(cstring_r));
28
gnode_array_init(r);
29
return r;
30
}
31
32
gnode_r *gnode_array_create (void) {
33
gnode_r *r = mem_alloc(sizeof(gnode_r));
34
gnode_array_init(r);
35
return r;
36
}
37
38
void gnode_array_sethead(gnode_r *list, gnode_t *node) {
39
// get old size
40
size_t list_size = gnode_array_size(list);
41
42
// push node at the end to trigger memory allocation (if needed)
43
gnode_array_push(list, node);
44
45
// shift elements in array
46
for (size_t i=list_size; i>0; --i) {
47
list->p[i] = list->p[i-1];
48
}
49
50
// set new array head
51
list->p[0] = node;
52
}
53
54
gnode_r *gnode_array_remove_byindex(gnode_r *old_list, size_t index) {
55
// get old size
56
size_t list_size = gnode_array_size(old_list);
57
if (index >= list_size) return NULL;
58
59
gnode_r *new_list = gnode_array_create();
60
for (size_t i=0; i<list_size; ++i) {
61
if (i == index) continue;
62
gnode_t *node = gnode_array_get(old_list, i);
63
gnode_array_push(new_list, node);
64
}
65
gnode_array_free(old_list);
66
return new_list;
67
}
68
69
gupvalue_t *gnode_function_add_upvalue(gnode_function_decl_t *f, gnode_var_t *symbol, uint16_t n) {
70
// create uplist if necessary
71
if (!f->uplist) {
72
f->uplist = mem_alloc(sizeof(gupvalue_r));
73
gnode_array_init(f->uplist);
74
}
75
76
// lookup symbol in uplist (if any)
77
gtype_array_each(f->uplist, {
78
// symbol already found in uplist so return its index
79
gnode_var_t *node = (gnode_var_t *)val->node;
80
if (strcmp(node->identifier, symbol->identifier) == 0) return val;
81
}, gupvalue_t *);
82
83
// symbol not found in uplist so add it
84
gupvalue_t *upvalue = mem_alloc(sizeof(gupvalue_t));
85
upvalue->node = (gnode_t *)symbol;
86
upvalue->index = (n == 1) ? symbol->index : (uint32_t)gnode_array_size(f->uplist);
87
upvalue->selfindex = (uint32_t)gnode_array_size(f->uplist);
88
upvalue->is_direct = (n == 1);
89
marray_push(gupvalue_t*, *f->uplist, upvalue);
90
91
// return symbol position in uplist
92
return upvalue;
93
}
94
95
// MARK: - Statements initializers -
96
97
gnode_t *gnode_jump_stat_create (gtoken_s token, gnode_t *expr) {
98
gnode_jump_stmt_t *node = (gnode_jump_stmt_t *)mem_alloc(sizeof(gnode_jump_stmt_t));
99
100
SETBASE(node, NODE_JUMP_STAT, token);
101
node->expr = expr;
102
return (gnode_t *)node;
103
}
104
105
gnode_t *gnode_label_stat_create (gtoken_s token, gnode_t *expr, gnode_t *stmt) {
106
gnode_label_stmt_t *node = (gnode_label_stmt_t *)mem_alloc(sizeof(gnode_label_stmt_t));
107
108
SETBASE(node, NODE_LABEL_STAT, token);
109
node->expr = expr;
110
node->stmt = stmt;
111
return (gnode_t *)node;
112
}
113
114
gnode_t *gnode_flow_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt1, gnode_t *stmt2) {
115
gnode_flow_stmt_t *node = (gnode_flow_stmt_t *)mem_alloc(sizeof(gnode_flow_stmt_t));
116
117
SETBASE(node, NODE_FLOW_STAT, token);
118
node->cond = cond;
119
node->stmt = stmt1;
120
node->elsestmt = stmt2;
121
return (gnode_t *)node;
122
}
123
124
gnode_t *gnode_loop_stat_create (gtoken_s token, gnode_t *cond, gnode_t *stmt, gnode_t *expr) {
125
gnode_loop_stmt_t *node = (gnode_loop_stmt_t *)mem_alloc(sizeof(gnode_loop_stmt_t));
126
127
SETBASE(node, NODE_LOOP_STAT, token);
128
node->cond = cond;
129
node->stmt = stmt;
130
node->expr = expr;
131
node->nclose = UINT32_MAX;
132
return (gnode_t *)node;
133
}
134
135
gnode_t *gnode_block_stat_create (gnode_n type, gtoken_s token, gnode_r *stmts) {
136
gnode_compound_stmt_t *node = (gnode_compound_stmt_t *)mem_alloc(sizeof(gnode_compound_stmt_t));
137
138
SETBASE(node, type, token);
139
node->stmts = stmts;
140
node->nclose = UINT32_MAX;
141
return (gnode_t *)node;
142
}
143
144
gnode_t *gnode_empty_stat_create (gtoken_s token) {
145
gnode_empty_stmt_t *node = (gnode_empty_stmt_t *)mem_alloc(sizeof(gnode_empty_stmt_t));
146
147
SETBASE(node, NODE_EMPTY_STAT, token);
148
return (gnode_t *)node;
149
}
150
151
// MARK: - Declarations initializers -
152
153
gnode_t *gnode_class_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_t *superclass, gnode_r *protocols, gnode_r *declarations, bool is_struct) {
154
gnode_class_decl_t *node = (gnode_class_decl_t *)mem_alloc(sizeof(gnode_class_decl_t));
155
node->is_struct = is_struct;
156
157
// before class creation, iterate declarations and set proper access specifiers
158
// default is PUBLIC but if IDENTIFIER begins with _ then set it to PRIVATE
159
gnode_array_each(declarations, {
160
if (val->tag == NODE_VARIABLE_DECL) {
161
// default access specifier for variables is TOK_KEY_PUBLIC
162
gnode_variable_decl_t *vdec_node = (gnode_variable_decl_t *)val;
163
bool is_private = ((gnode_array_size(vdec_node->decls) > 0) && (((gnode_var_t *)gnode_array_get(vdec_node->decls, 0))->identifier[0] == '_'));
164
if (vdec_node->access == 0) vdec_node->access = (is_private) ? TOK_KEY_PRIVATE : TOK_KEY_PUBLIC;
165
} else if (val->tag == NODE_FUNCTION_DECL) {
166
// default access specifier for functions is PUBLIC
167
gnode_function_decl_t *fdec_node = (gnode_function_decl_t *)val;
168
if (!fdec_node->identifier) continue;
169
bool is_private = (fdec_node->identifier[0] == '_');
170
if (fdec_node->access == 0) fdec_node->access = (is_private) ? TOK_KEY_PRIVATE : TOK_KEY_PUBLIC;
171
} else if (val->tag == NODE_CLASS_DECL) {
172
// default access specifier for inner class declarations is PUBLIC
173
gnode_class_decl_t *cdec_node = (gnode_class_decl_t *)val;
174
if (!cdec_node->identifier) continue;
175
bool is_private = (cdec_node->identifier[0] == '_');
176
if (cdec_node->access == 0) cdec_node->access = (is_private) ? TOK_KEY_PRIVATE : TOK_KEY_PUBLIC;
177
}
178
});
179
180
181
SETBASE(node, NODE_CLASS_DECL, token);
182
node->bridge = false;
183
node->identifier = identifier;
184
node->access = access_specifier;
185
node->storage = storage_specifier;
186
node->superclass = superclass;
187
node->protocols = protocols;
188
node->decls = declarations;
189
node->nivar = 0;
190
node->nsvar = 0;
191
192
return (gnode_t *)node;
193
}
194
195
gnode_t *gnode_module_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *declarations) {
196
gnode_module_decl_t *node = (gnode_module_decl_t *)mem_alloc(sizeof(gnode_module_decl_t));
197
198
SETBASE(node, NODE_MODULE_DECL, token);
199
node->identifier = identifier;
200
node->access = access_specifier;
201
node->storage = storage_specifier;
202
node->decls = declarations;
203
204
return (gnode_t *)node;
205
}
206
207
gnode_t *gnode_enum_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, symboltable_t *symtable) {
208
gnode_enum_decl_t *node = (gnode_enum_decl_t *)mem_alloc(sizeof(gnode_enum_decl_t));
209
210
SETBASE(node, NODE_ENUM_DECL, token);
211
node->identifier = identifier;
212
node->access = access_specifier;
213
node->storage = storage_specifier;
214
node->symtable= symtable;
215
216
return (gnode_t *)node;
217
}
218
219
gnode_t *gnode_function_decl_create (gtoken_s token, const char *identifier, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *params, gnode_compound_stmt_t *block) {
220
gnode_function_decl_t *node = (gnode_function_decl_t *)mem_alloc(sizeof(gnode_function_decl_t));
221
222
SETBASE(node, NODE_FUNCTION_DECL, token);
223
node->identifier = identifier;
224
node->access = access_specifier;
225
node->storage = storage_specifier;
226
node->params = params;
227
node->block = block;
228
node->nlocals = 0;
229
node->uplist = NULL;
230
return (gnode_t *)node;
231
}
232
233
gnode_t *gnode_variable_decl_create (gtoken_s token, gtoken_t type, gtoken_t access_specifier, gtoken_t storage_specifier, gnode_r *declarations) {
234
gnode_variable_decl_t *node = (gnode_variable_decl_t *)mem_alloc(sizeof(gnode_variable_decl_t));
235
236
SETBASE(node, NODE_VARIABLE_DECL, token);
237
node->type = type;
238
node->access = access_specifier;
239
node->storage = storage_specifier;
240
node->decls = declarations;
241
return (gnode_t *)node;
242
}
243
244
gnode_t *gnode_variable_create (gtoken_s token, const char *identifier, const char *annotation_type, gtoken_t access_specifier, gnode_t *expr) {
245
gnode_var_t *node = (gnode_var_t *)mem_alloc(sizeof(gnode_var_t));
246
247
SETBASE(node, NODE_VARIABLE, token);
248
node->identifier = identifier;
249
node->annotation_type = annotation_type;
250
node->expr = expr;
251
node->access = access_specifier;
252
return (gnode_t *)node;
253
}
254
255
// MARK: - Expressions initializers -
256
257
bool gnode_is_equal (gnode_t *node1, gnode_t *node2) {
258
// very simple gnode verification for map key uniqueness
259
gnode_base_t *_node1 = (gnode_base_t *)node1;
260
gnode_base_t *_node2 = (gnode_base_t *)node2;
261
if (_node1->base.tag != _node2->base.tag) return false;
262
if (gnode_is_literal(node1)) {
263
gnode_literal_expr_t *e1 = (gnode_literal_expr_t *)node1;
264
gnode_literal_expr_t *e2 = (gnode_literal_expr_t *)node2;
265
if (e1->type != e2->type) return false;
266
// LITERAL_STRING, LITERAL_FLOAT, LITERAL_INT, LITERAL_BOOL
267
if (e1->type == LITERAL_BOOL) return (e1->value.n64 == e1->value.n64);
268
if (e1->type == LITERAL_INT) return (e1->value.n64 == e1->value.n64);
269
if (e1->type == LITERAL_FLOAT) return (e1->value.d == e1->value.d);
270
if (e1->type == LITERAL_STRING) return (strcmp(e1->value.str, e2->value.str)==0);
271
}
272
return false;
273
}
274
275
bool gnode_is_expression (gnode_t *node) {
276
gnode_base_t *_node = (gnode_base_t *)node;
277
return ((_node->base.tag >= NODE_BINARY_EXPR) && (_node->base.tag <= NODE_KEYWORD_EXPR));
278
}
279
280
bool gnode_is_literal (gnode_t *node) {
281
gnode_base_t *_node = (gnode_base_t *)node;
282
return (_node->base.tag == NODE_LITERAL_EXPR);
283
}
284
285
bool gnode_is_literal_int (gnode_t *node) {
286
if (gnode_is_literal(node) == false) return false;
287
gnode_literal_expr_t *_node = (gnode_literal_expr_t *)node;
288
return (_node->type == LITERAL_INT);
289
}
290
291
bool gnode_is_literal_string (gnode_t *node) {
292
if (gnode_is_literal(node) == false) return false;
293
gnode_literal_expr_t *_node = (gnode_literal_expr_t *)node;
294
return (_node->type == LITERAL_STRING);
295
}
296
297
bool gnode_is_literal_number (gnode_t *node) {
298
if (gnode_is_literal(node) == false) return false;
299
gnode_literal_expr_t *_node = (gnode_literal_expr_t *)node;
300
return (_node->type != LITERAL_STRING);
301
}
302
303
gnode_t *gnode_binary_expr_create (gtoken_t op, gnode_t *left, gnode_t *right) {
304
if (!left || !right) return NULL;
305
306
gnode_binary_expr_t *node = (gnode_binary_expr_t *)mem_alloc(sizeof(gnode_binary_expr_t));
307
SETBASE(node, NODE_BINARY_EXPR, left->token);
308
node->op = op;
309
node->left = left;
310
node->right = right;
311
return (gnode_t *)node;
312
}
313
314
gnode_t *gnode_unary_expr_create (gtoken_t op, gnode_t *expr) {
315
if (!expr) return NULL;
316
317
gnode_unary_expr_t *node = (gnode_unary_expr_t *)mem_alloc(sizeof(gnode_unary_expr_t));
318
SETBASE(node, NODE_UNARY_EXPR, expr->token);
319
node->op = op;
320
node->expr = expr;
321
return (gnode_t *)node;
322
}
323
324
gnode_t *gnode_file_expr_create (gtoken_s token, cstring_r *list) {
325
if (!list) return NULL;
326
327
gnode_file_expr_t *node = (gnode_file_expr_t *)mem_alloc(sizeof(gnode_file_expr_t));
328
SETBASE(node, NODE_FILE_EXPR, token);
329
node->identifiers = list;
330
return (gnode_t *)node;
331
}
332
333
gnode_t *gnode_identifier_expr_create (gtoken_s token, const char *identifier, const char *identifier2) {
334
if (!identifier) return NULL;
335
336
gnode_identifier_expr_t *node = (gnode_identifier_expr_t *)mem_alloc(sizeof(gnode_identifier_expr_t));
337
SETBASE(node, NODE_IDENTIFIER_EXPR, token);
338
node->value = identifier;
339
node->value2 = identifier2;
340
return (gnode_t *)node;
341
}
342
343
void gnode_literal_dump (gnode_literal_expr_t *node, char *buffer, int buffersize) {
344
switch (node->type) {
345
case LITERAL_STRING: snprintf(buffer, buffersize, "STRING: %.*s", node->len, node->value.str); break;
346
case LITERAL_FLOAT: snprintf(buffer, buffersize, "FLOAT: %.2f", node->value.d); break;
347
case LITERAL_INT: snprintf(buffer, buffersize, "INT: %lld", (int64_t)node->value.n64); break;
348
case LITERAL_BOOL: snprintf(buffer, buffersize, "BOOL: %d", (int32_t)node->value.n64); break;
349
default: assert(0); // should never reach this point
350
}
351
}
352
353
static gnode_t *gnode_literal_value_expr_create (gtoken_s token, gliteral_t type, const char *s, double d, int64_t n64) {
354
gnode_literal_expr_t *node = (gnode_literal_expr_t *)mem_alloc(sizeof(gnode_literal_expr_t));
355
356
SETBASE(node, NODE_LITERAL_EXPR, token);
357
node->type = type;
358
node->len = 0;
359
360
switch (type) {
361
case LITERAL_STRING: node->value.str = (char *)s; break;
362
case LITERAL_FLOAT: node->value.d = d; node->len = (d < FLT_MAX) ? 32 : 64; break;
363
case LITERAL_INT: node->value.n64 = n64; node->len = (n64 < 2147483647) ? 32 : 64; break;
364
case LITERAL_BOOL: node->value.n64 = n64; node->len = 32; break;
365
default: assert(0); // should never reach this point
366
}
367
368
return (gnode_t *)node;
369
}
370
371
gnode_t *gnode_literal_string_expr_create (gtoken_s token, const char *s, uint32_t len) {
372
gnode_literal_expr_t *node = (gnode_literal_expr_t *)gnode_literal_value_expr_create(token, LITERAL_STRING, NULL, 0, 0);
373
374
node->len = len;
375
node->value.str = (char *)mem_alloc(len+1);
376
377
if (token.escaped) {
378
node->value.str = string_unescape(s, &len, node->value.str);
379
node->len = len;
380
} else {
381
memcpy((void *)node->value.str, (const void *)s, len);
382
}
383
384
return (gnode_t *)node;
385
}
386
387
gnode_t *gnode_literal_float_expr_create (gtoken_s token, double d) {
388
return gnode_literal_value_expr_create(token, LITERAL_FLOAT, NULL, d, 0);
389
}
390
391
gnode_t *gnode_literal_int_expr_create (gtoken_s token, int64_t n) {
392
return gnode_literal_value_expr_create(token, LITERAL_INT, NULL, 0, n);
393
}
394
395
gnode_t *gnode_literal_bool_expr_create (gtoken_s token, int32_t n) {
396
return gnode_literal_value_expr_create(token, LITERAL_BOOL, NULL, 0, n);
397
}
398
399
gnode_t *gnode_keyword_expr_create (gtoken_s token) {
400
gnode_keyword_expr_t *node = (gnode_keyword_expr_t *)mem_alloc(sizeof(gnode_keyword_expr_t));
401
402
SETBASE(node, NODE_KEYWORD_EXPR, token);
403
return (gnode_t *)node;
404
}
405
406
gnode_t *gnode_postfix_subexpr_create (gtoken_s token, gnode_n type, gnode_t *expr, gnode_r *list) {
407
gnode_postfix_subexpr_t *node = (gnode_postfix_subexpr_t *)mem_alloc(sizeof(gnode_postfix_subexpr_t));
408
409
if (type == NODE_CALL_EXPR)
410
node->args = list;
411
else
412
node->expr = expr;
413
414
SETBASE(node, type, token);
415
return (gnode_t *)node;
416
}
417
418
gnode_t *gnode_postfix_expr_create (gtoken_s token, gnode_t *id, gnode_r *list) {
419
gnode_postfix_expr_t *node = (gnode_postfix_expr_t *)mem_alloc(sizeof(gnode_postfix_expr_t));
420
421
node->id = id;
422
node->list = list;
423
424
SETBASE(node, NODE_POSTFIX_EXPR, token);
425
return (gnode_t *)node;
426
}
427
428
gnode_t *gnode_list_expr_create (gtoken_s token, gnode_r *list1, gnode_r *list2, bool ismap) {
429
gnode_list_expr_t *node = (gnode_list_expr_t *)mem_alloc(sizeof(gnode_list_expr_t));
430
431
SETBASE(node, NODE_LIST_EXPR, token);
432
node->ismap = ismap;
433
node->list1 = list1;
434
node->list2 = list2;
435
return (gnode_t *)node;
436
}
437
438
// MARK: -
439
440
gnode_t *gnode_duplicate (gnode_t *node, bool deep) {
441
if (deep == true) {
442
// deep is true so I need to examine node and perform a real duplication (only of the outer nodes)
443
// deep is true ONLY when node can also be part of an assignment and its assignment flag can be
444
// true is node is on the left and false when node is on the right
445
// true flag is used only by adjust_assignment_expression in parser.c
446
447
// node can be: identifier, file or postfix
448
if (NODE_ISA(node, NODE_IDENTIFIER_EXPR)) {
449
gnode_identifier_expr_t *expr = (gnode_identifier_expr_t *)node;
450
return gnode_identifier_expr_create(expr->base.token, string_dup(expr->value), (expr->value2) ? string_dup(expr->value2) : NULL);
451
} else if (NODE_ISA(node, NODE_FILE_EXPR)) {
452
gnode_file_expr_t *expr = (gnode_file_expr_t *)node;
453
cstring_r *list = cstring_array_create();
454
size_t count = gnode_array_size(expr->identifiers);
455
for (size_t i=0; i<count; ++i) {
456
const char *identifier = gnode_array_get(expr->identifiers, i);
457
cstring_array_push(list, string_dup(identifier));
458
}
459
return gnode_file_expr_create(expr->base.token, list);
460
} else if (NODE_ISA(node, NODE_POSTFIX_EXPR)) {
461
gnode_postfix_expr_t *expr = (gnode_postfix_expr_t *)node;
462
gnode_t *id = gnode_duplicate(expr->id, false);
463
gnode_r *list = gnode_array_create();
464
gnode_array_each(expr->list, {gnode_array_push(list, gnode_duplicate(val, false));});
465
return gnode_postfix_expr_create(expr->base.token, id, list);
466
} else {
467
printf("gnode_duplicate UNHANDLED case\n");
468
assert(0); // should never reach this point
469
}
470
// just return the original node and since it is invalid for an assignment a semantic error will be generated
471
}
472
473
// it means that I can perform a light duplication where
474
// duplicating a node means increase its refcount so it isn't freed more than once
475
++node->refcount;
476
return node;
477
}
478
479
// MARK: - AST deallocator -
480
481
// STATEMENTS
482
static void free_list_stmt (gvisitor_t *self, gnode_compound_stmt_t *node) {
483
CHECK_REFCOUNT(node);
484
gnode_array_each(node->stmts, {visit(val);});
485
gnode_array_free(node->stmts);
486
487
if (node->symtable) symboltable_free(node->symtable);
488
mem_free((gnode_t*)node);
489
}
490
491
static void free_compound_stmt (gvisitor_t *self, gnode_compound_stmt_t *node) {
492
CHECK_REFCOUNT(node);
493
gnode_array_each(node->stmts, {visit(val);});
494
gnode_array_free(node->stmts);
495
496
if (node->symtable) symboltable_free(node->symtable);
497
mem_free((gnode_t*)node);
498
}
499
500
static void free_label_stmt (gvisitor_t *self, gnode_label_stmt_t *node) {
501
CHECK_REFCOUNT(node);
502
if (node->expr) visit(node->expr);
503
if (node->stmt) visit(node->stmt);
504
mem_free((gnode_t*)node);
505
}
506
507
static void free_flow_stmt (gvisitor_t *self, gnode_flow_stmt_t *node) {
508
CHECK_REFCOUNT(node);
509
if (node->cond) visit(node->cond);
510
if (node->stmt) visit(node->stmt);
511
if (node->elsestmt) visit(node->elsestmt);
512
mem_free((gnode_t*)node);
513
}
514
515
static void free_loop_stmt (gvisitor_t *self, gnode_loop_stmt_t *node) {
516
CHECK_REFCOUNT(node);
517
if (node->stmt) visit(node->stmt);
518
if (node->cond) visit(node->cond);
519
if (node->expr) visit(node->expr);
520
mem_free((gnode_t*)node);
521
}
522
523
static void free_jump_stmt (gvisitor_t *self, gnode_jump_stmt_t *node) {
524
CHECK_REFCOUNT(node);
525
if (node->expr) visit(node->expr);
526
mem_free((gnode_t*)node);
527
}
528
529
static void free_empty_stmt (gvisitor_t *self, gnode_empty_stmt_t *node) {
530
#pragma unused(self)
531
CHECK_REFCOUNT(node);
532
mem_free((gnode_t*)node);
533
}
534
535
static void free_variable (gvisitor_t *self, gnode_var_t *p) {
536
CHECK_REFCOUNT(p);
537
if (p->identifier) mem_free((void *)p->identifier);
538
if (p->annotation_type) mem_free((void *)p->annotation_type);
539
if (p->expr) visit(p->expr);
540
mem_free((void *)p);
541
}
542
543
static void free_function_decl (gvisitor_t *self, gnode_function_decl_t *node) {
544
CHECK_REFCOUNT(node);
545
if (node->symtable) symboltable_free(node->symtable);
546
if (node->identifier) mem_free((void *)node->identifier);
547
if (node->params) {
548
gnode_array_each(node->params, {free_variable(self, (gnode_var_t *)val);});
549
gnode_array_free(node->params);
550
}
551
552
if (node->block) visit((gnode_t *)node->block);
553
if (node->uplist) {
554
gtype_array_each(node->uplist, {mem_free(val);}, gupvalue_t*);
555
gnode_array_free(node->uplist);
556
}
557
mem_free((gnode_t*)node);
558
}
559
560
static void free_variable_decl (gvisitor_t *self, gnode_variable_decl_t *node) {
561
CHECK_REFCOUNT(node);
562
if (node->decls) {
563
gnode_array_each(node->decls, {free_variable(self, (gnode_var_t *)val);});
564
gnode_array_free(node->decls);
565
}
566
mem_free((gnode_t*)node);
567
}
568
569
static void free_enum_decl (gvisitor_t *self, gnode_enum_decl_t *node) {
570
#pragma unused(self)
571
CHECK_REFCOUNT(node);
572
if (node->identifier) mem_free((void *)node->identifier);
573
if (node->symtable) symboltable_free(node->symtable);
574
mem_free((gnode_t*)node);
575
}
576
577
static void free_class_decl (gvisitor_t *self, gnode_class_decl_t *node) {
578
CHECK_REFCOUNT(node);
579
if (node->identifier) mem_free((void *)node->identifier);
580
if (node->decls) {
581
gnode_array_each(node->decls, {visit(val);});
582
gnode_array_free(node->decls);
583
}
584
585
if (node->symtable) symboltable_free(node->symtable);
586
mem_free((gnode_t*)node);
587
}
588
589
static void free_module_decl (gvisitor_t *self, gnode_module_decl_t *node) {
590
CHECK_REFCOUNT(node);
591
if (node->identifier) mem_free((void *)node->identifier);
592
if (node->decls) {
593
gnode_array_each(node->decls, {visit(val);});
594
gnode_array_free(node->decls);
595
}
596
597
if (node->symtable) symboltable_free(node->symtable);
598
mem_free((gnode_t*)node);
599
}
600
601
static void free_binary_expr (gvisitor_t *self, gnode_binary_expr_t *node) {
602
CHECK_REFCOUNT(node);
603
if (node->left) visit(node->left);
604
if (node->right) visit(node->right);
605
mem_free((gnode_t*)node);
606
}
607
608
static void free_unary_expr (gvisitor_t *self, gnode_unary_expr_t *node) {
609
CHECK_REFCOUNT(node);
610
if (node->expr) visit(node->expr);
611
mem_free((gnode_t*)node);
612
}
613
614
static void free_postfix_subexpr (gvisitor_t *self, gnode_postfix_subexpr_t *subnode) {
615
CHECK_REFCOUNT(subnode);
616
617
gnode_n tag = subnode->base.tag;
618
if (tag == NODE_CALL_EXPR) {
619
if (subnode->args) {
620
gnode_array_each(subnode->args, visit(val););
621
gnode_array_free(subnode->args);
622
}
623
} else {
624
visit(subnode->expr);
625
}
626
627
mem_free((gnode_t*)subnode);
628
}
629
630
static void free_postfix_expr (gvisitor_t *self, gnode_postfix_expr_t *node) {
631
CHECK_REFCOUNT(node);
632
633
visit(node->id);
634
635
// node->list can be NULL due to enum static conversion
636
size_t count = gnode_array_size(node->list);
637
for (size_t i=0; i<count; ++i) {
638
gnode_postfix_subexpr_t *subnode = (gnode_postfix_subexpr_t *) gnode_array_get(node->list, i);
639
free_postfix_subexpr(self, subnode);
640
}
641
if (node->list) gnode_array_free(node->list);
642
mem_free((gnode_t*)node);
643
}
644
645
static void free_file_expr (gvisitor_t *self, gnode_file_expr_t *node) {
646
#pragma unused(self)
647
CHECK_REFCOUNT(node);
648
cstring_array_each(node->identifiers, {
649
mem_free((void *)val);
650
});
651
652
gnode_array_free(node->identifiers);
653
mem_free((void *)node);
654
}
655
656
static void free_literal_expr (gvisitor_t *self, gnode_literal_expr_t *node) {
657
#pragma unused(self)
658
CHECK_REFCOUNT(node);
659
if (node->type == LITERAL_STRING) mem_free((void *)node->value.str);
660
mem_free((void *)node);
661
}
662
663
static void free_identifier_expr (gvisitor_t *self, gnode_identifier_expr_t *node) {
664
#pragma unused(self, node)
665
CHECK_REFCOUNT(node);
666
if (node->value) mem_free((void *)node->value);
667
if (node->value2) mem_free((void *)node->value2);
668
mem_free((void *)node);
669
}
670
671
static void free_keyword_expr (gvisitor_t *self, gnode_keyword_expr_t *node) {
672
#pragma unused(self)
673
CHECK_REFCOUNT(node);
674
mem_free((void *)node);
675
}
676
677
static void free_list_expr (gvisitor_t *self, gnode_list_expr_t *node) {
678
CHECK_REFCOUNT(node);
679
if (node->list1) {
680
gnode_array_each(node->list1, {visit(val);});
681
gnode_array_free(node->list1);
682
}
683
if (node->list2) {
684
gnode_array_each(node->list2, {visit(val);});
685
gnode_array_free(node->list2);
686
}
687
mem_free((gnode_t*)node);
688
}
689
690
static void gravity_astfree (void *node) {
691
gvisitor_t visitor = {
692
.nerr = 0,
693
.data = NULL,
694
.delegate = NULL,
695
696
// STATEMENTS: 7
697
.visit_list_stmt = free_list_stmt,
698
.visit_compound_stmt = free_compound_stmt,
699
.visit_label_stmt = free_label_stmt,
700
.visit_flow_stmt = free_flow_stmt,
701
.visit_loop_stmt = free_loop_stmt,
702
.visit_jump_stmt = free_jump_stmt,
703
.visit_empty_stmt = free_empty_stmt,
704
705
// DECLARATIONS: 5
706
.visit_function_decl = free_function_decl,
707
.visit_variable_decl = free_variable_decl,
708
.visit_enum_decl = free_enum_decl,
709
.visit_class_decl = free_class_decl,
710
.visit_module_decl = free_module_decl,
711
712
// EXPRESSIONS: 7+1
713
.visit_binary_expr = free_binary_expr,
714
.visit_unary_expr = free_unary_expr,
715
.visit_file_expr = free_file_expr,
716
.visit_literal_expr = free_literal_expr,
717
.visit_identifier_expr = free_identifier_expr,
718
.visit_keyword_expr = free_keyword_expr,
719
.visit_list_expr = free_list_expr,
720
.visit_postfix_expr = free_postfix_expr
721
};
722
723
gvisit(&visitor, (gnode_t*)node);
724
}
725
726
// MARK: -
727
728
void gnode_free (gnode_t *ast) {
729
gravity_astfree(ast);
730
}
731
732