From 833c3917b247baa46f5a5f6ad6ce478cffc1911d Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Mon, 18 Sep 2017 20:02:47 +0200 Subject: 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. --- core/variant.h | 2 +- core/variant_op.cpp | 87 ++++---------------------- modules/gdnative/gdnative/variant.cpp | 5 +- modules/gdnative/include/gdnative/variant.h | 2 +- modules/gdnative/include/gdnative_api_struct.h | 2 +- modules/gdscript/gd_function.cpp | 27 +------- 6 files changed, 20 insertions(+), 105 deletions(-) diff --git a/core/variant.h b/core/variant.h index edc86dedd4..5ea540a63f 100644 --- a/core/variant.h +++ b/core/variant.h @@ -390,7 +390,7 @@ public: uint32_t hash() const; bool hash_compare(const Variant &p_variant) const; - bool booleanize(bool &valid) const; + bool booleanize() const; void static_assign(const Variant &p_variant); static void get_constructor_list(Variant::Type p_type, List *p_list); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 8349f2fdf6..5d47936679 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -143,56 +143,13 @@ 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(_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(_data._mem)).is_valid(); - case OBJECT: - return _get_obj().obj; - case NODE_PATH: - return (*reinterpret_cast(_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) \ @@ -403,12 +360,6 @@ bool Variant::booleanize(bool &r_valid) const { _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, 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) { 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); } @@ -1190,12 +1137,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, SWITCH_OP(math, OP_OR, p_a.type) { 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); } @@ -1203,12 +1146,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, SWITCH_OP(math, OP_XOR, p_a.type) { 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)); } @@ -1216,9 +1155,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, SWITCH_OP(math, OP_NOT, p_a.type) { CASE_TYPE_ALL(math, OP_NOT) { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; + bool l = p_a.booleanize(); _RETURN(!l); } } diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp index 1b2aae607f..9ba4166c1d 100644 --- a/modules/gdnative/gdnative/variant.cpp +++ b/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); } -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; - bool &valid = *r_valid; - return self->booleanize(valid); + return self->booleanize(); } void GDAPI godot_variant_destroy(godot_variant *p_self) { diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index 969506585d..7b804c1eaf 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/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_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); diff --git a/modules/gdnative/include/gdnative_api_struct.h b/modules/gdnative/include/gdnative_api_struct.h index cfebeb08cc..c345e27227 100644 --- a/modules/gdnative/include/gdnative_api_struct.h +++ b/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_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_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_string_new, godot_string *r_dest) \ GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src) \ diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp index 438d484a41..df7b16c96e 100644 --- a/modules/gdscript/gd_function.cpp +++ b/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); - 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) { int to = _code_ptr[ip + 2]; 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); - 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) { int to = _code_ptr[ip + 2]; 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); #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) { -- cgit v1.2.3