Browse Source

Allow bitwise operation on enums

gingerBill 7 years ago
parent
commit
1830c1e57c
2 changed files with 32 additions and 24 deletions
  1. 13 14
      src/check_expr.cpp
  2. 19 10
      src/exact_value.cpp

+ 13 - 14
src/check_expr.cpp

@@ -1158,6 +1158,7 @@ bool check_unary_op(CheckerContext *c, Operand *o, Token op) {
 bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
 bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
 	// TODO(bill): Handle errors correctly
 	// TODO(bill): Handle errors correctly
 	Type *type = base_type(core_array_type(o->type));
 	Type *type = base_type(core_array_type(o->type));
+	Type *ct = core_type(type);
 	switch (op.kind) {
 	switch (op.kind) {
 	case Token_Sub:
 	case Token_Sub:
 	case Token_SubEq:
 	case Token_SubEq:
@@ -1197,7 +1198,7 @@ bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
 	case Token_OrEq:
 	case Token_OrEq:
 	case Token_Xor:
 	case Token_Xor:
 	case Token_XorEq:
 	case Token_XorEq:
-		if (!is_type_integer(type) && !is_type_boolean(type) && !is_type_bit_set(type)) {
+		if (!is_type_integer(ct) && !is_type_boolean(ct) && !is_type_bit_set(ct)) {
 			error(op, "Operator '%.*s' is only allowed with integers, booleans, or bit sets", LIT(op.string));
 			error(op, "Operator '%.*s' is only allowed with integers, booleans, or bit sets", LIT(op.string));
 			return false;
 			return false;
 		}
 		}
@@ -1215,7 +1216,7 @@ bool check_binary_op(CheckerContext *c, Operand *o, Token op) {
 
 
 	case Token_AndNot:
 	case Token_AndNot:
 	case Token_AndNotEq:
 	case Token_AndNotEq:
-		if (!is_type_integer(type) && !is_type_bit_set(type)) {
+		if (!is_type_integer(ct) && !is_type_bit_set(ct)) {
 			error(op, "Operator '%.*s' is only allowed with integers and bit sets", LIT(op.string));
 			error(op, "Operator '%.*s' is only allowed with integers and bit sets", LIT(op.string));
 			return false;
 			return false;
 		}
 		}
@@ -3746,18 +3747,16 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			operand->mode = Addressing_Value;
 			operand->mode = Addressing_Value;
 			operand->type = type;
 			operand->type = type;
 
 
-			convert_to_typed(c, &x, y.type);
-			if (x.mode == Addressing_Invalid) { return false; }
-			convert_to_typed(c, &y, x.type);
-			if (y.mode == Addressing_Invalid) { return false; }
-			convert_to_typed(c, &x, z.type);
-			if (x.mode == Addressing_Invalid) { return false; }
-			convert_to_typed(c, &z, x.type);
-			if (z.mode == Addressing_Invalid) { return false; }
-			convert_to_typed(c, &y, z.type);
-			if (y.mode == Addressing_Invalid) { return false; }
-			convert_to_typed(c, &z, y.type);
-			if (z.mode == Addressing_Invalid) { return false; }
+			Operand *ops[3] = {&x, &y, &z};
+			for (isize i = 0; i < 3; i++) {
+				Operand *a = ops[i];
+				for (isize j = 0; j < 3; j++) {
+					if (i == j) continue;
+					Operand *b = ops[j];
+					convert_to_typed(c, a, b->type);
+					if (a->mode == Addressing_Invalid) { return false; }
+				}
+			}
 
 
 			if (!are_types_identical(x.type, y.type) || !are_types_identical(x.type, z.type)) {
 			if (!are_types_identical(x.type, y.type) || !are_types_identical(x.type, z.type)) {
 				gbString type_x = type_to_string(x.type);
 				gbString type_x = type_to_string(x.type);

+ 19 - 10
src/exact_value.cpp

@@ -298,16 +298,6 @@ ExactValue exact_value_to_integer(ExactValue v) {
 	return r;
 	return r;
 }
 }
 
 
-i64 exact_value_to_i64(ExactValue v) {
-	v = exact_value_to_integer(v);
-	i64 result = 0;
-	if (v.kind == ExactValue_Integer) {
-		return big_int_to_i64(&v.value_integer);
-	}
-	return result;
-}
-
-
 ExactValue exact_value_to_float(ExactValue v) {
 ExactValue exact_value_to_float(ExactValue v) {
 	switch (v.kind) {
 	switch (v.kind) {
 	case ExactValue_Integer:
 	case ExactValue_Integer:
@@ -370,6 +360,25 @@ ExactValue exact_value_make_imag(ExactValue v) {
 	return r;
 	return r;
 }
 }
 
 
+i64 exact_value_to_i64(ExactValue v) {
+	v = exact_value_to_integer(v);
+	if (v.kind == ExactValue_Integer) {
+		return big_int_to_i64(&v.value_integer);
+	}
+	return 0;
+}
+f64 exact_value_to_f64(ExactValue v) {
+	v = exact_value_to_float(v);
+	if (v.kind == ExactValue_Float) {
+		return v.value_float;
+	}
+	return 0.0;
+}
+
+
+
+
+
 
 
 ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision, bool is_unsigned) {
 ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision, bool is_unsigned) {
 	switch (op) {
 	switch (op) {