diff --git a/src/ast/ast.c b/src/ast/ast.c index 4e3ba6f..4c8caa4 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -5,117 +5,130 @@ #include #include -struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value) { - DEBUG("creating new AST node: %d \"%s\"", kind, value); - assert(kind < AST_ELEMENT_COUNT); +struct AST_Node_t { + // parent node that owns this node + struct AST_Node_t *parent; - struct AST_Node_t *node = malloc(sizeof(struct AST_Node_t)); + // type of AST node: if, declaration, ... + enum AST_SyntaxElement_t kind; + // optional value: integer literal, string literal, ... + const char *value; - if (node == NULL) { - PANIC("failed to allocate AST node"); - } + TokenLocation location; - assert(node != NULL); + GArray *children; +}; - // init to discrete state - node->parent = NULL; - node->children = NULL; - node->child_count = 0; - node->kind = kind; - node->value = value; - node->location = location; +AST_NODE_PTR AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char *value) { + DEBUG("creating new AST node: %d \"%s\"", kind, value); + assert(kind < AST_ELEMENT_COUNT); - return node; + AST_NODE_PTR node = malloc(sizeof(struct AST_Node_t)); + + if (node == NULL) { + PANIC("failed to allocate AST node"); + } + + assert(node != NULL); + + // init to discrete state + node->parent = NULL; + node->children = NULL; + node->kind = kind; + node->value = value; + node->location = location; + + return node; } -static const char* lookup_table[AST_ELEMENT_COUNT] = { "__UNINIT__" }; +static const char *lookup_table[AST_ELEMENT_COUNT] = {"__UNINIT__"}; void AST_init() { - DEBUG("initializing global syntax tree..."); + DEBUG("initializing global syntax tree..."); - INFO("filling lookup table..."); - lookup_table[AST_Stmt] = "stmt"; - lookup_table[AST_Module] = "module"; - lookup_table[AST_Expr] = "expr"; + INFO("filling lookup table..."); + lookup_table[AST_Stmt] = "stmt"; + lookup_table[AST_Module] = "module"; + lookup_table[AST_Expr] = "expr"; - lookup_table[AST_Add] = "+"; - lookup_table[AST_Sub] = "-"; - lookup_table[AST_Mul] = "*"; - lookup_table[AST_Div] = "/"; + lookup_table[AST_Add] = "+"; + lookup_table[AST_Sub] = "-"; + lookup_table[AST_Mul] = "*"; + lookup_table[AST_Div] = "/"; - lookup_table[AST_BitAnd] = "&"; - lookup_table[AST_BitOr] = "|"; - lookup_table[AST_BitXor] = "^"; - lookup_table[AST_BitNot] = "!"; + lookup_table[AST_BitAnd] = "&"; + lookup_table[AST_BitOr] = "|"; + lookup_table[AST_BitXor] = "^"; + lookup_table[AST_BitNot] = "!"; - lookup_table[AST_Eq] = "=="; - lookup_table[AST_Less] = "<"; - lookup_table[AST_Greater] = ">"; + lookup_table[AST_Eq] = "=="; + lookup_table[AST_Less] = "<"; + lookup_table[AST_Greater] = ">"; - lookup_table[AST_BoolAnd] = "&&"; - lookup_table[AST_BoolOr] = "||"; - lookup_table[AST_BoolXor] = "^^"; - lookup_table[AST_BoolNot] = "!!"; + lookup_table[AST_BoolAnd] = "&&"; + lookup_table[AST_BoolOr] = "||"; + lookup_table[AST_BoolXor] = "^^"; + lookup_table[AST_BoolNot] = "!!"; - lookup_table[AST_While] = "while"; - lookup_table[AST_If] = "if"; - lookup_table[AST_IfElse] = "else if"; - lookup_table[AST_Else] = "else"; + lookup_table[AST_While] = "while"; + lookup_table[AST_If] = "if"; + lookup_table[AST_IfElse] = "else if"; + lookup_table[AST_Else] = "else"; - lookup_table[AST_Decl] = "decl"; - lookup_table[AST_Assign] = "assign"; - lookup_table[AST_Def] = "def"; + lookup_table[AST_Decl] = "decl"; + lookup_table[AST_Assign] = "assign"; + lookup_table[AST_Def] = "def"; - lookup_table[AST_Typedef] = "typedef"; - lookup_table[AST_Box] = "box"; - lookup_table[AST_Fun] = "fun"; + lookup_table[AST_Typedef] = "typedef"; + lookup_table[AST_Box] = "box"; + lookup_table[AST_Fun] = "fun"; - lookup_table[AST_Call] = "funcall"; - lookup_table[AST_Typecast] = "typecast"; - lookup_table[AST_Transmute] = "transmute"; - lookup_table[AST_Condition] = "condition"; - lookup_table[AST_List] = "list"; - lookup_table[AST_ExprList] = "expr list"; - lookup_table[AST_ArgList] = "arg list"; - lookup_table[AST_ParamList] = "param list"; - lookup_table[AST_StmtList] = "stmt list"; - lookup_table[AST_IdentList] = "ident list"; - lookup_table[AST_Type] = "type"; - lookup_table[AST_Negate] = "-"; - lookup_table[AST_Parameter] = "parameter"; - lookup_table[AST_ParamDecl] = "parameter-declaration"; - lookup_table[AST_AddressOf] = "address of"; - lookup_table[AST_Dereference] = "deref"; - lookup_table[AST_Reference] = "ref"; + lookup_table[AST_Call] = "funcall"; + lookup_table[AST_Typecast] = "typecast"; + lookup_table[AST_Transmute] = "transmute"; + lookup_table[AST_Condition] = "condition"; + lookup_table[AST_List] = "list"; + lookup_table[AST_ExprList] = "expr list"; + lookup_table[AST_ArgList] = "arg list"; + lookup_table[AST_ParamList] = "param list"; + lookup_table[AST_StmtList] = "stmt list"; + lookup_table[AST_IdentList] = "ident list"; + lookup_table[AST_Type] = "type"; + lookup_table[AST_Negate] = "-"; + lookup_table[AST_Parameter] = "parameter"; + lookup_table[AST_ParamDecl] = "parameter-declaration"; + lookup_table[AST_AddressOf] = "address of"; + lookup_table[AST_Dereference] = "deref"; + lookup_table[AST_Reference] = "ref"; } -const char* AST_node_to_string(const struct AST_Node_t* node) { - DEBUG("converting AST node to string: %p", node); - assert(node != NULL); +const char *AST_node_to_string(AST_NODE_PTR node) { + DEBUG("converting AST node to string: %p", node); + assert(node != NULL); - const char* string; + const char *string; - switch(node->kind) { - case AST_Int: - case AST_Float: - case AST_String: - case AST_Ident: - case AST_Macro: - case AST_Import: - case AST_Storage: - case AST_Typekind: - case AST_Sign: - case AST_Scale: - case AST_Qualifyier: - string = node->value; - break; - default: - string = lookup_table[node->kind]; - } + switch (node->kind) { + case AST_Int: + case AST_Float: + case AST_String: + case AST_Ident: + case AST_Macro: + case AST_Import: + case AST_Storage: + case AST_Typekind: + case AST_Sign: + case AST_Scale: + case AST_Qualifyier: + string = node->value; + break; + default: + string = lookup_table[node->kind]; + } - assert(string != NULL); + assert(string != NULL); - return string; + return string; } static inline unsigned long int min(unsigned long int a, unsigned long int b) { @@ -126,182 +139,174 @@ static inline unsigned long int max(unsigned long int a, unsigned long int b) { return a > b ? a : b; } -void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) { - DEBUG("Adding new node %p to %p", child, owner); - assert(owner != NULL); - assert(child != NULL); +void AST_push_node(AST_NODE_PTR owner, AST_NODE_PTR child) { + DEBUG("Adding new node %p to %p", child, owner); + assert(owner != NULL); + assert(child != NULL); - // if there are no children for now - if (owner->child_count == 0) { - DEBUG("Allocating new children array"); - owner->children = malloc(sizeof(struct AST_Node_t *)); - - } else { - DEBUG("Rellocating old children array"); - const size_t size = sizeof(struct AST_Node_t *) * (owner->child_count + 1); - owner->children = realloc(owner->children, size); - } - - if (owner->children == NULL) { - PANIC("failed to allocate children array of AST node"); - } - - owner->location.col_end = max(owner->location.col_end, child->location.col_end); - owner->location.line_end = max(owner->location.line_end, child->location.line_end); - - owner->location.col_start = min(owner->location.col_start, child->location.col_start); - owner->location.line_start = min(owner->location.line_start, child->location.line_start); - - assert(owner->children != NULL); - - owner->children[owner->child_count++] = child; -} - -struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, const size_t idx) { - DEBUG("retrvieng node %d from %p", idx, owner); - assert(owner != NULL); - assert(owner->children != NULL); - assert(idx < owner->child_count); - - if (owner->children == NULL) { - PANIC("AST owner node has no children"); - } - - struct AST_Node_t *child = owner->children[idx]; - - if (child == NULL) { - PANIC("child node is NULL"); - } - - return child; -} - -struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, const size_t idx) { - assert(owner != NULL); - assert(owner->children != NULL); - assert(idx < owner->child_count); - - struct AST_Node_t* child = owner->children[idx]; - - child->parent = NULL; - - owner->child_count--; - - // shift back every following element by one - for (size_t i = idx; i < owner->child_count; i++) { - owner->children[i] = owner->children[i + 1]; - } - - return child; -} - -struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child) { - assert(owner != NULL); - assert(child != NULL); - assert(owner->children != NULL); - - for (size_t i = 0; i < owner->child_count; i++) { - if (owner->children[i] == child) { - return AST_remove_child(owner, i); + // if there are no children for now + if (owner->children == NULL) { + DEBUG("Allocating new children array"); + owner->children = g_array_new(FALSE, FALSE, sizeof(AST_NODE_PTR)); } - } - PANIC("Child to detach not a child of parent"); + if (owner->children == NULL) { + PANIC("failed to allocate children array of AST node"); + } + + owner->location.col_end = max(owner->location.col_end, child->location.col_end); + owner->location.line_end = max(owner->location.line_end, child->location.line_end); + + owner->location.col_start = min(owner->location.col_start, child->location.col_start); + owner->location.line_start = min(owner->location.line_start, child->location.line_start); + + assert(owner->children != NULL); + + g_array_append_val(owner->children, child); } -void AST_delete_node(struct AST_Node_t *node) { - assert(node != NULL); +AST_NODE_PTR AST_get_node(AST_NODE_PTR owner, const size_t idx) { + DEBUG("retrvieng node %d from %p", idx, owner); + assert(owner != NULL); + assert(owner->children != NULL); + assert(idx < owner->children->len); - DEBUG("Deleting AST node: %p", node); + if (owner->children == NULL) { + PANIC("AST owner node has no children"); + } - if (node->children == NULL) { - return; - } + AST_NODE_PTR child = ((AST_NODE_PTR*) owner->children->data)[idx]; - if (node->parent != NULL) { - const struct AST_Node_t* child = AST_detach_child(node->parent, node); - assert(child == node); - } + if (child == NULL) { + PANIC("child node is NULL"); + } - for (size_t i = 0; i < node->child_count; i++) { - // prevent detach of children node - node->children[i]->parent = NULL; - AST_delete_node(node->children[i]); - } - - free(node->children); - free(node); + return child; } -static void AST_visit_nodes_recurse2(struct AST_Node_t *root, - void (*for_each)(struct AST_Node_t *node, - size_t depth), - const size_t depth) { - DEBUG("Recursive visit of %p at %d with %p", root, depth, for_each); +AST_NODE_PTR AST_remove_child(AST_NODE_PTR owner, const size_t idx) { + assert(owner != NULL); + assert(owner->children != NULL); + assert(idx < owner->children->len); - assert(root != NULL); + AST_NODE_PTR child = AST_get_node(owner, idx); - (for_each)(root, depth); + child->parent = NULL; - for (size_t i = 0; i < root->child_count; i++) { - AST_visit_nodes_recurse2(root->children[i], for_each, depth + 1); - } + g_array_remove_index(owner->children, idx); + + return child; } -void AST_visit_nodes_recurse(struct AST_Node_t *root, - void (*for_each)(struct AST_Node_t *node, +AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child) { + assert(owner != NULL); + assert(child != NULL); + assert(owner->children != NULL); + + for (size_t i = 0; i < owner->children->len; i++) { + if (AST_get_node(owner, i) == child) { + return AST_remove_child(owner, i); + } + } + + PANIC("Child to detach not a child of parent"); +} + +void AST_delete_node(AST_NODE_PTR node) { + assert(node != NULL); + + DEBUG("Deleting AST node: %p", node); + + if (node->children == NULL) { + return; + } + + if (node->parent != NULL) { + AST_NODE_PTR child = AST_detach_child(node->parent, node); + assert(child == node); + } + + for (size_t i = 0; i < node->children->len; i++) { + // prevent detach of children node + AST_NODE_PTR child = AST_get_node(node, i); + child->parent = NULL; + AST_delete_node(child); + } + + g_array_free(node->children, TRUE); + free(node); +} + +static void AST_visit_nodes_recurse2(AST_NODE_PTR root, + void (*for_each)(AST_NODE_PTR node, + size_t depth), + const size_t depth) { + DEBUG("Recursive visit of %p at %d with %p", root, depth, for_each); + + assert(root != NULL); + + (for_each)(root, depth); + + for (size_t i = 0; i < root->children->len; i++) { + AST_visit_nodes_recurse2(AST_get_node(root, i), for_each, depth + 1); + } +} + +void AST_visit_nodes_recurse(AST_NODE_PTR root, + void (*for_each)(AST_NODE_PTR node, size_t depth)) { - DEBUG("Starting recursive visit of %p with %p", root, for_each); + DEBUG("Starting recursive visit of %p with %p", root, for_each); - assert(root != NULL); - assert(for_each != NULL); + assert(root != NULL); + assert(for_each != NULL); - AST_visit_nodes_recurse2(root, for_each, 0); + AST_visit_nodes_recurse2(root, for_each, 0); } -static void AST_fprint_graphviz_node_definition(FILE* stream, const struct AST_Node_t* node) { - DEBUG("Printing graphviz definition of %p", node); +static void AST_fprint_graphviz_node_definition(FILE *stream, AST_NODE_PTR node) { + DEBUG("Printing graphviz definition of %p", node); - assert(stream != NULL); - assert(node != NULL); + assert(stream != NULL); + assert(node != NULL); - fprintf(stream, "\tnode%p [label=\"%s\"]\n", (void*) node, AST_node_to_string(node)); + fprintf(stream, "\tnode%p [label=\"%s\"]\n", (void *) node, AST_node_to_string(node)); - if (node->children == NULL) { - return; - } + if (node->children == NULL) { + return; + } - for (size_t i = 0; i < node->child_count; i++) { - AST_fprint_graphviz_node_definition(stream, node->children[i]); - } + for (size_t i = 0; i < node->children->len; i++) { + AST_fprint_graphviz_node_definition(stream, AST_get_node(node, i)); + } } -static void AST_fprint_graphviz_node_connection(FILE* stream, const struct AST_Node_t* node) { - DEBUG("Printing graphviz connection of %p", node); +static void AST_fprint_graphviz_node_connection(FILE *stream, AST_NODE_PTR node) { + DEBUG("Printing graphviz connection of %p", node); - assert(stream != NULL); - assert(node != NULL); + assert(stream != NULL); + assert(node != NULL); - if (node->children == NULL) { - return; - } + if (node->children == NULL) { + return; + } - for (size_t i = 0; i < node->child_count; i++) { - fprintf(stream, "\tnode%p -- node%p\n", (void*) node, (void*) node->children[i]); - AST_fprint_graphviz_node_connection(stream, node->children[i]); - } + for (size_t i = 0; i < node->children->len; i++) { + AST_NODE_PTR child = AST_get_node(node, i); + fprintf(stream, "\tnode%p -- node%p\n", (void *) node, (void *) child); + AST_fprint_graphviz_node_connection(stream, child); + } } -void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* root) { - DEBUG("Starting print of graphviz graph of %p", root); +void AST_fprint_graphviz(FILE *stream, AST_NODE_PTR root) { + DEBUG("Starting print of graphviz graph of %p", root); - assert(stream != NULL); - assert(root != NULL); + assert(stream != NULL); + assert(root != NULL); - fprintf(stream, "graph {\n"); + fprintf(stream, "graph {\n"); - AST_fprint_graphviz_node_definition(stream, root); - AST_fprint_graphviz_node_connection(stream, root); + AST_fprint_graphviz_node_definition(stream, root); + AST_fprint_graphviz_node_connection(stream, root); - fprintf(stream, "}\n"); + fprintf(stream, "}\n"); } diff --git a/src/ast/ast.h b/src/ast/ast.h index 519f10a..a619bb1 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1,6 +1,6 @@ -#ifndef _AST_H_ -#define _AST_H_ +#ifndef AST_H_ +#define AST_H_ #include #include @@ -89,23 +89,7 @@ enum AST_SyntaxElement_t { * - kind: The type of the node. Such as AST_Expr, AST_Add, ... * - value: A string representing an optional value. Can be a integer literal for kind AST_int */ -struct AST_Node_t { - // parent node that owns this node - struct AST_Node_t *parent; - - // type of AST node: if, declaration, ... - enum AST_SyntaxElement_t kind; - // optional value: integer literal, string literal, ... - const char* value; - - TokenLocation location; - - // number of child nodes ownd by this node - // length of children array - size_t child_count; - // variable amount of child nodes - struct AST_Node_t **children; -}; +struct AST_Node_t; /** * Shorthand type for a single AST node @@ -126,7 +110,7 @@ void AST_init(void); */ [[maybe_unused]] [[gnu::nonnull(1)]] -const char* AST_node_to_string(const struct AST_Node_t* node); +const char* AST_node_to_string(AST_NODE_PTR node); /** * @brief Create a new node struct on the system heap. Initializes the struct with the given values. @@ -139,7 +123,7 @@ const char* AST_node_to_string(const struct AST_Node_t* node); [[maybe_unused]] [[nodiscard("pointer must be freed")]] [[gnu::returns_nonnull]] -struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value); +AST_NODE_PTR AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value); /** * @brief Deallocate this node and all of its children. @@ -149,7 +133,7 @@ struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t */ [[maybe_unused]] [[gnu::nonnull(1)]] -void AST_delete_node(struct AST_Node_t * node); +void AST_delete_node(AST_NODE_PTR node); /** * @brief Add a new child node to a parent node @@ -159,7 +143,7 @@ void AST_delete_node(struct AST_Node_t * node); */ [[maybe_unused]] [[gnu::nonnull(1), gnu::nonnull(2)]] -void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child); +void AST_push_node(AST_NODE_PTR owner, AST_NODE_PTR child); /** * @brief Remove the specified child from the owner. @@ -172,7 +156,7 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child); [[maybe_unused]] [[nodiscard("pointer must be freed")]] [[gnu::nonnull(1)]] -struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx); +AST_NODE_PTR AST_remove_child(AST_NODE_PTR owner, size_t idx); /** * @brief Detach a child from its parent. This involves removing the child from its parent @@ -184,7 +168,7 @@ struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx); */ [[nodiscard("pointer must be freed")]] [[gnu::nonnull(1), gnu::nonnull(1)]] -struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child); +AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child); /** * @brief Return a pointer to the n-th child of a node @@ -197,7 +181,7 @@ struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_N */ [[maybe_unused]] [[gnu::nonnull(1)]] -struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx); +AST_NODE_PTR AST_get_node(AST_NODE_PTR owner, size_t idx); /** * @brief Execute a function for every child, grandchild, ... and the supplied node as topmost ancestor @@ -206,8 +190,8 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx); */ [[maybe_unused]] [[gnu::nonnull(1), gnu::nonnull(2)]] -void AST_visit_nodes_recurse(struct AST_Node_t *root, - void (*for_each)(struct AST_Node_t *node, +void AST_visit_nodes_recurse(AST_NODE_PTR root, + void (*for_each)(AST_NODE_PTR node, size_t depth)); /** @@ -217,6 +201,6 @@ void AST_visit_nodes_recurse(struct AST_Node_t *root, */ [[maybe_unused]] [[gnu::nonnull(1), gnu::nonnull(2)]] -void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* node); +void AST_fprint_graphviz(FILE* stream, AST_NODE_PTR node); -#endif +#endif // AST_H_