From dd8fbc20ed14d552b127429f6a83acac4b3c79ca Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 3 Jun 2022 15:35:27 +0200 Subject: [PATCH] Boolean operators --- new_types.kl | 5 +++ typecheck.cpp | 100 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/new_types.kl b/new_types.kl index db0a83b..4836c6c 100644 --- a/new_types.kl +++ b/new_types.kl @@ -22,6 +22,11 @@ binary_test :: () bit_or :: 1 | 4 bit_xor :: 8 ^ 7 + boolean_equals :: true == false + boolean_var: Bool = boolean_equals + + bvar2 := int_val > 1 + bvar3 := int_val < 1 basic_type_assignment :: () diff --git a/typecheck.cpp b/typecheck.cpp index 1112f34..b0b4879 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -95,7 +95,28 @@ value_get_float(Value value){ #include function Value eval_binary(Token *pos, Token_Kind op, Value a, Value b){ - if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", token_kind_string(op).str, docname(a.type)); + if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", token_kind_string(op).str, docname(a.type), docname(a.type)); + + // @warning: this bool path returns early, always should return untyped bool + if(is_bool(a.type) || is_bool(b.type)){ + if(!is_bool(a.type)) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type)); + if(!is_bool(b.type)) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type)); + + Value result; + result.type = untyped_bool; + switch(op){ + case TK_And: result.bool_val = a.bool_val && b.bool_val; break; + case TK_Or: result.bool_val = a.bool_val || b.bool_val; break; + case TK_GreaterThen: result.bool_val = a.bool_val > b.bool_val; break; + case TK_GreaterThenOrEqual: result.bool_val = a.bool_val >= b.bool_val; break; + case TK_LesserThen: result.bool_val = a.bool_val < b.bool_val; break; + case TK_LesserThenOrEqual: result.bool_val = a.bool_val <= b.bool_val; break; + case TK_Equals: result.bool_val = a.bool_val == b.bool_val; break; + case TK_NotEquals: result.bool_val = a.bool_val != b.bool_val; break; + invalid_default_case; + } + return result; + } Ast_Resolved_Type *final_type = 0; Value before_conversion; @@ -123,7 +144,53 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){ F64 right_float = value_get_float(b); // @WARNING: When introducing big ints & | ^ will be problematic + Value c; + c.type = untyped_bool; switch(op){ + + // @note: These return early, they don't need type evaluation + // always should return untyped bool + case TK_And: { + if(final_type == untyped_int) c.bool_val = left_int && right_int; + else c.bool_val = left_float && right_float; + return c; + }break; + case TK_Or: { + if(final_type == untyped_int) c.bool_val = left_int || right_int; + else c.bool_val = left_float || right_float; + return c; + }break; + case TK_GreaterThen: { + if(final_type == untyped_int) c.bool_val = left_int > right_int; + else c.bool_val = left_float > right_float; + return c; + }break; + case TK_GreaterThenOrEqual: { + if(final_type == untyped_int) c.bool_val = left_int >= right_int; + else c.bool_val = left_float >= right_float; + return c; + }break; + case TK_LesserThen: { + if(final_type == untyped_int) c.bool_val = left_int < right_int; + else c.bool_val = left_float < right_float; + return c; + }break; + case TK_LesserThenOrEqual: { + if(final_type == untyped_int) c.bool_val = left_int <= right_int; + else c.bool_val = left_float <= right_float; + return c; + }break; + case TK_Equals: { + if(final_type == untyped_int) c.bool_val = left_int == right_int; + else c.bool_val = left_float == right_float; + return c; + }break; + case TK_NotEquals: { + if(final_type == untyped_int) c.bool_val = left_int != right_int; + else c.bool_val = left_float != right_float; + return c; + }break; + case TK_Add: { left_int = left_int + right_int; left_float = left_float + right_float; @@ -156,7 +223,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){ left_int = left_int ^ right_int; if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str); } break; - invalid_default_case; + default: parsing_error(pos, "Binary operation %s is not allowed on types: left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type)); } if(before_conversion.type == untyped_float){ @@ -711,35 +778,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } //----------------------------------------------------------------------------- - //----------------------------------------------------------------------------- - else if(token_is_compare(node->op)){ - Operand left = resolve_expr(node->left); - Operand right = resolve_expr(node->right); - - if(left.is_const && right.is_const){ - if(result.type == type_int){ - switch(node->op){ - case TK_GreaterThen : result.bool_val = left.int_val > right.int_val; break; - case TK_GreaterThenOrEqual: result.bool_val = left.int_val >= right.int_val; break; - case TK_LesserThen : result.bool_val = left.int_val < right.int_val; break; - case TK_LesserThenOrEqual : result.bool_val = left.int_val <= right.int_val; break; - case TK_Equals : result.bool_val = left.int_val == right.int_val; break; - case TK_NotEquals : result.bool_val = left.int_val != right.int_val; break; - invalid_default_case; - } - } - else parsing_error(node->pos, "Arithmetic on type [%s] is not supported", type_names[result.type->kind]); - } - else if(left.type != right.type) { - parsing_error(node->pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(node->op).str, docname(left.type), docname(right.type)); - } - else{ - result = operand_rvalue(left.type); - } - - } - //----------------------------------------------------------------------------- - //----------------------------------------------------------------------------- else{ Operand left = resolve_expr(node->left);