#include "node.h" #include #include #include #include #include extern struct ast_node_type unit_node_ops; extern struct ast_node_type unit_package_node_ops; extern struct ast_node_type unit_import_node_ops; extern struct ast_node_type class_node_ops; extern struct ast_node_type msgh_node_ops; extern struct ast_node_type selector_node_ops; extern struct ast_node_type block_node_ops; extern struct ast_node_type msg_node_ops; extern struct ast_node_type do_node_ops; extern struct ast_node_type op_node_ops; extern struct ast_node_type global_node_ops; extern struct ast_node_type ident_node_ops; extern struct ast_node_type int_node_ops; extern struct ast_node_type double_node_ops; extern struct ast_node_type atom_node_ops; extern struct ast_node_type tuple_node_ops; extern struct ast_node_type string_node_ops; extern struct ast_node_type fstring_node_ops; extern struct ast_node_type cascade_node_ops; extern struct ast_node_type cond_group_node_ops; extern struct ast_node_type cond_node_ops; extern struct ast_node_type match_node_ops; extern struct ast_node_type while_loop_node_ops; extern struct ast_node_type for_loop_node_ops; extern struct ast_node_type loop_break_node_ops; extern struct ast_node_type loop_repeat_node_ops; extern struct ast_node_type return_node_ops; extern struct ast_node_type property_node_ops; extern struct ast_node_type pkg_static_node_ops; extern struct ast_node_type pkg_static_item_node_ops; extern struct ast_node_type pkg_dynamic_node_ops; extern struct ast_node_type discard_node_ops; extern struct ast_node_type try_node_ops; extern struct ast_node_type try_catch_node_ops; extern struct ast_node_type c_true_node_ops; extern struct ast_node_type c_false_node_ops; extern struct ast_node_type c_null_node_ops; static const struct ast_node_type *node_ops[] = { [IVY_AST_UNIT] = &unit_node_ops, [IVY_AST_UNIT_PACKAGE] = &unit_package_node_ops, [IVY_AST_UNIT_IMPORT] = &unit_import_node_ops, [IVY_AST_CLASS] = &class_node_ops, [IVY_AST_MSGH] = &msgh_node_ops, [IVY_AST_SELECTOR] = &selector_node_ops, [IVY_AST_BLOCK] = &block_node_ops, [IVY_AST_MSG] = &msg_node_ops, [IVY_AST_DO] = &do_node_ops, [IVY_AST_OP] = &op_node_ops, [IVY_AST_GLOBAL] = &global_node_ops, [IVY_AST_IDENT] = &ident_node_ops, [IVY_AST_INT] = &int_node_ops, [IVY_AST_DOUBLE] = &double_node_ops, [IVY_AST_ATOM] = &atom_node_ops, [IVY_AST_TUPLE] = &tuple_node_ops, [IVY_AST_STRING] = &string_node_ops, [IVY_AST_FSTRING] = &fstring_node_ops, [IVY_AST_CASCADE] = &cascade_node_ops, [IVY_AST_COND_GROUP] = &cond_group_node_ops, [IVY_AST_COND] = &cond_node_ops, [IVY_AST_MATCH] = &match_node_ops, [IVY_AST_WHILE_LOOP] = &while_loop_node_ops, [IVY_AST_FOR_LOOP] = &for_loop_node_ops, [IVY_AST_LOOP_BREAK] = &loop_break_node_ops, [IVY_AST_LOOP_REPEAT] = &loop_repeat_node_ops, [IVY_AST_RETURN] = &return_node_ops, [IVY_AST_PROPERTY] = &property_node_ops, [IVY_AST_PKG_STATIC] = &pkg_static_node_ops, [IVY_AST_PKG_ITEM] = &pkg_static_item_node_ops, [IVY_AST_PKG_DYNAMIC] = &pkg_dynamic_node_ops, [IVY_AST_DISCARD] = &discard_node_ops, [IVY_AST_TRY] = &try_node_ops, [IVY_AST_TRY_CATCH] = &try_catch_node_ops, [IVY_AST_C_TRUE] = &c_true_node_ops, [IVY_AST_C_FALSE] = &c_false_node_ops, [IVY_AST_C_NULL] = &c_null_node_ops, }; static const size_t nr_node_ops = sizeof node_ops / sizeof node_ops[0]; const struct ast_node_type *get_ast_node_type(enum ivy_ast_node_type type) { if (type >= nr_node_ops) { return NULL; } return node_ops[type]; } struct ivy_ast_node *ivy_ast_node_create(enum ivy_ast_node_type type) { return ast_node_create(type); } struct ivy_ast_node *ast_node_create(enum ivy_ast_node_type type) { const struct ast_node_type *type_info = get_ast_node_type(type); if (!type_info) { return NULL; } struct ivy_ast_node *node = malloc(type_info->n_node_size); if (!node) { return NULL; } memset(node, 0x0, type_info->n_node_size); node->n_type = type; return node; } void ivy_ast_node_to_string(struct ivy_ast_node *node, fx_string *out) { const struct ast_node_type *type_info = get_ast_node_type(node->n_type); if (!type_info) { return; } if (type_info->n_to_string) { type_info->n_to_string(node, out); } else { fx_string_append_cstr( out, ivy_ast_node_type_to_string(node->n_type)); } } void ivy_ast_node_set_bounds_from_token( struct ivy_ast_node *parent, const struct ivy_token *tok) { parent->n_start = tok->t_start; parent->n_end = tok->t_end; } void ivy_ast_node_extend_bounds( struct ivy_ast_node *parent, const struct ivy_ast_node *child) { if (child->n_start.c_row < parent->n_start.c_row) { parent->n_start = child->n_start; } else if (child->n_start.c_col < parent->n_start.c_col) { parent->n_start.c_col = child->n_start.c_col; } if (child->n_end.c_row > parent->n_end.c_row) { parent->n_end = child->n_end; } else if (child->n_end.c_col > parent->n_end.c_col) { parent->n_end.c_col = child->n_end.c_col; } } void ivy_ast_node_extend_bounds_recursive( struct ivy_ast_node *parent, const struct ivy_ast_node *child) { while (parent) { ivy_ast_node_extend_bounds(parent, child); child = parent; parent = parent->n_parent; } } void ivy_ast_node_destroy(struct ivy_ast_node *node) { struct ivy_ast_node_iterator it = {}; fx_queue_push_back(&it.it_queue, &node->n_it.it_entry); node->n_it.it_depth = 0; fx_queue_entry *entry = fx_queue_first(&it.it_queue); while (entry) { struct ivy_ast_node_iterator_entry *it_entry = fx_unbox( struct ivy_ast_node_iterator_entry, entry, it_entry); node = fx_unbox(struct ivy_ast_node, it_entry, n_it); if (!node) { /* this should never happen. */ return; } const struct ast_node_type *type = get_ast_node_type(node->n_type); if (type->n_collect_children) { it.it_insert_after = entry; type->n_collect_children(node, &it); } entry = fx_queue_next(entry); } while (!fx_queue_empty(&it.it_queue)) { fx_queue_entry *entry = fx_queue_pop_back(&it.it_queue); if (!entry) { break; } node = fx_unbox(struct ivy_ast_node, entry, n_it); const struct ast_node_type *type = get_ast_node_type(node->n_type); if (type && type->n_destroy) { type->n_destroy(node); } free(node); } } #define ENUM_STR(x) \ case x: \ return #x const char *ivy_ast_node_type_to_string(enum ivy_ast_node_type v) { switch (v) { ENUM_STR(IVY_AST_NONE); ENUM_STR(IVY_AST_UNIT); ENUM_STR(IVY_AST_OP); ENUM_STR(IVY_AST_DO); ENUM_STR(IVY_AST_MSG); ENUM_STR(IVY_AST_CLASS); ENUM_STR(IVY_AST_MSGH); ENUM_STR(IVY_AST_PROPERTY); ENUM_STR(IVY_AST_SELECTOR); ENUM_STR(IVY_AST_UNIT_PACKAGE); ENUM_STR(IVY_AST_UNIT_IMPORT); ENUM_STR(IVY_AST_DISCARD); ENUM_STR(IVY_AST_INT); ENUM_STR(IVY_AST_GLOBAL); ENUM_STR(IVY_AST_DOUBLE); ENUM_STR(IVY_AST_STRING); ENUM_STR(IVY_AST_FSTRING); ENUM_STR(IVY_AST_ATOM); ENUM_STR(IVY_AST_IDENT); ENUM_STR(IVY_AST_FOR_LOOP); ENUM_STR(IVY_AST_WHILE_LOOP); ENUM_STR(IVY_AST_LOOP_BREAK); ENUM_STR(IVY_AST_LOOP_REPEAT); ENUM_STR(IVY_AST_CASCADE); ENUM_STR(IVY_AST_COND_GROUP); ENUM_STR(IVY_AST_MATCH); ENUM_STR(IVY_AST_COND); ENUM_STR(IVY_AST_TUPLE); ENUM_STR(IVY_AST_BLOCK); ENUM_STR(IVY_AST_PKG_STATIC); ENUM_STR(IVY_AST_PKG_ITEM); ENUM_STR(IVY_AST_PKG_DYNAMIC); ENUM_STR(IVY_AST_RETURN); ENUM_STR(IVY_AST_TRY); ENUM_STR(IVY_AST_TRY_CATCH); ENUM_STR(IVY_AST_TYPE_COUNT); ENUM_STR(IVY_AST_C_TRUE); ENUM_STR(IVY_AST_C_FALSE); ENUM_STR(IVY_AST_C_NULL); default: return ""; } } void ivy_ast_unit_add_node(struct ivy_ast_unit_node *unit, struct ivy_ast_node *child) { fx_queue_push_back(&unit->n_children, &child->n_entry); } struct ivy_ast_node *ivy_ast_unit_dequeue_node(struct ivy_ast_unit_node *unit) { fx_queue_entry *entry = fx_queue_pop_front(&unit->n_children); if (!entry) { return NULL; } return fx_unbox(struct ivy_ast_node, entry, n_entry); }