diff options
author | Bad Diode <bd@badd10de.dev> | 2022-04-25 11:17:12 -0300 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-04-25 11:17:12 -0300 |
commit | cc8600eaff00904650c21052d3e2be2508410876 (patch) | |
tree | 8910f8ff68d4d1c728f6bd5539cf851c4f4e1386 | |
parent | 46c86de715afcf15af6dc4532969d0736a3a2e48 (diff) | |
download | bdl-cc8600eaff00904650c21052d3e2be2508410876.tar.gz bdl-cc8600eaff00904650c21052d3e2be2508410876.zip |
Add more error types for different pipeline stages
-rw-r--r-- | src/errors.c | 2 | ||||
-rw-r--r-- | src/errors.h | 2 | ||||
-rw-r--r-- | src/ir.c | 28 | ||||
-rw-r--r-- | 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) { | |||
59 | switch (current_error.type) { | 59 | switch (current_error.type) { |
60 | case ERR_TYPE_LEXER: { fprintf(stderr, ": [lexer] "); } break; | 60 | case ERR_TYPE_LEXER: { fprintf(stderr, ": [lexer] "); } break; |
61 | case ERR_TYPE_PARSER: { fprintf(stderr, ": [parser] "); } break; | 61 | case ERR_TYPE_PARSER: { fprintf(stderr, ": [parser] "); } break; |
62 | case ERR_TYPE_SEMANTIC: { fprintf(stderr, ": [semantic] "); } break; | ||
63 | case ERR_TYPE_BASM: { fprintf(stderr, ": [basm] "); } break; | ||
62 | default: break; | 64 | default: break; |
63 | } | 65 | } |
64 | fprintf(stderr, "%s\n", error_msgs[current_error.value]); | 66 | 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 @@ | |||
6 | typedef enum ErrorType { | 6 | typedef enum ErrorType { |
7 | ERR_TYPE_LEXER, | 7 | ERR_TYPE_LEXER, |
8 | ERR_TYPE_PARSER, | 8 | ERR_TYPE_PARSER, |
9 | ERR_TYPE_SEMANTIC, | ||
10 | ERR_TYPE_BASM, | ||
9 | } ErrorType; | 11 | } ErrorType; |
10 | 12 | ||
11 | typedef enum ErrorValue { | 13 | typedef enum ErrorValue { |
@@ -173,7 +173,7 @@ emit_builtin(ProgramBASM *program, Node *node) { | |||
173 | case TOKEN_LE: { return emit_numcomp(program, node, OP_JMP_GT); } break; | 173 | case TOKEN_LE: { return emit_numcomp(program, node, OP_JMP_GT); } break; |
174 | case TOKEN_GE: { return emit_numcomp(program, node, OP_JMP_LT); } break; | 174 | case TOKEN_GE: { return emit_numcomp(program, node, OP_JMP_LT); } break; |
175 | default: { | 175 | default: { |
176 | // TODO: assert unreachable. | 176 | push_error(ERR_TYPE_BASM, ERR_UNIMPLEMENTED, node->line, node->col); |
177 | return (Operand){0}; | 177 | return (Operand){0}; |
178 | } break; | 178 | } break; |
179 | } | 179 | } |
@@ -190,12 +190,36 @@ emit_number(ProgramBASM *program, Node *node) { | |||
190 | } | 190 | } |
191 | 191 | ||
192 | Operand | 192 | Operand |
193 | emit_bool(ProgramBASM *program, Node *node) { | ||
194 | LineInfo line = (LineInfo){.line = node->line, .col = node->col}; | ||
195 | Operand reg_dst = NEW_REG(); | ||
196 | Operand val; | ||
197 | if (node->boolean) { | ||
198 | val = NEW_S64(1); | ||
199 | } else { | ||
200 | val = NEW_S64(0); | ||
201 | } | ||
202 | EMIT_1(program, line, OP_LD8, reg_dst, val); | ||
203 | return reg_dst; | ||
204 | } | ||
205 | |||
206 | // TODO: emit_if | ||
207 | // TODO: emit_and | ||
208 | // TODO: emit_or | ||
209 | // TODO: emit_not | ||
210 | // TODO: emit_global | ||
211 | // TODO: emit_local | ||
212 | // TODO: emit_procedure | ||
213 | // TODO: emit_proc_call | ||
214 | |||
215 | Operand | ||
193 | emit_basm(ProgramBASM *program, Node *node) { | 216 | emit_basm(ProgramBASM *program, Node *node) { |
194 | switch (node->type) { | 217 | switch (node->type) { |
218 | case NODE_BOOL: { return emit_bool(program, node); } break; | ||
195 | case NODE_NUMBER: { return emit_number(program, node); } break; | 219 | case NODE_NUMBER: { return emit_number(program, node); } break; |
196 | case NODE_BUILTIN: { return emit_builtin(program, node); } break; | 220 | case NODE_BUILTIN: { return emit_builtin(program, node); } break; |
197 | default: { | 221 | default: { |
198 | printf("UNIMPLEMENTED\n"); | 222 | push_error(ERR_TYPE_BASM, ERR_UNIMPLEMENTED, node->line, node->col); |
199 | return (Operand){0}; | 223 | return (Operand){0}; |
200 | } break; | 224 | } break; |
201 | } | 225 | } |
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) { | |||
130 | } | 130 | } |
131 | scope = scope->parent; | 131 | scope = scope->parent; |
132 | } | 132 | } |
133 | push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TYPE, type->line, type->col); | 133 | push_error(ERR_TYPE_SEMANTIC, ERR_UNKNOWN_TYPE, type->line, type->col); |
134 | return NULL; | 134 | return NULL; |
135 | } | 135 | } |
136 | 136 | ||
@@ -139,7 +139,7 @@ insert_symbol(Scope *scope, Node *symbol, Symbol *val) { | |||
139 | // Check if symbol already exists. | 139 | // Check if symbol already exists. |
140 | HashTable *symbols = scope->symbols; | 140 | HashTable *symbols = scope->symbols; |
141 | if (ht_lookup(symbols, symbol) != NULL) { | 141 | if (ht_lookup(symbols, symbol) != NULL) { |
142 | push_error(ERR_TYPE_PARSER, ERR_SYMBOL_REDEF, symbol->line, symbol->col); | 142 | push_error(ERR_TYPE_SEMANTIC, ERR_SYMBOL_REDEF, symbol->line, symbol->col); |
143 | return false; | 143 | return false; |
144 | } | 144 | } |
145 | ht_insert(symbols, symbol, val); | 145 | ht_insert(symbols, symbol, val); |
@@ -214,7 +214,7 @@ find_symbol(Scope *scope, Node *node) { | |||
214 | } | 214 | } |
215 | scope = scope->parent; | 215 | scope = scope->parent; |
216 | } | 216 | } |
217 | push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_SYMBOL, node->line, node->col); | 217 | push_error(ERR_TYPE_SEMANTIC, ERR_UNKNOWN_SYMBOL, node->line, node->col); |
218 | return NULL; | 218 | return NULL; |
219 | } | 219 | } |
220 | 220 | ||
@@ -244,7 +244,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
244 | 244 | ||
245 | // Check that all arguments are numbers. | 245 | // Check that all arguments are numbers. |
246 | if (!type_is_numeric(arg->expr_type)) { | 246 | if (!type_is_numeric(arg->expr_type)) { |
247 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, | 247 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_NUM, |
248 | arg->line, arg->col); | 248 | arg->line, arg->col); |
249 | return false; | 249 | return false; |
250 | } | 250 | } |
@@ -259,13 +259,15 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
259 | } break; | 259 | } break; |
260 | // Bools. | 260 | // Bools. |
261 | case TOKEN_NOT: | 261 | case TOKEN_NOT: |
262 | // TODO: not should only take one argument and | ||
263 | // return the inverse. | ||
262 | case TOKEN_AND: | 264 | case TOKEN_AND: |
263 | case TOKEN_OR: { | 265 | case TOKEN_OR: { |
264 | // Check that all arguments are boolean. | 266 | // Check that all arguments are boolean. |
265 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 267 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { |
266 | Node *arg = node->builtin.args[i]; | 268 | Node *arg = node->builtin.args[i]; |
267 | if (arg->expr_type != &default_types[TYPE_BOOL]) { | 269 | if (arg->expr_type != &default_types[TYPE_BOOL]) { |
268 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_BOOL, | 270 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_BOOL, |
269 | arg->line, arg->col); | 271 | arg->line, arg->col); |
270 | return false; | 272 | return false; |
271 | } | 273 | } |
@@ -283,7 +285,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
283 | // TODO: Make sure all arguments have the same type, | 285 | // TODO: Make sure all arguments have the same type, |
284 | // like with numeric expressions. | 286 | // like with numeric expressions. |
285 | if (!type_is_numeric(arg->expr_type)) { | 287 | if (!type_is_numeric(arg->expr_type)) { |
286 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, | 288 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_NUM, |
287 | arg->line, arg->col); | 289 | arg->line, arg->col); |
288 | return false; | 290 | return false; |
289 | } | 291 | } |
@@ -354,7 +356,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
354 | StringView *type_body = &node->fun.body->expr_type->name; | 356 | StringView *type_body = &node->fun.body->expr_type->name; |
355 | StringView *return_type = &node->fun.return_type->string; | 357 | StringView *return_type = &node->fun.return_type->string; |
356 | if (!sv_equal(type_body, return_type)) { | 358 | if (!sv_equal(type_body, return_type)) { |
357 | push_error(ERR_TYPE_PARSER, ERR_WRONG_RET_TYPE, node->line, node->col); | 359 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_RET_TYPE, node->line, node->col); |
358 | return false; | 360 | return false; |
359 | } | 361 | } |
360 | } break; | 362 | } break; |
@@ -390,7 +392,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
390 | // Check ifexpr.cond is a bool. | 392 | // Check ifexpr.cond is a bool. |
391 | Type *type_cond = node->ifexpr.cond->expr_type; | 393 | Type *type_cond = node->ifexpr.cond->expr_type; |
392 | if (!sv_equal(&type_cond->name, &default_types[TYPE_BOOL].name)) { | 394 | if (!sv_equal(&type_cond->name, &default_types[TYPE_BOOL].name)) { |
393 | push_error(ERR_TYPE_PARSER, ERR_WRONG_COND_TYPE, | 395 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_COND_TYPE, |
394 | node->line, node->col); | 396 | node->line, node->col); |
395 | return false; | 397 | return false; |
396 | } | 398 | } |
@@ -401,7 +403,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
401 | if (type_is_numeric(type_true) && type_is_numeric(type_false)) { | 403 | if (type_is_numeric(type_true) && type_is_numeric(type_false)) { |
402 | node->expr_type = coerce_numeric_types(type_true, type_false); | 404 | node->expr_type = coerce_numeric_types(type_true, type_false); |
403 | } else if (!sv_equal(&type_true->name, &type_false->name)) { | 405 | } else if (!sv_equal(&type_true->name, &type_false->name)) { |
404 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_T_F, | 406 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_T_F, |
405 | node->line, node->col); | 407 | node->line, node->col); |
406 | return false; | 408 | return false; |
407 | } | 409 | } |
@@ -418,7 +420,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
418 | Node *symbol = node->set.symbol; | 420 | Node *symbol = node->set.symbol; |
419 | Node *value = node->set.value; | 421 | Node *value = node->set.value; |
420 | if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { | 422 | if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { |
421 | push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, | 423 | push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, |
422 | node->line, node->col); | 424 | node->line, node->col); |
423 | return false; | 425 | return false; |
424 | } | 426 | } |
@@ -446,7 +448,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
446 | Node *symbol = node->def.symbol; | 448 | Node *symbol = node->def.symbol; |
447 | Node *value = node->def.value; | 449 | Node *value = node->def.value; |
448 | if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { | 450 | if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { |
449 | push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, | 451 | push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, |
450 | node->line, node->col); | 452 | node->line, node->col); |
451 | return false; | 453 | return false; |
452 | } | 454 | } |
@@ -474,12 +476,12 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
474 | return false; | 476 | return false; |
475 | } | 477 | } |
476 | if (val->type != SYMBOL_FUN) { | 478 | if (val->type != SYMBOL_FUN) { |
477 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_FUN, | 479 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_FUN, |
478 | node->funcall.name->line, node->funcall.name->col); | 480 | node->funcall.name->line, node->funcall.name->col); |
479 | return false; | 481 | return false; |
480 | } | 482 | } |
481 | if (array_size(node->funcall.args) != array_size(val->fun.param_types)) { | 483 | if (array_size(node->funcall.args) != array_size(val->fun.param_types)) { |
482 | push_error(ERR_TYPE_PARSER, ERR_BAD_ARGS, node->line, node->col); | 484 | push_error(ERR_TYPE_SEMANTIC, ERR_BAD_ARGS, node->line, node->col); |
483 | return false; | 485 | return false; |
484 | } | 486 | } |
485 | node->expr_type = node->funcall.name->expr_type; | 487 | node->expr_type = node->funcall.name->expr_type; |
@@ -490,7 +492,7 @@ resolve_type(ParseTree *ast, Scope *scope, Node *node) { | |||
490 | } | 492 | } |
491 | Node *expected = val->fun.param_types[i]; | 493 | Node *expected = val->fun.param_types[i]; |
492 | if (!sv_equal(&arg->expr_type->name, &expected->string)) { | 494 | if (!sv_equal(&arg->expr_type->name, &expected->string)) { |
493 | push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, | 495 | push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, |
494 | arg->line, arg->col); | 496 | arg->line, arg->col); |
495 | return false; | 497 | return false; |
496 | } | 498 | } |