diff options
Diffstat (limited to 'src/checker/expr.cpp')
| -rw-r--r-- | src/checker/expr.cpp | 244 |
1 files changed, 137 insertions, 107 deletions
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 77854a603..a4931ed94 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -384,11 +384,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { Type *elem = check_type(c, vt->elem); Type *be = get_base_type(elem); i64 count = check_array_count(c, vt->count); - if (!is_type_vector(be) && - !(is_type_boolean(be) || is_type_numeric(be))) { + if (!is_type_boolean(be) && !is_type_numeric(be)) { err_str = type_to_string(elem); - error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be a boolean, numerical, or vector. Got `%s`", err_str); - } else { + error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be numerical or a boolean. Got `%s`", err_str); } type = make_type_vector(c->allocator, elem, count); set_base_type(named_type, type); @@ -433,7 +431,7 @@ end: b32 check_unary_op(Checker *c, Operand *o, Token op) { // TODO(bill): Handle errors correctly - Type *type = get_base_type(base_vector_type(o->type)); + Type *type = get_base_type(base_vector_type(get_base_type(o->type))); gbString str = NULL; defer (gb_string_free(str)); switch (op.kind) { @@ -702,13 +700,11 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { update_expr_type(c, y->expr, default_type(y->type), true); } - if (is_type_vector(x->type)) { - Type *vec_bool = NULL; - do { - } while (is_type_vector(x->type->vector.elem)); + if (is_type_vector(get_base_type(y->type))) { + x->type = make_type_vector(c->allocator, t_bool, get_base_type(y->type)->vector.count); + } else { + x->type = t_untyped_bool; } - x->type = t_untyped_bool; - } void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { @@ -805,6 +801,101 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { x->mode = Addressing_Value; } +b32 check_castable_to(Checker *c, Operand *operand, Type *y) { + if (check_is_assignable_to(c, operand, y)) + return true; + + Type *x = operand->type; + Type *xb = get_base_type(x); + Type *yb = get_base_type(y); + if (are_types_identical(xb, yb)) + return true; + + + // Cast between booleans and integers + if (is_type_boolean(x) || is_type_integer(x)) { + if (is_type_boolean(y) || is_type_integer(y)) + return true; + } + + // Cast between numbers + if (is_type_integer(x) || is_type_float(x)) { + if (is_type_integer(y) || is_type_float(y)) + return true; + } + + // Cast between pointers + if (is_type_pointer(x)) { + if (is_type_pointer(y)) + return true; + } + + // untyped integers -> pointers + if (is_type_untyped(xb) && is_type_integer(xb)) { + if (is_type_pointer(yb)) + return true; + } + + // (u)int <-> pointer + if (is_type_pointer(xb) || is_type_int_or_uint(xb)) { + if (is_type_pointer(yb)) + return true; + } + if (is_type_pointer(xb)) { + if (is_type_pointer(yb) || is_type_int_or_uint(yb)) + return true; + } + + // []byte/[]u8 <-> string + if (is_type_u8_slice(xb) && is_type_string(yb)) { + return true; + } + if (is_type_string(xb) && is_type_u8_slice(yb)) { + return true; + } + + return false; +} + +void check_cast_expr(Checker *c, Operand *operand, Type *type) { + b32 is_const_expr = operand->mode == Addressing_Constant; + b32 can_convert = false; + + if (is_const_expr && is_type_constant_type(type)) { + Type *t = get_base_type(type); + if (t->kind == Type_Basic) { + if (check_value_is_expressible(c, operand->value, t, &operand->value)) { + can_convert = true; + } + } + } else if (check_castable_to(c, operand, type)) { + operand->mode = Addressing_Value; + can_convert = true; + } + + if (!can_convert) { + gbString expr_str = expr_to_string(operand->expr); + gbString type_str = type_to_string(type); + defer (gb_string_free(expr_str)); + defer (gb_string_free(type_str)); + error(&c->error_collector, ast_node_token(operand->expr), "Cannot cast `%s` to `%s`", expr_str, type_str); + + operand->mode = Addressing_Invalid; + return; + } + + if (is_type_untyped(operand->type)) { + Type *final_type = type; + if (is_const_expr && !is_type_constant_type(type)) { + final_type = default_type(operand->type); + } + update_expr_type(c, operand->expr, final_type, true); + } + + operand->type = type; +} + + void check_binary_expr(Checker *c, Operand *x, AstNode *node) { GB_ASSERT(node->kind == AstNode_BinaryExpr); Operand y_ = {}, *y = &y_; @@ -813,6 +904,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { ast_node(be, BinaryExpr, node); + if (be->op.kind == Token_as) { + check_expr(c, x, be->left); + Type *cast_type = check_type(c, be->right); + if (x->mode == Addressing_Invalid) + return; + check_cast_expr(c, x, cast_type); + return; + } + check_expr(c, x, be->left); check_expr(c, y, be->right); if (x->mode == Addressing_Invalid) { @@ -890,7 +990,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { } if (x->mode == Addressing_Constant && - y->mode == Addressing_Constant) { + y->mode == Addressing_Constant) { ExactValue a = x->value; ExactValue b = y->value; @@ -943,7 +1043,18 @@ void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) { found->type = get_base_type(type); map_set(&c->info.untyped, key, *found); } else { + ExpressionInfo old = *found; map_remove(&c->info.untyped, key); + + if (old.is_lhs && !is_type_integer(type)) { + gbString expr_str = expr_to_string(e); + gbString type_str = type_to_string(type); + defer (gb_string_free(expr_str)); + defer (gb_string_free(type_str)); + error(&c->error_collector, ast_node_token(e), "Shifted operand %s must be an integer, got %s", expr_str, type_str); + return; + } + add_type_and_value(&c->info, e, found->mode, type, found->value); } } @@ -1349,6 +1460,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) value = make_exact_value_integer(t->array.count); break; + case Type_Vector: + mode = Addressing_Constant; + value = make_exact_value_integer(t->vector.count); + break; + case Type_Slice: mode = Addressing_Value; break; @@ -1600,85 +1716,6 @@ ExpressionKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { return Expression_Statement; } -b32 check_castable_to(Checker *c, Operand *operand, Type *y) { - if (check_is_assignable_to(c, operand, y)) - return true; - - Type *x = operand->type; - Type *xb = get_base_type(x); - Type *yb = get_base_type(y); - if (are_types_identical(xb, yb)) - return true; - - // Cast between numbers - if (is_type_integer(x) || is_type_float(x)) { - if (is_type_integer(y) || is_type_float(y)) - return true; - } - - // Cast between pointers - if (is_type_pointer(x)) { - if (is_type_pointer(y)) - return true; - } - - // untyped integers -> pointers - if (is_type_untyped(xb) && is_type_integer(xb)) { - if (is_type_pointer(yb)) - return true; - } - - // (u)int <-> pointer - if (is_type_pointer(xb) || is_type_int_or_uint(xb)) { - if (is_type_pointer(yb)) - return true; - } - if (is_type_pointer(xb)) { - if (is_type_pointer(yb) || is_type_int_or_uint(yb)) - return true; - } - - // []byte/[]u8 <-> string - if (is_type_u8_slice(xb) && is_type_string(yb)) { - return true; - } - if (is_type_string(xb) && is_type_u8_slice(yb)) { - return true; - } - - return false; -} - -void check_cast_expr(Checker *c, Operand *operand, Type *type) { - b32 is_const_expr = operand->mode == Addressing_Constant; - b32 can_convert = false; - - if (is_const_expr && is_type_constant_type(type)) { - Type *t = get_base_type(type); - if (t->kind == Type_Basic) { - if (check_value_is_expressible(c, operand->value, t, &operand->value)) { - can_convert = true; - } - } - } else if (check_castable_to(c, operand, type)) { - operand->mode = Addressing_Value; - can_convert = true; - } - - if (!can_convert) { - gbString expr_str = expr_to_string(operand->expr); - gbString type_str = type_to_string(type); - defer (gb_string_free(expr_str)); - defer (gb_string_free(type_str)); - error(&c->error_collector, ast_node_token(operand->expr), "Cannot cast `%s` to `%s`", expr_str, type_str); - - operand->mode = Addressing_Invalid; - return; - } - - operand->type = type; -} - void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) { check_expr_base(c, o, e, t); check_not_tuple(c, o); @@ -1924,6 +1961,15 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ o->type = t->array.elem; break; + case Type_Vector: + valid = true; + max_count = t->vector.count; + if (o->mode != Addressing_Variable) + o->mode = Addressing_Value; + o->type = t->vector.elem; + break; + + case Type_Slice: valid = true; o->type = t->slice.elem; @@ -2039,15 +2085,6 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ case_end; - case_ast_node(ce, CastExpr, node); - Type *cast_type = check_type(c, ce->type); - check_expr_or_type(c, o, ce->expr); - if (o->mode != Addressing_Invalid) - check_cast_expr(c, o, cast_type); - - case_end; - - case_ast_node(ce, CallExpr, node); return check_call_expr(c, o, node); case_end; @@ -2287,13 +2324,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "]"); case_end; - case_ast_node(ce, CastExpr, node); - str = gb_string_appendc(str, "cast("); - str = write_expr_to_string(str, ce->type); - str = gb_string_appendc(str, ")"); - str = write_expr_to_string(str, ce->expr); - case_end; - case_ast_node(e, Ellipsis, node); str = gb_string_appendc(str, ".."); case_end; |