From 141299eb02bc9a7330daa30d75d279e84ba28cc3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 31 Oct 2021 19:39:01 +0000 Subject: Change the behaviour change is for when a `bit_set` of range/enum and the underlying type has been specified * If the lower bound is greater than zero, it will become zero (thus removing the compatification) * If the lower bound is negative, it is an error This means that an integer value N, maps directly to the N-th bit. Example ``` foo :: enum u8 { a = 2, b = 3, c = 4, } set0: bit_set[foo] set0 += {.a, .b} // internally set0 == 1<<(2-2) | 1<<(3-2) set1: bit_set[foo; u32] set1 += {.a, .b} // internally set1 == 1<<(2-0) | 1<<(3-0) ``` --- src/check_type.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 7 deletions(-) (limited to 'src/check_type.cpp') diff --git a/src/check_type.cpp b/src/check_type.cpp index 813990020..7c01bd5ba 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -921,26 +921,51 @@ void check_bit_set_type(CheckerContext *c, Type *type, Type *named_type, Ast *no } i64 lower = big_int_to_i64(&i); i64 upper = big_int_to_i64(&j); - + + bool lower_changed = false; i64 bits = MAX_BITS; if (type->BitSet.underlying != nullptr) { bits = 8*type_size_of(type->BitSet.underlying); + + if (lower > 0) { + lower = 0; + lower_changed = true; + } else if (lower < 0) { + error(bs->elem, "bit_set does not allow a negative lower bound (%lld) when an underlying type is set", lower); + } + } + + i64 bits_required = upper-lower; + switch (be->op.kind) { + case Token_Ellipsis: + case Token_RangeFull: + bits_required += 1; + break; } + bool is_valid = true; switch (be->op.kind) { case Token_Ellipsis: case Token_RangeFull: if (upper - lower >= bits) { - error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", bits, (upper-lower+1)); + is_valid = false; } break; case Token_RangeHalf: if (upper - lower > bits) { - error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", bits, (upper-lower)); + is_valid = false; } upper -= 1; break; } + if (!is_valid) { + if (lower_changed) { + error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required (internal the lower changed was changed 0 as an underlying type was set)", bits, bits_required); + } else { + error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", bits, bits_required); + } + } + type->BitSet.elem = t; type->BitSet.lower = lower; type->BitSet.upper = upper; @@ -996,7 +1021,8 @@ void check_bit_set_type(CheckerContext *c, Type *type, Type *named_type, Ast *no } GB_ASSERT(lower <= upper); - + + bool lower_changed = false; i64 bits = MAX_BITS ; if (bs->underlying != nullptr) { Type *u = check_type(c, bs->underlying); @@ -1008,17 +1034,31 @@ void check_bit_set_type(CheckerContext *c, Type *type, Type *named_type, Ast *no } type->BitSet.underlying = u; bits = 8*type_size_of(u); + + if (lower > 0) { + lower = 0; + lower_changed = true; + } else if (lower < 0) { + gbString s = type_to_string(elem); + error(bs->elem, "bit_set does not allow a negative lower bound (%lld) of the element type '%s' when an underlying type is set", lower, s); + gb_string_free(s); + } } - if (upper - lower >= MAX_BITS) { - error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", MAX_BITS, (upper-lower+1)); + if (upper - lower >= bits) { + i64 bits_required = upper-lower+1; + if (lower_changed) { + error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required (internal the lower changed was changed 0 as an underlying type was set)", bits, bits_required); + } else { + error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", bits, bits_required); + } } type->BitSet.lower = lower; type->BitSet.upper = upper; } } - } + } } -- cgit v1.2.3