aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-08-14 18:32:34 +0100
committergingerBill <bill@gingerbill.org>2018-08-14 18:32:34 +0100
commit966249c10a32425b408df5a5ea6085781f38b8a7 (patch)
tree2338b20fac3e649db3f2682fe3cfd4218b300bad /src/check_expr.cpp
parentacc010cba5df63b38704245254e721187335a7b2 (diff)
`bit_set` constants
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp74
1 files changed, 72 insertions, 2 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index d12f162ed..3c3c94b0f 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -503,6 +503,10 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
}
}
+ if (is_type_bit_set(dst) && are_types_identical(dst->BitSet.base_type, operand->type)) {
+ return 3;
+ }
+
#if 0
if (are_types_identical(dst, src) && (!is_type_named(dst) || !is_type_named(src))) {
return 1;
@@ -1345,6 +1349,10 @@ bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Typ
// return true;
}
if (out_value) *out_value = in_value;
+ } else if (is_type_bit_set(type)) {
+ if (in_value.kind == ExactValue_Integer) {
+ return true;
+ }
}
@@ -2019,6 +2027,42 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node) {
break;
}
+ case Token_in:
+ check_expr(c, x, be->left);
+ check_expr(c, y, be->right);
+ if (x->mode == Addressing_Invalid) {
+ return;
+ }
+ if (y->mode == Addressing_Invalid) {
+ x->mode = Addressing_Invalid;
+ x->expr = y->expr;
+ return;
+ }
+
+ if (is_type_map(y->type)) {
+ Type *yt = base_type(y->type);
+ check_assignment(c, x, yt->Map.key, str_lit("map 'in'"));
+
+ add_package_dependency(c, "runtime", "__dynamic_map_get");
+ } else if (is_type_bit_set(y->type)) {
+ Type *yt = base_type(y->type);
+ check_assignment(c, x, yt->BitSet.base_type, str_lit("bit_set 'in'"));
+ } else {
+ gbString t = type_to_string(y->type);
+ error(x->expr, "expected either a map or bitset for 'in', got %s", t);
+ gb_string_free(t);
+ x->expr = node;
+ x->mode = Addressing_Invalid;
+ return;
+ }
+ if (x->mode != Addressing_Invalid) {
+ x->mode = Addressing_Value;
+ x->type = t_untyped_bool;
+ }
+ x->expr = node;
+
+ return;
+
default:
check_expr(c, x, be->left);
check_expr(c, y, be->right);
@@ -2151,7 +2195,8 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node) {
ExactValue a = x->value;
ExactValue b = y->value;
- Type *type = base_type(x->type);
+ // Type *type = base_type(x->type);
+ Type *type = x->type;
if (is_type_pointer(type)) {
GB_ASSERT(op.kind == Token_Sub);
i64 bytes = a.value_pointer - b.value_pointer;
@@ -5422,6 +5467,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (cl->elems[0]->kind == Ast_FieldValue) {
error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed");
+ is_constant = false;
} else {
for_array(index, cl->elems) {
Entity *field = nullptr;
@@ -5457,7 +5503,31 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
if (is_constant) {
o->mode = Addressing_Constant;
- o->value = exact_value_compound(node);
+
+ if (is_type_bit_set(type)) {
+ // NOTE(bill): Encode as an integer
+
+ i64 lower = base_type(type)->BitSet.min;
+
+ u64 bits = 0;
+ for_array(index, cl->elems) {
+ Entity *field = nullptr;
+ Ast *elem = cl->elems[index];
+ GB_ASSERT(elem->kind != Ast_FieldValue);
+ TypeAndValue tav = elem->tav;
+ ExactValue i = exact_value_to_integer(tav.value);
+ if (i.kind != ExactValue_Integer) {
+ continue;
+ }
+ i64 val = big_int_to_i64(&i.value_integer);
+ val -= lower;
+ u64 bit = u64(1ll<<val);
+ bits |= bit;
+ }
+ o->value = exact_value_u64(bits);
+ } else {
+ o->value = exact_value_compound(node);
+ }
} else {
o->mode = Addressing_Value;
}