diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-25 10:36:02 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-25 10:36:02 +0200 |
commit | bcc40682a0d699e8c36df62975c12cdea491d167 (patch) | |
tree | 6511cdef1730d39bb81fceaf9839658654280f32 /src/main.c | |
parent | 9eb5c9bfa3fcf8d7b03efd7d4def71e39ae3f799 (diff) | |
download | bdl-bcc40682a0d699e8c36df62975c12cdea491d167.tar.gz bdl-bcc40682a0d699e8c36df62975c12cdea491d167.zip |
Add struct literals typechecking
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 58 |
1 files changed, 49 insertions, 9 deletions
@@ -12,6 +12,8 @@ | |||
12 | // TODO: nested structs | 12 | // TODO: nested structs |
13 | // TODO: unions | 13 | // TODO: unions |
14 | // TODO: match deconstruct structs | 14 | // TODO: match deconstruct structs |
15 | // TODO: arrays and pointers | ||
16 | // TODO: struct literals | ||
15 | 17 | ||
16 | typedef enum ExecMode { | 18 | typedef enum ExecMode { |
17 | RUN_NORMAL, | 19 | RUN_NORMAL, |
@@ -486,13 +488,18 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
486 | } | 488 | } |
487 | // TODO: Consider compatible types. | 489 | // TODO: Consider compatible types. |
488 | if (!str_eq(type, type_name)) { | 490 | if (!str_eq(type, type_name)) { |
489 | eprintln( | 491 | // Special case, enums can be treated as ints. |
490 | "%s:%d:%d: error: type mismatch, trying to assing " | 492 | EnumMap *e = find_enum(scope, type_name); |
491 | "%s" | 493 | if (!(e && str_eq(type, cstr("int")))) { |
492 | " to a variable of type %s", | 494 | eprintln( |
493 | a->file_name, node->var_type->line, | 495 | "%s:%d:%d: error: type mismatch, trying to " |
494 | node->var_type->col, type, type_name); | 496 | "assing " |
495 | return cstr(""); | 497 | "%s" |
498 | " to a variable of type %s", | ||
499 | a->file_name, node->var_type->line, | ||
500 | node->var_type->col, type, type_name); | ||
501 | return cstr(""); | ||
502 | } | ||
496 | } | 503 | } |
497 | } | 504 | } |
498 | typemap_insert(&scope->types, symbol, type->val, a->storage); | 505 | typemap_insert(&scope->types, symbol, type->val, a->storage); |
@@ -515,8 +522,7 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
515 | "%s:%d:%d: error: type mismatch, trying to assing " | 522 | "%s:%d:%d: error: type mismatch, trying to assing " |
516 | "%s" | 523 | "%s" |
517 | " to a variable of type %s", | 524 | " to a variable of type %s", |
518 | a->file_name, node->line, node->col, | 525 | a->file_name, node->line, node->col, val, name); |
519 | val, name); | ||
520 | return cstr(""); | 526 | return cstr(""); |
521 | } | 527 | } |
522 | node->type = cstr("nil"); | 528 | node->type = cstr("nil"); |
@@ -849,6 +855,40 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
849 | node->type = type->val; | 855 | node->type = type->val; |
850 | return node->type; | 856 | return node->type; |
851 | } break; | 857 | } break; |
858 | case NODE_STRUCT_LIT: { | ||
859 | Str name = node->value.str; | ||
860 | StructMap *s = find_struct(scope, name); | ||
861 | if (!s) { | ||
862 | eprintln("%s:%d:%d: error: unknown struct type '%s'", | ||
863 | a->file_name, node->line, node->col, name); | ||
864 | return cstr(""); | ||
865 | } | ||
866 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
867 | Node *next = node->elements[i]; | ||
868 | Str field_name = next->field_name->value.str; | ||
869 | FieldMap *field = fieldmap_lookup(&s->val.fields, field_name); | ||
870 | if (!field) { | ||
871 | eprintln( | ||
872 | "%s:%d:%d: error: unknown struct field for symbol '%s'", | ||
873 | a->file_name, next->line, next->col, field_name); | ||
874 | } else { | ||
875 | if (next->field_val) { | ||
876 | Type type = type_inference(a, next->field_val, scope); | ||
877 | if (!str_eq(type, field->val.type)) { | ||
878 | eprintln( | ||
879 | "%s:%d:%d: error: mismatched types in struct " | ||
880 | "value " | ||
881 | "for '%s.%s': %s expected %s", | ||
882 | a->file_name, next->line, next->col, name, | ||
883 | field_name, type, field->val.type); | ||
884 | } | ||
885 | } | ||
886 | next->type = field->val.type; | ||
887 | } | ||
888 | } | ||
889 | node->type = name; | ||
890 | return node->type; | ||
891 | } break; | ||
852 | case NODE_FUNCALL: { | 892 | case NODE_FUNCALL: { |
853 | Str symbol = node->value.str; | 893 | Str symbol = node->value.str; |
854 | FunMap *fun = find_fun(scope, symbol); | 894 | FunMap *fun = find_fun(scope, symbol); |