diff options
author | Bad Diode <bd@badd10de.dev> | 2022-04-07 12:41:34 -0300 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-04-07 12:41:34 -0300 |
commit | 9f934cbc0f0fd60a6938ac1c4c84edc270de94ca (patch) | |
tree | 9304f9bc802eac175b594de4bf81730b7d815513 /src | |
parent | a718a62a45b081bfd2cff8da56da2d2856ca244b (diff) | |
download | bdl-9f934cbc0f0fd60a6938ac1c4c84edc270de94ca.tar.gz bdl-9f934cbc0f0fd60a6938ac1c4c84edc270de94ca.zip |
Add initial implementation of typeclass resolution
Diffstat (limited to 'src')
-rw-r--r-- | src/nodes.c | 1 | ||||
-rw-r--r-- | src/nodes.h | 9 | ||||
-rw-r--r-- | src/parser.c | 89 |
3 files changed, 94 insertions, 5 deletions
diff --git a/src/nodes.c b/src/nodes.c index a5b67d1..5689d18 100644 --- a/src/nodes.c +++ b/src/nodes.c | |||
@@ -9,6 +9,7 @@ alloc_node(NodeType type) { | |||
9 | node->line = 0; | 9 | node->line = 0; |
10 | node->col = 0; | 10 | node->col = 0; |
11 | node->scope = NULL; | 11 | node->scope = NULL; |
12 | node->type_class = TYPE_UNK; | ||
12 | return node; | 13 | return node; |
13 | } | 14 | } |
14 | 15 | ||
diff --git a/src/nodes.h b/src/nodes.h index acbe19e..853495a 100644 --- a/src/nodes.h +++ b/src/nodes.h | |||
@@ -15,11 +15,20 @@ typedef enum NodeType { | |||
15 | NODE_IF, | 15 | NODE_IF, |
16 | } NodeType; | 16 | } NodeType; |
17 | 17 | ||
18 | typedef enum TypeClass { | ||
19 | TYPE_UNK, | ||
20 | TYPE_NONE, | ||
21 | TYPE_NUM, | ||
22 | TYPE_BOOL, | ||
23 | TYPE_STRING, | ||
24 | } TypeClass; | ||
25 | |||
18 | typedef struct Node { | 26 | typedef struct Node { |
19 | NodeType type; | 27 | NodeType type; |
20 | size_t line; | 28 | size_t line; |
21 | size_t col; | 29 | size_t col; |
22 | struct Scope *scope; | 30 | struct Scope *scope; |
31 | TypeClass type_class; | ||
23 | 32 | ||
24 | union { | 33 | union { |
25 | // Numbers. | 34 | // Numbers. |
diff --git a/src/parser.c b/src/parser.c index 841a516..cf7aebb 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -505,7 +505,9 @@ symbol_check(Parser *parser, Node *node) { | |||
505 | case NODE_BUILTIN: { | 505 | case NODE_BUILTIN: { |
506 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 506 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { |
507 | Node *arg = node->builtin.args[i]; | 507 | Node *arg = node->builtin.args[i]; |
508 | symbol_check(parser, arg); | 508 | if (!symbol_check(parser, arg)) { |
509 | return false; | ||
510 | } | ||
509 | } | 511 | } |
510 | } break; | 512 | } break; |
511 | case NODE_SYMBOL: { | 513 | case NODE_SYMBOL: { |
@@ -541,10 +543,14 @@ symbol_check(Parser *parser, Node *node) { | |||
541 | body->scope = parser->parse_tree->current_scope; | 543 | body->scope = parser->parse_tree->current_scope; |
542 | for (size_t i = 0; i < array_size(body->block.expr); ++i) { | 544 | for (size_t i = 0; i < array_size(body->block.expr); ++i) { |
543 | Node *expr = body->block.expr[i]; | 545 | Node *expr = body->block.expr[i]; |
544 | symbol_check(parser, expr); | 546 | if (!symbol_check(parser, expr)) { |
547 | return false; | ||
548 | } | ||
545 | } | 549 | } |
546 | } else { | 550 | } else { |
547 | symbol_check(parser, body); | 551 | if (!symbol_check(parser, body)) { |
552 | return false; | ||
553 | } | ||
548 | } | 554 | } |
549 | parser->parse_tree->current_scope = prev_scope; | 555 | parser->parse_tree->current_scope = prev_scope; |
550 | } break; | 556 | } break; |
@@ -554,7 +560,9 @@ symbol_check(Parser *parser, Node *node) { | |||
554 | node->scope = parser->parse_tree->current_scope; | 560 | node->scope = parser->parse_tree->current_scope; |
555 | for (size_t i = 0; i < array_size(node->block.expr); ++i) { | 561 | for (size_t i = 0; i < array_size(node->block.expr); ++i) { |
556 | Node *expr = node->block.expr[i]; | 562 | Node *expr = node->block.expr[i]; |
557 | symbol_check(parser, expr); | 563 | if (!symbol_check(parser, expr)) { |
564 | return false; | ||
565 | } | ||
558 | } | 566 | } |
559 | parser->parse_tree->current_scope = prev_scope; | 567 | parser->parse_tree->current_scope = prev_scope; |
560 | } break; | 568 | } break; |
@@ -585,6 +593,72 @@ symbol_check(Parser *parser, Node *node) { | |||
585 | } | 593 | } |
586 | 594 | ||
587 | bool | 595 | bool |
596 | resolve_typeclass(Parser *parser, Node *node) { | ||
597 | switch (node->type) { | ||
598 | case NODE_BUILTIN: { | ||
599 | switch (node->builtin.type) { | ||
600 | // Numbers. | ||
601 | case TOKEN_ADD: | ||
602 | case TOKEN_SUB: | ||
603 | case TOKEN_MUL: | ||
604 | case TOKEN_DIV: | ||
605 | case TOKEN_MOD: { node->type_class = TYPE_NUM; } break; | ||
606 | // Bools. | ||
607 | case TOKEN_NOT: | ||
608 | case TOKEN_AND: | ||
609 | case TOKEN_OR: | ||
610 | case TOKEN_EQ: | ||
611 | case TOKEN_LT: | ||
612 | case TOKEN_GT: | ||
613 | case TOKEN_LE: | ||
614 | case TOKEN_GE: { node->type_class = TYPE_BOOL; } break; | ||
615 | default: break; | ||
616 | } | ||
617 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | ||
618 | Node *arg = node->builtin.args[i]; | ||
619 | resolve_typeclass(parser, arg); | ||
620 | } | ||
621 | } break; | ||
622 | case NODE_SYMBOL: { | ||
623 | // TODO: Resolve symbol type? | ||
624 | } break; | ||
625 | case NODE_FUN: { | ||
626 | // TODO: Resolve `node->type_class` based on the return value. | ||
627 | resolve_typeclass(parser, node->fun.body); | ||
628 | } break; | ||
629 | case NODE_BLOCK: { | ||
630 | for (size_t i = 0; i < array_size(node->block.expr); ++i) { | ||
631 | Node *expr = node->block.expr[i]; | ||
632 | resolve_typeclass(parser, expr); | ||
633 | } | ||
634 | Node *last_expr = node->block.expr[array_size(node->block.expr) - 1]; | ||
635 | node->type_class = last_expr->type_class; | ||
636 | } break; | ||
637 | case NODE_IF: { | ||
638 | node->type_class = TYPE_NONE; | ||
639 | resolve_typeclass(parser, node->ifexpr.cond); | ||
640 | resolve_typeclass(parser, node->ifexpr.expr_true); | ||
641 | if (node->ifexpr.expr_false != NULL) { | ||
642 | resolve_typeclass(parser, node->ifexpr.expr_false); | ||
643 | } | ||
644 | } break; | ||
645 | case NODE_SET: { | ||
646 | node->type_class = TYPE_NONE; | ||
647 | resolve_typeclass(parser, node->set.value); | ||
648 | } break; | ||
649 | case NODE_DEF: { | ||
650 | node->type_class = TYPE_NONE; | ||
651 | resolve_typeclass(parser, node->def.value); | ||
652 | } break; | ||
653 | case NODE_NUMBER: { node->type_class = TYPE_NUM; } break; | ||
654 | case NODE_BOOL: { node->type_class = TYPE_BOOL; } break; | ||
655 | case NODE_STRING: { node->type_class = TYPE_STRING; } break; | ||
656 | case NODE_TYPE: { node->type_class = TYPE_NONE; } break; | ||
657 | } | ||
658 | return true; | ||
659 | } | ||
660 | |||
661 | bool | ||
588 | semantic_analysis(Parser *parser) { | 662 | semantic_analysis(Parser *parser) { |
589 | // Fill up global function symbols. | 663 | // Fill up global function symbols. |
590 | for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { | 664 | for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { |
@@ -597,11 +671,16 @@ semantic_analysis(Parser *parser) { | |||
597 | } | 671 | } |
598 | } | 672 | } |
599 | 673 | ||
600 | // Fill up symbol tables in proper scope and check existance. | ||
601 | for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { | 674 | for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { |
675 | // Fill up symbol tables in proper scope and check existance. | ||
602 | symbol_check(parser, parser->parse_tree->roots[i]); | 676 | symbol_check(parser, parser->parse_tree->roots[i]); |
677 | // Resolve TypeClass for all elements. | ||
678 | resolve_typeclass(parser, parser->parse_tree->roots[i]); | ||
603 | } | 679 | } |
604 | 680 | ||
681 | // TODO: Resolve concrete types. | ||
682 | // TODO: Type check. | ||
683 | |||
605 | return true; | 684 | return true; |
606 | } | 685 | } |
607 | 686 | ||