From 5de2e1fd9f426348127a66d2c51c300cb90cc3a4 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 00:20:00 -0300 Subject: gas: Generate code for if statement If statements are now working, the only exception is for the comparators || and && that will be addressed in a further commit. Checks tested: fn main(): i32 { let n: i32 = 11; if (n == 11) { if n != 12 { if n < 12 { if n <= 11 { if n > 10 { if n >= 11 { return 42; } } } } } } return n; } To compile the && and || a precedence issue must be addressed: they must have the highest precedence, witch is not working now: 1 == 2 || 3 != 2 The or should be the higher level of the tree in the example above. Signed-off-by: Carlos Maniero --- src/ast_pretty_printer.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/ast_pretty_printer.c') diff --git a/src/ast_pretty_printer.c b/src/ast_pretty_printer.c index e2d007a..b14bf34 100644 --- a/src/ast_pretty_printer.c +++ b/src/ast_pretty_printer.c @@ -22,10 +22,12 @@ #include #include -const char operation_kinds[AST_BINOP_N] = { [AST_BINOP_ADITION] = '+', - [AST_BINOP_SUBTRACTION] = '-', - [AST_BINOP_MULTIPLICATION] = '*', - [AST_BINOP_DIVISION] = '/' }; +const char *operation_kinds[AST_BINOP_N] = { + [AST_BINOP_ADITION] = "+", [AST_BINOP_SUBTRACTION] = "-", [AST_BINOP_MULTIPLICATION] = "*", + [AST_BINOP_DIVISION] = "/", [AST_BINOP_EQUAL] = "==", [AST_BINOP_NOT_EQUAL] = "!=", + [AST_BINOP_AND] = "&&", [AST_BINOP_OR] = "||", [AST_BINOP_GT] = ">", + [AST_BINOP_LT] = "<", [AST_BINOP_LT_EQUAL] = "<=", [AST_BINOP_GT_EQUAL] = ">=", +}; void ast_pretty_printer_init(ast_pretty_printer_t *printer, FILE *stream); @@ -76,6 +78,7 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) ast_pretty_printer_rm_indentation(printer); } + ast_pretty_printer_set_lst_children(printer); ast_pretty_printer_printf(printer, "body:\n"); ast_pretty_printer_add_indentation(printer); { @@ -90,7 +93,7 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) } case AST_BINARY_OPERATION: { ast_binary_operation_t binop = ast->data.binary_operation; - ast_pretty_printer_printf(printer, "BinaryOperation operation='%c'\n", operation_kinds[binop.kind]); + ast_pretty_printer_printf(printer, "BinaryOperation operation='%s'\n", operation_kinds[binop.kind]); ast_pretty_printer_add_indentation(printer); { @@ -130,6 +133,7 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) ast_pretty_printer_add_indentation(printer); { + ast_pretty_printer_set_lst_children(printer); ast_pretty_printer_print_ast(printer, ast->data.function.body); ast_pretty_printer_rm_indentation(printer); } @@ -139,7 +143,6 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) break; } case AST_BLOCK: { - ast_pretty_printer_set_lst_children(printer); ast_pretty_printer_printf(printer, "Block\n"); ast_pretty_printer_add_indentation(printer); { -- cgit v1.2.3 From 75639fbf01bd6ae1212521b6cf822025eb8b598d Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 16:07:39 -0300 Subject: namespaces: Add a namespace structure that represents a file We have been always parsing a single function. Since we want to have multiple functions in a near future, this patch introduces an namespace that represents an entire file. To ensure a function is defined inside a namespace, a helper function was created. Today our ast_node structure is highly exposed, and this is something that Johnny and I have been discussed. So then, this is a first step to try to protected the code generation from our ast tree. Signed-off-by: Carlos Maniero --- src/ast_pretty_printer.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/ast_pretty_printer.c') diff --git a/src/ast_pretty_printer.c b/src/ast_pretty_printer.c index b14bf34..f5fcf70 100644 --- a/src/ast_pretty_printer.c +++ b/src/ast_pretty_printer.c @@ -65,6 +65,19 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) assert(ast); switch (ast->kind) { + case AST_NAMESPACE: + ast_pretty_printer_printf(printer, "Namespace\n"); + ast_pretty_printer_add_indentation(printer); + { + for (size_t i = 0; i < ast->data.ns.nodes->size; ++i) { + if (i + 1 >= ast->data.ns.nodes->size) { + ast_pretty_printer_set_lst_children(printer); + } + ast_pretty_printer_print_ast(printer, vector_at(ast->data.ns.nodes, i)); + } + ast_pretty_printer_rm_indentation(printer); + } + break; case AST_IF_STMT: { ast_if_stmt_t if_stmt = ast->data.if_stmt; ast_pretty_printer_printf(printer, "IfStmt\n"); -- cgit v1.2.3 From 3129b741064c2b4f2c6c2408bd42cc83f7341ea8 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 16:53:05 -0300 Subject: gas: Generate function call This is an initial commit that enables function calls. At this point only functions with no parameters is going to work. Signed-off-by: Carlos Maniero --- src/ast_pretty_printer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/ast_pretty_printer.c') diff --git a/src/ast_pretty_printer.c b/src/ast_pretty_printer.c index f5fcf70..0d8b66c 100644 --- a/src/ast_pretty_printer.c +++ b/src/ast_pretty_printer.c @@ -155,6 +155,11 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) } break; } + case AST_FUNCTION_CALL: { + ast_function_call_t var = ast->data.function_call; + ast_pretty_printer_printf(printer, "FunctionCall name='" SVFMT "'\n", SVARG(&var.identifier->name)); + break; + } case AST_BLOCK: { ast_pretty_printer_printf(printer, "Block\n"); ast_pretty_printer_add_indentation(printer); -- cgit v1.2.3 From 5042a4ffc1363d6f0f99a3afd79f76cf2da738d6 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 22:24:14 -0300 Subject: gas: implement function calls For now function calls are following the C's calling convention, which means they are using the following registers to pass functions' arguments: rdi, rsi, rdx, rcx, r8, r9 If a function has more then 6 parameters, the compilation will fail. To enable function with more than 6 parameters we will need to save the extra arguments on stack. Naming: parameters: function parameters are the variables a function receives. arguments: Arguments are the values passed to a function when calling it. Calling mechanism: When a function is called, all the expressions passed as argument are evaluated, after the evaluation, the result is stored on the register that represents its argument position, the first argument will be stored on rdi, the second on rsi and so on. Receiving mechanism: When a function starts, the first thing it does is store all the registers onto the stack. So rdi will be stored on -8(rbp), rsi on -16(rbp) and so on. And, a ref_entry is created making the relationship parameter-stack_offset. Signed-off-by: Carlos Maniero --- src/ast_pretty_printer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/ast_pretty_printer.c') diff --git a/src/ast_pretty_printer.c b/src/ast_pretty_printer.c index 0d8b66c..a211fa4 100644 --- a/src/ast_pretty_printer.c +++ b/src/ast_pretty_printer.c @@ -65,6 +65,8 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) assert(ast); switch (ast->kind) { + case AST_FUNCTION_PARAMETER: + break; case AST_NAMESPACE: ast_pretty_printer_printf(printer, "Namespace\n"); ast_pretty_printer_add_indentation(printer); @@ -136,8 +138,8 @@ ast_pretty_printer_print_ast(ast_pretty_printer_t *printer, ast_node_t *ast) break; } case AST_FUNCTION_DECLARATION: { - ast_function_declaration_t function = ast->data.function; - ast_pretty_printer_printf(printer, "FunctionDecl name='" SVFMT "'\n", SVARG(&function.identifier.name)); + string_view_t function_name = ast_node_function_declaration_name(ast); + ast_pretty_printer_printf(printer, "FunctionDecl name='" SVFMT "'\n", SVARG(&function_name)); ast_pretty_printer_add_indentation(printer); { -- cgit v1.2.3