diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-25 12:01:47 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-25 12:01:47 +0200 |
commit | 1980bc35c8d161089d3f996abcce80bc67056736 (patch) | |
tree | 07686fbe2d00aafe34b66ed4dcb858e7dc129548 /src | |
parent | f39149eaac8a7e6400aca1edea4bf47e3941a3fc (diff) | |
download | bdl-1980bc35c8d161089d3f996abcce80bc67056736.tar.gz bdl-1980bc35c8d161089d3f996abcce80bc67056736.zip |
Add compound types for anonymous struct fields
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 62 | ||||
-rw-r--r-- | src/parser.c | 97 |
2 files changed, 81 insertions, 78 deletions
@@ -534,33 +534,35 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
534 | // TODO: make sure it didn't exist before. | 534 | // TODO: make sure it didn't exist before. |
535 | StructMap *e = structmap_insert( | 535 | StructMap *e = structmap_insert( |
536 | &scope->structs, symbol, (Struct){.name = symbol}, a->storage); | 536 | &scope->structs, symbol, (Struct){.name = symbol}, a->storage); |
537 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 537 | // for (sz i = 0; i < array_size(node->struct_field); i++) { |
538 | Node *field = node->struct_field[i]; | 538 | // Node *field = node->struct_field[i]; |
539 | Str field_name = field->field_name->value.str; | 539 | // // TODO: handle compound types |
540 | Str field_type = field->field_type->value.str; | 540 | // Str field_name = field->value.str; |
541 | if (fieldmap_lookup(&e->val.fields, field_name)) { | 541 | // Str field_type = field->field_type->value.str; |
542 | eprintln( | 542 | // if (fieldmap_lookup(&e->val.fields, field_name)) { |
543 | "%s:%d:%d: error: struct field '%s.%s' already exists", | 543 | // eprintln( |
544 | a->file_name, field->line, field->col, symbol, | 544 | // "%s:%d:%d: error: struct field '%s.%s' already exists", |
545 | field_name); | 545 | // a->file_name, field->line, field->col, symbol, |
546 | } | 546 | // field_name); |
547 | if (field->field_val) { | 547 | // } |
548 | Type type = type_inference(a, field->field_val, scope); | 548 | // if (field->field_val) { |
549 | if (!str_eq(type, field_type)) { | 549 | // Type type = type_inference(a, field->field_val, scope); |
550 | eprintln( | 550 | // if (!str_eq(type, field_type)) { |
551 | "%s:%d:%d: error: mismatched types in struct value " | 551 | // eprintln( |
552 | "for '%s.%s' ", | 552 | // "%s:%d:%d: error: mismatched types in struct " |
553 | a->file_name, field->line, field->col, symbol, | 553 | // "value " |
554 | field_name); | 554 | // "for '%s.%s': %s expected %s", |
555 | } | 555 | // a->file_name, field->line, field->col, symbol, |
556 | } | 556 | // field_name, type, field_type); |
557 | fieldmap_insert(&e->val.fields, field_name, | 557 | // } |
558 | (Field){.name = field_name, | 558 | // } |
559 | .type = field_type, | 559 | // fieldmap_insert(&e->val.fields, field_name, |
560 | .val = field->field_val}, | 560 | // (Field){.name = field_name, |
561 | a->storage); | 561 | // .type = field_type, |
562 | field->type = field_type; | 562 | // .val = field->field_val}, |
563 | } | 563 | // a->storage); |
564 | // field->type = field_type; | ||
565 | // } | ||
564 | typemap_insert(&scope->types, symbol, symbol, a->storage); | 566 | typemap_insert(&scope->types, symbol, symbol, a->storage); |
565 | return node->type; | 567 | return node->type; |
566 | } break; | 568 | } break; |
@@ -572,7 +574,7 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
572 | (Enum){.name = symbol}, a->storage); | 574 | (Enum){.name = symbol}, a->storage); |
573 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 575 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
574 | Node *field = node->struct_field[i]; | 576 | Node *field = node->struct_field[i]; |
575 | Str field_name = field->field_name->value.str; | 577 | Str field_name = field->value.str; |
576 | if (fieldmap_lookup(&e->val.fields, field_name)) { | 578 | if (fieldmap_lookup(&e->val.fields, field_name)) { |
577 | eprintln( | 579 | eprintln( |
578 | "%s:%d:%d: error: enum field '%s.%s' already exists", | 580 | "%s:%d:%d: error: enum field '%s.%s' already exists", |
@@ -865,7 +867,7 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
865 | } | 867 | } |
866 | for (sz i = 0; i < array_size(node->elements); i++) { | 868 | for (sz i = 0; i < array_size(node->elements); i++) { |
867 | Node *next = node->elements[i]; | 869 | Node *next = node->elements[i]; |
868 | Str field_name = next->field_name->value.str; | 870 | Str field_name = next->value.str; |
869 | FieldMap *field = fieldmap_lookup(&s->val.fields, field_name); | 871 | FieldMap *field = fieldmap_lookup(&s->val.fields, field_name); |
870 | if (!field) { | 872 | if (!field) { |
871 | eprintln( | 873 | eprintln( |
@@ -1154,7 +1156,7 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { | |||
1154 | // TODO: symcheck the value expression? | 1156 | // TODO: symcheck the value expression? |
1155 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 1157 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
1156 | Node *field = node->struct_field[i]; | 1158 | Node *field = node->struct_field[i]; |
1157 | Str field_name = field->field_name->value.str; | 1159 | Str field_name = field->value.str; |
1158 | if (symmap_lookup(&map->val.fields, field_name) != NULL) { | 1160 | if (symmap_lookup(&map->val.fields, field_name) != NULL) { |
1159 | eprintln( | 1161 | eprintln( |
1160 | "%s:%d:%d: error: enum field '%s.%s' already exists", | 1162 | "%s:%d:%d: error: enum field '%s.%s' already exists", |
diff --git a/src/parser.c b/src/parser.c index a6d9f83..1e54776 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -62,8 +62,9 @@ typedef enum NodeKind { | |||
62 | // Helpers. | 62 | // Helpers. |
63 | NODE_SYMBOL_IDX, | 63 | NODE_SYMBOL_IDX, |
64 | NODE_TYPE, | 64 | NODE_TYPE, |
65 | NODE_COMPOUND_TYPE, | ||
65 | NODE_ARR_TYPE, | 66 | NODE_ARR_TYPE, |
66 | NODE_VAL_FIELD, | 67 | NODE_FIELD, |
67 | NODE_BLOCK, | 68 | NODE_BLOCK, |
68 | } NodeKind; | 69 | } NodeKind; |
69 | 70 | ||
@@ -120,9 +121,10 @@ Str node_str[] = { | |||
120 | [NODE_WHILE] = cstr("WHILE"), | 121 | [NODE_WHILE] = cstr("WHILE"), |
121 | // Helpers. | 122 | // Helpers. |
122 | [NODE_TYPE] = cstr("TYPE"), | 123 | [NODE_TYPE] = cstr("TYPE"), |
124 | [NODE_COMPOUND_TYPE] = cstr("COMPOUND TYPE"), | ||
123 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), | 125 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), |
124 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), | 126 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), |
125 | [NODE_VAL_FIELD] = cstr("FIELD"), | 127 | [NODE_FIELD] = cstr("FIELD"), |
126 | [NODE_BLOCK] = cstr("BLOCK"), | 128 | [NODE_BLOCK] = cstr("BLOCK"), |
127 | }; | 129 | }; |
128 | 130 | ||
@@ -163,7 +165,6 @@ typedef struct Node { | |||
163 | struct Node *cond_else; | 165 | struct Node *cond_else; |
164 | }; | 166 | }; |
165 | struct { | 167 | struct { |
166 | struct Node *field_name; | ||
167 | struct Node *field_type; | 168 | struct Node *field_type; |
168 | struct Node *field_val; | 169 | struct Node *field_val; |
169 | }; | 170 | }; |
@@ -485,6 +486,42 @@ parse_type(Parser *parser) { | |||
485 | } | 486 | } |
486 | 487 | ||
487 | void | 488 | void |
489 | parse_struct_field(Parser *parser) { | ||
490 | if (parser->panic) return; | ||
491 | Token prev = parser->previous; | ||
492 | #if DEBUG == 1 | ||
493 | print("parsing struct field "); | ||
494 | print_token(prev); | ||
495 | #endif | ||
496 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); | ||
497 | if (!field) return; | ||
498 | parse_consume(parser, TOK_SYMBOL, | ||
499 | cstr("expected symbol name on struct field")); | ||
500 | field->value.sym = parser->previous.val; | ||
501 | parse_consume(parser, TOK_COLON, cstr("expected type in struct field")); | ||
502 | if (parse_match(parser, TOK_LCURLY)) { | ||
503 | Node *type = node_alloc(parser, NODE_COMPOUND_TYPE, parser->current); | ||
504 | if (!type) return; | ||
505 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | ||
506 | parse_struct_field(parser); | ||
507 | Node *subfield = array_pop(parser->nodes); | ||
508 | array_push(type->elements, subfield, parser->storage); | ||
509 | } | ||
510 | field->field_type = type; | ||
511 | } else { | ||
512 | parse_type(parser); | ||
513 | field->field_type = array_pop(parser->nodes); | ||
514 | } | ||
515 | |||
516 | // Optional assignment. | ||
517 | if (parse_match(parser, TOK_ASSIGN)) { | ||
518 | parse_expr(parser, PREC_LOW); | ||
519 | field->field_val = array_pop(parser->nodes); | ||
520 | } | ||
521 | array_push(parser->nodes, field, parser->storage); | ||
522 | } | ||
523 | |||
524 | void | ||
488 | parse_keyword(Parser *parser) { | 525 | parse_keyword(Parser *parser) { |
489 | if (parser->panic) return; | 526 | if (parser->panic) return; |
490 | Token prev = parser->previous; | 527 | Token prev = parser->previous; |
@@ -549,37 +586,8 @@ parse_keyword(Parser *parser) { | |||
549 | cstr("expected '{' on struct definition")); | 586 | cstr("expected '{' on struct definition")); |
550 | 587 | ||
551 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 588 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
552 | Node *field = | 589 | parse_struct_field(parser); |
553 | node_alloc(parser, NODE_VAL_FIELD, parser->current); | 590 | Node *field = array_pop(parser->nodes); |
554 | if (!field) return; | ||
555 | parse_consume( | ||
556 | parser, TOK_SYMBOL, | ||
557 | cstr("expected symbol name on struct definition")); | ||
558 | parse_symbol(parser); | ||
559 | field->field_name = array_pop(parser->nodes); | ||
560 | if (field->field_name->next || | ||
561 | field->field_name->kind == NODE_SYMBOL_IDX) { | ||
562 | parse_emit_err(parser, prev, | ||
563 | cstr("invalid symbol name in struct field")); | ||
564 | return; | ||
565 | } | ||
566 | parse_consume(parser, TOK_COLON, | ||
567 | cstr("expected type in struct field")); | ||
568 | // TODO: if consume curly | ||
569 | if (parse_match(parser, TOK_LCURLY)) { | ||
570 | // TODO: nested struct | ||
571 | } else { | ||
572 | parse_type(parser); | ||
573 | field->field_type = array_pop(parser->nodes); | ||
574 | } | ||
575 | // while (!parse_match(parser, TOK_RCURLY) && | ||
576 | // !parser->panic) { | ||
577 | |||
578 | // Optional assignment. | ||
579 | if (parse_match(parser, TOK_ASSIGN)) { | ||
580 | parse_expr(parser, PREC_LOW); | ||
581 | field->field_val = array_pop(parser->nodes); | ||
582 | } | ||
583 | 591 | ||
584 | array_push(node->struct_field, field, parser->storage); | 592 | array_push(node->struct_field, field, parser->storage); |
585 | } | 593 | } |
@@ -635,19 +643,11 @@ parse_keyword(Parser *parser) { | |||
635 | parse_consume(parser, TOK_LCURLY, | 643 | parse_consume(parser, TOK_LCURLY, |
636 | cstr("expected '{' on enum definition")); | 644 | cstr("expected '{' on enum definition")); |
637 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 645 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
638 | Node *field = | 646 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); |
639 | node_alloc(parser, NODE_VAL_FIELD, parser->current); | ||
640 | if (!field) return; | 647 | if (!field) return; |
641 | parse_consume(parser, TOK_SYMBOL, | 648 | parse_consume(parser, TOK_SYMBOL, |
642 | cstr("expected symbol name on enum definition")); | 649 | cstr("expected symbol name on enum definition")); |
643 | parse_symbol(parser); | 650 | field->value.sym = parser->previous.val; |
644 | field->field_name = array_pop(parser->nodes); | ||
645 | if (field->field_name->next || | ||
646 | field->field_name->kind == NODE_SYMBOL_IDX) { | ||
647 | parse_emit_err(parser, prev, | ||
648 | cstr("invalid symbol name in enum field")); | ||
649 | return; | ||
650 | } | ||
651 | if (parse_match(parser, TOK_ASSIGN)) { | 651 | if (parse_match(parser, TOK_ASSIGN)) { |
652 | parse_expr(parser, PREC_LOW); | 652 | parse_expr(parser, PREC_LOW); |
653 | field->field_val = array_pop(parser->nodes); | 653 | field->field_val = array_pop(parser->nodes); |
@@ -941,10 +941,9 @@ parse_symbol(Parser *parser) { | |||
941 | // Struct literal. | 941 | // Struct literal. |
942 | node->kind = NODE_STRUCT_LIT; | 942 | node->kind = NODE_STRUCT_LIT; |
943 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 943 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
944 | Node *field = node_alloc(parser, NODE_VAL_FIELD, parser->current); | 944 | Node *field = node_alloc(parser, NODE_FIELD, parser->current); |
945 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); | 945 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); |
946 | parse_symbol(parser); | 946 | field->value.sym = parser->previous.val; |
947 | field->field_name = array_pop(parser->nodes); | ||
948 | parse_consume(parser, TOK_ASSIGN, cstr("expected assignment")); | 947 | parse_consume(parser, TOK_ASSIGN, cstr("expected assignment")); |
949 | parse_expr(parser, PREC_LOW); | 948 | parse_expr(parser, PREC_LOW); |
950 | field->field_val = array_pop(parser->nodes); | 949 | field->field_val = array_pop(parser->nodes); |
@@ -1011,6 +1010,7 @@ graph_node(Node *node) { | |||
1011 | case NODE_SYMBOL: | 1010 | case NODE_SYMBOL: |
1012 | case NODE_FUNCALL: | 1011 | case NODE_FUNCALL: |
1013 | case NODE_ARR_TYPE: | 1012 | case NODE_ARR_TYPE: |
1013 | case NODE_FIELD: | ||
1014 | case NODE_TYPE: { | 1014 | case NODE_TYPE: { |
1015 | if (node->is_ptr) { | 1015 | if (node->is_ptr) { |
1016 | print("| Name: @%s", node->value.sym); | 1016 | print("| Name: @%s", node->value.sym); |
@@ -1067,6 +1067,7 @@ graph_node(Node *node) { | |||
1067 | case NODE_FUNCALL: | 1067 | case NODE_FUNCALL: |
1068 | case NODE_RETURN: | 1068 | case NODE_RETURN: |
1069 | case NODE_BLOCK: | 1069 | case NODE_BLOCK: |
1070 | case NODE_COMPOUND_TYPE: | ||
1070 | case NODE_STRUCT_LIT: { | 1071 | case NODE_STRUCT_LIT: { |
1071 | for (sz i = 0; i < array_size(node->elements); i++) { | 1072 | for (sz i = 0; i < array_size(node->elements); i++) { |
1072 | Node *next = node->elements[i]; | 1073 | Node *next = node->elements[i]; |
@@ -1096,7 +1097,7 @@ graph_node(Node *node) { | |||
1096 | graph_node(node->cond_else); | 1097 | graph_node(node->cond_else); |
1097 | } | 1098 | } |
1098 | } break; | 1099 | } break; |
1099 | case NODE_VAL_FIELD: | 1100 | case NODE_FIELD: |
1100 | case NODE_SET: | 1101 | case NODE_SET: |
1101 | case NODE_LET: { | 1102 | case NODE_LET: { |
1102 | if (node->var_name) { | 1103 | if (node->var_name) { |