Browse Source

bit_set['A'..'Z'], bit_set[0..8]

gingerBill 7 years ago
parent
commit
884d5fed9f
12 changed files with 273 additions and 101 deletions
  1. 43 4
      core/fmt/fmt.odin
  2. 3 1
      core/runtime/core.odin
  3. 5 1
      core/types/types.odin
  4. 41 27
      examples/demo/demo.odin
  5. 18 9
      src/check_expr.cpp
  6. 3 18
      src/check_stmt.cpp
  7. 137 31
      src/check_type.cpp
  8. 9 2
      src/ir.cpp
  9. 1 1
      src/ir_print.cpp
  10. 6 1
      src/parser.cpp
  11. 1 0
      src/tokenizer.cpp
  12. 6 6
      src/types.cpp

+ 43 - 4
core/fmt/fmt.odin

@@ -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);
-		e := et.variant.(runtime.Type_Info_Enum);
+		et := runtime.type_info_base(info.elem);
 
 
 		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]);

+ 3 - 1
core/runtime/core.odin

@@ -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 {

+ 5 - 1
core/types/types.odin

@@ -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;

+ 41 - 27
examples/demo/demo.odin

@@ -713,33 +713,47 @@ deprecated_attribute :: proc() {
 }
 }
 
 
 bit_set_type :: proc() {
 bit_set_type :: proc() {
-	using Day :: enum {
-		Sunday,
-		Monday,
-		Tuesday,
-		Wednesday,
-		Thursday,
-		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);
+	{
+		using Day :: enum {
+			Sunday,
+			Monday,
+			Tuesday,
+			Wednesday,
+			Thursday,
+			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]
+
+		x |= {'F'};
+		assert('F' in x);
+
+		y |= {1, 4, 2};
+		assert(2 in y);
+	}
 }
 }
 
 
 main :: proc() {
 main :: proc() {

+ 18 - 9
src/check_expr.cpp

@@ -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 bits = big_int_to_i64(&v.value_integer);
-
-				x->mode = Addressing_Constant;
-				x->type = t_untyped_bool;
-				x->value = exact_value_bool((bit & bits) != 0);
-				x->expr = node;
-				return;
+				i64 key = big_int_to_i64(&k.value_integer);
+				i64 lower = yt->BitSet.lower;
+				i64 upper = yt->BitSet.upper;
+
+				if (lower <= key && key <= upper) {
+					i64 bit = 1ll<<key;
+					i64 bits = big_int_to_i64(&v.value_integer);
+
+					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
src/check_stmt.cpp

@@ -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);

+ 137 - 31
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);
 	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)) {
+		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;
 			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);
 	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
src/ir.cpp

@@ -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
src/ir_print.cpp

@@ -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
src/parser.cpp

@@ -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);

+ 1 - 0
src/tokenizer.cpp

@@ -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
src/types.cpp

@@ -180,8 +180,8 @@ struct TypeStruct {
 	})                                                    \
 	})                                                    \
 	TYPE_KIND(BitSet, struct {                            \
 	TYPE_KIND(BitSet, struct {                            \
 		Type *base;                                       \
 		Type *base;                                       \
-		i64   min;                                        \
-		i64   max;                                        \
+		i64   lower;                                      \
+		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
 	}
 	}
 	}
 	}