From 366227511912bf6aec670f187437c48ddb09293b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 10 Jul 2021 11:18:19 +0100 Subject: [PATCH] Allow `x in ptr_to_map_or_bit_set` --- src/check_expr.cpp | 20 +++++++++++--------- src/check_stmt.cpp | 3 ++- src/llvm_backend.cpp | 5 +++++ 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: {