aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-25 19:21:04 +0200
committerBad Diode <bd@badd10de.dev>2024-06-25 19:21:04 +0200
commite61947196d898232d40a63d5bbe40ec82b260c03 (patch)
tree878b580d6403143bcca43392c28a1ef525f2b02a /src
parent90507290b8b6f9d15605c53480225f5a10a36ca7 (diff)
downloadbdl-e61947196d898232d40a63d5bbe40ec82b260c03.tar.gz
bdl-e61947196d898232d40a63d5bbe40ec82b260c03.zip
Bugfixes for struct accessors
Diffstat (limited to 'src')
-rw-r--r--src/main.c96
1 files changed, 45 insertions, 51 deletions
diff --git a/src/main.c b/src/main.c
index c8584e4..6d25b2d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -13,6 +13,8 @@
13// TODO: match deconstruct structs 13// TODO: match deconstruct structs
14// TODO: arrays and pointers 14// TODO: arrays and pointers
15// TODO: struct literals with compound types 15// TODO: struct literals with compound types
16// FIXME: there may be an issue with shadowed structs sharing fields... we may
17// want to consider moving the fields to separate maps again...
16 18
17typedef enum ExecMode { 19typedef enum ExecMode {
18 RUN_NORMAL, 20 RUN_NORMAL,
@@ -378,23 +380,19 @@ emit_semantic_error(Analyzer *a, Node *n, Str msg) {
378Type type_inference(Analyzer *a, Node *node, TypeScope *scope); 380Type type_inference(Analyzer *a, Node *node, TypeScope *scope);
379 381
380void 382void
381typecheck_field(Analyzer *a, 383typecheck_field(Analyzer *a, Node *node, TypeScope *scope, Str symbol) {
382 Node *node,
383 TypeScope *scope,
384 Str symbol,
385 StructMap *map) {
386 // TODO: ensure the tables are filled properly. 384 // TODO: ensure the tables are filled properly.
387 if (node->field_type->kind == NODE_COMPOUND_TYPE) { 385 if (node->field_type->kind == NODE_COMPOUND_TYPE) {
388 Str field_name = str_concat(symbol, cstr("."), a->storage); 386 Str field_name = str_concat(symbol, cstr("."), a->storage);
389 field_name = str_concat(field_name, node->value.str, a->storage); 387 field_name = str_concat(field_name, node->value.str, a->storage);
390 if (structmap_lookup(&map, field_name)) { 388 if (structmap_lookup(&scope->structs, field_name)) {
391 eprintln("%s:%d:%d: error: struct field '%s' already exists", 389 eprintln("%s:%d:%d: error: struct field '%s' already exists",
392 a->file_name, node->line, node->col, field_name); 390 a->file_name, node->line, node->col, field_name);
393 } 391 }
394 Str type = cstr("\\{ "); 392 Str type = cstr("\\{ ");
395 for (sz i = 0; i < array_size(node->field_type->elements); i++) { 393 for (sz i = 0; i < array_size(node->field_type->elements); i++) {
396 Node *field = node->field_type->elements[i]; 394 Node *field = node->field_type->elements[i];
397 typecheck_field(a, field, scope, field_name, map); 395 typecheck_field(a, field, scope, field_name);
398 type = str_concat(type, field->type, a->storage); 396 type = str_concat(type, field->type, a->storage);
399 type = str_concat(type, cstr(" "), a->storage); 397 type = str_concat(type, cstr(" "), a->storage);
400 } 398 }
@@ -408,7 +406,7 @@ typecheck_field(Analyzer *a,
408 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, 406 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name,
409 node->field_type->line, node->field_type->col, field_type); 407 node->field_type->line, node->field_type->col, field_type);
410 } 408 }
411 if (structmap_lookup(&map, field_name)) { 409 if (structmap_lookup(&scope->structs, field_name)) {
412 eprintln("%s:%d:%d: error: struct field '%s' already exists", 410 eprintln("%s:%d:%d: error: struct field '%s' already exists",
413 a->file_name, node->line, node->col, field_name); 411 a->file_name, node->line, node->col, field_name);
414 } 412 }
@@ -423,7 +421,7 @@ typecheck_field(Analyzer *a,
423 field_type); 421 field_type);
424 } 422 }
425 } 423 }
426 structmap_insert(&map, field_name, 424 structmap_insert(&scope->structs, field_name,
427 (Struct){ 425 (Struct){
428 .name = field_name, 426 .name = field_name,
429 .type = field_type, 427 .type = field_type,
@@ -584,11 +582,11 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
584 node->type = cstr("nil"); 582 node->type = cstr("nil");
585 Str symbol = node->value.str; 583 Str symbol = node->value.str;
586 // TODO: make sure it didn't exist before. 584 // TODO: make sure it didn't exist before.
587 StructMap *e = structmap_insert( 585 structmap_insert(&scope->structs, symbol, (Struct){.name = symbol},
588 &scope->structs, symbol, (Struct){.name = symbol}, a->storage); 586 a->storage);
589 for (sz i = 0; i < array_size(node->struct_field); i++) { 587 for (sz i = 0; i < array_size(node->struct_field); i++) {
590 Node *field = node->struct_field[i]; 588 Node *field = node->struct_field[i];
591 typecheck_field(a, field, scope, symbol, e); 589 typecheck_field(a, field, scope, symbol);
592 } 590 }
593 typemap_insert(&scope->types, symbol, symbol, a->storage); 591 typemap_insert(&scope->types, symbol, symbol, a->storage);
594 return node->type; 592 return node->type;
@@ -597,18 +595,18 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
597 node->type = cstr("nil"); 595 node->type = cstr("nil");
598 Str symbol = node->value.str; 596 Str symbol = node->value.str;
599 // TODO: make sure it didn't exist before. 597 // TODO: make sure it didn't exist before.
600 EnumMap *e = enummap_insert(&scope->enums, symbol, 598 enummap_insert(&scope->enums, symbol,
601 (Enum){ 599 (Enum){
602 .name = symbol, 600 .name = symbol,
603 .val = node->field_val, 601 .val = node->field_val,
604 }, 602 },
605 a->storage); 603 a->storage);
606 for (sz i = 0; i < array_size(node->struct_field); i++) { 604 for (sz i = 0; i < array_size(node->struct_field); i++) {
607 Node *field = node->struct_field[i]; 605 Node *field = node->struct_field[i];
608 Str field_name = str_concat(symbol, cstr("."), a->storage); 606 Str field_name = str_concat(symbol, cstr("."), a->storage);
609 field_name = 607 field_name =
610 str_concat(field_name, field->value.str, a->storage); 608 str_concat(field_name, field->value.str, a->storage);
611 if (enummap_lookup(&e, field_name)) { 609 if (enummap_lookup(&scope->enums, field_name)) {
612 eprintln("%s:%d:%d: error: enum field '%s' already exists", 610 eprintln("%s:%d:%d: error: enum field '%s' already exists",
613 a->file_name, field->line, field->col, field_name); 611 a->file_name, field->line, field->col, field_name);
614 } 612 }
@@ -621,8 +619,8 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
621 field_name); 619 field_name);
622 } 620 }
623 } 621 }
624 enummap_insert(&e, field_name, (Enum){.name = field_name}, 622 enummap_insert(&scope->enums, field_name,
625 a->storage); 623 (Enum){.name = field_name}, a->storage);
626 field->type = cstr("int"); 624 field->type = cstr("int");
627 } 625 }
628 typemap_insert(&scope->types, symbol, symbol, a->storage); 626 typemap_insert(&scope->types, symbol, symbol, a->storage);
@@ -899,28 +897,39 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
899 a->file_name, node->line, node->col, name); 897 a->file_name, node->line, node->col, name);
900 return cstr(""); 898 return cstr("");
901 } 899 }
900
901 StrSet *set = NULL;
902 for (sz i = 0; i < array_size(node->elements); i++) { 902 for (sz i = 0; i < array_size(node->elements); i++) {
903 Node *next = node->elements[i]; 903 Node *next = node->elements[i];
904 Str field_name = next->value.str; 904 Str field_name = str_concat(name, cstr("."), a->storage);
905 FieldMap *field = fieldmap_lookup(&s->val.fields, field_name); 905 field_name =
906 if (!field) { 906 str_concat(field_name, next->value.str, a->storage);
907
908 if (strset_lookup(&set, field_name)) {
907 eprintln( 909 eprintln(
908 "%s:%d:%d: error: unknown struct field for symbol '%s'", 910 "%s:%d:%d: error: field '%s' already present in struct "
911 "literal",
909 a->file_name, next->line, next->col, field_name); 912 a->file_name, next->line, next->col, field_name);
910 } else { 913 } else {
911 if (next->field_val) { 914 strset_insert(&set, field_name, a->storage);
912 Type type = type_inference(a, next->field_val, scope); 915 }
913 if (!str_eq(type, field->val.type)) { 916
914 eprintln( 917 StructMap *field = find_struct(scope, field_name);
915 "%s:%d:%d: error: mismatched types in struct " 918 if (!field) {
916 "value " 919 eprintln("%s:%d:%d: error: unknown struct field '%s'",
917 "for '%s.%s': %s expected %s", 920 a->file_name, next->line, next->col, field_name);
918 a->file_name, next->line, next->col, name, 921 } else {
919 field_name, type, field->val.type); 922 Type type = type_inference(a, next->field_val, scope);
920 } 923 if (!str_eq(type, field->val.type)) {
924 eprintln(
925 "%s:%d:%d: error: mismatched types in struct "
926 "literal for '%s': %s expected %s ",
927 a->file_name, next->line, next->col, field_name,
928 type, field->val.type);
921 } 929 }
922 next->type = field->val.type; 930 next->type = type;
923 } 931 }
932 // TODO: nested fields.
924 } 933 }
925 node->type = name; 934 node->type = name;
926 return node->type; 935 return node->type;
@@ -1088,21 +1097,6 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
1088 1097
1089void 1098void
1090analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { 1099analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
1091 // TODO: Struct field initializers need to be checked... when we
1092 // get to that. Note that for checking symbol chains, we need to
1093 // first perform type analysis to know the variable is a certain
1094 // type:
1095 //
1096 // struct T {
1097 // field_a: int
1098 // field_b: int
1099 // }
1100 // let a:my_struct
1101 // set a.field_a = 1
1102 //
1103 // In this case we need to know that variable a is of type `T` which
1104 // contains fields `field_a` and `field_b`.
1105 //
1106 assert(a); 1100 assert(a);
1107 assert(scope); 1101 assert(scope);
1108 if (!node) { 1102 if (!node) {