From 140cd959daabf5c18b9cccc210a58ab50351e884 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 11 Apr 2022 18:39:27 -0300 Subject: Add funcall node type and fix type resolution bugs --- src/main.c | 1 + src/nodes.c | 15 ++++++++++ src/nodes.h | 7 +++++ src/parser.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/viz.c | 13 +++++++++ 5 files changed, 116 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index a0d26d0..863d9d1 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,7 @@ process_source(const StringView *source, const char *file_name) { // Read tokens. Token *tokens = tokenize(source); check_errors(file_name); + // print_tokens(tokens); // Parser. ParseTree *parse_tree = parse(tokens); diff --git a/src/nodes.c b/src/nodes.c index 51cc9ef..b8a5f09 100644 --- a/src/nodes.c +++ b/src/nodes.c @@ -114,6 +114,21 @@ print_node(Node *node) { print_node(node->fun.body); printf(")"); } break; + case NODE_FUNCALL: { + printf("("); + print_node(node->funcall.name); + size_t n_args = array_size(node->funcall.args); + if (n_args != 0) { + printf(" "); + } + for (size_t i = 0; i < n_args; ++i) { + print_node(node->funcall.args[i]); + if (i < n_args - 1) { + printf(" "); + } + } + printf(")"); + } break; default: { printf("{#unknown#}"); } break; } } diff --git a/src/nodes.h b/src/nodes.h index 52022cc..11b30dd 100644 --- a/src/nodes.h +++ b/src/nodes.h @@ -13,6 +13,7 @@ typedef enum NodeType { NODE_FUN, NODE_BLOCK, NODE_IF, + NODE_FUNCALL, } NodeType; typedef struct Node { @@ -43,6 +44,12 @@ typedef struct Node { struct Node **args; } builtin; + // Function call. + struct { + struct Node *name; + struct Node **args; + } funcall; + // Variable definition. struct { struct Node *symbol; diff --git a/src/parser.c b/src/parser.c index 252ceaa..92f7654 100644 --- a/src/parser.c +++ b/src/parser.c @@ -233,6 +233,34 @@ parse_builtin(Parser *parser) { return NULL; } +Node * +parse_funcall(Parser *parser) { + Token tok = peek_token(parser); + Node *name = parse_symbol(parser); + if (name == NULL) { + return NULL; + } + Node *node = alloc_node(NODE_FUNCALL); + node->funcall.name = name; + node->line = tok.line; + node->col = tok.col; + array_init(node->funcall.args, 0); + while (has_next(parser)) { + Token next = peek_token(parser); + if (next.type == TOKEN_RPAREN) { + next_token(parser); + return node; + } + Node *arg = parse_next(parser); + if (arg == NULL) { + break; + } + array_push(node->funcall.args, arg); + } + push_error(ERR_TYPE_PARSER, ERR_UNMATCHED_PAREN, tok.line, tok.col); + return NULL; +} + Node * parse_def(Parser *parser) { Token tok = next_token(parser); @@ -416,8 +444,7 @@ parse_paren(Parser *parser) { default: break; } - push_error(ERR_TYPE_PARSER, ERR_UNIMPLEMENTED, tok.line, tok.col); - return NULL; + return parse_funcall(parser); } Node * @@ -518,6 +545,10 @@ alloc_parsetree(void) { bool parse_roots(Parser *parser) { while (has_next(parser)) { + Token tok = peek_token(parser); + if (tok.type == TOKEN_EOF) { + break; + } Node *node = parse_next(parser); if (node == NULL) { return false; @@ -679,6 +710,11 @@ symbol_check(Parser *parser, Node *node) { return false; } } break; + case NODE_FUNCALL: { + if (!symbol_check(parser, node->funcall.name)) { + return false; + } + } break; default: break; } return true; @@ -799,7 +835,9 @@ resolve_type(Parser *parser, Node *node) { case NODE_BUILTIN: { for (size_t i = 0; i < array_size(node->builtin.args); ++i) { Node *arg = node->builtin.args[i]; - resolve_type(parser, arg); + if (!resolve_type(parser, arg)) { + return false; + } } switch (node->builtin.type) { // Numbers. @@ -865,7 +903,9 @@ resolve_type(Parser *parser, Node *node) { node->expr_type = find_symbol(parser, node); } break; case NODE_FUN: { - resolve_type(parser, node->fun.body); + if (!resolve_type(parser, node->fun.body)) { + return false; + } // Check that the type of body matches the return type. StringView *type_body = &node->fun.body->expr_type->name; StringView *return_type = &node->fun.return_type->string; @@ -877,18 +917,26 @@ resolve_type(Parser *parser, Node *node) { case NODE_BLOCK: { for (size_t i = 0; i < array_size(node->block.expr); ++i) { Node *expr = node->block.expr[i]; - resolve_type(parser, expr); + if (!resolve_type(parser, expr)) { + return false; + } } Node *last_expr = node->block.expr[array_size(node->block.expr) - 1]; node->expr_type = last_expr->expr_type; } break; case NODE_IF: { - resolve_type(parser, node->ifexpr.cond); - resolve_type(parser, node->ifexpr.expr_true); + if (!resolve_type(parser, node->ifexpr.cond)) { + return false; + } + if (!resolve_type(parser, node->ifexpr.expr_true)) { + return false; + } Type *type_true = node->ifexpr.expr_true->expr_type; node->expr_type = type_true; if (node->ifexpr.expr_false != NULL) { - resolve_type(parser, node->ifexpr.expr_false); + if (!resolve_type(parser, node->ifexpr.expr_false)) { + return false; + } } // Check ifexpr.cond is a bool. @@ -913,11 +961,15 @@ resolve_type(Parser *parser, Node *node) { } break; case NODE_SET: { node->expr_type = &default_types[TYPE_VOID]; - resolve_type(parser, node->set.value); + if (!resolve_type(parser, node->set.value)) { + return false; + } } break; case NODE_DEF: { node->expr_type = &default_types[TYPE_VOID]; - resolve_type(parser, node->def.value); + if (!resolve_type(parser, node->def.value)) { + return false; + } } break; case NODE_NUMBER: { if (node->number.fractional != 0) { @@ -934,6 +986,18 @@ resolve_type(Parser *parser, Node *node) { case NODE_STRING: { node->expr_type = &default_types[TYPE_STR]; } break; + case NODE_FUNCALL: { + if (!resolve_type(parser, node->funcall.name)) { + return false; + } + node->expr_type = node->funcall.name->expr_type; + for (size_t i = 0; i < array_size(node->funcall.args); ++i) { + Node *arg = node->funcall.args[i]; + if (!resolve_type(parser, arg)) { + return false; + } + } + } break; default: break; } if (node->scope != NULL) { @@ -960,9 +1024,13 @@ semantic_analysis(Parser *parser) { for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { // Fill up symbol tables in proper scope and check existance. - symbol_check(parser, parser->parse_tree->roots[i]); + if (!symbol_check(parser, parser->parse_tree->roots[i])) { + return false; + } // Resolve type of expression for all elements. - resolve_type(parser, parser->parse_tree->roots[i]); + if (!resolve_type(parser, parser->parse_tree->roots[i])) { + return false; + } } return true; diff --git a/src/viz.c b/src/viz.c index 8b5d4cf..81cc1ff 100644 --- a/src/viz.c +++ b/src/viz.c @@ -10,6 +10,7 @@ static const char* node_str[] = { [NODE_FUN] = "FUN", [NODE_BLOCK] = "BLOCK", [NODE_IF] = "IF", + [NODE_FUNCALL] = "FUNCALL", }; void @@ -135,6 +136,18 @@ viz_node(Node *node) { viz_node(node->fun.body); printf("%zu:bod:e->%zu:top:w;\n", node->id, node->fun.body->id); } break; + case NODE_FUNCALL: { + printf(" | Name: "); + sv_write(&node->funcall.name->string); + printf(" | Args: "); + printf("\"];\n"); + size_t n_args = array_size(node->funcall.args); + for (size_t i = 0; i < n_args; ++i) { + viz_node(node->funcall.args[i]); + printf("%zu:args:e->%zu:top:w;\n", node->id, + node->funcall.args[i]->id); + } + } break; } } -- cgit v1.2.1