aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-25 17:45:27 +0200
committerBad Diode <bd@badd10de.dev>2024-06-25 17:45:27 +0200
commitbc9aa6e8ad03cd739cd54a9b97f78a14287b9fbd (patch)
tree03f4fa7387a931ea62c7999e3bc4f8839ccce355 /src
parent1980bc35c8d161089d3f996abcce80bc67056736 (diff)
downloadbdl-bc9aa6e8ad03cd739cd54a9b97f78a14287b9fbd.tar.gz
bdl-bc9aa6e8ad03cd739cd54a9b97f78a14287b9fbd.zip
Add inner struct typechecking
Diffstat (limited to 'src')
-rw-r--r--src/main.c206
1 files changed, 133 insertions, 73 deletions
diff --git a/src/main.c b/src/main.c
index f792b10..d3c171c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -9,11 +9,10 @@
9 9
10// TODO: in a let/set expression if the type is a struct check that we 10// TODO: in a let/set expression if the type is a struct check that we
11// are assigning a struct literal, not just a symbol. 11// are assigning a struct literal, not just a symbol.
12// TODO: nested structs
13// TODO: unions 12// TODO: unions
14// TODO: match deconstruct structs 13// TODO: match deconstruct structs
15// TODO: arrays and pointers 14// TODO: arrays and pointers
16// TODO: struct literals 15// TODO: struct literals with compound types
17 16
18typedef enum ExecMode { 17typedef enum ExecMode {
19 RUN_NORMAL, 18 RUN_NORMAL,
@@ -68,20 +67,15 @@ typedef struct Fun {
68 Str return_type; 67 Str return_type;
69} Fun; 68} Fun;
70 69
71typedef struct Field {
72 Str name;
73 Str type;
74 Node *val;
75} Field;
76
77typedef struct Enum { 70typedef struct Enum {
78 Str name; 71 Str name;
79 struct FieldMap *fields; 72 Node *val;
80} Enum; 73} Enum;
81 74
82typedef struct Struct { 75typedef struct Struct {
83 Str name; 76 Str name;
84 struct FieldMap *fields; 77 Str type;
78 Node *val;
85} Struct; 79} Struct;
86 80
87MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) 81MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq)
@@ -89,7 +83,6 @@ MAPDEF(TypeMap, typemap, Str, Type, str_hash, str_eq)
89MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) 83MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq)
90MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) 84MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq)
91MAPDEF(StructMap, structmap, Str, Struct, str_hash, str_eq) 85MAPDEF(StructMap, structmap, Str, Struct, str_hash, str_eq)
92MAPDEF(FieldMap, fieldmap, Str, Field, str_hash, str_eq)
93 86
94typedef struct Scope { 87typedef struct Scope {
95 sz id; 88 sz id;
@@ -382,6 +375,65 @@ emit_semantic_error(Analyzer *a, Node *n, Str msg) {
382 eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg); 375 eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg);
383} 376}
384 377
378Type type_inference(Analyzer *a, Node *node, TypeScope *scope);
379
380void
381typecheck_field(Analyzer *a,
382 Node *node,
383 TypeScope *scope,
384 Str symbol,
385 StructMap *map) {
386 // TODO: ensure the tables are filled properly.
387 if (node->field_type->kind == NODE_COMPOUND_TYPE) {
388 Str field_name = str_concat(symbol, cstr("."), a->storage);
389 field_name = str_concat(field_name, node->value.str, a->storage);
390 if (structmap_lookup(&map, field_name)) {
391 eprintln("%s:%d:%d: error: struct field '%s' already exists",
392 a->file_name, node->line, node->col, field_name);
393 }
394 Str type = cstr("\\{ ");
395 for (sz i = 0; i < array_size(node->field_type->elements); i++) {
396 Node *field = node->field_type->elements[i];
397 typecheck_field(a, field, scope, field_name, map);
398 type = str_concat(type, field->type, a->storage);
399 type = str_concat(type, cstr(" "), a->storage);
400 }
401 type = str_concat(type, cstr("\\}"), a->storage);
402 node->type = type;
403 } else {
404 Str field_name = str_concat(symbol, cstr("."), a->storage);
405 field_name = str_concat(field_name, node->value.str, a->storage);
406 Str field_type = node->field_type->value.str;
407 if (!find_type(scope, field_type)) {
408 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name,
409 node->field_type->line, node->field_type->col, field_type);
410 }
411 if (structmap_lookup(&map, field_name)) {
412 eprintln("%s:%d:%d: error: struct field '%s' already exists",
413 a->file_name, node->line, node->col, field_name);
414 }
415 if (node->field_val) {
416 Type type = type_inference(a, node->field_val, scope);
417 if (!str_eq(type, field_type)) {
418 eprintln(
419 "%s:%d:%d: error: mismatched types in struct "
420 "value "
421 "for '%s': %s expected %s",
422 a->file_name, node->line, node->col, field_name, type,
423 field_type);
424 }
425 }
426 structmap_insert(&map, field_name,
427 (Struct){
428 .name = field_name,
429 .type = field_type,
430 .val = node->field_val,
431 },
432 a->storage);
433 node->type = field_type;
434 }
435}
436
385void 437void
386typecheck_returns(Analyzer *a, Node *node, Str expected) { 438typecheck_returns(Analyzer *a, Node *node, Str expected) {
387 if (!node) { 439 if (!node) {
@@ -534,35 +586,10 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
534 // TODO: make sure it didn't exist before. 586 // TODO: make sure it didn't exist before.
535 StructMap *e = structmap_insert( 587 StructMap *e = structmap_insert(
536 &scope->structs, symbol, (Struct){.name = symbol}, a->storage); 588 &scope->structs, symbol, (Struct){.name = symbol}, a->storage);
537 // for (sz i = 0; i < array_size(node->struct_field); i++) { 589 for (sz i = 0; i < array_size(node->struct_field); i++) {
538 // Node *field = node->struct_field[i]; 590 Node *field = node->struct_field[i];
539 // // TODO: handle compound types 591 typecheck_field(a, field, scope, symbol, e);
540 // Str field_name = field->value.str; 592 }
541 // Str field_type = field->field_type->value.str;
542 // if (fieldmap_lookup(&e->val.fields, field_name)) {
543 // eprintln(
544 // "%s:%d:%d: error: struct field '%s.%s' already exists",
545 // a->file_name, field->line, field->col, symbol,
546 // field_name);
547 // }
548 // if (field->field_val) {
549 // Type type = type_inference(a, field->field_val, scope);
550 // if (!str_eq(type, field_type)) {
551 // eprintln(
552 // "%s:%d:%d: error: mismatched types in struct "
553 // "value "
554 // "for '%s.%s': %s expected %s",
555 // a->file_name, field->line, field->col, symbol,
556 // field_name, type, field_type);
557 // }
558 // }
559 // fieldmap_insert(&e->val.fields, field_name,
560 // (Field){.name = field_name,
561 // .type = field_type,
562 // .val = field->field_val},
563 // a->storage);
564 // field->type = field_type;
565 // }
566 typemap_insert(&scope->types, symbol, symbol, a->storage); 593 typemap_insert(&scope->types, symbol, symbol, a->storage);
567 return node->type; 594 return node->type;
568 } break; 595 } break;
@@ -574,12 +601,12 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
574 (Enum){.name = symbol}, a->storage); 601 (Enum){.name = symbol}, a->storage);
575 for (sz i = 0; i < array_size(node->struct_field); i++) { 602 for (sz i = 0; i < array_size(node->struct_field); i++) {
576 Node *field = node->struct_field[i]; 603 Node *field = node->struct_field[i];
577 Str field_name = field->value.str; 604 Str field_name = str_concat(symbol, cstr("."), a->storage);
578 if (fieldmap_lookup(&e->val.fields, field_name)) { 605 field_name =
579 eprintln( 606 str_concat(field_name, field->value.str, a->storage);
580 "%s:%d:%d: error: enum field '%s.%s' already exists", 607 if (enummap_lookup(&e, field_name)) {
581 a->file_name, field->line, field->col, symbol, 608 eprintln("%s:%d:%d: error: enum field '%s' already exists",
582 field_name); 609 a->file_name, field->line, field->col, field_name);
583 } 610 }
584 if (field->field_val) { 611 if (field->field_val) {
585 Type type = type_inference(a, field->field_val, scope); 612 Type type = type_inference(a, field->field_val, scope);
@@ -590,11 +617,8 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
590 field_name); 617 field_name);
591 } 618 }
592 } 619 }
593 fieldmap_insert(&e->val.fields, field_name, 620 enummap_insert(&e, field_name, (Enum){.name = field_name},
594 (Field){.name = field_name, 621 a->storage);
595 .type = cstr("int"),
596 .val = field->field_val},
597 a->storage);
598 field->type = cstr("int"); 622 field->type = cstr("int");
599 } 623 }
600 typemap_insert(&scope->types, symbol, symbol, a->storage); 624 typemap_insert(&scope->types, symbol, symbol, a->storage);
@@ -825,11 +849,14 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
825 return cstr(""); 849 return cstr("");
826 } 850 }
827 // Check if there is a next and it matches the enum field. 851 // Check if there is a next and it matches the enum field.
828 if (!fieldmap_lookup(&e->val.fields, node->next->value.str)) { 852 Str field = str_concat(type->val, cstr("."), a->storage);
853 field = str_concat(field, node->next->value.str, a->storage);
854 if (!find_enum(scope, field)) {
829 eprintln( 855 eprintln(
830 "%s:%d:%d: error: unknown enum field for symbol " 856 "%s:%d:%d: error: unknown enum field for "
831 "'%s'", 857 "'%s': %s",
832 a->file_name, node->line, node->col, symbol); 858 a->file_name, node->line, node->col, symbol,
859 node->next->value.str);
833 return cstr(""); 860 return cstr("");
834 } 861 }
835 node->next->type = cstr("int"); 862 node->next->type = cstr("int");
@@ -1159,7 +1186,7 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
1159 Str field_name = field->value.str; 1186 Str field_name = field->value.str;
1160 if (symmap_lookup(&map->val.fields, field_name) != NULL) { 1187 if (symmap_lookup(&map->val.fields, field_name) != NULL) {
1161 eprintln( 1188 eprintln(
1162 "%s:%d:%d: error: enum field '%s.%s' already exists", 1189 "%s:%d:%d: error: struct field '%s.%s' already exists",
1163 a->file_name, field->line, field->col, symbol, 1190 a->file_name, field->line, field->col, symbol,
1164 field_name); 1191 field_name);
1165 return; 1192 return;
@@ -1439,26 +1466,59 @@ process_file(Str path) {
1439 } 1466 }
1440 1467
1441#if DEBUG == 1 1468#if DEBUG == 1
1442 for (sz i = 0; i < array_size(analyzer.scopes); i++) { 1469 println("======== enums ========");
1470 for (sz i = 0; i < array_size(analyzer.types); i++) {
1443 Arena scratch = lexer_arena; 1471 Arena scratch = lexer_arena;
1444 Scope *scope = analyzer.scopes[i]; 1472 TypeScope *scope = analyzer.types[i];
1445 SymbolMapIter iter = symmap_iterator(scope->symbols, &scratch); 1473 EnumMapIter iter = enummap_iterator(scope->enums, &scratch);
1446 SymbolMap *sym = symmap_next(&iter, &scratch); 1474 EnumMap *m = enummap_next(&iter, &scratch);
1447 while (sym) { 1475 while (m) {
1448 println("%s: SCOPE: %d DEPTH: %d\t%s %s", path, scope->id, 1476 println("%s: enum: %s", path, m->val.name);
1449 scope->depth, sym_kind_str[sym->val.kind], sym->val.name); 1477 m = enummap_next(&iter, &scratch);
1450 SymbolMapIter field_iter =
1451 symmap_iterator(sym->val.fields, &scratch);
1452 SymbolMap *field = symmap_next(&field_iter, &scratch);
1453 while (field) {
1454 println("%s: SCOPE: %d DEPTH: %d\t%s %s.%s", path, scope->id,
1455 scope->depth, sym_kind_str[field->val.kind],
1456 sym->val.name, field->val.name);
1457 field = symmap_next(&field_iter, &scratch);
1458 }
1459 sym = symmap_next(&iter, &lexer_arena);
1460 } 1478 }
1461 } 1479 }
1480 println("======== structs ========");
1481 for (sz i = 0; i < array_size(analyzer.types); i++) {
1482 Arena scratch = lexer_arena;
1483 TypeScope *scope = analyzer.types[i];
1484 StructMapIter iter = structmap_iterator(scope->structs, &scratch);
1485 StructMap *m = structmap_next(&iter, &scratch);
1486 while (m) {
1487 println("%s: struct: %s", path, m->val.name);
1488 m = structmap_next(&iter, &scratch);
1489 }
1490 }
1491 println("======== functions ========");
1492 for (sz i = 0; i < array_size(analyzer.types); i++) {
1493 Arena scratch = lexer_arena;
1494 TypeScope *scope = analyzer.types[i];
1495 FunMapIter iter = funmap_iterator(scope->funcs, &scratch);
1496 FunMap *m = funmap_next(&iter, &scratch);
1497 while (m) {
1498 println("%s: func: %s(%s): (%s)", path, m->val.name,
1499 m->val.param_type, m->val.return_type);
1500 m = funmap_next(&iter, &scratch);
1501 }
1502 }
1503 // println("======== symbols ========");
1504 // SymbolMapIter iter = symmap_iterator(scope->symbols, &scratch);
1505 // SymbolMap *sym = symmap_next(&iter, &scratch);
1506 // while (sym) {
1507 // println("%s: SCOPE: %d DEPTH: %d\t%s %s", path, scope->id,
1508 // scope->depth, sym_kind_str[sym->val.kind],
1509 // sym->val.name);
1510 // SymbolMapIter field_iter =
1511 // symmap_iterator(sym->val.fields, &scratch);
1512 // SymbolMap *field = symmap_next(&field_iter, &scratch);
1513 // while (field) {
1514 // println("%s: SCOPE: %d DEPTH: %d\t%s %s.%s", path, scope->id,
1515 // scope->depth, sym_kind_str[field->val.kind],
1516 // sym->val.name, field->val.name);
1517 // field = symmap_next(&field_iter, &scratch);
1518 // }
1519 // sym = symmap_next(&iter, &lexer_arena);
1520 // }
1521 // }
1462#endif 1522#endif
1463 1523
1464 // TODO: Type checking. 1524 // TODO: Type checking.