diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-26 08:54:55 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-26 08:54:55 +0200 |
commit | aad6b8707d59efc5c4136db470896112a45e82b1 (patch) | |
tree | a5bc48f201e5236778b46bb98b279b18a919bec5 /src/main.c | |
parent | 5453e1545b4b3663408456ac8c8aedf2da856ac0 (diff) | |
download | bdl-aad6b8707d59efc5c4136db470896112a45e82b1.tar.gz bdl-aad6b8707d59efc5c4136db470896112a45e82b1.zip |
Fix typechecking for nested struct literals
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 53 |
1 files changed, 35 insertions, 18 deletions
@@ -441,6 +441,40 @@ typecheck_field(Analyzer *a, Node *node, TypeScope *scope, Str symbol) { | |||
441 | } | 441 | } |
442 | 442 | ||
443 | void | 443 | void |
444 | typecheck_lit_field(Analyzer *a, Node *node, TypeScope *scope, Str symbol) { | ||
445 | if (node->field_val->kind == NODE_COMPOUND_TYPE) { | ||
446 | Str type = cstr("\\{ "); | ||
447 | for (sz i = 0; i < array_size(node->field_val->elements); i++) { | ||
448 | Node *field = node->field_val->elements[i]; | ||
449 | Str field_name = str_concat(symbol, cstr("."), a->storage); | ||
450 | field_name = str_concat(field_name, field->value.str, a->storage); | ||
451 | typecheck_lit_field(a, field, scope, field_name); | ||
452 | type = str_concat(type, field->type, a->storage); | ||
453 | type = str_concat(type, cstr(" "), a->storage); | ||
454 | } | ||
455 | type = str_concat(type, cstr("\\}"), a->storage); | ||
456 | node->type = type; | ||
457 | } else { | ||
458 | StructMap *s = structmap_lookup(&scope->structs, symbol); | ||
459 | if (!s) { | ||
460 | eprintln("%s:%d:%d: error: unknown struct field '%s'", a->file_name, | ||
461 | node->line, node->col, symbol); | ||
462 | return; | ||
463 | } | ||
464 | Str field_type = s->val.type; | ||
465 | Type type = type_inference(a, node->field_val, scope); | ||
466 | if (!str_eq(type, field_type)) { | ||
467 | eprintln( | ||
468 | "%s:%d:%d: error: mismatched types in struct " | ||
469 | "value " | ||
470 | "for '%s': %s expected %s", | ||
471 | a->file_name, node->line, node->col, symbol, type, field_type); | ||
472 | } | ||
473 | node->type = field_type; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | void | ||
444 | typecheck_returns(Analyzer *a, Node *node, Str expected) { | 478 | typecheck_returns(Analyzer *a, Node *node, Str expected) { |
445 | if (!node) { | 479 | if (!node) { |
446 | return; | 480 | return; |
@@ -922,24 +956,7 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
922 | } else { | 956 | } else { |
923 | strset_insert(&set, field_name, a->storage); | 957 | strset_insert(&set, field_name, a->storage); |
924 | } | 958 | } |
925 | 959 | typecheck_lit_field(a, next, s.scope, field_name); | |
926 | StructMap *field = | ||
927 | structmap_lookup(&s.scope->structs, field_name); | ||
928 | if (!field) { | ||
929 | eprintln("%s:%d:%d: error: unknown struct field '%s'", | ||
930 | a->file_name, next->line, next->col, field_name); | ||
931 | } else { | ||
932 | Type type = type_inference(a, next->field_val, scope); | ||
933 | if (!str_eq(type, field->val.type)) { | ||
934 | eprintln( | ||
935 | "%s:%d:%d: error: mismatched types in struct " | ||
936 | "literal for '%s': %s expected %s ", | ||
937 | a->file_name, next->line, next->col, field_name, | ||
938 | type, field->val.type); | ||
939 | } | ||
940 | next->type = type; | ||
941 | } | ||
942 | // TODO: nested fields. | ||
943 | } | 960 | } |
944 | node->type = name; | 961 | node->type = name; |
945 | return node->type; | 962 | return node->type; |