diff options
-rw-r--r-- | src/ast.c | 42 | ||||
-rw-r--r-- | src/ast.h | 16 | ||||
-rw-r--r-- | src/ast_pretty_printer.c | 13 | ||||
-rw-r--r-- | src/gas_assembly_generator.c | 20 | ||||
-rw-r--r-- | src/gas_assembly_generator.h | 3 | ||||
-rw-r--r-- | src/main.c | 14 | ||||
-rw-r--r-- | src/parser.c | 37 | ||||
-rw-r--r-- | src/parser.h | 3 | ||||
-rw-r--r-- | test/parser_test.c | 12 |
9 files changed, 140 insertions, 20 deletions
@@ -44,6 +44,9 @@ void ast_node_destroy(ast_node_t *node) { switch (node->kind) { + case AST_NAMESPACE: + ast_node_destroy_vector(node->data.ns.nodes); + break; case AST_FUNCTION_DECLARATION: ast_node_destroy(node->data.function.body); break; @@ -108,6 +111,24 @@ ast_node_new_function_declaration(string_view_t function_name, type_t return_typ } ast_node_t * +ast_node_new_namespace(vector_t *nodes) +{ + ast_node_t *node = ast_node_new(); + + *node = (ast_node_t){ + .kind = AST_NAMESPACE, + .result_type = TYPE_VOID, + .data = { + .ns = { + .nodes = nodes, + } + }, + }; + + return node; +} + +ast_node_t * ast_node_new_block(vector_t *body) { ast_node_t *node = ast_node_new(); @@ -254,6 +275,27 @@ ast_node_new_variable(ast_identifier_t *identifier, type_t result_type) return node; } +ast_node_t * +ast_node_ns_get_function_node_by_sv(ast_node_t *ns, string_view_t name) +{ + assert(ns->kind == AST_NAMESPACE); + + for (size_t i = 0; i < ns->data.ns.nodes->size; i++) { + ast_node_t *node = vector_at(ns->data.ns.nodes, i); + + if (node->kind == AST_FUNCTION_DECLARATION && string_view_eq(node->data.function.identifier.name, name)) { + return node; + } + } + return NULL; +} + +ast_node_t * +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)); +} + char * ast_type_to_str(type_t type) { @@ -29,6 +29,11 @@ typedef enum typedef struct ast_node_t ast_node_t; +typedef struct ast_namespace_t +{ + vector_t *nodes; +} ast_namespace_t; + typedef struct ast_block_t { vector_t *body; @@ -119,6 +124,7 @@ typedef struct ast_if_stmt_t typedef enum { + AST_NAMESPACE, AST_BINARY_OPERATION, AST_BLOCK, AST_FUNCTION_DECLARATION, @@ -133,6 +139,7 @@ typedef enum typedef union { + ast_namespace_t ns; ast_binary_operation_t binary_operation; ast_function_declaration_t function; ast_literal_t literal; @@ -164,6 +171,9 @@ void ast_node_destroy(ast_node_t *node); ast_node_t * +ast_node_new_namespace(vector_t *nodes); + +ast_node_t * ast_node_new_binary_operation(ast_binary_operation_kind_t kind, ast_node_t *left, ast_node_t *right, @@ -196,4 +206,10 @@ ast_node_new_variable_assignment(ast_identifier_t *identifier, ast_node_t *expre ast_node_t * ast_node_new_if_stmt(ast_node_t *condition, ast_node_t *body); +ast_node_t * +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); + #endif /* AST_H */ 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"); diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index 413fbb0..4326b27 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -147,6 +147,9 @@ gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast) gen->latest_evaluation.kind = EVALUATION_RESULT_VOID; switch (ast->kind) { + case AST_NAMESPACE: + gas_assembly_generator_compile_ns(gen, &ast->data.ns); + break; case AST_BINARY_OPERATION: gas_assembly_generator_binary_operation(gen, &ast->data.binary_operation); break; @@ -179,6 +182,14 @@ gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast) } } +void +gas_assembly_generator_compile_ns(gas_assembly_generator_t *gen, ast_namespace_t *ns) +{ + for (size_t i = 0; i < ns->nodes->size; i++) { + gas_assembly_generator_compile(gen, vector_at(ns->nodes, i)); + } +} + static void gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_function_declaration_t *func) { @@ -201,12 +212,9 @@ gas_assembly_generator_compile_function(gas_assembly_generator_t *gen, ast_funct } void -gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_node_t *func) +gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_node_t *ns) { - assert(func); - assert(func->kind == AST_FUNCTION_DECLARATION); - - if (!string_view_eq(func->data.function.identifier.name, string_view_from_str("main"))) { + if (ast_node_ns_get_function_node_by_name(ns, "main") == NULL) { fprintf(stderr, "[ERROR]: no main function has been defined!\n"); exit(EXIT_FAILURE); } @@ -214,7 +222,7 @@ gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_nod fprintf(gen->stream, ".global _start\n"); fprintf(gen->stream, ".text\n"); - gas_assembly_generator_compile(gen, func); + gas_assembly_generator_compile(gen, ns); fprintf(gen->stream, "_start:\n"); fprintf(gen->stream, " call main\n"); diff --git a/src/gas_assembly_generator.h b/src/gas_assembly_generator.h index 18ffb7f..26aa87b 100644 --- a/src/gas_assembly_generator.h +++ b/src/gas_assembly_generator.h @@ -60,6 +60,9 @@ void gas_assembly_generator_compile(gas_assembly_generator_t *gen, ast_node_t *ast); void +gas_assembly_generator_compile_ns(gas_assembly_generator_t *gen, ast_namespace_t *ns); + +void gas_assembly_generator_compile_linux_main(gas_assembly_generator_t *gen, ast_node_t *func); #endif /* GAS_ASSEMBLY_GENERATOR_H */ @@ -27,11 +27,11 @@ #include "string_view.h" static void -generate_gas_x86_64_linux(ast_node_t *func) +generate_gas_x86_64_linux(ast_node_t *ns) { gas_assembly_generator_t gen; gas_assembly_generator_init(&gen, stdout); - gas_assembly_generator_compile_linux_main(&gen, func); + gas_assembly_generator_compile_linux_main(&gen, ns); } static void @@ -89,20 +89,20 @@ main(int argc, char **argv) parser_t parser; parser_init(&parser, &lexer, scope); - ast_node_t *func = parser_parse_function_declaration(&parser); + ast_node_t *ns = parser_parse_ns(&parser); - if (func == NULL) { + if (ns == NULL) { parser_print_errors(&parser); return EXIT_FAILURE; } if (should_dump_ast) { - pretty_print_ast(func); + pretty_print_ast(ns); } else { - generate_gas_x86_64_linux(func); + generate_gas_x86_64_linux(ns); } scope_destroy(scope); - ast_node_destroy(func); + ast_node_destroy(ns); return EXIT_SUCCESS; } diff --git a/src/parser.c b/src/parser.c index e3f157f..b94087f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -571,6 +571,22 @@ is_next_statement_return(parser_t *parser) } static bool +is_next_function_declaration(parser_t *parser) +{ + token_t token; + lexer_peek_next_token(parser->lexer, &token); + return token.kind == TOKEN_KEYWORD_FN; +} + +static bool +is_next_token_eof(parser_t *parser) +{ + token_t token; + lexer_peek_next_token(parser->lexer, &token); + return token.kind == TOKEN_EOF; +} + +static bool is_block_end(parser_t *parser) { token_t token; @@ -746,3 +762,24 @@ parser_parse_function_declaration(parser_t *parser) return node; } + +ast_node_t * +parser_parse_ns(parser_t *parser) +{ + vector_t *nodes = vector_new(); + + while (!is_next_token_eof(parser)) { + if (is_next_function_declaration(parser)) { + ast_node_t *node = parser_parse_function_declaration(parser); + + if (node == NULL) { + ast_node_destroy_vector(nodes); + return NULL; + } + + vector_push_back(nodes, node); + } + } + + return ast_node_new_namespace(nodes); +} diff --git a/src/parser.h b/src/parser.h index ef5dff5..7bebee7 100644 --- a/src/parser.h +++ b/src/parser.h @@ -46,4 +46,7 @@ parser_parse_function_declaration(parser_t *parser); ast_node_t * parser_parse_expression(parser_t *parser); +ast_node_t * +parser_parse_ns(parser_t *parser); + #endif /* PARSER_H */ diff --git a/test/parser_test.c b/test/parser_test.c index 8565dc8..78e2e23 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -64,17 +64,15 @@ test_parse_function(const MunitParameter params[], void *user_data_or_fixture) lexer_t lexer; scope_t *scope = scope_new(); - make_lexer_from_static_src(&lexer, "fn main(): i32 { \nreturn 42;\n }"); + make_lexer_from_static_src(&lexer, "fn add(): i32 { return 2; } fn main(): i32 { \nreturn 42;\n }"); parser_init(&parser, &lexer, scope); - ast_node_t *ast_function = parser_parse_function_declaration(&parser); + ast_node_t *ast_ns = parser_parse_ns(&parser); - assert_not_null(ast_function); + assert_not_null(ast_ns); - char actual[5]; + ast_node_t *ast_function = ast_node_ns_get_function_node_by_name(ast_ns, "main"); - string_view_to_str(&ast_function->data.function.identifier.name, actual); - assert_string_equal("main", actual); - assert_int(AST_FUNCTION_DECLARATION, ==, ast_function->kind); + assert_not_null(ast_function); ast_node_t *ast_return = vector_at(ast_function->data.function.body->data.block.body, 0); |