From cc8600eaff00904650c21052d3e2be2508410876 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 25 Apr 2022 11:17:12 -0300 Subject: Add more error types for different pipeline stages --- src/errors.c | 2 ++ src/errors.h | 2 ++ src/ir.c | 28 ++++++++++++++++++++++++++-- src/semantic.c | 30 ++++++++++++++++-------------- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/errors.c b/src/errors.c index 6a69064..e854cf0 100644 --- a/src/errors.c +++ b/src/errors.c @@ -59,6 +59,8 @@ check_errors(const char *file_name) { switch (current_error.type) { case ERR_TYPE_LEXER: { fprintf(stderr, ": [lexer] "); } break; case ERR_TYPE_PARSER: { fprintf(stderr, ": [parser] "); } break; + case ERR_TYPE_SEMANTIC: { fprintf(stderr, ": [semantic] "); } break; + case ERR_TYPE_BASM: { fprintf(stderr, ": [basm] "); } break; default: break; } fprintf(stderr, "%s\n", error_msgs[current_error.value]); diff --git a/src/errors.h b/src/errors.h index f2737d0..8ddba25 100644 --- a/src/errors.h +++ b/src/errors.h @@ -6,6 +6,8 @@ typedef enum ErrorType { ERR_TYPE_LEXER, ERR_TYPE_PARSER, + ERR_TYPE_SEMANTIC, + ERR_TYPE_BASM, } ErrorType; typedef enum ErrorValue { diff --git a/src/ir.c b/src/ir.c index 2b289d9..075ebe3 100644 --- a/src/ir.c +++ b/src/ir.c @@ -173,7 +173,7 @@ emit_builtin(ProgramBASM *program, Node *node) { case TOKEN_LE: { return emit_numcomp(program, node, OP_JMP_GT); } break; case TOKEN_GE: { return emit_numcomp(program, node, OP_JMP_LT); } break; default: { - // TODO: assert unreachable. + push_error(ERR_TYPE_BASM, ERR_UNIMPLEMENTED, node->line, node->col); return (Operand){0}; } break; } @@ -189,13 +189,37 @@ emit_number(ProgramBASM *program, Node *node) { return reg_dst; } +Operand +emit_bool(ProgramBASM *program, Node *node) { + LineInfo line = (LineInfo){.line = node->line, .col = node->col}; + Operand reg_dst = NEW_REG(); + Operand val; + if (node->boolean) { + val = NEW_S64(1); + } else { + val = NEW_S64(0); + } + EMIT_1(program, line, OP_LD8, reg_dst, val); + return reg_dst; +} + +// TODO: emit_if +// TODO: emit_and +// TODO: emit_or +// TODO: emit_not +// TODO: emit_global +// TODO: emit_local +// TODO: emit_procedure +// TODO: emit_proc_call + Operand emit_basm(ProgramBASM *program, Node *node) { switch (node->type) { + case NODE_BOOL: { return emit_bool(program, node); } break; case NODE_NUMBER: { return emit_number(program, node); } break; case NODE_BUILTIN: { return emit_builtin(program, node); } break; default: { - printf("UNIMPLEMENTED\n"); + push_error(ERR_TYPE_BASM, ERR_UNIMPLEMENTED, node->line, node->col); return (Operand){0}; } break; } diff --git a/src/semantic.c b/src/semantic.c index 22d290e..fe88249 100644 --- a/src/semantic.c +++ b/src/semantic.c @@ -130,7 +130,7 @@ find_type(Scope *scope, Node *type) { } scope = scope->parent; } - push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TYPE, type->line, type->col); + push_error(ERR_TYPE_SEMANTIC, ERR_UNKNOWN_TYPE, type->line, type->col); return NULL; } @@ -139,7 +139,7 @@ insert_symbol(Scope *scope, Node *symbol, Symbol *val) { // Check if symbol already exists. HashTable *symbols = scope->symbols; if (ht_lookup(symbols, symbol) != NULL) { - push_error(ERR_TYPE_PARSER, ERR_SYMBOL_REDEF, symbol->line, symbol->col); + push_error(ERR_TYPE_SEMANTIC, ERR_SYMBOL_REDEF, symbol->line, symbol->col); return false; } ht_insert(symbols, symbol, val); @@ -214,7 +214,7 @@ find_symbol(Scope *scope, Node *node) { } scope = scope->parent; } - push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_SYMBOL, node->line, node->col); + push_error(ERR_TYPE_SEMANTIC, ERR_UNKNOWN_SYMBOL, node->line, node->col); return NULL; } @@ -244,7 +244,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { // Check that all arguments are numbers. if (!type_is_numeric(arg->expr_type)) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_NUM, arg->line, arg->col); return false; } @@ -259,13 +259,15 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { } break; // Bools. case TOKEN_NOT: + // TODO: not should only take one argument and + // return the inverse. case TOKEN_AND: case TOKEN_OR: { // Check that all arguments are boolean. for (size_t i = 0; i < array_size(node->builtin.args); ++i) { Node *arg = node->builtin.args[i]; if (arg->expr_type != &default_types[TYPE_BOOL]) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_BOOL, + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_BOOL, arg->line, arg->col); return false; } @@ -283,7 +285,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { // TODO: Make sure all arguments have the same type, // like with numeric expressions. if (!type_is_numeric(arg->expr_type)) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_NUM, arg->line, arg->col); return false; } @@ -354,7 +356,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { StringView *type_body = &node->fun.body->expr_type->name; StringView *return_type = &node->fun.return_type->string; if (!sv_equal(type_body, return_type)) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_RET_TYPE, node->line, node->col); + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_RET_TYPE, node->line, node->col); return false; } } break; @@ -390,7 +392,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { // Check ifexpr.cond is a bool. Type *type_cond = node->ifexpr.cond->expr_type; if (!sv_equal(&type_cond->name, &default_types[TYPE_BOOL].name)) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_COND_TYPE, + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_COND_TYPE, node->line, node->col); return false; } @@ -401,7 +403,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { if (type_is_numeric(type_true) && type_is_numeric(type_false)) { node->expr_type = coerce_numeric_types(type_true, type_false); } else if (!sv_equal(&type_true->name, &type_false->name)) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_T_F, + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_T_F, node->line, node->col); return false; } @@ -418,7 +420,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { 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, + push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, node->line, node->col); return false; } @@ -446,7 +448,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { 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, + push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, node->line, node->col); return false; } @@ -474,12 +476,12 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { return false; } if (val->type != SYMBOL_FUN) { - push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_FUN, + push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_FUN, node->funcall.name->line, node->funcall.name->col); return false; } if (array_size(node->funcall.args) != array_size(val->fun.param_types)) { - push_error(ERR_TYPE_PARSER, ERR_BAD_ARGS, node->line, node->col); + push_error(ERR_TYPE_SEMANTIC, ERR_BAD_ARGS, node->line, node->col); return false; } node->expr_type = node->funcall.name->expr_type; @@ -490,7 +492,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { } Node *expected = val->fun.param_types[i]; if (!sv_equal(&arg->expr_type->name, &expected->string)) { - push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, + push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, arg->line, arg->col); return false; } -- cgit v1.2.1