diff options
-rw-r--r-- | src/errors.c | 2 | ||||
-rw-r--r-- | src/errors.h | 2 | ||||
-rw-r--r-- | src/parser.c | 127 |
3 files changed, 100 insertions, 31 deletions
diff --git a/src/errors.c b/src/errors.c index e2dee00..6a69064 100644 --- a/src/errors.c +++ b/src/errors.c | |||
@@ -24,6 +24,8 @@ static const char* error_msgs[] = { | |||
24 | [ERR_WRONG_TYPE_T_F] = "error: unmatched types between true and false expression", | 24 | [ERR_WRONG_TYPE_T_F] = "error: unmatched types between true and false expression", |
25 | [ERR_WRONG_TYPE_NUM] = "error: non numeric argument types", | 25 | [ERR_WRONG_TYPE_NUM] = "error: non numeric argument types", |
26 | [ERR_WRONG_TYPE_BOOL] = "error: non bool argument types", | 26 | [ERR_WRONG_TYPE_BOOL] = "error: non bool argument types", |
27 | [ERR_WRONG_TYPE_FUN] = "error: not a function", | ||
28 | [ERR_BAD_ARGS] = "error: arguments don't match expected types", | ||
27 | [ERR_TYPE_MISMATCH] = "error: type mismatch", | 29 | [ERR_TYPE_MISMATCH] = "error: type mismatch", |
28 | }; | 30 | }; |
29 | 31 | ||
diff --git a/src/errors.h b/src/errors.h index a814549..f2737d0 100644 --- a/src/errors.h +++ b/src/errors.h | |||
@@ -32,7 +32,9 @@ typedef enum ErrorValue { | |||
32 | ERR_WRONG_TYPE_T_F, | 32 | ERR_WRONG_TYPE_T_F, |
33 | ERR_WRONG_TYPE_NUM, | 33 | ERR_WRONG_TYPE_NUM, |
34 | ERR_WRONG_TYPE_BOOL, | 34 | ERR_WRONG_TYPE_BOOL, |
35 | ERR_WRONG_TYPE_FUN, | ||
35 | ERR_TYPE_MISMATCH, | 36 | ERR_TYPE_MISMATCH, |
37 | ERR_BAD_ARGS, | ||
36 | ERR_OK, | 38 | ERR_OK, |
37 | } ErrorValue; | 39 | } ErrorValue; |
38 | 40 | ||
diff --git a/src/parser.c b/src/parser.c index 10d82d1..0cf70d7 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -33,6 +33,27 @@ static Type default_types[] = { | |||
33 | [TYPE_F64] = {STRING("f64"), 8}, | 33 | [TYPE_F64] = {STRING("f64"), 8}, |
34 | }; | 34 | }; |
35 | 35 | ||
36 | typedef enum SymbolType { | ||
37 | SYMBOL_VAR, | ||
38 | SYMBOL_FUN, | ||
39 | } SymbolType; | ||
40 | |||
41 | typedef struct SymbolValue { | ||
42 | Node *name; | ||
43 | SymbolType type; | ||
44 | |||
45 | union { | ||
46 | struct { | ||
47 | Node *type; | ||
48 | } var; | ||
49 | |||
50 | struct { | ||
51 | Node **param_types; | ||
52 | Node *return_type; | ||
53 | } fun; | ||
54 | }; | ||
55 | } SymbolValue; | ||
56 | |||
36 | Token | 57 | Token |
37 | next_token(Parser *parser) { | 58 | next_token(Parser *parser) { |
38 | return parser->tokens[parser->current_token++]; | 59 | return parser->tokens[parser->current_token++]; |
@@ -542,6 +563,14 @@ alloc_parsetree(void) { | |||
542 | return parse_tree; | 563 | return parse_tree; |
543 | } | 564 | } |
544 | 565 | ||
566 | SymbolValue * | ||
567 | alloc_symval(Node *name, SymbolType type) { | ||
568 | SymbolValue *val = malloc(sizeof(SymbolValue)); | ||
569 | val->name = name; | ||
570 | val->type = type; | ||
571 | return val; | ||
572 | } | ||
573 | |||
545 | bool | 574 | bool |
546 | parse_roots(Parser *parser) { | 575 | parse_roots(Parser *parser) { |
547 | while (has_next(parser)) { | 576 | while (has_next(parser)) { |
@@ -573,36 +602,22 @@ find_type(Scope *scope, Node *type) { | |||
573 | return NULL; | 602 | return NULL; |
574 | } | 603 | } |
575 | 604 | ||
576 | Type * | 605 | bool |
577 | find_symbol(Scope *scope, Node *node) { | 606 | insert_symbol(Scope *scope, Node *symbol, SymbolValue *val) { |
578 | while (scope != NULL) { | 607 | // Check if symbol already exists. |
579 | Type *type = ht_lookup(scope->symbols, node); | ||
580 | if (type != NULL) { | ||
581 | return type; | ||
582 | } | ||
583 | scope = scope->parent; | ||
584 | } | ||
585 | push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_SYMBOL, node->line, node->col); | ||
586 | return NULL; | ||
587 | } | ||
588 | |||
589 | Type * | ||
590 | insert_symbol(Scope *scope, Node *symbol, Node *type) { | ||
591 | HashTable *symbols = scope->symbols; | 608 | HashTable *symbols = scope->symbols; |
592 | if (ht_lookup(symbols, symbol) != NULL) { | 609 | if (ht_lookup(symbols, symbol) != NULL) { |
593 | push_error(ERR_TYPE_PARSER, ERR_SYMBOL_REDEF, symbol->line, symbol->col); | 610 | push_error(ERR_TYPE_PARSER, ERR_SYMBOL_REDEF, symbol->line, symbol->col); |
594 | return NULL; | 611 | return false; |
595 | } | ||
596 | Type *t = find_type(scope, type); | ||
597 | if (t == NULL) { | ||
598 | return NULL; | ||
599 | } | 612 | } |
600 | ht_insert(symbols, symbol, t); | 613 | ht_insert(symbols, symbol, val); |
601 | return t; | 614 | return true; |
602 | } | 615 | } |
603 | 616 | ||
604 | Type * | 617 | Type * |
605 | coerce_numeric_types(Type *a, Type *b) { | 618 | coerce_numeric_types(Type *a, Type *b) { |
619 | // TODO: Decide what to do with mixed numeric types. What are the promotion | ||
620 | // rules, etc. | ||
606 | if (a == &default_types[TYPE_U8]) { | 621 | if (a == &default_types[TYPE_U8]) { |
607 | if (b == &default_types[TYPE_U16] || | 622 | if (b == &default_types[TYPE_U16] || |
608 | b == &default_types[TYPE_U32] || | 623 | b == &default_types[TYPE_U32] || |
@@ -658,6 +673,19 @@ type_is_numeric(Type *t) { | |||
658 | return false; | 673 | return false; |
659 | } | 674 | } |
660 | 675 | ||
676 | SymbolValue * | ||
677 | find_symbol(Scope *scope, Node *node) { | ||
678 | while (scope != NULL) { | ||
679 | SymbolValue *val = ht_lookup(scope->symbols, node); | ||
680 | if (val != NULL) { | ||
681 | return val; | ||
682 | } | ||
683 | scope = scope->parent; | ||
684 | } | ||
685 | push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_SYMBOL, node->line, node->col); | ||
686 | return NULL; | ||
687 | } | ||
688 | |||
661 | bool | 689 | bool |
662 | resolve_type(Scope *scope, Node *node) { | 690 | resolve_type(Scope *scope, Node *node) { |
663 | if (node->expr_type != NULL) { | 691 | if (node->expr_type != NULL) { |
@@ -732,7 +760,20 @@ resolve_type(Scope *scope, Node *node) { | |||
732 | } | 760 | } |
733 | } break; | 761 | } break; |
734 | case NODE_SYMBOL: { | 762 | case NODE_SYMBOL: { |
735 | Type *type = find_symbol(scope, node); | 763 | SymbolValue *val = find_symbol(scope, node); |
764 | if (val == NULL) { | ||
765 | return false; | ||
766 | } | ||
767 | |||
768 | Type *type = NULL; | ||
769 | switch (val->type) { | ||
770 | case SYMBOL_VAR: { | ||
771 | type = find_type(scope, val->var.type); | ||
772 | } break; | ||
773 | case SYMBOL_FUN: { | ||
774 | type = find_type(scope, val->fun.return_type); | ||
775 | } break; | ||
776 | } | ||
736 | if (type == NULL) { | 777 | if (type == NULL) { |
737 | return false; | 778 | return false; |
738 | } | 779 | } |
@@ -746,7 +787,9 @@ resolve_type(Scope *scope, Node *node) { | |||
746 | for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { | 787 | for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { |
747 | Node *param = node->fun.param_names[i]; | 788 | Node *param = node->fun.param_names[i]; |
748 | Node *type = node->fun.param_types[i]; | 789 | Node *type = node->fun.param_types[i]; |
749 | if (insert_symbol(scope, param, type) == NULL) { | 790 | SymbolValue *var = alloc_symval(param, SYMBOL_VAR); |
791 | var->var.type = type; | ||
792 | if (!insert_symbol(scope, param, var)) { | ||
750 | return false; | 793 | return false; |
751 | } | 794 | } |
752 | } | 795 | } |
@@ -840,7 +883,14 @@ resolve_type(Scope *scope, Node *node) { | |||
840 | } | 883 | } |
841 | } break; | 884 | } break; |
842 | case NODE_DEF: { | 885 | case NODE_DEF: { |
843 | Type *type = insert_symbol(scope, node->def.symbol, node->def.type); | 886 | // Prepare value for symbol table. |
887 | SymbolValue *var = alloc_symval(node->def.symbol, SYMBOL_VAR); | ||
888 | var->var.type = node->def.type; | ||
889 | if (!insert_symbol(scope, node->def.symbol, var)) { | ||
890 | return false; | ||
891 | } | ||
892 | |||
893 | Type *type = find_type(scope, node->def.type); | ||
844 | if (type == NULL) { | 894 | if (type == NULL) { |
845 | return false; | 895 | return false; |
846 | } | 896 | } |
@@ -862,7 +912,7 @@ resolve_type(Scope *scope, Node *node) { | |||
862 | case NODE_NUMBER: { | 912 | case NODE_NUMBER: { |
863 | // TODO: Numbers are f64/s64 unless explicitely annotated. Annotated | 913 | // TODO: Numbers are f64/s64 unless explicitely annotated. Annotated |
864 | // numbers must fit in the given range (e.g. no negative constants | 914 | // numbers must fit in the given range (e.g. no negative constants |
865 | // inside a U64, no numbers bigger than 255 in a u8, etc.). | 915 | // inside a u64, no numbers bigger than 255 in a u8, etc.). |
866 | if (node->number.fractional != 0) { | 916 | if (node->number.fractional != 0) { |
867 | node->expr_type = &default_types[TYPE_F64]; | 917 | node->expr_type = &default_types[TYPE_F64]; |
868 | } else { | 918 | } else { |
@@ -876,16 +926,31 @@ resolve_type(Scope *scope, Node *node) { | |||
876 | node->expr_type = &default_types[TYPE_STR]; | 926 | node->expr_type = &default_types[TYPE_STR]; |
877 | } break; | 927 | } break; |
878 | case NODE_FUNCALL: { | 928 | case NODE_FUNCALL: { |
879 | // TODO: Check that arguments type check with expectations. | 929 | SymbolValue *val = find_symbol(scope, node->funcall.name); |
880 | if (!resolve_type(scope, node->funcall.name)) { | 930 | if (!resolve_type(scope, node->funcall.name)) { |
881 | return false; | 931 | return false; |
882 | } | 932 | } |
933 | if (val->type != SYMBOL_FUN) { | ||
934 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_FUN, | ||
935 | node->funcall.name->line, node->funcall.name->col); | ||
936 | return false; | ||
937 | } | ||
938 | if (array_size(node->funcall.args) != array_size(val->fun.param_types)) { | ||
939 | push_error(ERR_TYPE_PARSER, ERR_BAD_ARGS, node->line, node->col); | ||
940 | return false; | ||
941 | } | ||
883 | node->expr_type = node->funcall.name->expr_type; | 942 | node->expr_type = node->funcall.name->expr_type; |
884 | for (size_t i = 0; i < array_size(node->funcall.args); ++i) { | 943 | for (size_t i = 0; i < array_size(node->funcall.args); ++i) { |
885 | Node *arg = node->funcall.args[i]; | 944 | Node *arg = node->funcall.args[i]; |
886 | if (!resolve_type(scope, arg)) { | 945 | if (!resolve_type(scope, arg)) { |
887 | return false; | 946 | return false; |
888 | } | 947 | } |
948 | Node *expected = val->fun.param_types[i]; | ||
949 | if (!sv_equal(&arg->expr_type->name, &expected->string)) { | ||
950 | push_error(ERR_TYPE_PARSER, ERR_TYPE_MISMATCH, | ||
951 | arg->line, arg->col); | ||
952 | return false; | ||
953 | } | ||
889 | } | 954 | } |
890 | } break; | 955 | } break; |
891 | default: break; | 956 | default: break; |
@@ -901,10 +966,10 @@ semantic_analysis(Parser *parser) { | |||
901 | Node *root = parser->parse_tree->roots[i]; | 966 | Node *root = parser->parse_tree->roots[i]; |
902 | if (root->type == NODE_FUN) { | 967 | if (root->type == NODE_FUN) { |
903 | Node *name = root->fun.name; | 968 | Node *name = root->fun.name; |
904 | // TODO: make sure we store information in the symbol table that | 969 | SymbolValue *fun = alloc_symval(root->fun.name, SYMBOL_FUN); |
905 | // this is actually a function, not just a variable with | 970 | fun->fun.param_types = root->fun.param_types; |
906 | // return_type. | 971 | fun->fun.return_type = root->fun.return_type; |
907 | if (insert_symbol(scope, name, root->fun.return_type) == NULL) { | 972 | if (!insert_symbol(scope, name, fun)) { |
908 | return false; | 973 | return false; |
909 | } | 974 | } |
910 | } | 975 | } |