فهرست منبع

Allow booleanization of all types

We now allow booleanization of all types. This means that empty versions
of all types now evaluate to false. So a Vector2(0,0), Dictionary(),
etc.

This allows you to write GDScript like:
if not Dictionary():
  print("Empty dict")

Booleanization can now also no longer fail. There is no more valid flag,
this changes Variant and GDNative API.
Hein-Pieter van Braam 8 سال پیش
والد
کامیت
833c3917b2

+ 1 - 1
core/variant.h

@@ -390,7 +390,7 @@ public:
 	uint32_t hash() const;
 	uint32_t hash() const;
 
 
 	bool hash_compare(const Variant &p_variant) const;
 	bool hash_compare(const Variant &p_variant) const;
-	bool booleanize(bool &valid) const;
+	bool booleanize() const;
 
 
 	void static_assign(const Variant &p_variant);
 	void static_assign(const Variant &p_variant);
 	static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
 	static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);

+ 12 - 75
core/variant_op.cpp

@@ -143,56 +143,13 @@
 
 
 Variant::operator bool() const {
 Variant::operator bool() const {
 
 
-	bool b;
-	return booleanize(b);
+	return booleanize();
 }
 }
 
 
-bool Variant::booleanize(bool &r_valid) const {
-
-	r_valid = true;
-	switch (type) {
-		case NIL:
-			return false;
-		case BOOL:
-			return _data._bool;
-		case INT:
-			return _data._int;
-		case REAL:
-			return _data._real;
-		case STRING:
-			return (*reinterpret_cast<const String *>(_data._mem)) != "";
-		case VECTOR2:
-		case RECT2:
-		case TRANSFORM2D:
-		case VECTOR3:
-		case PLANE:
-		case RECT3:
-		case QUAT:
-		case BASIS:
-		case TRANSFORM:
-		case COLOR:
-		case _RID:
-			return (*reinterpret_cast<const RID *>(_data._mem)).is_valid();
-		case OBJECT:
-			return _get_obj().obj;
-		case NODE_PATH:
-			return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath();
-		case DICTIONARY:
-		case ARRAY:
-		case POOL_BYTE_ARRAY:
-		case POOL_INT_ARRAY:
-		case POOL_REAL_ARRAY:
-		case POOL_STRING_ARRAY:
-		case POOL_VECTOR2_ARRAY:
-		case POOL_VECTOR3_ARRAY:
-		case POOL_COLOR_ARRAY:
-			r_valid = false;
-			return false;
-		default: {
-		}
-	}
-
-	return false;
+// We consider all unitialized or empty types to be false based on the type's
+// zeroiness.
+bool Variant::booleanize() const {
+	return !is_zero();
 }
 }
 
 
 #define _RETURN(m_what) \
 #define _RETURN(m_what) \
@@ -403,12 +360,6 @@ bool Variant::booleanize(bool &r_valid) const {
 		_RETURN(sum);                                                                                      \
 		_RETURN(sum);                                                                                      \
 	}
 	}
 
 
-#define DEFAULT_OP_FAIL(m_name) \
-	case m_name: {              \
-		r_valid = false;        \
-		return;                 \
-	}
-
 void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 		const Variant &p_b, Variant &r_ret, bool &r_valid) {
 		const Variant &p_b, Variant &r_ret, bool &r_valid) {
 
 
@@ -1177,12 +1128,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 
 
 		SWITCH_OP(math, OP_AND, p_a.type) {
 		SWITCH_OP(math, OP_AND, p_a.type) {
 			CASE_TYPE_ALL(math, OP_AND) {
 			CASE_TYPE_ALL(math, OP_AND) {
-				bool l = p_a.booleanize(r_valid);
-				if (!r_valid)
-					return;
-				bool r = p_b.booleanize(r_valid);
-				if (!r_valid)
-					return;
+				bool l = p_a.booleanize();
+				bool r = p_b.booleanize();
 
 
 				_RETURN(l && r);
 				_RETURN(l && r);
 			}
 			}
@@ -1190,12 +1137,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 
 
 		SWITCH_OP(math, OP_OR, p_a.type) {
 		SWITCH_OP(math, OP_OR, p_a.type) {
 			CASE_TYPE_ALL(math, OP_OR) {
 			CASE_TYPE_ALL(math, OP_OR) {
-				bool l = p_a.booleanize(r_valid);
-				if (!r_valid)
-					return;
-				bool r = p_b.booleanize(r_valid);
-				if (!r_valid)
-					return;
+				bool l = p_a.booleanize();
+				bool r = p_b.booleanize();
 
 
 				_RETURN(l || r);
 				_RETURN(l || r);
 			}
 			}
@@ -1203,12 +1146,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 
 
 		SWITCH_OP(math, OP_XOR, p_a.type) {
 		SWITCH_OP(math, OP_XOR, p_a.type) {
 			CASE_TYPE_ALL(math, OP_XOR) {
 			CASE_TYPE_ALL(math, OP_XOR) {
-				bool l = p_a.booleanize(r_valid);
-				if (!r_valid)
-					return;
-				bool r = p_b.booleanize(r_valid);
-				if (!r_valid)
-					return;
+				bool l = p_a.booleanize();
+				bool r = p_b.booleanize();
 
 
 				_RETURN((l || r) && !(l && r));
 				_RETURN((l || r) && !(l && r));
 			}
 			}
@@ -1216,9 +1155,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
 
 
 		SWITCH_OP(math, OP_NOT, p_a.type) {
 		SWITCH_OP(math, OP_NOT, p_a.type) {
 			CASE_TYPE_ALL(math, OP_NOT) {
 			CASE_TYPE_ALL(math, OP_NOT) {
-				bool l = p_a.booleanize(r_valid);
-				if (!r_valid)
-					return;
+				bool l = p_a.booleanize();
 				_RETURN(!l);
 				_RETURN(!l);
 			}
 			}
 		}
 		}

+ 2 - 3
modules/gdnative/gdnative/variant.cpp

@@ -480,10 +480,9 @@ godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const g
 	return self->hash_compare(*other);
 	return self->hash_compare(*other);
 }
 }
 
 
-godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid) {
+godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
-	bool &valid = *r_valid;
-	return self->booleanize(valid);
+	return self->booleanize();
 }
 }
 
 
 void GDAPI godot_variant_destroy(godot_variant *p_self) {
 void GDAPI godot_variant_destroy(godot_variant *p_self) {

+ 1 - 1
modules/gdnative/include/gdnative/variant.h

@@ -190,7 +190,7 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const
 
 
 godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other);
 godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other);
 
 
-godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid);
+godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self);
 
 
 void GDAPI godot_variant_destroy(godot_variant *p_self);
 void GDAPI godot_variant_destroy(godot_variant *p_self);
 
 

+ 1 - 1
modules/gdnative/include/gdnative_api_struct.h

@@ -534,7 +534,7 @@ extern "C" {
 	GDAPI_FUNC(godot_variant_operator_equal, godot_bool, const godot_variant *p_self, const godot_variant *p_other)                                                                                                                   \
 	GDAPI_FUNC(godot_variant_operator_equal, godot_bool, const godot_variant *p_self, const godot_variant *p_other)                                                                                                                   \
 	GDAPI_FUNC(godot_variant_operator_less, godot_bool, const godot_variant *p_self, const godot_variant *p_other)                                                                                                                    \
 	GDAPI_FUNC(godot_variant_operator_less, godot_bool, const godot_variant *p_self, const godot_variant *p_other)                                                                                                                    \
 	GDAPI_FUNC(godot_variant_hash_compare, godot_bool, const godot_variant *p_self, const godot_variant *p_other)                                                                                                                     \
 	GDAPI_FUNC(godot_variant_hash_compare, godot_bool, const godot_variant *p_self, const godot_variant *p_other)                                                                                                                     \
-	GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self, godot_bool *r_valid)                                                                                                                                \
+	GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self)                                                                                                                                                     \
 	GDAPI_FUNC_VOID(godot_variant_destroy, godot_variant *p_self)                                                                                                                                                                     \
 	GDAPI_FUNC_VOID(godot_variant_destroy, godot_variant *p_self)                                                                                                                                                                     \
 	GDAPI_FUNC_VOID(godot_string_new, godot_string *r_dest)                                                                                                                                                                           \
 	GDAPI_FUNC_VOID(godot_string_new, godot_string *r_dest)                                                                                                                                                                           \
 	GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src)                                                                                                                                           \
 	GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src)                                                                                                                                           \

+ 3 - 24
modules/gdscript/gd_function.cpp

@@ -982,15 +982,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
 
 
 				GET_VARIANT_PTR(test, 1);
 				GET_VARIANT_PTR(test, 1);
 
 
-				bool valid;
-				bool result = test->booleanize(valid);
-#ifdef DEBUG_ENABLED
-				if (!valid) {
+				bool result = test->booleanize();
 
 
-					err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
-					break;
-				}
-#endif
 				if (result) {
 				if (result) {
 					int to = _code_ptr[ip + 2];
 					int to = _code_ptr[ip + 2];
 					GD_ERR_BREAK(to < 0 || to > _code_size);
 					GD_ERR_BREAK(to < 0 || to > _code_size);
@@ -1006,15 +999,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
 
 
 				GET_VARIANT_PTR(test, 1);
 				GET_VARIANT_PTR(test, 1);
 
 
-				bool valid;
-				bool result = test->booleanize(valid);
-#ifdef DEBUG_ENABLED
-				if (!valid) {
+				bool result = test->booleanize();
 
 
-					err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
-					break;
-				}
-#endif
 				if (!result) {
 				if (!result) {
 					int to = _code_ptr[ip + 2];
 					int to = _code_ptr[ip + 2];
 					GD_ERR_BREAK(to < 0 || to > _code_size);
 					GD_ERR_BREAK(to < 0 || to > _code_size);
@@ -1107,14 +1093,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
 				GET_VARIANT_PTR(test, 1);
 				GET_VARIANT_PTR(test, 1);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
-				bool valid;
-				bool result = test->booleanize(valid);
-
-				if (!valid) {
-
-					err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
-					break;
-				}
+				bool result = test->booleanize();
 
 
 				if (!result) {
 				if (!result) {