aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-26 17:36:21 +0200
committerBad Diode <bd@badd10de.dev>2024-06-26 17:36:21 +0200
commit3b9cfd8b515d5b2969e242ea730792ae26f5fbfe (patch)
treefcc2a9f518481d612a304bc374f247be090bf9e2 /src/main.c
parenta93323df87caeb345df74a2141c72d591db91c7b (diff)
downloadbdl-3b9cfd8b515d5b2969e242ea730792ae26f5fbfe.tar.gz
bdl-3b9cfd8b515d5b2969e242ea730792ae26f5fbfe.zip
Add enum de-structuring and int matching on match expr
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c65
1 files changed, 54 insertions, 11 deletions
diff --git a/src/main.c b/src/main.c
index 5c99a10..8026d0d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,8 +8,8 @@
8#include "vm.c" 8#include "vm.c"
9 9
10// TODO: unions 10// TODO: unions
11// TODO: match deconstruct enums
12// TODO: arrays and pointers 11// TODO: arrays and pointers
12// TODO: embed (binary file) and include (source file)
13 13
14typedef enum ExecMode { 14typedef enum ExecMode {
15 RUN_NORMAL, 15 RUN_NORMAL,
@@ -600,7 +600,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
600 &scope->symbols, field_name, 600 &scope->symbols, field_name,
601 (Symbol){.name = field_name, .kind = SYM_ENUM_FIELD}, 601 (Symbol){.name = field_name, .kind = SYM_ENUM_FIELD},
602 a->storage); 602 a->storage);
603 field->type = cstr("int"); 603 field->type = symbol;
604 } 604 }
605 symmap_insert(&scope->symbols, symbol, 605 symmap_insert(&scope->symbols, symbol,
606 (Symbol){.name = symbol, .kind = SYM_ENUM}, 606 (Symbol){.name = symbol, .kind = SYM_ENUM},
@@ -652,11 +652,57 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
652 node->type = cstr("nil"); 652 node->type = cstr("nil");
653 return node->type; 653 return node->type;
654 } break; 654 } break;
655 case NODE_COND: 655 case NODE_COND: {
656 Str previous = cstr("");
657 for (sz i = 0; i < array_size(node->match_cases); i++) {
658 Node *expr = node->match_cases[i];
659 Str next = type_inference(a, expr, scope);
660 if (i != 0 && !str_eq(next, previous)) {
661 emit_semantic_error(
662 a, node,
663 cstr("non-matching types for cond expressions"));
664 return cstr("");
665 }
666 previous = next;
667 }
668 node->type = previous;
669 return node->type;
670 } break;
656 case NODE_MATCH: { 671 case NODE_MATCH: {
657 // TODO: proper typecheck matchcase expressions here... 672 Str e = type_inference(a, node->match_expr, scope);
658 if (node->match_expr) { 673 if (str_eq(e, cstr("int"))) {
659 type_inference(a, node->match_expr, scope); 674 // Integer matching.
675 for (sz i = 0; i < array_size(node->match_cases); i++) {
676 Node *field = node->match_cases[i];
677 if (field->case_value) {
678 if (field->case_value->kind != NODE_NUM_INT &&
679 field->case_value->kind != NODE_NUM_UINT) {
680 emit_semantic_error(
681 a, field->case_value,
682 cstr(
683 "non-integer or enum types on match case"));
684 }
685 }
686 }
687 } else {
688 // Get enum type and de-structure the match.
689 FindEnumResult res = find_enum(scope, e);
690 Str enum_prefix =
691 str_concat(res.map->val.name, cstr("."), a->storage);
692 for (sz i = 0; i < array_size(node->match_cases); i++) {
693 Node *field = node->match_cases[i];
694 if (field->case_value) {
695 Str field_name = str_concat(
696 enum_prefix, field->case_value->value.str,
697 a->storage);
698 if (!enummap_lookup(&res.scope->enums, field_name)) {
699 eprintln("%s:%d:%d: error: unknown enum field '%s'",
700 a->file_name, field->case_value->line,
701 field->case_value->col, field_name);
702 a->err = true;
703 }
704 }
705 }
660 } 706 }
661 Str previous = cstr(""); 707 Str previous = cstr("");
662 for (sz i = 0; i < array_size(node->match_cases); i++) { 708 for (sz i = 0; i < array_size(node->match_cases); i++) {
@@ -665,7 +711,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
665 if (i != 0 && !str_eq(next, previous)) { 711 if (i != 0 && !str_eq(next, previous)) {
666 emit_semantic_error( 712 emit_semantic_error(
667 a, node, 713 a, node,
668 cstr("non-matching types for case expressions")); 714 cstr("non-matching types for match expressions"));
669 return cstr(""); 715 return cstr("");
670 } 716 }
671 previous = next; 717 previous = next;
@@ -674,9 +720,6 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
674 return node->type; 720 return node->type;
675 } break; 721 } break;
676 case NODE_CASE_MATCH: { 722 case NODE_CASE_MATCH: {
677 if (node->case_value) {
678 type_inference(a, node->case_value, scope);
679 }
680 if (node->case_expr->kind != NODE_BLOCK) { 723 if (node->case_expr->kind != NODE_BLOCK) {
681 scope = typescope_alloc(a, scope); 724 scope = typescope_alloc(a, scope);
682 } 725 }
@@ -846,7 +889,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
846 a->err = true; 889 a->err = true;
847 return cstr(""); 890 return cstr("");
848 } 891 }
849 node->next->type = cstr("int"); 892 node->next->type = type->val.name;
850 node->type = type->val.name; 893 node->type = type->val.name;
851 return node->next->type; 894 return node->next->type;
852 } 895 }