summaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
authorCarlos Maniero <carlosmaniero@gmail.com>2023-04-20 11:05:54 -0300
committerJohnny Richard <johnny@johnnyrichard.com>2023-04-20 16:14:14 +0200
commita47e5ceb6eefdac9c5f5473e1fee0d33a5f4646e (patch)
tree20beb62b87998ec301d461175c8500f222101a75 /src/ast.c
parent547643d357aadfcb402ec9b951e23975da8593cc (diff)
ast: Allows recursive nodes
Previously, the abstract syntax tree (AST) used static types, meaning that an ast_function_t would always have a ast_return_stmt_t as its body. However, this assumption is not always true, as we may have void functions that do not have a return statement. Additionally, the ast_return_stmt_t always had a number associated with it, but this too is not always the case. To make this possible, I need to perform a few changes in the whole project. One of the main changes is that there is no longer the inheritance hack. That mechanism was replaced by composition and pointers where required for recursive type reference. It is important to mention that I decided to use union type to implement the composition. There is two main advantages in this approach: 1. There is only one function to allocate memory for all kind of nodes. 2. There is no need to cast the data. In summary, this commit introduces changes to support dynamic typing in the AST, by replacing the inheritance hack with composition and using union types to simplify memory allocation and type casting. Signed-off-by: Carlos Maniero <carlosmaniero@gmail.com> Reviewed-by: Johnny Richard <johnny@johnnyrichard.com>
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/src/ast.c b/src/ast.c
index f8c2713..50f6a2e 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -15,6 +15,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "ast.h"
void
@@ -26,38 +28,69 @@ ast_node_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
}
static void
-ast_function_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
+ast_node_function_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
{
- visitor->visit_function(visitor, (ast_function_t *) node);
+ visitor->visit_function(visitor, &node->data.function);
}
static void
-ast_return_stmt_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
+ast_node_return_stmt_accept_visitor(ast_node_t *node, ast_visitor_t *visitor)
{
- visitor->visit_return_stmt(visitor, (ast_return_stmt_t *) node);
+ visitor->visit_return_stmt(visitor, &node->data.return_stmt);
}
-ast_return_stmt_t
-ast_return_stmt_create(uint32_t number)
+ast_node_t*
+ast_node_new()
{
- return (ast_return_stmt_t) {
- .super = (ast_node_t) {
- .accept_visitor = &ast_return_stmt_accept_visitor
- },
- .number = number
+ ast_node_t *node = (ast_node_t*) malloc(sizeof(ast_node_t));
+ if (node == NULL) {
+ printf("OOO: could no allocate a node");
+ exit(EXIT_FAILURE);
+ }
+ node->kind = AST_UNKOWN_NODE;
+ return node;
+}
+
+void
+ast_node_destroy(ast_node_t *node)
+{
+ switch (node->kind) {
+ case AST_FUNCTION_DECLARATION:
+ ast_node_destroy(node->data.function.body);
+ break;
+ case AST_RETURN_STMT:
+ break;
+ case AST_UNKOWN_NODE:
+ break;
+ default:
+ assert(false && "unmapped free strategy");
+ }
+ free(node);
+}
+
+void
+ast_node_init_return_stmt(ast_node_t *node, uint32_t number)
+{
+ node->accept_visitor = &ast_node_return_stmt_accept_visitor,
+ node->kind = AST_RETURN_STMT;
+ node->data = (ast_node_data_t) {
+ .return_stmt = {
+ .number = number
+ }
};
}
-ast_function_t
-ast_function_create(string_view_t name, type_t return_type, ast_return_stmt_t body)
+void
+ast_node_init_function_declaration(ast_node_t *node, string_view_t name, type_t return_type, ast_node_t* body)
{
- return (ast_function_t) {
- .super = (ast_node_t) {
- .accept_visitor = &ast_function_accept_visitor
- },
- .name = name,
- .return_type = return_type,
- .body = body
+ node->accept_visitor = &ast_node_function_accept_visitor,
+ node->kind = AST_FUNCTION_DECLARATION;
+ node->data = (ast_node_data_t) {
+ .function = {
+ .name = name,
+ .return_type = return_type,
+ .body = body
+ }
};
}