mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
bit_set['A'..'Z'], bit_set[0..8]
This commit is contained in:
+43
-4
@@ -67,6 +67,34 @@ write_rune :: proc(buf: ^String_Buffer, r: rune) {
|
|||||||
b, n := utf8.encode_rune(r);
|
b, n := utf8.encode_rune(r);
|
||||||
write_bytes(buf, b[:n]);
|
write_bytes(buf, b[:n]);
|
||||||
}
|
}
|
||||||
|
write_encoded_rune :: proc(buf: ^String_Buffer, r: rune) {
|
||||||
|
write_byte(buf, '\'');
|
||||||
|
switch r {
|
||||||
|
case '\a': write_string(buf, "\\a");
|
||||||
|
case '\b': write_string(buf, "\\b");
|
||||||
|
case '\e': write_string(buf, "\\e");
|
||||||
|
case '\f': write_string(buf, "\\f");
|
||||||
|
case '\n': write_string(buf, "\\n");
|
||||||
|
case '\r': write_string(buf, "\\r");
|
||||||
|
case '\t': write_string(buf, "\\t");
|
||||||
|
case '\v': write_string(buf, "\\v");
|
||||||
|
case:
|
||||||
|
if r < 32 {
|
||||||
|
write_string(buf, "\\x");
|
||||||
|
b: [2]byte;
|
||||||
|
s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil);
|
||||||
|
switch len(s) {
|
||||||
|
case 0: write_string(buf, "00");
|
||||||
|
case 1: write_rune(buf, '0');
|
||||||
|
case 2: write_string(buf, s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write_rune(buf, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
write_byte(buf, '\'');
|
||||||
|
}
|
||||||
|
|
||||||
write_i64 :: proc(buf: ^String_Buffer, i: i64, base: int) {
|
write_i64 :: proc(buf: ^String_Buffer, i: i64, base: int) {
|
||||||
b: [129]byte;
|
b: [129]byte;
|
||||||
@@ -315,7 +343,18 @@ write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) {
|
|||||||
|
|
||||||
case runtime.Type_Info_Bit_Set:
|
case runtime.Type_Info_Bit_Set:
|
||||||
write_string(buf, "bit_set[");
|
write_string(buf, "bit_set[");
|
||||||
write_type(buf, info.base);
|
switch {
|
||||||
|
case types.is_enum(info.elem):
|
||||||
|
write_type(buf, info.elem);
|
||||||
|
case types.is_rune(info.elem):
|
||||||
|
write_encoded_rune(buf, rune(info.lower));
|
||||||
|
write_string(buf, "..");
|
||||||
|
write_encoded_rune(buf, rune(info.upper));
|
||||||
|
case:
|
||||||
|
write_i64(buf, info.lower, 10);
|
||||||
|
write_string(buf, "..");
|
||||||
|
write_i64(buf, info.upper, 10);
|
||||||
|
}
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -763,8 +802,7 @@ fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
|
|||||||
case: panic("unknown bit_size size");
|
case: panic("unknown bit_size size");
|
||||||
}
|
}
|
||||||
|
|
||||||
et := runtime.type_info_base(info.base);
|
et := runtime.type_info_base(info.elem);
|
||||||
e := et.variant.(runtime.Type_Info_Enum);
|
|
||||||
|
|
||||||
if name != "" {
|
if name != "" {
|
||||||
write_string(fi.buf, name);
|
write_string(fi.buf, name);
|
||||||
@@ -774,6 +812,7 @@ fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
|
|||||||
write_byte(fi.buf, '{');
|
write_byte(fi.buf, '{');
|
||||||
defer write_byte(fi.buf, '}');
|
defer write_byte(fi.buf, '}');
|
||||||
|
|
||||||
|
e, is_enum := et.variant.(runtime.Type_Info_Enum);
|
||||||
commas := 0;
|
commas := 0;
|
||||||
loop: for i in 0 .. bit_size-1 {
|
loop: for i in 0 .. bit_size-1 {
|
||||||
if bits & (1<<i) == 0 {
|
if bits & (1<<i) == 0 {
|
||||||
@@ -784,7 +823,7 @@ fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
|
|||||||
|
|
||||||
defer commas += 1;
|
defer commas += 1;
|
||||||
|
|
||||||
for ev, evi in e.values {
|
if is_enum do for ev, evi in e.values {
|
||||||
v := enum_value_to_u64(ev);
|
v := enum_value_to_u64(ev);
|
||||||
if v == i {
|
if v == i {
|
||||||
write_string(fi.buf, e.names[evi]);
|
write_string(fi.buf, e.names[evi]);
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ Type_Info_Bit_Field :: struct {
|
|||||||
offsets: []i32,
|
offsets: []i32,
|
||||||
};
|
};
|
||||||
Type_Info_Bit_Set :: struct {
|
Type_Info_Bit_Set :: struct {
|
||||||
base: ^Type_Info,
|
elem: ^Type_Info,
|
||||||
|
lower: i64,
|
||||||
|
upper: i64,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type_Info :: struct {
|
Type_Info :: struct {
|
||||||
|
|||||||
@@ -148,8 +148,12 @@ are_types_identical :: proc(a, b: ^rt.Type_Info) -> bool {
|
|||||||
if xo != yo do return false;
|
if xo != yo do return false;
|
||||||
if xn != yn do return false;
|
if xn != yn do return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case rt.Type_Info_Bit_Set:
|
||||||
|
y, ok := b.variant.(rt.Type_Info_Bit_Set);
|
||||||
|
if !ok do return false;
|
||||||
|
return x.elem == y.elem && x.lower == y.lower && x.upper == y.upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+37
-23
@@ -713,33 +713,47 @@ deprecated_attribute :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bit_set_type :: proc() {
|
bit_set_type :: proc() {
|
||||||
using Day :: enum {
|
{
|
||||||
Sunday,
|
using Day :: enum {
|
||||||
Monday,
|
Sunday,
|
||||||
Tuesday,
|
Monday,
|
||||||
Wednesday,
|
Tuesday,
|
||||||
Thursday,
|
Wednesday,
|
||||||
Friday,
|
Thursday,
|
||||||
Saturday,
|
Friday,
|
||||||
|
Saturday,
|
||||||
|
}
|
||||||
|
|
||||||
|
Days :: distinct bit_set[Day];
|
||||||
|
WEEKEND :: Days{Sunday, Saturday};
|
||||||
|
|
||||||
|
d: Days;
|
||||||
|
d = {Sunday, Monday};
|
||||||
|
x := Tuesday;
|
||||||
|
e := d | WEEKEND;
|
||||||
|
e |= {Monday};
|
||||||
|
fmt.println(d, e);
|
||||||
|
|
||||||
|
ok := Saturday in e; // `in` is only allowed for `map` and `bit_set` types
|
||||||
|
fmt.println(ok);
|
||||||
|
if Saturday in e {
|
||||||
|
fmt.println("Saturday in", e);
|
||||||
|
}
|
||||||
|
X :: Saturday in WEEKEND; // Constant evaluation
|
||||||
|
fmt.println(X);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
x: bit_set['A'..'Z'];
|
||||||
|
y: bit_set[0..8];
|
||||||
|
fmt.println(typeid_of(type_of(x))); // bit_set[A..Z]
|
||||||
|
fmt.println(typeid_of(type_of(y))); // bit_set[0..8]
|
||||||
|
|
||||||
Days :: distinct bit_set[Day];
|
x |= {'F'};
|
||||||
WEEKEND :: Days{Sunday, Saturday};
|
assert('F' in x);
|
||||||
|
|
||||||
d: Days;
|
y |= {1, 4, 2};
|
||||||
d = {Sunday, Monday};
|
assert(2 in y);
|
||||||
x := Tuesday;
|
|
||||||
e := d | WEEKEND;
|
|
||||||
e |= {Monday};
|
|
||||||
fmt.println(d, e);
|
|
||||||
|
|
||||||
ok := Saturday in e; // `in` is only allowed for `map` and `bit_set` types
|
|
||||||
fmt.println(ok);
|
|
||||||
if Saturday in e {
|
|
||||||
fmt.println("Saturday in", e);
|
|
||||||
}
|
}
|
||||||
X :: Saturday in WEEKEND; // Constant evaluation
|
|
||||||
fmt.println(X);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
|||||||
+17
-8
@@ -2047,14 +2047,23 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, bool use_lhs_as
|
|||||||
ExactValue v = exact_value_to_integer(y->value);
|
ExactValue v = exact_value_to_integer(y->value);
|
||||||
GB_ASSERT(k.kind == ExactValue_Integer);
|
GB_ASSERT(k.kind == ExactValue_Integer);
|
||||||
GB_ASSERT(v.kind == ExactValue_Integer);
|
GB_ASSERT(v.kind == ExactValue_Integer);
|
||||||
i64 bit = 1ll<<big_int_to_i64(&k.value_integer);
|
i64 key = big_int_to_i64(&k.value_integer);
|
||||||
i64 bits = big_int_to_i64(&v.value_integer);
|
i64 lower = yt->BitSet.lower;
|
||||||
|
i64 upper = yt->BitSet.upper;
|
||||||
|
|
||||||
x->mode = Addressing_Constant;
|
if (lower <= key && key <= upper) {
|
||||||
x->type = t_untyped_bool;
|
i64 bit = 1ll<<key;
|
||||||
x->value = exact_value_bool((bit & bits) != 0);
|
i64 bits = big_int_to_i64(&v.value_integer);
|
||||||
x->expr = node;
|
|
||||||
return;
|
x->mode = Addressing_Constant;
|
||||||
|
x->type = t_untyped_bool;
|
||||||
|
x->value = exact_value_bool((bit & bits) != 0);
|
||||||
|
x->expr = node;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
error(x->expr, "key '%lld' out of range of bit set, %lld..%lld", key, lower, upper);
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -5591,7 +5600,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
|||||||
if (is_type_bit_set(type)) {
|
if (is_type_bit_set(type)) {
|
||||||
// NOTE(bill): Encode as an integer
|
// NOTE(bill): Encode as an integer
|
||||||
|
|
||||||
i64 lower = base_type(type)->BitSet.min;
|
i64 lower = base_type(type)->BitSet.lower;
|
||||||
|
|
||||||
u64 bits = 0;
|
u64 bits = 0;
|
||||||
for_array(index, cl->elems) {
|
for_array(index, cl->elems) {
|
||||||
|
|||||||
+3
-18
@@ -706,42 +706,27 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TokenKind op = Token_Invalid;
|
|
||||||
|
|
||||||
Operand a = lhs;
|
Operand a = lhs;
|
||||||
Operand b = rhs;
|
Operand b = rhs;
|
||||||
check_comparison(ctx, &a, &x, Token_LtEq);
|
check_comparison(ctx, &a, &x, Token_LtEq);
|
||||||
if (a.mode == Addressing_Invalid) {
|
if (a.mode == Addressing_Invalid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (ie->op.kind) {
|
|
||||||
case Token_Ellipsis: op = Token_GtEq; break;
|
|
||||||
default: error(ie->op, "Invalid interval operator"); continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_comparison(ctx, &b, &x, op);
|
check_comparison(ctx, &b, &x, Token_GtEq);
|
||||||
if (b.mode == Addressing_Invalid) {
|
if (b.mode == Addressing_Invalid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ie->op.kind) {
|
|
||||||
case Token_Ellipsis: op = Token_LtEq; break;
|
|
||||||
default: error(ie->op, "Invalid interval operator"); continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Operand a1 = lhs;
|
Operand a1 = lhs;
|
||||||
Operand b1 = rhs;
|
Operand b1 = rhs;
|
||||||
check_comparison(ctx, &a1, &b1, op);
|
check_comparison(ctx, &a1, &b1, Token_LtEq);
|
||||||
if (complete) {
|
if (complete) {
|
||||||
error(lhs.expr, "#complete switch statement does not allow ranges");
|
error(lhs.expr, "#complete switch statement does not allow ranges");
|
||||||
}
|
}
|
||||||
|
|
||||||
add_constant_switch_case(ctx, &seen, lhs);
|
add_constant_switch_case(ctx, &seen, lhs);
|
||||||
if (op == Token_LtEq) {
|
add_constant_switch_case(ctx, &seen, rhs);
|
||||||
add_constant_switch_case(ctx, &seen, rhs);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Operand y = {};
|
Operand y = {};
|
||||||
check_expr(ctx, &y, expr);
|
check_expr(ctx, &y, expr);
|
||||||
|
|||||||
+139
-33
@@ -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);
|
ast_node(bs, BitSetType, node);
|
||||||
GB_ASSERT(type->kind == Type_BitSet);
|
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)) {
|
||||||
type->BitSet.base = bt;
|
ast_node(be, BinaryExpr, base);
|
||||||
if (!is_type_enum(bt)) {
|
Operand lhs = {};
|
||||||
error(bs->base, "Expected an enum type for a bit_set");
|
Operand rhs = {};
|
||||||
} else {
|
check_expr(c, &lhs, be->left);
|
||||||
Type *et = base_type(bt);
|
check_expr(c, &rhs, be->right);
|
||||||
GB_ASSERT(et->kind == Type_Enum);
|
if (lhs.mode == Addressing_Invalid) {
|
||||||
if (!is_type_integer(et->Enum.base_type)) {
|
|
||||||
error(bs->base, "Enum type for bit_set must be an integer");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i64 min_value = 0;
|
if (rhs.mode == Addressing_Invalid) {
|
||||||
i64 max_value = 0;
|
return;
|
||||||
BigInt v64 = {}; big_int_from_i64(&v64, 64);
|
}
|
||||||
|
convert_to_typed(c, &lhs, rhs.type);
|
||||||
for_array(i, et->Enum.fields) {
|
if (lhs.mode == Addressing_Invalid) {
|
||||||
Entity *e = et->Enum.fields[i];
|
return;
|
||||||
if (e->kind != Entity_Constant) {
|
}
|
||||||
continue;
|
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);
|
||||||
}
|
}
|
||||||
ExactValue value = exact_value_to_integer(e->Constant.value);
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_ASSERT(min_value <= max_value);
|
if (!is_type_valid_bit_set_range(lhs.type)) {
|
||||||
|
gbString str = type_to_string(lhs.type);
|
||||||
if (max_value - min_value > 64) {
|
error(bs->base, "'%s' is invalid for an interval expression, expected an integer or rune", str);
|
||||||
error(bs->base, "bit_set range is greater than 64 bits");
|
gb_string_free(str);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
type->BitSet.min = min_value;
|
if (lhs.mode != Addressing_Constant || rhs.mode != Addressing_Constant) {
|
||||||
type->BitSet.max = max_value;
|
error(bs->base, "Intervals must be constant values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 *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);
|
case_ast_node(bs, BitSetType, e);
|
||||||
*type = alloc_type_bit_set();
|
*type = alloc_type_bit_set();
|
||||||
set_base_type(named_type, *type);
|
set_base_type(named_type, *type);
|
||||||
check_open_scope(ctx, e);
|
|
||||||
check_bit_set_type(ctx, *type, e);
|
check_bit_set_type(ctx, *type, e);
|
||||||
check_close_scope(ctx);
|
|
||||||
return true;
|
return true;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+9
-2
@@ -4915,7 +4915,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
|
|||||||
Type *it = bit_set_to_int(rt);
|
Type *it = bit_set_to_int(rt);
|
||||||
left = ir_emit_conv(proc, left, it);
|
left = ir_emit_conv(proc, left, it);
|
||||||
|
|
||||||
irValue *lower = ir_value_constant(it, exact_value_i64(rt->BitSet.min));
|
irValue *lower = ir_value_constant(it, exact_value_i64(rt->BitSet.lower));
|
||||||
irValue *key = ir_emit_arith(proc, Token_Sub, left, lower, it);
|
irValue *key = ir_emit_arith(proc, Token_Sub, left, lower, it);
|
||||||
irValue *bit = ir_emit_arith(proc, Token_Shl, v_one, key, it);
|
irValue *bit = ir_emit_arith(proc, Token_Shl, v_one, key, it);
|
||||||
|
|
||||||
@@ -5883,7 +5883,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
|||||||
if (cl->elems.count > 0 && sz > 0) {
|
if (cl->elems.count > 0 && sz > 0) {
|
||||||
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
|
||||||
|
|
||||||
irValue *lower = ir_value_constant(t_int, exact_value_i64(bt->BitSet.min));
|
irValue *lower = ir_value_constant(t_int, exact_value_i64(bt->BitSet.lower));
|
||||||
for_array(i, cl->elems) {
|
for_array(i, cl->elems) {
|
||||||
Ast *elem = cl->elems[i];
|
Ast *elem = cl->elems[i];
|
||||||
GB_ASSERT(elem->kind != Ast_FieldValue);
|
GB_ASSERT(elem->kind != Ast_FieldValue);
|
||||||
@@ -6484,6 +6484,7 @@ void ir_type_case_body(irProcedure *proc, Ast *label, Ast *clause, irBlock *body
|
|||||||
ir_emit_jump(proc, done);
|
ir_emit_jump(proc, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
|
void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case_ast_node(bs, EmptyStmt, node);
|
case_ast_node(bs, EmptyStmt, node);
|
||||||
@@ -8116,9 +8117,15 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
|||||||
case Type_BitSet:
|
case Type_BitSet:
|
||||||
ir_emit_comment(proc, str_lit("Type_Info_Bit_Set"));
|
ir_emit_comment(proc, str_lit("Type_Info_Bit_Set"));
|
||||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_bit_set_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_bit_set_ptr);
|
||||||
|
|
||||||
|
GB_ASSERT(is_type_typed(t->BitSet.base));
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->BitSet.base));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->BitSet.base));
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), ir_const_i64(t->BitSet.lower));
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_const_i64(t->BitSet.upper));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag != nullptr) {
|
if (tag != nullptr) {
|
||||||
|
|||||||
+1
-1
@@ -807,7 +807,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
|||||||
}
|
}
|
||||||
GB_ASSERT(tav.value.kind == ExactValue_Integer);
|
GB_ASSERT(tav.value.kind == ExactValue_Integer);
|
||||||
i64 v = big_int_to_i64(&tav.value.value_integer);
|
i64 v = big_int_to_i64(&tav.value.value_integer);
|
||||||
i64 lower = type->BitSet.min;
|
i64 lower = type->BitSet.lower;
|
||||||
bits |= 1ull<<cast(u64)(v-lower);
|
bits |= 1ull<<cast(u64)(v-lower);
|
||||||
}
|
}
|
||||||
ir_write_u64(f, bits);
|
ir_write_u64(f, bits);
|
||||||
|
|||||||
+6
-1
@@ -1962,7 +1962,12 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
|||||||
case Token_bit_set: {
|
case Token_bit_set: {
|
||||||
Token token = expect_token(f, Token_bit_set);
|
Token token = expect_token(f, Token_bit_set);
|
||||||
Token open = expect_token(f, Token_OpenBracket);
|
Token open = expect_token(f, Token_OpenBracket);
|
||||||
Ast * base = parse_type(f);
|
|
||||||
|
bool prev_allow_range = f->allow_range;
|
||||||
|
f->allow_range = true;
|
||||||
|
Ast *base = parse_expr(f, false);
|
||||||
|
f->allow_range = prev_allow_range;
|
||||||
|
|
||||||
Token close = expect_token(f, Token_CloseBracket);
|
Token close = expect_token(f, Token_CloseBracket);
|
||||||
|
|
||||||
return ast_bit_set_type(f, token, base);
|
return ast_bit_set_type(f, token, base);
|
||||||
|
|||||||
@@ -674,6 +674,7 @@ bool scan_escape(Tokenizer *t) {
|
|||||||
Rune r = t->curr_rune;
|
Rune r = t->curr_rune;
|
||||||
if (r == 'a' ||
|
if (r == 'a' ||
|
||||||
r == 'b' ||
|
r == 'b' ||
|
||||||
|
r == 'e' ||
|
||||||
r == 'f' ||
|
r == 'f' ||
|
||||||
r == 'n' ||
|
r == 'n' ||
|
||||||
r == 'r' ||
|
r == 'r' ||
|
||||||
|
|||||||
+6
-6
@@ -180,8 +180,8 @@ struct TypeStruct {
|
|||||||
}) \
|
}) \
|
||||||
TYPE_KIND(BitSet, struct { \
|
TYPE_KIND(BitSet, struct { \
|
||||||
Type *base; \
|
Type *base; \
|
||||||
i64 min; \
|
i64 lower; \
|
||||||
i64 max; \
|
i64 upper; \
|
||||||
}) \
|
}) \
|
||||||
|
|
||||||
|
|
||||||
@@ -2069,13 +2069,13 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_BitSet: {
|
case Type_BitSet: {
|
||||||
i64 bits = t->BitSet.max - t->BitSet.min + 1;
|
i64 bits = t->BitSet.upper - t->BitSet.lower + 1;
|
||||||
if (bits == 0) return 0;
|
if (bits == 0) return 0;
|
||||||
if (bits <= 8) return 1;
|
if (bits <= 8) return 1;
|
||||||
if (bits <= 16) return 2;
|
if (bits <= 16) return 2;
|
||||||
if (bits <= 32) return 4;
|
if (bits <= 32) return 4;
|
||||||
if (bits <= 64) return 8;
|
if (bits <= 64) return 8;
|
||||||
return 8;
|
return 8; // NOTE(bill): Could be an invalid range so limit it for now
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2296,13 +2296,13 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_BitSet: {
|
case Type_BitSet: {
|
||||||
i64 bits = t->BitSet.max - t->BitSet.min + 1;
|
i64 bits = t->BitSet.upper - t->BitSet.lower + 1;
|
||||||
if (bits == 0) return 0;
|
if (bits == 0) return 0;
|
||||||
if (bits <= 8) return 1;
|
if (bits <= 8) return 1;
|
||||||
if (bits <= 16) return 2;
|
if (bits <= 16) return 2;
|
||||||
if (bits <= 32) return 4;
|
if (bits <= 32) return 4;
|
||||||
if (bits <= 64) return 8;
|
if (bits <= 64) return 8;
|
||||||
return 8;
|
return 8; // NOTE(bill): Could be an invalid range so limit it for now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user