aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-10-06 14:55:25 +0100
committergingerBill <bill@gingerbill.org>2019-10-06 14:55:25 +0100
commit6c69e8c043e7dcf9d9965c7b28c7bdae44e0537c (patch)
treeaf5f3434bcbc20a87e905a4f7646dc958b00ae8d /src/check_expr.cpp
parent7fa2d25eea28955c12d8fc6a597e8615562c0ee9 (diff)
Make `typeid` semantics consistent across variables and constants
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp61
1 files changed, 47 insertions, 14 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 697abef5f..6a0d8221f 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -442,6 +442,10 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
}
if (operand->mode == Addressing_Type) {
+ if (is_type_typeid(type)) {
+ add_type_info_type(c, operand->type);
+ return 4;
+ }
return -1;
}
@@ -755,7 +759,12 @@ void check_assignment(CheckerContext *c, Operand *operand, Type *type, String co
return;
}
- if (!check_is_assignable_to(c, operand, type)) {
+ if (check_is_assignable_to(c, operand, type)) {
+ if (operand->mode == Addressing_Type && is_type_typeid(type)) {
+ add_type_info_type(c, operand->type);
+ add_type_and_value(c->info, operand->expr, Addressing_Value, type, exact_value_typeid(operand->type));
+ }
+ } else {
gbString expr_str = expr_to_string(operand->expr);
gbString op_type_str = type_to_string(operand->type);
gbString type_str = type_to_string(type);
@@ -1734,6 +1743,23 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
return;
}
+ if (x->mode == Addressing_Type && is_type_typeid(y->type)) {
+ add_type_info_type(c, x->type);
+ add_type_and_value(c->info, x->expr, Addressing_Value, y->type, exact_value_typeid(x->type));
+
+ x->mode = Addressing_Value;
+ x->type = t_untyped_bool;
+ return;
+ } else if (is_type_typeid(x->type) && y->mode == Addressing_Type) {
+ add_type_info_type(c, y->type);
+ add_type_and_value(c->info, y->expr, Addressing_Value, x->type, exact_value_typeid(y->type));
+
+ x->mode = Addressing_Value;
+ x->type = t_untyped_bool;
+ return;
+ }
+
+
gbString err_str = nullptr;
defer (if (err_str != nullptr) {
@@ -2324,8 +2350,16 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
// If only one is a type, this is an error
if (xt ^ yt) {
GB_ASSERT(xt != yt);
- if (xt) error_operand_not_expression(x);
- if (yt) error_operand_not_expression(y);
+ if (xt) {
+ if (!is_type_typeid(y->type)) {
+ error_operand_not_expression(x);
+ }
+ }
+ if (yt) {
+ if (!is_type_typeid(x->type)) {
+ error_operand_not_expression(y);
+ }
+ }
}
break;
@@ -5254,6 +5288,11 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
}
}
score += s;
+
+ if (o.mode == Addressing_Type && is_type_typeid(e->type)) {
+ add_type_info_type(c, o.type);
+ add_type_and_value(c->info, o.expr, Addressing_Value, e->type, exact_value_typeid(o.type));
+ }
}
if (variadic) {
@@ -5496,6 +5535,11 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
}
score += s;
}
+
+ if (o->mode == Addressing_Type && is_type_typeid(e->type)) {
+ add_type_info_type(c, o->type);
+ add_type_and_value(c->info, o->expr, Addressing_Value, e->type, exact_value_typeid(o->type));
+ }
}
if (data) {
@@ -6432,17 +6476,6 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call) {
}
}
- // NOTE(bill): Should this be here or on the `add_entity_use`?
- // if (ce->proc != nullptr) {
- // Entity *e = entity_of_node(&c->info, ce->proc);
- // if (e != nullptr && e->kind == Entity_Procedure) {
- // String msg = e->Procedure.deprecated_message;
- // if (msg.len > 0) {
- // warning(call, "%.*s is deprecated: %.*s", LIT(e->token.string), LIT(msg));
- // }
- // }
- // }
-
CallArgumentData data = check_call_arguments(c, operand, proc_type, call);
Type *result_type = data.result_type;
gb_zero_item(operand);