From 729e7aee8651f845a207d68d25b4f70a326edfbd Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Mon, 6 Jun 2022 22:14:30 +0200 Subject: [PATCH] Fixing type checking --- ccodegen.cpp | 16 +-- globals.kl | 1 - main.cpp | 9 +- new_ast.cpp | 44 +++++++ new_types.kl | 5 + typecheck.cpp | 349 +++++++++++++++++++++++--------------------------- 6 files changed, 219 insertions(+), 205 deletions(-) diff --git a/ccodegen.cpp b/ccodegen.cpp index 228d2d0..061f910 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -130,19 +130,9 @@ gen_expr(Ast_Expr *ast){ } CASE(UNARY, Unary){ - switch(node->op){ - case TK_Pointer: { - gen("(*"); - gen_expr(node->expr); - gen(")"); - } break; - case TK_Dereference: { - gen("(&"); - gen_expr(node->expr); - gen(")"); - } break; - invalid_default_case; - } + gen("(%s", name(node->op)); + gen_expr(node->expr); + gen(")"); BREAK(); } diff --git a/globals.kl b/globals.kl index 363d3da..c2a847b 100644 --- a/globals.kl +++ b/globals.kl @@ -10,7 +10,6 @@ const_function_alias :: test_function // Booleans //----------------------------------------------------------------------------- Boolean: Bool = true -value_of_Bool: S64 = cast(Boolean: S64) //----------------------------------------------------------------------------- // Nulls diff --git a/main.cpp b/main.cpp index 98b6834..01579a2 100644 --- a/main.cpp +++ b/main.cpp @@ -68,10 +68,17 @@ cast(expr: type) convert between typed to other typed check if types compatible +Stmt: + Return - Expression should match lambda return type +Expr: + Lambda - Arguments, default values should match type + ArrayT - Should match type int and be constant or not at all + Call - Arguments should match type @todo [ ] - Fix casting +[ ] - Make sure pointer arithmetic works [ ] - Passing down program to compile through command line [ ] - More for loop variations [ ] - Write up on order independent declarations @@ -160,7 +167,7 @@ int main(){ String result = {}; -#if 0 +#if 1 result = compile_file("globals.kl"_s); printf("%s", result.str); result = compile_file("enums.kl"_s); diff --git a/new_ast.cpp b/new_ast.cpp index 3f4eedb..9cf9658 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -564,6 +564,50 @@ ast_package(Token *pos, String name, Array decls){ return result; } +//----------------------------------------------------------------------------- +// Value +//----------------------------------------------------------------------------- +function Value +value_bool(B32 v){ + Value value; + value.bool_val = v; + value.type = untyped_bool; + return value; +} + +function Value +value_int(BigInt b){ + Value value; + value.big_int_val = b; + value.type = untyped_int; + return value; +} + +function Value +value_int(S64 s64){ + Value value; + value.type = untyped_int; + bigint_init_signed(&value.big_int_val, s64); + return value; +} + +function Value +value_float(F64 b){ + Value value; + value.f64_val = b; + value.type = untyped_float; + return value; +} + +function Value +value_float(BigInt a){ + Value value; + value.f64_val = bigint_as_float(&a); + value.type = untyped_float; + return value; +} + + //----------------------------------------------------------------------------- // Utillities //----------------------------------------------------------------------------- diff --git a/new_types.kl b/new_types.kl index 0919847..0110d2f 100644 --- a/new_types.kl +++ b/new_types.kl @@ -14,6 +14,11 @@ unary_test :: () neg32: S32 = ~int_val big_neg32: U32 = ~cast(41512512: U32) + var1: S64 + var2: S64 = 20 + var_bool: Bool = !var1 == !var2 + + // uns: U64 = -int_val // int_float: S64 = float_val // string :: -"Thing" diff --git a/typecheck.cpp b/typecheck.cpp index 3d9d1a6..660114c 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -31,46 +31,6 @@ type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual, //----------------------------------------------------------------------------- // Evaluating constant expressions //----------------------------------------------------------------------------- -function Value -value_bool(B32 v){ - Value value; - value.bool_val = v; - value.type = untyped_bool; - return value; -} - -function Value -value_int(BigInt b){ - Value value; - value.big_int_val = b; - value.type = untyped_int; - return value; -} - -function Value -value_int(S64 s64){ - Value value; - value.type = untyped_int; - bigint_init_signed(&value.big_int_val, s64); - return value; -} - -function Value -value_float(F64 b){ - Value value; - value.f64_val = b; - value.type = untyped_float; - return value; -} - -function Value -value_float(BigInt a){ - Value value; - value.f64_val = bigint_as_float(&a); - value.type = untyped_float; - return value; -} - function void check_value_bounds(Token *pos, Value *a){ if(!is_int(a->type)) return; @@ -83,7 +43,7 @@ check_value_bounds(Token *pos, Value *a){ } function Value -convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ +convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){ assert(new_type); if(a.type == 0) return a; if(is_typed(a.type)) return a; @@ -106,19 +66,19 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ } function void -match_values(Token *pos, Value *a, Value *b){ +make_sure_types_are_compatible(Token *pos, Value *a, Value *b){ if(is_typed(a->type) && is_typed(b->type)){ if(a->type != b->type){ - parsing_error(pos, "Type mismatch in match_values - left: %s right: %s", docname(a->type), docname(b->type)); + parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type)); } } if(is_untyped(a->type) && is_typed(b->type)){ assert(is_typed(b->type)); - *a = convert_untyped(pos, *a, b->type); + *a = convert_untyped_to_typed(pos, *a, b->type); } else if(is_typed(a->type) && is_untyped(b->type)){ assert(is_typed(a->type)); - *b = convert_untyped(pos, *b, a->type); + *b = convert_untyped_to_typed(pos, *b, a->type); } else if(is_int(a->type) && is_float(b->type)){ @@ -130,175 +90,178 @@ match_values(Token *pos, Value *a, Value *b){ } function Value -compare_values(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 and %s is not allowed", name(op), docname(a.type), docname(a.type)); - match_values(pos, &a, &b); +compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){ + 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", name(op), docname(a.type), docname(a.type)); + + make_sure_types_are_compatible(pos, &a, &b); B32 result = 0; - switch(a.type->kind){ - CASE_INT:{ - CmpRes cmp = bigint_cmp(&a.big_int_val, &b.big_int_val); - switch(op){ - case TK_LesserThenOrEqual: result = (cmp == CMP_LT) || (cmp == CMP_EQ); break; - case TK_GreaterThenOrEqual: result = (cmp == CMP_GT) || (cmp == CMP_EQ); break; - case TK_GreaterThen: result = cmp == CMP_GT; break; - case TK_LesserThen: result = cmp == CMP_LT; break; - case TK_Equals: result = cmp == CMP_EQ; break; - case TK_NotEquals: result = cmp != CMP_EQ; break; - invalid_default_case; - } - }break; - CASE_BOOL:{ - switch(op){ - case TK_Equals: result = a.bool_val == b.bool_val; break; - case TK_NotEquals: result = a.bool_val != b.bool_val; break; - invalid_default_case; - } - }break; - CASE_FLOAT:{ - switch(op){ - case TK_LesserThenOrEqual: result = a.f64_val <= b.f64_val; break; - case TK_GreaterThenOrEqual: result = a.f64_val >= b.f64_val; break; - case TK_GreaterThen: result = a.f64_val > b.f64_val; break; - case TK_LesserThen: result = a.f64_val < b.f64_val; break; - case TK_Equals: result = a.f64_val == b.f64_val; break; - case TK_NotEquals: result = a.f64_val != b.f64_val; break; - invalid_default_case; - } - }break; - CASE_STRING:{ - invalid_codepath; - }break; - invalid_default_case; + if(is_const){ + switch(a.type->kind){ + CASE_INT:{ + CmpRes cmp = bigint_cmp(&a.big_int_val, &b.big_int_val); + switch(op){ + case TK_LesserThenOrEqual: result = (cmp == CMP_LT) || (cmp == CMP_EQ); break; + case TK_GreaterThenOrEqual: result = (cmp == CMP_GT) || (cmp == CMP_EQ); break; + case TK_GreaterThen: result = cmp == CMP_GT; break; + case TK_LesserThen: result = cmp == CMP_LT; break; + case TK_Equals: result = cmp == CMP_EQ; break; + case TK_NotEquals: result = cmp != CMP_EQ; break; + invalid_default_case; + } + }break; + CASE_BOOL:{ + switch(op){ + case TK_Equals: result = a.bool_val == b.bool_val; break; + case TK_NotEquals: result = a.bool_val != b.bool_val; break; + invalid_default_case; + } + }break; + CASE_FLOAT:{ + switch(op){ + case TK_LesserThenOrEqual: result = a.f64_val <= b.f64_val; break; + case TK_GreaterThenOrEqual: result = a.f64_val >= b.f64_val; break; + case TK_GreaterThen: result = a.f64_val > b.f64_val; break; + case TK_LesserThen: result = a.f64_val < b.f64_val; break; + case TK_Equals: result = a.f64_val == b.f64_val; break; + case TK_NotEquals: result = a.f64_val != b.f64_val; break; + invalid_default_case; + } + }break; + CASE_STRING:{ + invalid_codepath; + }break; + invalid_default_case; + } } + return value_bool(result); } function Value -eval_binary(Token *pos, Token_Kind op, Value a, Value b){ - if(token_is_compare(op)){ - return compare_values(pos, op, a, b); - } +eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){ + if(token_is_compare(op)) + return compare_values(pos, op, a, b, is_const); - 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", name(op), docname(a.type), docname(a.type)); - match_values(pos, &a, &b); + 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", name(op), docname(a.type), docname(a.type)); + + make_sure_types_are_compatible(pos, &a, &b); Value result = {}; result.type = a.type; - switch(a.type->kind){ - CASE_INT:{ - switch(op){ - case TK_BitXor: bigint_xor(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_BitAnd: bigint_and(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_BitOr: bigint_or(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_Add: bigint_add(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_Sub: bigint_sub(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_Mul: bigint_mul(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_Div: bigint_div_trunc(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_Mod: bigint_mod(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_LeftShift: bigint_shl(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - case TK_RightShift: bigint_shr(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; - invalid_default_case; - } - }break; - CASE_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_BitAnd: result.bool_val = a.bool_val & b.bool_val; break; - case TK_BitOr: result.bool_val = a.bool_val | b.bool_val; break; - case TK_BitXor: result.bool_val = a.bool_val ^ b.bool_val; break; - invalid_default_case; - } - }break; - CASE_FLOAT:{ - switch(op){ - case TK_Add: result.f64_val = a.f64_val + b.f64_val; break; - case TK_Sub: result.f64_val = a.f64_val - b.f64_val; break; - case TK_Mul: result.f64_val = a.f64_val * b.f64_val; break; - case TK_Div: result.f64_val = a.f64_val / b.f64_val; break; - invalid_default_case; - } - }break; - CASE_STRING:{ - invalid_codepath; - }break; - invalid_default_case; + if(is_const){ + switch(a.type->kind){ + CASE_INT:{ + switch(op){ + case TK_BitXor: bigint_xor(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_BitAnd: bigint_and(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_BitOr: bigint_or(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_Add: bigint_add(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_Sub: bigint_sub(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_Mul: bigint_mul(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_Div: bigint_div_trunc(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_Mod: bigint_mod(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_LeftShift: bigint_shl(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + case TK_RightShift: bigint_shr(&result.big_int_val, &a.big_int_val, &b.big_int_val); break; + invalid_default_case; + } + }break; + CASE_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_BitAnd: result.bool_val = a.bool_val & b.bool_val; break; + case TK_BitOr: result.bool_val = a.bool_val | b.bool_val; break; + case TK_BitXor: result.bool_val = a.bool_val ^ b.bool_val; break; + invalid_default_case; + } + }break; + CASE_FLOAT:{ + switch(op){ + case TK_Add: result.f64_val = a.f64_val + b.f64_val; break; + case TK_Sub: result.f64_val = a.f64_val - b.f64_val; break; + case TK_Mul: result.f64_val = a.f64_val * b.f64_val; break; + case TK_Div: result.f64_val = a.f64_val / b.f64_val; break; + invalid_default_case; + } + }break; + CASE_STRING:{ + invalid_codepath; + }break; + invalid_default_case; + } } return result; } function S64 -digit_count(Value a){ - S64 digit_count = a.big_int_val.digit_count*64; - if(is_typed(a.type)){ - digit_count = a.type->size*8; +digit_count(const Value *a){ + S64 digit_count = a->big_int_val.digit_count*64; + if(is_typed(a->type)){ + digit_count = a->type->size*8; } return digit_count; } -function Value -eval_unary(Token *pos, Token_Kind op, Value a){ +function void +eval_unary(Token *pos, Token_Kind op, Value *a, bool is_const){ + Ast_Resolved_Type *type = a->type; + if(!is_numeric(type)) + parsing_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type)); + + if(op == TK_Not) + a->type = untyped_bool; + + if(!is_const) + return; + BigInt result = {}; switch(op){ - case TK_Add:{ - return a; - } break; + case TK_Add:{} break; case TK_Sub:{ - switch(a.type->kind){ + switch(type->kind){ CASE_INT:{ - bigint_negate(&result, &a.big_int_val); - return value_int(result); + bigint_negate(&result, &a->big_int_val); + a->big_int_val = result; }break; CASE_FLOAT:{ - return value_float(-a.f64_val); + a->f64_val = -a->f64_val; }break; default:goto failure; } } break; case TK_Neg:{ - - - switch(a.type->kind){ - CASE_SINT: case TYPE_UNTYPED_INT:{ - bigint_not(&result, &a.big_int_val, digit_count(a), 1); - return value_int(result); - }break; - CASE_UINT:{ - bigint_not(&result, &a.big_int_val, digit_count(a), 0); - return value_int(result); - } + switch(type->kind){ + CASE_SINT: case TYPE_UNTYPED_INT: + bigint_not(&result, &a->big_int_val, digit_count(a), 1); break; + CASE_UINT: + bigint_not(&result, &a->big_int_val, digit_count(a), 0); break; default:goto failure; } + a->big_int_val = result; } break; case TK_Not:{ - switch(a.type->kind){ + switch(type->kind){ CASE_INT: { - if(CMP_EQ == bigint_cmp_zero(&a.big_int_val)) - return value_bool(1); - return value_bool(0); - }break; - CASE_FLOAT:{ - return value_bool(!a.f64_val); - }break; - CASE_BOOL:{ - a.bool_val = !a.bool_val; - return a; + if(CMP_EQ == bigint_cmp_zero(&a->big_int_val)) + a->bool_val = 1; + a->bool_val = 0; }break; + CASE_FLOAT: a->bool_val = !a->f64_val; break; + CASE_BOOL: a->bool_val = !a->bool_val; break; default:goto failure; } } break; - default:goto failure; + default: failure: parsing_error(pos, "Constant application of unary %s on values of type %s is not allowed", name(op), docname(a->type)); } - - failure: parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", name(op), docname(a.type)); - invalid_return; } function void -try_untyping(Operand *op){ +convert_untyped_to_typed_default(Operand *op){ if(!op) return; if(is_untyped(op->type)){ if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_s64; @@ -310,18 +273,18 @@ try_untyping(Operand *op){ } function void -resolve_var(Token *pos, Operand *expr, Ast_Resolved_Type *type = 0){ - if(type == expr->type) { +make_sure_types_are_compatible_for_assignment(Token *pos, Operand *expr, Ast_Resolved_Type *type = 0){ + if(type == expr->type){ assert(expr->type); return; } if(!type) - try_untyping(expr); + convert_untyped_to_typed_default(expr); else if(!expr->type) expr->type = type; else if(is_untyped(expr->type)) - expr->value = convert_untyped(pos, expr->value, type); + expr->value = convert_untyped_to_typed(pos, expr->value, type); if(type && expr->type != type){ parsing_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type)); @@ -349,9 +312,12 @@ _rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){ function Ast_Resolved_Type * resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ - if(ast_can_be_null && ast == 0) return 0; + if(ast_can_be_null && ast == 0) + return 0; + Operand resolved = resolve_expr(ast); - if(resolved.type != type_type) parsing_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); + if(resolved.type != type_type) + parsing_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); return resolved.type_val; } @@ -373,7 +339,7 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ CASE(RETURN, Return){ // @todo: need to check if all paths return a value Operand op = resolve_expr(node->expr); if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type)); - op.value = convert_untyped(node->pos, op.value, ret); + op.value = convert_untyped_to_typed(node->pos, op.value, ret); if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type)); BREAK(); } @@ -415,6 +381,7 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ default:{ if(is_flag_set(ast->flags, AST_EXPR)){ + assert(is_flag_set(ast->flags, AST_STMT)); resolve_expr((Ast_Expr *)ast); } else invalid_codepath; @@ -440,9 +407,10 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret); Array args = {scratch}; For(lambda->args){ - Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL); + Ast_Resolved_Type *type = + resolve_typespec(it->typespec, AST_CANT_BE_NULL); Operand default_value = resolve_expr(it->default_value, type); - resolve_var(it->pos, &default_value, type); + make_sure_types_are_compatible_for_assignment(it->pos, &default_value, type); args.add(type); } @@ -569,7 +537,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(index > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store"); } Operand expr = resolve_expr(i->item, item_type); - expr.value = convert_untyped(i->pos, expr.value, item_type); + expr.value = convert_untyped_to_typed(i->pos, expr.value, item_type); + // @todo I don't think this detects when types are different } } else if(type->kind == TYPE_STRUCT){ @@ -608,7 +577,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res Operand op = resolve_expr(expr->item, found_type->type); - op.value = convert_untyped(node->pos, op.value, found_type->type); + op.value = convert_untyped_to_typed(node->pos, op.value, found_type->type); if(found_type->type != op.type) parsing_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]); } @@ -649,7 +618,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(item){ item->flags = set_flag(item->flags, AST_ITEM_INCLUDED); Operand expr = resolve_expr(item->item); - expr.value = convert_untyped(node->pos, expr.value, resolved); + expr.value = convert_untyped_to_typed(node->pos, expr.value, resolved); if(expr.type != resolved) type_error(item->pos, resolved, expr.type, "Type is not matching function definition"); items.add(item); @@ -690,7 +659,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res else goto failure; } break; CASE_UNTYPED: { - expr.value = convert_untyped(node->pos, expr.value, type); + expr.value = convert_untyped_to_typed(node->pos, expr.value, type); } break; CASE_UINT: CASE_SINT:{ @@ -734,11 +703,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res case TK_Dereference:{return operand_lvalue(type_pointer(value.type));}break; case TK_Neg:case TK_Not:case TK_Add:case TK_Sub:{ Operand op = resolve_expr(node->expr); - if(!is_numeric(op.type)) parsing_error(node->pos, "Unary [%s] cant be applied to value of type %s", name(node->op), docname(op.type)); + eval_unary(node->pos, node->op, &op.value, op.is_const); if(op.is_const){ - Value value = eval_unary(node->pos, node->op, op.value); - rewrite_into_const(node, Ast_Unary, value); - return operand_const_rvalue(value); + rewrite_into_const(node, Ast_Unary, op.value); + return operand_const_rvalue(op.value); } return operand_rvalue(op.value.type); }break; @@ -756,7 +724,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res assert(node->left->kind == AST_IDENT); Operand right = resolve_expr(node->right); - resolve_var(node->pos, &right); + make_sure_types_are_compatible_for_assignment(node->pos, &right); assert(right.type); auto atom = (Ast_Atom *)node->left; @@ -771,7 +739,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue"); Operand right = resolve_expr(node->right); - right.value = convert_untyped(node->pos, right.value, left.type); + right.value = convert_untyped_to_typed(node->pos, right.value, left.type); if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type)); } //----------------------------------------------------------------------------- @@ -866,8 +834,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res else{ Operand left = resolve_expr(node->left); Operand right = resolve_expr(node->right); - Value value = eval_binary(node->pos, node->op, left.value, right.value); - if(left.is_const && right.is_const){ + B32 is_const = left.is_const && right.is_const; + Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const); + if(is_const){ rewrite_into_const(node, Ast_Binary, value); result = operand_const_rvalue(value); } @@ -934,7 +903,7 @@ resolve_binding(Ast *ast, Sym *sym){ Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL); Operand expr = resolve_expr(node->expr, type); assert(expr.type != 0 || type != 0); - resolve_var(node->pos, &expr, type); + make_sure_types_are_compatible_for_assignment(node->pos, &expr, type); assert(expr.type); return expr; BREAK();