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 --- examples/main.pipa | 6 +++++- src/ast.c | 27 +++++++++++++++++++++++++++ src/ast.h | 16 ++++++++++++++++ src/ast_pretty_printer.c | 5 +++++ src/gas_assembly_generator.c | 13 +++++++++++++ src/parser.c | 22 +++++++++++++++++----- 6 files changed, 83 insertions(+), 6 deletions(-) diff --git a/examples/main.pipa b/examples/main.pipa index 2da2231..5ea0077 100644 --- a/examples/main.pipa +++ b/examples/main.pipa @@ -1,3 +1,7 @@ -fn main(): i32 { +fn give_me_the_number(): i32 { return 69; } + +fn main(): i32 { + return give_me_the_number(); +} diff --git a/src/ast.c b/src/ast.c index 47d658d..e9aa677 100644 --- a/src/ast.c +++ b/src/ast.c @@ -72,6 +72,7 @@ ast_node_destroy(ast_node_t *node) case AST_LITERAL: case AST_UNKOWN_NODE: case AST_VARIABLE: + case AST_FUNCTION_CALL: break; } free(node); @@ -275,6 +276,20 @@ ast_node_new_variable(ast_identifier_t *identifier, type_t result_type) return node; } +ast_node_t * +ast_node_new_function_call(ast_identifier_t *identifier, type_t result_type) +{ + ast_node_t *node = ast_node_new(); + + *node = (ast_node_t){ + .kind = AST_FUNCTION_CALL, + .result_type = result_type, + .data = { .function_call = { .identifier = identifier } }, + }; + + return node; +} + ast_node_t * ast_node_ns_get_function_node_by_sv(ast_node_t *ns, string_view_t name) { @@ -296,6 +311,18 @@ ast_node_ns_get_function_node_by_name(ast_node_t *ns, char *function_name) return ast_node_ns_get_function_node_by_sv(ns, string_view_from_str(function_name)); } +bool +ast_node_is_variable_declaration(ast_node_t *node) +{ + return node->kind == AST_VARIABLE_DECLARATION; +} + +bool +ast_node_is_function_declaration(ast_node_t *node) +{ + return node->kind == AST_FUNCTION_DECLARATION; +} + char * ast_type_to_str(type_t type) { diff --git a/src/ast.h b/src/ast.h index 7d2d2f1..315de1e 100644 --- a/src/ast.h +++ b/src/ast.h @@ -54,6 +54,11 @@ typedef struct ast_variable_t ast_identifier_t *identifier; } ast_variable_t; +typedef struct ast_function_call_t +{ + ast_identifier_t *identifier; +} ast_function_call_t; + typedef struct ast_function_declaration_t { ast_identifier_t identifier; @@ -128,6 +133,7 @@ typedef enum AST_BINARY_OPERATION, AST_BLOCK, AST_FUNCTION_DECLARATION, + AST_FUNCTION_CALL, AST_LITERAL, AST_RETURN_STMT, AST_IF_STMT, @@ -142,6 +148,7 @@ typedef union ast_namespace_t ns; ast_binary_operation_t binary_operation; ast_function_declaration_t function; + ast_function_call_t function_call; ast_literal_t literal; ast_block_t block; ast_if_stmt_t if_stmt; @@ -182,6 +189,9 @@ ast_node_new_binary_operation(ast_binary_operation_kind_t kind, ast_node_t * ast_node_new_function_declaration(string_view_t function_name, type_t return_type, ast_node_t *body); +ast_node_t * +ast_node_new_function_call(ast_identifier_t *identifier, type_t result_type); + ast_node_t * ast_node_new_return_stmt(ast_node_t *argument); @@ -212,4 +222,10 @@ ast_node_ns_get_function_node_by_sv(ast_node_t *ns, string_view_t name); ast_node_t * ast_node_ns_get_function_node_by_name(ast_node_t *ns, char *function_name); +bool +ast_node_is_variable_declaration(ast_node_t *node); + +bool +ast_node_is_function_declaration(ast_node_t *node); + #endif /* AST_H */ 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); diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index 4326b27..2d6b993 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -28,6 +28,9 @@ gas_assembly_generator_binary_operation(gas_assembly_generator_t *gen, ast_binar static void gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_function_declaration_t *func); +static void +gas_assembly_generator_compile_function_call(gas_assembly_generator_t *gen, ast_function_call_t *func_call); + static void gas_assembly_generator_compile_literal(gas_assembly_generator_t *gen, ast_literal_t *literal); @@ -156,6 +159,9 @@ gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast) case AST_FUNCTION_DECLARATION: gas_assembly_generator_compile_function(gen, &ast->data.function); break; + case AST_FUNCTION_CALL: + gas_assembly_generator_compile_function_call(gen, &ast->data.function_call); + break; case AST_LITERAL: gas_assembly_generator_compile_literal(gen, &ast->data.literal); break; @@ -211,6 +217,13 @@ gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_funct gen->return_label_index = previous_index; } +static void +gas_assembly_generator_compile_function_call(gas_assembly_generator_t *gen, ast_function_call_t *func_call) +{ + fprintf(gen->stream, " call " SVFMT "\n", SVARG(&func_call->identifier->name)); + gas_assembly_generator_set_latest_evaluation_to_rax(gen); +} + void gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_node_t *ns) { diff --git a/src/parser.c b/src/parser.c index b94087f..578514c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -339,10 +339,9 @@ parser_parse_factor(parser_t *parser) return expression; } case TOKEN_NAME: { - // TODO: Check node kind, today accepts only variables - ast_node_t *var_node = scope_get(parser->scope, token.value); + ast_node_t *referenced_node = scope_get(parser->scope, token.value); - if (var_node == NULL) { + if (referenced_node == NULL) { parser_error_t error; error.token = token; sprintf(error.message, "identifier '" SVFMT "' not defined", SVARG(&token.value)); @@ -350,8 +349,21 @@ parser_parse_factor(parser_t *parser) return NULL; } - return ast_node_new_variable(&var_node->data.variable_declaration.identifier, - var_node->data.variable_declaration.type); + if (referenced_node->kind == AST_VARIABLE_DECLARATION) { + return ast_node_new_variable(&referenced_node->data.variable_declaration.identifier, + referenced_node->data.variable_declaration.type); + } + + // Parse function parameters + if (!drop_expected_token(parser, TOKEN_OPAREN)) { + return NULL; + } + if (!drop_expected_token(parser, TOKEN_CPAREN)) { + return NULL; + } + + return ast_node_new_function_call(&referenced_node->data.function.identifier, + referenced_node->data.function.return_type); } default: { parser_error_t error; -- cgit v1.2.3