aboutsummaryrefslogtreecommitdiff
path: root/src/check_type.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-08-16 15:16:57 +0100
committergingerBill <bill@gingerbill.org>2018-08-16 15:16:57 +0100
commit884d5fed9f2894a91ede38fb073338b1fe94a483 (patch)
tree41867331fdc096743e0072bf55067f77ebc306fb /src/check_type.cpp
parentec84188597b6558970e66ec7918851f1267888df (diff)
bit_set['A'..'Z'], bit_set[0..8]
Diffstat (limited to 'src/check_type.cpp')
-rw-r--r--src/check_type.cpp168
1 files changed, 137 insertions, 31 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 6b93fbd68..bbae12654 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -680,49 +680,157 @@ void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Ast *node)
}
}
+bool is_type_valid_bit_set_range(Type *t) {
+ if (is_type_integer(t)) {
+ return true;
+ }
+ if (is_type_rune(t)) {
+ return true;
+ }
+ return false;
+}
-void check_bit_set_type(CheckerContext *ctx, Type *type, Ast *node) {
+void check_bit_set_type(CheckerContext *c, Type *type, Ast *node) {
ast_node(bs, BitSetType, node);
GB_ASSERT(type->kind == Type_BitSet);
- Type *bt = check_type_expr(ctx, bs->base, nullptr);
+ Ast *base = unparen_expr(bs->base);
+ if (is_ast_range(base)) {
+ ast_node(be, BinaryExpr, base);
+ Operand lhs = {};
+ Operand rhs = {};
+ check_expr(c, &lhs, be->left);
+ check_expr(c, &rhs, be->right);
+ if (lhs.mode == Addressing_Invalid) {
+ return;
+ }
+ if (rhs.mode == Addressing_Invalid) {
+ return;
+ }
+ convert_to_typed(c, &lhs, rhs.type);
+ if (lhs.mode == Addressing_Invalid) {
+ return;
+ }
+ convert_to_typed(c, &rhs, lhs.type);
+ if (rhs.mode == Addressing_Invalid) {
+ return;
+ }
+ if (!are_types_identical(lhs.type, rhs.type)) {
+ if (lhs.type != t_invalid &&
+ rhs.type != t_invalid) {
+ gbString xt = type_to_string(lhs.type);
+ gbString yt = type_to_string(rhs.type);
+ gbString expr_str = expr_to_string(bs->base);
+ error(bs->base, "Mismatched types in range '%s' : '%s' vs '%s'", expr_str, xt, yt);
+ gb_string_free(expr_str);
+ gb_string_free(yt);
+ gb_string_free(xt);
+ }
+ return;
+ }
- type->BitSet.base = bt;
- if (!is_type_enum(bt)) {
- error(bs->base, "Expected an enum type for a bit_set");
- } else {
- Type *et = base_type(bt);
- GB_ASSERT(et->kind == Type_Enum);
- if (!is_type_integer(et->Enum.base_type)) {
- error(bs->base, "Enum type for bit_set must be an integer");
+ if (!is_type_valid_bit_set_range(lhs.type)) {
+ gbString str = type_to_string(lhs.type);
+ error(bs->base, "'%s' is invalid for an interval expression, expected an integer or rune", str);
+ gb_string_free(str);
return;
}
- i64 min_value = 0;
- i64 max_value = 0;
- BigInt v64 = {}; big_int_from_i64(&v64, 64);
- for_array(i, et->Enum.fields) {
- Entity *e = et->Enum.fields[i];
- if (e->kind != Entity_Constant) {
- continue;
- }
- ExactValue value = exact_value_to_integer(e->Constant.value);
- GB_ASSERT(value.kind == ExactValue_Integer);
- i64 x = big_int_to_i64(&value.value_integer);
- min_value = gb_min(min_value, x);
- max_value = gb_max(max_value, x);
+ if (lhs.mode != Addressing_Constant || rhs.mode != Addressing_Constant) {
+ error(bs->base, "Intervals must be constant values");
+ return;
}
- GB_ASSERT(min_value <= max_value);
+ ExactValue iv = exact_value_to_integer(lhs.value);
+ ExactValue jv = exact_value_to_integer(rhs.value);
+ GB_ASSERT(iv.kind == ExactValue_Integer);
+ GB_ASSERT(jv.kind == ExactValue_Integer);
- if (max_value - min_value > 64) {
- error(bs->base, "bit_set range is greater than 64 bits");
+ BigInt i = iv.value_integer;
+ BigInt j = jv.value_integer;
+ if (big_int_cmp(&i, &j) > 0) {
+ gbAllocator a = heap_allocator();
+ String si = big_int_to_string(a, &i);
+ String sj = big_int_to_string(a, &j);
+ error(bs->base, "Lower interval bound larger than upper bound, %.*s .. %.*s", LIT(si), LIT(sj));
+ gb_free(a, si.text);
+ gb_free(a, sj.text);
+ return;
}
- type->BitSet.min = min_value;
- type->BitSet.max = max_value;
- }
+ Type *t = default_type(lhs.type);
+ bool ok = true;
+ ok = check_representable_as_constant(c, iv, t, nullptr);
+ if (!ok) {
+ gbAllocator a = heap_allocator();
+ String s = big_int_to_string(a, &i);
+ gbString ts = type_to_string(t);
+ error(bs->base, "%.*s is not representable by %s", LIT(s), ts);
+ gb_string_free(ts);
+ gb_free(a, s.text);
+ return;
+ }
+ ok = check_representable_as_constant(c, iv, t, nullptr);
+ if (!ok) {
+ gbAllocator a = heap_allocator();
+ String s = big_int_to_string(a, &j);
+ gbString ts = type_to_string(t);
+ error(bs->base, "%.*s is not representable by %s", LIT(s), ts);
+ gb_string_free(ts);
+ gb_free(a, s.text);
+ return;
+ }
+ i64 lower = big_int_to_i64(&i);
+ i64 upper = big_int_to_i64(&j);
+
+ if (upper - lower > 64) {
+ error(bs->base, "bit_set range is greater than 64 bits, %lld bits are required", (upper-lower+1));
+ }
+ type->BitSet.base = t;
+ type->BitSet.lower = lower;
+ type->BitSet.upper = upper;
+
+ } else {
+ Type *bt = check_type_expr(c, bs->base, nullptr);
+
+ type->BitSet.base = bt;
+ if (!is_type_enum(bt)) {
+ error(bs->base, "Expected an enum type for a bit_set");
+ } else {
+ Type *et = base_type(bt);
+ GB_ASSERT(et->kind == Type_Enum);
+ if (!is_type_integer(et->Enum.base_type)) {
+ error(bs->base, "Enum type for bit_set must be an integer");
+ return;
+ }
+ i64 lower = 0;
+ i64 upper = 0;
+ BigInt v64 = {}; big_int_from_i64(&v64, 64);
+
+ for_array(i, et->Enum.fields) {
+ Entity *e = et->Enum.fields[i];
+ if (e->kind != Entity_Constant) {
+ continue;
+ }
+ ExactValue value = exact_value_to_integer(e->Constant.value);
+ GB_ASSERT(value.kind == ExactValue_Integer);
+ // NOTE(bill): enum types should be able to store i64 values
+ i64 x = big_int_to_i64(&value.value_integer);
+ lower = gb_min(lower, x);
+ upper = gb_max(upper, x);
+ }
+
+ GB_ASSERT(lower <= upper);
+
+ if (upper - lower > 64) {
+ error(bs->base, "bit_set range is greater than 64 bits, %lld bits are required", (upper-lower+1));
+ }
+
+ type->BitSet.lower = lower;
+ type->BitSet.upper = upper;
+ }
+ }
}
@@ -1951,9 +2059,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
case_ast_node(bs, BitSetType, e);
*type = alloc_type_bit_set();
set_base_type(named_type, *type);
- check_open_scope(ctx, e);
check_bit_set_type(ctx, *type, e);
- check_close_scope(ctx);
return true;
case_end;