aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-07-10 11:18:19 +0100
committergingerBill <bill@gingerbill.org>2021-07-10 11:18:19 +0100
commit366227511912bf6aec670f187437c48ddb09293b (patch)
tree4ce17d70ed110f9be484a1b9e93b0732d2831a4f /src
parent141573c18cba4ecde552fec53d73c74f854e2b8b (diff)
Allow `x in ptr_to_map_or_bit_set`
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp20
-rw-r--r--src/check_stmt.cpp3
-rw-r--r--src/llvm_backend.cpp5
3 files changed, 18 insertions, 10 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index d0c792943..68909acaa 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -2597,15 +2597,16 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
case Token_in:
case Token_not_in:
+ {
// IMPORTANT NOTE(bill): This uses right-left evaluation in type checking only no in
-
check_expr(c, y, be->right);
+ Type *rhs_type = type_deref(y->type);
- if (is_type_bit_set(y->type)) {
- Type *elem = base_type(y->type)->BitSet.elem;
+ if (is_type_bit_set(rhs_type)) {
+ Type *elem = base_type(rhs_type)->BitSet.elem;
check_expr_with_type_hint(c, x, be->left, elem);
- } else if (is_type_map(y->type)) {
- Type *key = base_type(y->type)->Map.key;
+ } else if (is_type_map(rhs_type)) {
+ Type *key = base_type(rhs_type)->Map.key;
check_expr_with_type_hint(c, x, be->left, key);
} else {
check_expr(c, x, be->left);
@@ -2620,8 +2621,8 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
return;
}
- if (is_type_map(y->type)) {
- Type *yt = base_type(y->type);
+ if (is_type_map(rhs_type)) {
+ Type *yt = base_type(rhs_type);
if (op.kind == Token_in) {
check_assignment(c, x, yt->Map.key, str_lit("map 'in'"));
} else {
@@ -2629,8 +2630,8 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
}
add_package_dependency(c, "runtime", "__dynamic_map_get");
- } else if (is_type_bit_set(y->type)) {
- Type *yt = base_type(y->type);
+ } else if (is_type_bit_set(rhs_type)) {
+ Type *yt = base_type(rhs_type);
if (op.kind == Token_in) {
check_assignment(c, x, yt->BitSet.elem, str_lit("bit_set 'in'"));
@@ -2679,6 +2680,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
x->expr = node;
return;
+ }
default:
if (is_ise_expr(be->left)) {
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index d68524994..5ae82bc5e 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1884,7 +1884,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
error(operand.expr, "Cannot iterate over '%s' of type '%s'", s, t);
if (rs->vals.count == 1) {
- if (is_type_map(operand.type) || is_type_bit_set(operand.type)) {
+ Type *t = type_deref(operand.type);
+ if (is_type_map(t) || is_type_bit_set(t)) {
gbString v = expr_to_string(rs->vals[0]);
defer (gb_string_free(v));
error_line("\tSuggestion: place parentheses around the expression\n");
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 1df07f986..0466d76cf 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -7753,6 +7753,11 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
Type *type = default_type(tv.type);
lbValue right = lb_build_expr(p, be->right);
Type *rt = base_type(right.type);
+ if (is_type_pointer(rt)) {
+ right = lb_emit_load(p, right);
+ rt = type_deref(rt);
+ }
+
switch (rt->kind) {
case Type_Map:
{