diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-26 16:30:57 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-26 16:30:57 +0200 |
commit | a93323df87caeb345df74a2141c72d591db91c7b (patch) | |
tree | 919881d8de05040b6cc8675189d093dce88ac890 /src/main.c | |
parent | 56510571a9d2c6c1242d5efc26c4ab2905269930 (diff) | |
download | bdl-a93323df87caeb345df74a2141c72d591db91c7b.tar.gz bdl-a93323df87caeb345df74a2141c72d591db91c7b.zip |
Add err to analyzer context
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 35 |
1 files changed, 33 insertions, 2 deletions
@@ -10,7 +10,6 @@ | |||
10 | // TODO: unions | 10 | // TODO: unions |
11 | // TODO: match deconstruct enums | 11 | // TODO: match deconstruct enums |
12 | // TODO: arrays and pointers | 12 | // TODO: arrays and pointers |
13 | // TODO: if we have errors make sure we mark the analyzer as such | ||
14 | 13 | ||
15 | typedef enum ExecMode { | 14 | typedef enum ExecMode { |
16 | RUN_NORMAL, | 15 | RUN_NORMAL, |
@@ -98,6 +97,7 @@ typedef struct Analyzer { | |||
98 | Scope **scopes; | 97 | Scope **scopes; |
99 | StrSet *numeric_types; | 98 | StrSet *numeric_types; |
100 | StrSet *integer_types; | 99 | StrSet *integer_types; |
100 | bool err; | ||
101 | } Analyzer; | 101 | } Analyzer; |
102 | 102 | ||
103 | Scope * | 103 | Scope * |
@@ -274,6 +274,7 @@ graph_types(Scope **scopes, Arena a) { | |||
274 | void | 274 | void |
275 | emit_semantic_error(Analyzer *a, Node *n, Str msg) { | 275 | emit_semantic_error(Analyzer *a, Node *n, Str msg) { |
276 | eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg); | 276 | eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg); |
277 | a->err = true; | ||
277 | } | 278 | } |
278 | 279 | ||
279 | Str type_inference(Analyzer *a, Node *node, Scope *scope); | 280 | Str type_inference(Analyzer *a, Node *node, Scope *scope); |
@@ -286,6 +287,7 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
286 | if (structmap_lookup(&scope->structs, field_name)) { | 287 | if (structmap_lookup(&scope->structs, field_name)) { |
287 | eprintln("%s:%d:%d: error: struct field '%s' already exists", | 288 | eprintln("%s:%d:%d: error: struct field '%s' already exists", |
288 | a->file_name, node->line, node->col, field_name); | 289 | a->file_name, node->line, node->col, field_name); |
290 | a->err = true; | ||
289 | } | 291 | } |
290 | Str type = cstr("\\{ "); | 292 | Str type = cstr("\\{ "); |
291 | for (sz i = 0; i < array_size(node->field_type->elements); i++) { | 293 | for (sz i = 0; i < array_size(node->field_type->elements); i++) { |
@@ -303,10 +305,12 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
303 | if (!find_type(scope, field_type)) { | 305 | if (!find_type(scope, field_type)) { |
304 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 306 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
305 | node->field_type->line, node->field_type->col, field_type); | 307 | node->field_type->line, node->field_type->col, field_type); |
308 | a->err = true; | ||
306 | } | 309 | } |
307 | if (structmap_lookup(&scope->structs, field_name)) { | 310 | if (structmap_lookup(&scope->structs, field_name)) { |
308 | eprintln("%s:%d:%d: error: struct field '%s' already exists", | 311 | eprintln("%s:%d:%d: error: struct field '%s' already exists", |
309 | a->file_name, node->line, node->col, field_name); | 312 | a->file_name, node->line, node->col, field_name); |
313 | a->err = true; | ||
310 | } | 314 | } |
311 | if (node->field_val) { | 315 | if (node->field_val) { |
312 | Str type = type_inference(a, node->field_val, scope); | 316 | Str type = type_inference(a, node->field_val, scope); |
@@ -317,6 +321,7 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
317 | "for '%s': %s expected %s", | 321 | "for '%s': %s expected %s", |
318 | a->file_name, node->line, node->col, field_name, type, | 322 | a->file_name, node->line, node->col, field_name, type, |
319 | field_type); | 323 | field_type); |
324 | a->err = true; | ||
320 | } | 325 | } |
321 | } | 326 | } |
322 | structmap_insert(&scope->structs, field_name, | 327 | structmap_insert(&scope->structs, field_name, |
@@ -352,6 +357,7 @@ typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
352 | if (!s) { | 357 | if (!s) { |
353 | eprintln("%s:%d:%d: error: unknown struct field '%s'", a->file_name, | 358 | eprintln("%s:%d:%d: error: unknown struct field '%s'", a->file_name, |
354 | node->line, node->col, symbol); | 359 | node->line, node->col, symbol); |
360 | a->err = true; | ||
355 | return; | 361 | return; |
356 | } | 362 | } |
357 | Str field_type = s->val.type; | 363 | Str field_type = s->val.type; |
@@ -362,6 +368,7 @@ typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
362 | "value " | 368 | "value " |
363 | "for '%s': %s expected %s", | 369 | "for '%s': %s expected %s", |
364 | a->file_name, node->line, node->col, symbol, type, field_type); | 370 | a->file_name, node->line, node->col, symbol, type, field_type); |
371 | a->err = true; | ||
365 | } | 372 | } |
366 | node->type = field_type; | 373 | node->type = field_type; |
367 | } | 374 | } |
@@ -387,6 +394,7 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
387 | eprintln( | 394 | eprintln( |
388 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 395 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
389 | a->file_name, node->line, node->col, node->type, expected); | 396 | a->file_name, node->line, node->col, node->type, expected); |
397 | a->err = true; | ||
390 | } | 398 | } |
391 | } break; | 399 | } break; |
392 | case NODE_BLOCK: { | 400 | case NODE_BLOCK: { |
@@ -457,6 +465,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
457 | "scope ", | 465 | "scope ", |
458 | a->file_name, node->var_name->line, node->var_name->col, | 466 | a->file_name, node->var_name->line, node->var_name->col, |
459 | symbol); | 467 | symbol); |
468 | a->err = true; | ||
460 | return cstr(""); | 469 | return cstr(""); |
461 | } | 470 | } |
462 | if (node->var_type) { | 471 | if (node->var_type) { |
@@ -466,6 +475,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
466 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 475 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
467 | node->var_type->line, node->var_type->col, | 476 | node->var_type->line, node->var_type->col, |
468 | type_name); | 477 | type_name); |
478 | a->err = true; | ||
469 | return cstr(""); | 479 | return cstr(""); |
470 | } | 480 | } |
471 | if (node->var_val) { | 481 | if (node->var_val) { |
@@ -476,6 +486,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
476 | "'%s'", | 486 | "'%s'", |
477 | a->file_name, node->var_type->line, | 487 | a->file_name, node->var_type->line, |
478 | node->var_type->col, symbol); | 488 | node->var_type->col, symbol); |
489 | a->err = true; | ||
479 | return cstr(""); | 490 | return cstr(""); |
480 | } | 491 | } |
481 | // TODO: Consider compatible types. | 492 | // TODO: Consider compatible types. |
@@ -490,6 +501,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
490 | " to a variable of type %s", | 501 | " to a variable of type %s", |
491 | a->file_name, node->var_type->line, | 502 | a->file_name, node->var_type->line, |
492 | node->var_type->col, type, type_name); | 503 | node->var_type->col, type, type_name); |
504 | a->err = true; | ||
493 | return cstr(""); | 505 | return cstr(""); |
494 | } | 506 | } |
495 | } | 507 | } |
@@ -517,6 +529,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
517 | "%s" | 529 | "%s" |
518 | " to a variable of type %s", | 530 | " to a variable of type %s", |
519 | a->file_name, node->line, node->col, val, name); | 531 | a->file_name, node->line, node->col, val, name); |
532 | a->err = true; | ||
520 | return cstr(""); | 533 | return cstr(""); |
521 | } | 534 | } |
522 | node->type = cstr("nil"); | 535 | node->type = cstr("nil"); |
@@ -530,6 +543,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
530 | "%s:%d:%d: error: struct '%s' already exists in current " | 543 | "%s:%d:%d: error: struct '%s' already exists in current " |
531 | "scope", | 544 | "scope", |
532 | a->file_name, node->line, node->col, symbol); | 545 | a->file_name, node->line, node->col, symbol); |
546 | a->err = true; | ||
533 | return cstr(""); | 547 | return cstr(""); |
534 | } | 548 | } |
535 | structmap_insert(&scope->structs, symbol, (Struct){.name = symbol}, | 549 | structmap_insert(&scope->structs, symbol, (Struct){.name = symbol}, |
@@ -551,6 +565,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
551 | "%s:%d:%d: error: enum '%s' already exists in current " | 565 | "%s:%d:%d: error: enum '%s' already exists in current " |
552 | "scope", | 566 | "scope", |
553 | a->file_name, node->line, node->col, symbol); | 567 | a->file_name, node->line, node->col, symbol); |
568 | a->err = true; | ||
554 | return cstr(""); | 569 | return cstr(""); |
555 | } | 570 | } |
556 | enummap_insert(&scope->enums, symbol, | 571 | enummap_insert(&scope->enums, symbol, |
@@ -567,6 +582,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
567 | if (enummap_lookup(&scope->enums, field_name)) { | 582 | if (enummap_lookup(&scope->enums, field_name)) { |
568 | eprintln("%s:%d:%d: error: enum field '%s' already exists", | 583 | eprintln("%s:%d:%d: error: enum field '%s' already exists", |
569 | a->file_name, field->line, field->col, field_name); | 584 | a->file_name, field->line, field->col, field_name); |
585 | a->err = true; | ||
570 | } | 586 | } |
571 | if (field->field_val) { | 587 | if (field->field_val) { |
572 | Str type = type_inference(a, field->field_val, scope); | 588 | Str type = type_inference(a, field->field_val, scope); |
@@ -575,6 +591,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
575 | "%s:%d:%d: error: non int enum value for '%s.%s'", | 591 | "%s:%d:%d: error: non int enum value for '%s.%s'", |
576 | a->file_name, field->line, field->col, symbol, | 592 | a->file_name, field->line, field->col, symbol, |
577 | field_name); | 593 | field_name); |
594 | a->err = true; | ||
578 | } | 595 | } |
579 | } | 596 | } |
580 | enummap_insert(&scope->enums, field_name, | 597 | enummap_insert(&scope->enums, field_name, |
@@ -803,6 +820,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
803 | if (!type) { | 820 | if (!type) { |
804 | eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'", | 821 | eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'", |
805 | a->file_name, node->line, node->col, symbol); | 822 | a->file_name, node->line, node->col, symbol); |
823 | a->err = true; | ||
806 | return cstr(""); | 824 | return cstr(""); |
807 | } | 825 | } |
808 | 826 | ||
@@ -813,6 +831,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
813 | "%s:%d:%d: error: unspecified enum field for symbol " | 831 | "%s:%d:%d: error: unspecified enum field for symbol " |
814 | "'%s'", | 832 | "'%s'", |
815 | a->file_name, node->line, node->col, symbol); | 833 | a->file_name, node->line, node->col, symbol); |
834 | a->err = true; | ||
816 | return cstr(""); | 835 | return cstr(""); |
817 | } | 836 | } |
818 | // Check if there is a next and it matches the enum field. | 837 | // Check if there is a next and it matches the enum field. |
@@ -824,6 +843,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
824 | "'%s': %s", | 843 | "'%s': %s", |
825 | a->file_name, node->line, node->col, symbol, | 844 | a->file_name, node->line, node->col, symbol, |
826 | node->next->value.str); | 845 | node->next->value.str); |
846 | a->err = true; | ||
827 | return cstr(""); | 847 | return cstr(""); |
828 | } | 848 | } |
829 | node->next->type = cstr("int"); | 849 | node->next->type = cstr("int"); |
@@ -839,6 +859,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
839 | "'%s', did you mean to use %s:{}?", | 859 | "'%s', did you mean to use %s:{}?", |
840 | a->file_name, node->line, node->col, type->val, | 860 | a->file_name, node->line, node->col, type->val, |
841 | type->val); | 861 | type->val); |
862 | a->err = true; | ||
842 | return cstr(""); | 863 | return cstr(""); |
843 | } else { | 864 | } else { |
844 | if (node->next) { | 865 | if (node->next) { |
@@ -856,6 +877,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
856 | eprintln( | 877 | eprintln( |
857 | "%s:%d:%d: error: unknown struct field '%s'", | 878 | "%s:%d:%d: error: unknown struct field '%s'", |
858 | a->file_name, node->line, node->col, chain); | 879 | a->file_name, node->line, node->col, chain); |
880 | a->err = true; | ||
859 | return cstr(""); | 881 | return cstr(""); |
860 | } | 882 | } |
861 | node->type = field->val.type; | 883 | node->type = field->val.type; |
@@ -872,6 +894,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
872 | if (!s.map) { | 894 | if (!s.map) { |
873 | eprintln("%s:%d:%d: error: unknown struct type '%s'", | 895 | eprintln("%s:%d:%d: error: unknown struct type '%s'", |
874 | a->file_name, node->line, node->col, name); | 896 | a->file_name, node->line, node->col, name); |
897 | a->err = true; | ||
875 | return cstr(""); | 898 | return cstr(""); |
876 | } | 899 | } |
877 | 900 | ||
@@ -887,6 +910,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
887 | "%s:%d:%d: error: field '%s' already present in struct " | 910 | "%s:%d:%d: error: field '%s' already present in struct " |
888 | "literal", | 911 | "literal", |
889 | a->file_name, next->line, next->col, field_name); | 912 | a->file_name, next->line, next->col, field_name); |
913 | a->err = true; | ||
890 | } else { | 914 | } else { |
891 | strset_insert(&set, field_name, a->storage); | 915 | strset_insert(&set, field_name, a->storage); |
892 | } | 916 | } |
@@ -903,6 +927,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
903 | "%s:%d:%d: error: function '%s' doesn't exist in current " | 927 | "%s:%d:%d: error: function '%s' doesn't exist in current " |
904 | "scope ", | 928 | "scope ", |
905 | a->file_name, node->line, node->col, symbol); | 929 | a->file_name, node->line, node->col, symbol); |
930 | a->err = true; | ||
906 | return cstr(""); | 931 | return cstr(""); |
907 | } | 932 | } |
908 | // Check that actual parameters typecheck | 933 | // Check that actual parameters typecheck |
@@ -924,6 +949,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
924 | "%s:%d:%d: error: mismatched parameter types: %s expected " | 949 | "%s:%d:%d: error: mismatched parameter types: %s expected " |
925 | "%s", | 950 | "%s", |
926 | a->file_name, node->line, node->col, args, expected); | 951 | a->file_name, node->line, node->col, args, expected); |
952 | a->err = true; | ||
927 | } | 953 | } |
928 | node->type = fun->val.return_type; | 954 | node->type = fun->val.return_type; |
929 | return node->type; | 955 | return node->type; |
@@ -1002,6 +1028,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1002 | "scope ", | 1028 | "scope ", |
1003 | a->file_name, node->var_name->line, node->var_name->col, | 1029 | a->file_name, node->var_name->line, node->var_name->col, |
1004 | symbol); | 1030 | symbol); |
1031 | a->err = true; | ||
1005 | return cstr(""); | 1032 | return cstr(""); |
1006 | } | 1033 | } |
1007 | symmap_insert(&scope->symbols, symbol, | 1034 | symmap_insert(&scope->symbols, symbol, |
@@ -1035,6 +1062,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1035 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 1062 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
1036 | a->file_name, node->line, node->col, node->func_body->type, | 1063 | a->file_name, node->line, node->col, node->func_body->type, |
1037 | ret_type); | 1064 | ret_type); |
1065 | a->err = true; | ||
1038 | } | 1066 | } |
1039 | 1067 | ||
1040 | // Ensure ALL return statements match the function prototype. | 1068 | // Ensure ALL return statements match the function prototype. |
@@ -1115,6 +1143,7 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
1115 | "scope ", | 1143 | "scope ", |
1116 | a->file_name, root->var_name->line, root->var_name->col, | 1144 | a->file_name, root->var_name->line, root->var_name->col, |
1117 | symbol); | 1145 | symbol); |
1146 | a->err = true; | ||
1118 | } | 1147 | } |
1119 | symmap_insert(&scope->symbols, symbol, | 1148 | symmap_insert(&scope->symbols, symbol, |
1120 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1149 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
@@ -1198,10 +1227,12 @@ process_file(Str path) { | |||
1198 | .file_name = path, | 1227 | .file_name = path, |
1199 | }; | 1228 | }; |
1200 | symbolic_analysis(&analyzer, &parser); | 1229 | symbolic_analysis(&analyzer, &parser); |
1230 | if (analyzer.err) { | ||
1231 | exit(EXIT_FAILURE); | ||
1232 | } | ||
1201 | 1233 | ||
1202 | // Printing symbol tables. | 1234 | // Printing symbol tables. |
1203 | if (mode == PRINT_SYMTABLES) { | 1235 | if (mode == PRINT_SYMTABLES) { |
1204 | // graph_symbols(analyzer.scopes, lexer_arena); | ||
1205 | graph_types(analyzer.scopes, lexer_arena); | 1236 | graph_types(analyzer.scopes, lexer_arena); |
1206 | } | 1237 | } |
1207 | if (mode == PRINT_SEMANTIC) { | 1238 | if (mode == PRINT_SEMANTIC) { |