From 891ea6836072a1201083669a8a212b03af0c2d5c Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 18 Apr 2022 12:30:42 -0300 Subject: Refactor to remove redundant symbol_check function --- src/errors.c | 1 + src/errors.h | 1 + src/parser.c | 309 +++++++++++++++++++---------------------------------------- 3 files changed, 99 insertions(+), 212 deletions(-) (limited to 'src') diff --git a/src/errors.c b/src/errors.c index 3974281..e2dee00 100644 --- a/src/errors.c +++ b/src/errors.c @@ -24,6 +24,7 @@ static const char* error_msgs[] = { [ERR_WRONG_TYPE_T_F] = "error: unmatched types between true and false expression", [ERR_WRONG_TYPE_NUM] = "error: non numeric argument types", [ERR_WRONG_TYPE_BOOL] = "error: non bool argument types", + [ERR_TYPE_MISMATCH] = "error: type mismatch", }; static Error current_error = {.value = ERR_OK}; diff --git a/src/errors.h b/src/errors.h index 3c85307..a814549 100644 --- a/src/errors.h +++ b/src/errors.h @@ -32,6 +32,7 @@ typedef enum ErrorValue { ERR_WRONG_TYPE_T_F, ERR_WRONG_TYPE_NUM, ERR_WRONG_TYPE_BOOL, + ERR_TYPE_MISMATCH, ERR_OK, } ErrorValue; diff --git a/src/parser.c b/src/parser.c index 92f7654..10d82d1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -559,16 +559,10 @@ parse_roots(Parser *parser) { } Type * -find_type(Parser *parser, Node *type) { - // Normally default types will be used more often. Since we don't - // allow type shadowing, we search first on the global scope. - Scope *scope = parser->parse_tree->global_scope; - Type *ret = ht_lookup(scope->types, &type->string); - if (ret != NULL) { - return ret; - } - scope = parser->parse_tree->current_scope; - while (scope->parent != NULL) { +find_type(Scope *scope, Node *type) { + // TODO: Normally default types will be used more often. Since we don't + // allow type shadowing, we should search first on the global scope. + while (scope != NULL) { Type *ret = ht_lookup(scope->types, &type->string); if (ret != NULL) { return ret; @@ -579,22 +573,8 @@ find_type(Parser *parser, Node *type) { return NULL; } -// TODO: Review this function when needed -// bool -// insert_type(Parser *parser, Node *type, size_t size) { -// HashTable *types = parser->parse_tree->current_scope->types; -// if (ht_lookup(types, type) != NULL) { -// push_error(ERR_TYPE_PARSER, ERR_TYPE_REDEF, type->line, type->col); -// return false; -// } -// // TODO: alloc_type. -// ht_insert(types, &type->string, type); -// return true; -// } - Type * -find_symbol(Parser *parser, Node *node) { - Scope *scope = parser->parse_tree->current_scope; +find_symbol(Scope *scope, Node *node) { while (scope != NULL) { Type *type = ht_lookup(scope->symbols, node); if (type != NULL) { @@ -606,118 +586,19 @@ find_symbol(Parser *parser, Node *node) { return NULL; } -bool -insert_symbol(Parser *parser, Node *symbol, Node *type) { - HashTable *symbols = parser->parse_tree->current_scope->symbols; +Type * +insert_symbol(Scope *scope, Node *symbol, Node *type) { + HashTable *symbols = scope->symbols; if (ht_lookup(symbols, symbol) != NULL) { push_error(ERR_TYPE_PARSER, ERR_SYMBOL_REDEF, symbol->line, symbol->col); - return false; + return NULL; } - Type *t = find_type(parser, type); + Type *t = find_type(scope, type); if (t == NULL) { return NULL; } ht_insert(symbols, symbol, t); - return true; -} - -bool -symbol_check(Parser *parser, Node *node) { - switch (node->type) { - case NODE_BUILTIN: { - for (size_t i = 0; i < array_size(node->builtin.args); ++i) { - Node *arg = node->builtin.args[i]; - if (!symbol_check(parser, arg)) { - return false; - } - } - } break; - case NODE_SYMBOL: { - if (find_symbol(parser, node) == NULL) { - return false; - } - } break; - case NODE_SET: { - Node *symbol = node->set.symbol; - if (find_symbol(parser, symbol) == NULL) { - return false; - } - if (!symbol_check(parser, node->set.value)) { - return false; - } - } break; - case NODE_FUN: { - Scope *prev_scope = parser->parse_tree->current_scope; - parser->parse_tree->current_scope = alloc_scope(prev_scope); - node->scope = parser->parse_tree->current_scope; - - // Parameters. - for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { - Node *param = node->fun.param_names[i]; - Node *type = node->fun.param_types[i]; - if (!insert_symbol(parser, param, type)) { - return false; - } - } - - // Body. - Node *body = node->fun.body; - if (body->type == NODE_BLOCK) { - body->scope = parser->parse_tree->current_scope; - for (size_t i = 0; i < array_size(body->block.expr); ++i) { - Node *expr = body->block.expr[i]; - if (!symbol_check(parser, expr)) { - return false; - } - } - } else { - if (!symbol_check(parser, body)) { - return false; - } - } - parser->parse_tree->current_scope = prev_scope; - } break; - case NODE_BLOCK: { - Scope *prev_scope = parser->parse_tree->current_scope; - parser->parse_tree->current_scope = alloc_scope(prev_scope); - node->scope = parser->parse_tree->current_scope; - for (size_t i = 0; i < array_size(node->block.expr); ++i) { - Node *expr = node->block.expr[i]; - if (!symbol_check(parser, expr)) { - return false; - } - } - parser->parse_tree->current_scope = prev_scope; - } break; - case NODE_IF: { - if (!symbol_check(parser, node->ifexpr.cond)) { - return false; - } - if (!symbol_check(parser, node->ifexpr.expr_true)) { - return false; - } - if (node->ifexpr.expr_false != NULL) { - if (!symbol_check(parser, node->ifexpr.expr_false)) { - return false; - } - } - } break; - case NODE_DEF: { - if (!symbol_check(parser, node->def.value)) { - return false; - } - if (!insert_symbol(parser, node->def.symbol, node->def.type)) { - return false; - } - } break; - case NODE_FUNCALL: { - if (!symbol_check(parser, node->funcall.name)) { - return false; - } - } break; - default: break; - } - return true; + return t; } Type * @@ -725,75 +606,31 @@ coerce_numeric_types(Type *a, Type *b) { if (a == &default_types[TYPE_U8]) { if (b == &default_types[TYPE_U16] || b == &default_types[TYPE_U32] || - b == &default_types[TYPE_U64] || - b == &default_types[TYPE_S8] || - b == &default_types[TYPE_S16] || - b == &default_types[TYPE_S32] || - b == &default_types[TYPE_S64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { + b == &default_types[TYPE_U64]) { return b; } } else if (a == &default_types[TYPE_U16]) { if (b == &default_types[TYPE_U32] || - b == &default_types[TYPE_S16] || - b == &default_types[TYPE_S32] || - b == &default_types[TYPE_S64] || - b == &default_types[TYPE_U64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { + b == &default_types[TYPE_U64]) { return b; } - if (b == &default_types[TYPE_S8]) { - return &default_types[TYPE_S16]; - } } else if (a == &default_types[TYPE_U32]) { - if (b == &default_types[TYPE_U64] || - b == &default_types[TYPE_S32] || - b == &default_types[TYPE_S64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { - return b; - } - if (b == &default_types[TYPE_S8] || - b == &default_types[TYPE_S16]) { - return &default_types[TYPE_S32]; - } - } else if (a == &default_types[TYPE_U64]) { - if (b == &default_types[TYPE_S64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { + if (b == &default_types[TYPE_U64]) { return b; } - if (b == &default_types[TYPE_S8] || - b == &default_types[TYPE_S16] || - b == &default_types[TYPE_S32]) { - return &default_types[TYPE_S64]; - } } else if (a == &default_types[TYPE_S8]) { if (b == &default_types[TYPE_S16] || b == &default_types[TYPE_S32] || - b == &default_types[TYPE_S64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { + b == &default_types[TYPE_S64]) { return b; } } else if (a == &default_types[TYPE_S16]) { if (b == &default_types[TYPE_S32] || - b == &default_types[TYPE_S64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { + b == &default_types[TYPE_S64]) { return b; } } else if (a == &default_types[TYPE_S32]) { - if (b == &default_types[TYPE_S64] || - b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { - return b; - } - } else if (a == &default_types[TYPE_S64]) { - if (b == &default_types[TYPE_F32] || - b == &default_types[TYPE_F64]) { + if (b == &default_types[TYPE_S64]) { return b; } } else if (a == &default_types[TYPE_F32]) { @@ -822,20 +659,15 @@ type_is_numeric(Type *t) { } bool -resolve_type(Parser *parser, Node *node) { +resolve_type(Scope *scope, Node *node) { if (node->expr_type != NULL) { return true; } - Scope *prev_scope = NULL; - if (node->scope != NULL) { - prev_scope = parser->parse_tree->current_scope; - parser->parse_tree->current_scope = node->scope; - } switch (node->type) { case NODE_BUILTIN: { for (size_t i = 0; i < array_size(node->builtin.args); ++i) { Node *arg = node->builtin.args[i]; - if (!resolve_type(parser, arg)) { + if (!resolve_type(scope, arg)) { return false; } } @@ -850,7 +682,7 @@ resolve_type(Parser *parser, Node *node) { for (size_t i = 0; i < array_size(node->builtin.args); ++i) { Node *arg = node->builtin.args[i]; - // Check that all arguments are nums. + // Check that all arguments are numbers. if (!type_is_numeric(arg->expr_type)) { push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, arg->line, arg->col); @@ -900,12 +732,43 @@ resolve_type(Parser *parser, Node *node) { } } break; case NODE_SYMBOL: { - node->expr_type = find_symbol(parser, node); + Type *type = find_symbol(scope, node); + if (type == NULL) { + return false; + } + node->expr_type = type; } break; case NODE_FUN: { - if (!resolve_type(parser, node->fun.body)) { - return false; + // Fill up new scope with parameters + scope = alloc_scope(scope); + + // Parameters. + for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { + Node *param = node->fun.param_names[i]; + Node *type = node->fun.param_types[i]; + if (insert_symbol(scope, param, type) == NULL) { + return false; + } } + + // Body. + Node *body = node->fun.body; + if (body->type == NODE_BLOCK) { + body->scope = scope; + for (size_t i = 0; i < array_size(body->block.expr); ++i) { + Node *expr = body->block.expr[i]; + if (!resolve_type(scope, expr)) { + return false; + } + } + Node *last_expr = body->block.expr[array_size(body->block.expr) - 1]; + node->expr_type = last_expr->expr_type; + } else { + if (!resolve_type(scope, 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; @@ -915,9 +778,10 @@ resolve_type(Parser *parser, Node *node) { } } break; case NODE_BLOCK: { + scope = alloc_scope(scope); for (size_t i = 0; i < array_size(node->block.expr); ++i) { Node *expr = node->block.expr[i]; - if (!resolve_type(parser, expr)) { + if (!resolve_type(scope, expr)) { return false; } } @@ -925,16 +789,16 @@ resolve_type(Parser *parser, Node *node) { node->expr_type = last_expr->expr_type; } break; case NODE_IF: { - if (!resolve_type(parser, node->ifexpr.cond)) { + if (!resolve_type(scope, node->ifexpr.cond)) { return false; } - if (!resolve_type(parser, node->ifexpr.expr_true)) { + if (!resolve_type(scope, 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) { - if (!resolve_type(parser, node->ifexpr.expr_false)) { + if (!resolve_type(scope, node->ifexpr.expr_false)) { return false; } } @@ -961,23 +825,48 @@ resolve_type(Parser *parser, Node *node) { } break; case NODE_SET: { node->expr_type = &default_types[TYPE_VOID]; - if (!resolve_type(parser, node->set.value)) { + if (!resolve_type(scope, node->set.symbol)) { + return false; + } + if (!resolve_type(scope, node->set.value)) { + return false; + } + Node *symbol = node->set.symbol; + Node *value = node->set.value; + if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { + push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, + node->line, node->col); return false; } } break; case NODE_DEF: { + Type *type = insert_symbol(scope, node->def.symbol, node->def.type); + if (type == NULL) { + return false; + } + node->def.symbol->expr_type = type; + node->expr_type = &default_types[TYPE_VOID]; - if (!resolve_type(parser, node->def.value)) { + // TODO: type inference from right side when not annotated? + if (!resolve_type(scope, node->def.value)) { + return false; + } + Node *symbol = node->def.symbol; + Node *value = node->def.value; + if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { + push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, + node->line, node->col); return false; } } break; case NODE_NUMBER: { + // TODO: Numbers are f64/s64 unless explicitely annotated. Annotated + // numbers must fit in the given range (e.g. no negative constants + // inside a U64, no numbers bigger than 255 in a u8, etc.). if (node->number.fractional != 0) { node->expr_type = &default_types[TYPE_F64]; - } else if (node->number.negative) { - node->expr_type = &default_types[TYPE_S64]; } else { - node->expr_type = &default_types[TYPE_U64]; + node->expr_type = &default_types[TYPE_S64]; } } break; case NODE_BOOL: { @@ -987,28 +876,27 @@ resolve_type(Parser *parser, Node *node) { node->expr_type = &default_types[TYPE_STR]; } break; case NODE_FUNCALL: { - if (!resolve_type(parser, node->funcall.name)) { + // TODO: Check that arguments type check with expectations. + if (!resolve_type(scope, 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)) { + if (!resolve_type(scope, arg)) { return false; } } } break; default: break; } - if (node->scope != NULL) { - parser->parse_tree->current_scope = prev_scope; - } return true; } bool semantic_analysis(Parser *parser) { // Fill up global function symbols. + Scope *scope = parser->parse_tree->global_scope; for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { Node *root = parser->parse_tree->roots[i]; if (root->type == NODE_FUN) { @@ -1016,19 +904,16 @@ semantic_analysis(Parser *parser) { // TODO: make sure we store information in the symbol table that // this is actually a function, not just a variable with // return_type. - if (!insert_symbol(parser, name, root->fun.return_type)) { + if (insert_symbol(scope, name, root->fun.return_type) == NULL) { return false; } } } for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { - // Fill up symbol tables in proper scope and check existance. - if (!symbol_check(parser, parser->parse_tree->roots[i])) { - return false; - } - // Resolve type of expression for all elements. - if (!resolve_type(parser, parser->parse_tree->roots[i])) { + // Fill up symbol tables in proper scope and resolve type of expression + // for all elements. + if (!resolve_type(scope, parser->parse_tree->roots[i])) { return false; } } -- cgit v1.2.1