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