aboutsummaryrefslogtreecommitdiff
path: root/src/checker
diff options
context:
space:
mode:
authorgingerBill <ginger.bill.22@gmail.com>2016-08-14 15:31:11 +0100
committergingerBill <ginger.bill.22@gmail.com>2016-08-14 15:31:11 +0100
commitb44bc99b889bb07dfe4f843ddeefd7483e0fba82 (patch)
tree9ce3fe6b7267e35a8a498c98c7fc88b77771090d /src/checker
parentee002364120a773753d37cf5575baa6e86d0502c (diff)
append :: proc(s: ^[]T, i: T) -> bool
Diffstat (limited to 'src/checker')
-rw-r--r--src/checker/expr.cpp115
-rw-r--r--src/checker/type.cpp5
2 files changed, 79 insertions, 41 deletions
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp
index a4931ed94..ced7402af 100644
--- a/src/checker/expr.cpp
+++ b/src/checker/expr.cpp
@@ -857,45 +857,6 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) {
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_;
@@ -906,10 +867,82 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
if (be->op.kind == Token_as) {
check_expr(c, x, be->left);
- Type *cast_type = check_type(c, be->right);
+ Type *type = check_type(c, be->right);
if (x->mode == Addressing_Invalid)
return;
- check_cast_expr(c, x, cast_type);
+
+ b32 is_const_expr = x->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, x->value, t, &x->value)) {
+ can_convert = true;
+ }
+ }
+ } else if (check_castable_to(c, x, type)) {
+ x->mode = Addressing_Value;
+ can_convert = true;
+ }
+
+ if (!can_convert) {
+ gbString expr_str = expr_to_string(x->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(x->expr), "Cannot cast `%s` to `%s`", expr_str, type_str);
+
+ x->mode = Addressing_Invalid;
+ return;
+ }
+
+ if (is_type_untyped(x->type)) {
+ Type *final_type = type;
+ if (is_const_expr && !is_type_constant_type(type)) {
+ final_type = default_type(x->type);
+ }
+ update_expr_type(c, x->expr, final_type, true);
+ }
+
+ x->type = type;
+ return;
+ } else if (be->op.kind == Token_transmute) {
+ check_expr(c, x, be->left);
+ Type *type = check_type(c, be->right);
+ if (x->mode == Addressing_Invalid)
+ return;
+
+ if (x->mode == Addressing_Constant) {
+ gbString expr_str = expr_to_string(x->expr);
+ defer (gb_string_free(expr_str));
+ error(&c->error_collector, ast_node_token(x->expr), "Cannot transmute constant expression: `%s`", expr_str);
+ x->mode = Addressing_Invalid;
+ return;
+ }
+
+ if (is_type_untyped(x->type)) {
+ gbString expr_str = expr_to_string(x->expr);
+ defer (gb_string_free(expr_str));
+ error(&c->error_collector, ast_node_token(x->expr), "Cannot transmute untyped expression: `%s`", expr_str);
+ x->mode = Addressing_Invalid;
+ return;
+ }
+
+ i64 otz = type_size_of(c->sizes, c->allocator, x->type);
+ i64 ttz = type_size_of(c->sizes, c->allocator, type);
+ if (otz != ttz) {
+ gbString expr_str = expr_to_string(x->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(x->expr), "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, otz, ttz);
+ x->mode = Addressing_Invalid;
+ return;
+ }
+
+ x->type = type;
+
return;
}
diff --git a/src/checker/type.cpp b/src/checker/type.cpp
index 12a96e1a5..4504cd06f 100644
--- a/src/checker/type.cpp
+++ b/src/checker/type.cpp
@@ -438,6 +438,11 @@ b32 are_types_identical(Type *x, Type *y) {
return (x->vector.count == y->vector.count) && are_types_identical(x->vector.elem, y->vector.elem);
break;
+ case Type_Slice:
+ if (y->kind == Type_Slice)
+ return are_types_identical(x->slice.elem, y->slice.elem);
+ break;
+
case Type_Structure:
if (y->kind == Type_Structure) {
if (x->structure.field_count == y->structure.field_count) {