diff options
author | Bad Diode <bd@badd10de.dev> | 2022-04-09 08:22:31 -0300 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-04-09 08:22:31 -0300 |
commit | ab3e064c6f90ec94daad99b5a4c56e0abbcc79bb (patch) | |
tree | 597b3d8a3d10ea5914bb86d6c3774bde1b333eeb /src/parser.c | |
parent | 233dd92768a54060df9096558aa58c1f598cce7d (diff) | |
download | bdl-ab3e064c6f90ec94daad99b5a4c56e0abbcc79bb.tar.gz bdl-ab3e064c6f90ec94daad99b5a4c56e0abbcc79bb.zip |
Add more type rules and numeric type coercion
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 183 |
1 files changed, 163 insertions, 20 deletions
diff --git a/src/parser.c b/src/parser.c index ddcee56..252ceaa 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -684,6 +684,107 @@ symbol_check(Parser *parser, Node *node) { | |||
684 | return true; | 684 | return true; |
685 | } | 685 | } |
686 | 686 | ||
687 | Type * | ||
688 | coerce_numeric_types(Type *a, Type *b) { | ||
689 | if (a == &default_types[TYPE_U8]) { | ||
690 | if (b == &default_types[TYPE_U16] || | ||
691 | b == &default_types[TYPE_U32] || | ||
692 | b == &default_types[TYPE_U64] || | ||
693 | b == &default_types[TYPE_S8] || | ||
694 | b == &default_types[TYPE_S16] || | ||
695 | b == &default_types[TYPE_S32] || | ||
696 | b == &default_types[TYPE_S64] || | ||
697 | b == &default_types[TYPE_F32] || | ||
698 | b == &default_types[TYPE_F64]) { | ||
699 | return b; | ||
700 | } | ||
701 | } else if (a == &default_types[TYPE_U16]) { | ||
702 | if (b == &default_types[TYPE_U32] || | ||
703 | b == &default_types[TYPE_S16] || | ||
704 | b == &default_types[TYPE_S32] || | ||
705 | b == &default_types[TYPE_S64] || | ||
706 | b == &default_types[TYPE_U64] || | ||
707 | b == &default_types[TYPE_F32] || | ||
708 | b == &default_types[TYPE_F64]) { | ||
709 | return b; | ||
710 | } | ||
711 | if (b == &default_types[TYPE_S8]) { | ||
712 | return &default_types[TYPE_S16]; | ||
713 | } | ||
714 | } else if (a == &default_types[TYPE_U32]) { | ||
715 | if (b == &default_types[TYPE_U64] || | ||
716 | b == &default_types[TYPE_S32] || | ||
717 | b == &default_types[TYPE_S64] || | ||
718 | b == &default_types[TYPE_F32] || | ||
719 | b == &default_types[TYPE_F64]) { | ||
720 | return b; | ||
721 | } | ||
722 | if (b == &default_types[TYPE_S8] || | ||
723 | b == &default_types[TYPE_S16]) { | ||
724 | return &default_types[TYPE_S32]; | ||
725 | } | ||
726 | } else if (a == &default_types[TYPE_U64]) { | ||
727 | if (b == &default_types[TYPE_S64] || | ||
728 | b == &default_types[TYPE_F32] || | ||
729 | b == &default_types[TYPE_F64]) { | ||
730 | return b; | ||
731 | } | ||
732 | if (b == &default_types[TYPE_S8] || | ||
733 | b == &default_types[TYPE_S16] || | ||
734 | b == &default_types[TYPE_S32]) { | ||
735 | return &default_types[TYPE_S64]; | ||
736 | } | ||
737 | } else if (a == &default_types[TYPE_S8]) { | ||
738 | if (b == &default_types[TYPE_S16] || | ||
739 | b == &default_types[TYPE_S32] || | ||
740 | b == &default_types[TYPE_S64] || | ||
741 | b == &default_types[TYPE_F32] || | ||
742 | b == &default_types[TYPE_F64]) { | ||
743 | return b; | ||
744 | } | ||
745 | } else if (a == &default_types[TYPE_S16]) { | ||
746 | if (b == &default_types[TYPE_S32] || | ||
747 | b == &default_types[TYPE_S64] || | ||
748 | b == &default_types[TYPE_F32] || | ||
749 | b == &default_types[TYPE_F64]) { | ||
750 | return b; | ||
751 | } | ||
752 | } else if (a == &default_types[TYPE_S32]) { | ||
753 | if (b == &default_types[TYPE_S64] || | ||
754 | b == &default_types[TYPE_F32] || | ||
755 | b == &default_types[TYPE_F64]) { | ||
756 | return b; | ||
757 | } | ||
758 | } else if (a == &default_types[TYPE_S64]) { | ||
759 | if (b == &default_types[TYPE_F32] || | ||
760 | b == &default_types[TYPE_F64]) { | ||
761 | return b; | ||
762 | } | ||
763 | } else if (a == &default_types[TYPE_F32]) { | ||
764 | if (b == &default_types[TYPE_F64]) { | ||
765 | return b; | ||
766 | } | ||
767 | } | ||
768 | return a; | ||
769 | } | ||
770 | |||
771 | bool | ||
772 | type_is_numeric(Type *t) { | ||
773 | if (t == &default_types[TYPE_U8] || | ||
774 | t == &default_types[TYPE_U16] || | ||
775 | t == &default_types[TYPE_U32] || | ||
776 | t == &default_types[TYPE_U64] || | ||
777 | t == &default_types[TYPE_S8] || | ||
778 | t == &default_types[TYPE_S16] || | ||
779 | t == &default_types[TYPE_S32] || | ||
780 | t == &default_types[TYPE_S64] || | ||
781 | t == &default_types[TYPE_F32] || | ||
782 | t == &default_types[TYPE_F64]) { | ||
783 | return true; | ||
784 | } | ||
785 | return false; | ||
786 | } | ||
787 | |||
687 | bool | 788 | bool |
688 | resolve_type(Parser *parser, Node *node) { | 789 | resolve_type(Parser *parser, Node *node) { |
689 | if (node->expr_type != NULL) { | 790 | if (node->expr_type != NULL) { |
@@ -696,6 +797,10 @@ resolve_type(Parser *parser, Node *node) { | |||
696 | } | 797 | } |
697 | switch (node->type) { | 798 | switch (node->type) { |
698 | case NODE_BUILTIN: { | 799 | case NODE_BUILTIN: { |
800 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | ||
801 | Node *arg = node->builtin.args[i]; | ||
802 | resolve_type(parser, arg); | ||
803 | } | ||
699 | switch (node->builtin.type) { | 804 | switch (node->builtin.type) { |
700 | // Numbers. | 805 | // Numbers. |
701 | case TOKEN_ADD: | 806 | case TOKEN_ADD: |
@@ -703,35 +808,67 @@ resolve_type(Parser *parser, Node *node) { | |||
703 | case TOKEN_MUL: | 808 | case TOKEN_MUL: |
704 | case TOKEN_DIV: | 809 | case TOKEN_DIV: |
705 | case TOKEN_MOD: { | 810 | case TOKEN_MOD: { |
706 | // TODO: Properly resolve this | 811 | Type *type = NULL; |
707 | node->expr_type = &default_types[TYPE_U64]; | 812 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { |
813 | Node *arg = node->builtin.args[i]; | ||
814 | |||
815 | // Check that all arguments are nums. | ||
816 | if (!type_is_numeric(arg->expr_type)) { | ||
817 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, | ||
818 | arg->line, arg->col); | ||
819 | return false; | ||
820 | } | ||
821 | |||
822 | if (type == NULL) { | ||
823 | type = arg->expr_type; | ||
824 | } else if (type != arg->expr_type) { | ||
825 | type = coerce_numeric_types(type, arg->expr_type); | ||
826 | } | ||
827 | } | ||
828 | node->expr_type = type; | ||
708 | } break; | 829 | } break; |
709 | // Bools. | 830 | // Bools. |
710 | case TOKEN_NOT: | 831 | case TOKEN_NOT: |
711 | case TOKEN_AND: | 832 | case TOKEN_AND: |
712 | case TOKEN_OR: | 833 | case TOKEN_OR: { |
834 | // Check that all arguments are boolean. | ||
835 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | ||
836 | Node *arg = node->builtin.args[i]; | ||
837 | if (arg->expr_type != &default_types[TYPE_BOOL]) { | ||
838 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_BOOL, | ||
839 | arg->line, arg->col); | ||
840 | return false; | ||
841 | } | ||
842 | } | ||
843 | node->expr_type = &default_types[TYPE_BOOL]; | ||
844 | } break; | ||
713 | case TOKEN_EQ: | 845 | case TOKEN_EQ: |
714 | case TOKEN_LT: | 846 | case TOKEN_LT: |
715 | case TOKEN_GT: | 847 | case TOKEN_GT: |
716 | case TOKEN_LE: | 848 | case TOKEN_LE: |
717 | case TOKEN_GE: { | 849 | case TOKEN_GE: { |
850 | // Check that all arguments are nums. | ||
851 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | ||
852 | Node *arg = node->builtin.args[i]; | ||
853 | if (!type_is_numeric(arg->expr_type)) { | ||
854 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_NUM, | ||
855 | arg->line, arg->col); | ||
856 | return false; | ||
857 | } | ||
858 | } | ||
718 | node->expr_type = &default_types[TYPE_BOOL]; | 859 | node->expr_type = &default_types[TYPE_BOOL]; |
719 | } break; | 860 | } break; |
720 | default: break; | 861 | default: break; |
721 | } | 862 | } |
722 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | ||
723 | Node *arg = node->builtin.args[i]; | ||
724 | resolve_type(parser, arg); | ||
725 | } | ||
726 | } break; | 863 | } break; |
727 | case NODE_SYMBOL: { | 864 | case NODE_SYMBOL: { |
728 | node->expr_type = find_symbol(parser, node); | 865 | node->expr_type = find_symbol(parser, node); |
729 | } break; | 866 | } break; |
730 | case NODE_FUN: { | 867 | case NODE_FUN: { |
731 | resolve_type(parser, node->fun.body); | 868 | resolve_type(parser, node->fun.body); |
869 | // Check that the type of body matches the return type. | ||
732 | StringView *type_body = &node->fun.body->expr_type->name; | 870 | StringView *type_body = &node->fun.body->expr_type->name; |
733 | StringView *return_type = &node->fun.return_type->string; | 871 | StringView *return_type = &node->fun.return_type->string; |
734 | // Check that the type of body matches the return type. | ||
735 | if (!sv_equal(type_body, return_type)) { | 872 | if (!sv_equal(type_body, return_type)) { |
736 | push_error(ERR_TYPE_PARSER, ERR_WRONG_RET_TYPE, node->line, node->col); | 873 | push_error(ERR_TYPE_PARSER, ERR_WRONG_RET_TYPE, node->line, node->col); |
737 | return false; | 874 | return false; |
@@ -747,22 +884,32 @@ resolve_type(Parser *parser, Node *node) { | |||
747 | } break; | 884 | } break; |
748 | case NODE_IF: { | 885 | case NODE_IF: { |
749 | resolve_type(parser, node->ifexpr.cond); | 886 | resolve_type(parser, node->ifexpr.cond); |
887 | resolve_type(parser, node->ifexpr.expr_true); | ||
888 | Type *type_true = node->ifexpr.expr_true->expr_type; | ||
889 | node->expr_type = type_true; | ||
890 | if (node->ifexpr.expr_false != NULL) { | ||
891 | resolve_type(parser, node->ifexpr.expr_false); | ||
892 | } | ||
893 | |||
750 | // Check ifexpr.cond is a bool. | 894 | // Check ifexpr.cond is a bool. |
751 | if (!sv_equal(&node->ifexpr.cond->expr_type->name, &default_types[TYPE_BOOL].name)) { | 895 | Type *type_cond = node->ifexpr.cond->expr_type; |
752 | push_error(ERR_TYPE_PARSER, ERR_WRONG_COND_TYPE, node->line, node->col); | 896 | if (!sv_equal(&type_cond->name, &default_types[TYPE_BOOL].name)) { |
897 | push_error(ERR_TYPE_PARSER, ERR_WRONG_COND_TYPE, | ||
898 | node->line, node->col); | ||
753 | return false; | 899 | return false; |
754 | } | 900 | } |
755 | 901 | ||
756 | resolve_type(parser, node->ifexpr.expr_true); | 902 | // Check if types of expr_true and expr_false match |
757 | if (node->ifexpr.expr_false != NULL) { | 903 | if (node->ifexpr.expr_false != NULL) { |
758 | resolve_type(parser, node->ifexpr.expr_false); | 904 | Type *type_false = node->ifexpr.expr_false->expr_type; |
759 | // Check if types of expr_true and expr_false match | 905 | if (type_is_numeric(type_true) && type_is_numeric(type_false)) { |
760 | if (!sv_equal(&node->ifexpr.expr_true->expr_type->name, &node->ifexpr.expr_false->expr_type->name)) { | 906 | node->expr_type = coerce_numeric_types(type_true, type_false); |
761 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_T_F, node->line, node->col); | 907 | } else if (!sv_equal(&type_true->name, &type_false->name)) { |
908 | push_error(ERR_TYPE_PARSER, ERR_WRONG_TYPE_T_F, | ||
909 | node->line, node->col); | ||
762 | return false; | 910 | return false; |
763 | } | 911 | } |
764 | } | 912 | } |
765 | node->expr_type = node->ifexpr.expr_true->expr_type; | ||
766 | } break; | 913 | } break; |
767 | case NODE_SET: { | 914 | case NODE_SET: { |
768 | node->expr_type = &default_types[TYPE_VOID]; | 915 | node->expr_type = &default_types[TYPE_VOID]; |
@@ -773,10 +920,6 @@ resolve_type(Parser *parser, Node *node) { | |||
773 | resolve_type(parser, node->def.value); | 920 | resolve_type(parser, node->def.value); |
774 | } break; | 921 | } break; |
775 | case NODE_NUMBER: { | 922 | case NODE_NUMBER: { |
776 | // TODO: Is this the best way of doing it? We probably need a more | ||
777 | // sophisticated way of approaching this. For example: | ||
778 | // `(if (< 1 2) 1 -2)` will currently fail with this approach, since | ||
779 | // 1:u64 and -2:s64 | ||
780 | if (node->number.fractional != 0) { | 923 | if (node->number.fractional != 0) { |
781 | node->expr_type = &default_types[TYPE_F64]; | 924 | node->expr_type = &default_types[TYPE_F64]; |
782 | } else if (node->number.negative) { | 925 | } else if (node->number.negative) { |