diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-26 17:36:21 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-26 17:36:21 +0200 |
commit | 3b9cfd8b515d5b2969e242ea730792ae26f5fbfe (patch) | |
tree | fcc2a9f518481d612a304bc374f247be090bf9e2 /src/main.c | |
parent | a93323df87caeb345df74a2141c72d591db91c7b (diff) | |
download | bdl-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.c | 65 |
1 files changed, 54 insertions, 11 deletions
@@ -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 | ||
14 | typedef enum ExecMode { | 14 | typedef 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 | } |