mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
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)
```
This commit is contained in:
+47
-7
@@ -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 lower = big_int_to_i64(&i);
|
||||||
i64 upper = big_int_to_i64(&j);
|
i64 upper = big_int_to_i64(&j);
|
||||||
|
|
||||||
|
bool lower_changed = false;
|
||||||
i64 bits = MAX_BITS;
|
i64 bits = MAX_BITS;
|
||||||
if (type->BitSet.underlying != nullptr) {
|
if (type->BitSet.underlying != nullptr) {
|
||||||
bits = 8*type_size_of(type->BitSet.underlying);
|
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) {
|
switch (be->op.kind) {
|
||||||
case Token_Ellipsis:
|
case Token_Ellipsis:
|
||||||
case Token_RangeFull:
|
case Token_RangeFull:
|
||||||
if (upper - lower >= bits) {
|
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;
|
break;
|
||||||
case Token_RangeHalf:
|
case Token_RangeHalf:
|
||||||
if (upper - lower > bits) {
|
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;
|
upper -= 1;
|
||||||
break;
|
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.elem = t;
|
||||||
type->BitSet.lower = lower;
|
type->BitSet.lower = lower;
|
||||||
type->BitSet.upper = upper;
|
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);
|
GB_ASSERT(lower <= upper);
|
||||||
|
|
||||||
|
bool lower_changed = false;
|
||||||
i64 bits = MAX_BITS
|
i64 bits = MAX_BITS
|
||||||
; if (bs->underlying != nullptr) {
|
; if (bs->underlying != nullptr) {
|
||||||
Type *u = check_type(c, bs->underlying);
|
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;
|
type->BitSet.underlying = u;
|
||||||
bits = 8*type_size_of(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) {
|
if (upper - lower >= bits) {
|
||||||
error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", MAX_BITS, (upper-lower+1));
|
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.lower = lower;
|
||||||
type->BitSet.upper = upper;
|
type->BitSet.upper = upper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user