Prechádzať zdrojové kódy

Make some variant internal functions public.

-Make constructors, ops and setget inline functions public
-Should help optimizing the GDScript VM
reduz 4 rokov pred
rodič
commit
2c81e5fa0e

+ 1 - 537
core/variant/variant_construct.cpp

@@ -28,543 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "variant.h"
-
-#include "core/core_string_names.h"
-#include "core/crypto/crypto_core.h"
-#include "core/debugger/engine_debugger.h"
-#include "core/io/compression.h"
-#include "core/object/class_db.h"
-#include "core/os/os.h"
-#include "core/templates/local_vector.h"
-#include "core/templates/oa_hash_map.h"
-
-template <class T>
-struct PtrConstruct {};
-
-#define MAKE_PTRCONSTRUCT(m_type)                                                  \
-	template <>                                                                    \
-	struct PtrConstruct<m_type> {                                                  \
-		_FORCE_INLINE_ static void construct(const m_type &p_value, void *p_ptr) { \
-			memnew_placement(p_ptr, m_type(p_value));                              \
-		}                                                                          \
-	};
-
-MAKE_PTRCONSTRUCT(bool);
-MAKE_PTRCONSTRUCT(int64_t);
-MAKE_PTRCONSTRUCT(double);
-MAKE_PTRCONSTRUCT(String);
-MAKE_PTRCONSTRUCT(Vector2);
-MAKE_PTRCONSTRUCT(Vector2i);
-MAKE_PTRCONSTRUCT(Rect2);
-MAKE_PTRCONSTRUCT(Rect2i);
-MAKE_PTRCONSTRUCT(Vector3);
-MAKE_PTRCONSTRUCT(Vector3i);
-MAKE_PTRCONSTRUCT(Transform2D);
-MAKE_PTRCONSTRUCT(Plane);
-MAKE_PTRCONSTRUCT(Quaternion);
-MAKE_PTRCONSTRUCT(AABB);
-MAKE_PTRCONSTRUCT(Basis);
-MAKE_PTRCONSTRUCT(Transform3D);
-MAKE_PTRCONSTRUCT(Color);
-MAKE_PTRCONSTRUCT(StringName);
-MAKE_PTRCONSTRUCT(NodePath);
-MAKE_PTRCONSTRUCT(RID);
-
-template <>
-struct PtrConstruct<Object *> {
-	_FORCE_INLINE_ static void construct(Object *p_value, void *p_ptr) {
-		*((Object **)p_ptr) = p_value;
-	}
-};
-
-MAKE_PTRCONSTRUCT(Callable);
-MAKE_PTRCONSTRUCT(Signal);
-MAKE_PTRCONSTRUCT(Dictionary);
-MAKE_PTRCONSTRUCT(Array);
-MAKE_PTRCONSTRUCT(PackedByteArray);
-MAKE_PTRCONSTRUCT(PackedInt32Array);
-MAKE_PTRCONSTRUCT(PackedInt64Array);
-MAKE_PTRCONSTRUCT(PackedFloat32Array);
-MAKE_PTRCONSTRUCT(PackedFloat64Array);
-MAKE_PTRCONSTRUCT(PackedStringArray);
-MAKE_PTRCONSTRUCT(PackedVector2Array);
-MAKE_PTRCONSTRUCT(PackedVector3Array);
-MAKE_PTRCONSTRUCT(PackedColorArray);
-MAKE_PTRCONSTRUCT(Variant);
-
-template <class T, class... P>
-class VariantConstructor {
-	template <size_t... Is>
-	static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
-		r_error.error = Callable::CallError::CALL_OK;
-
-#ifdef DEBUG_METHODS_ENABLED
-		base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
-#else
-		base = T(VariantCaster<P>::cast(*p_args[Is])...);
-#endif
-	}
-
-	template <size_t... Is>
-	static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) {
-		base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...);
-	}
-
-	template <size_t... Is>
-	static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) {
-		PtrConstruct<T>::construct(T(PtrToArg<P>::convert(p_args[Is])...), base);
-	}
-
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		r_error.error = Callable::CallError::CALL_OK;
-		VariantTypeChanger<T>::change(&r_ret);
-		construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantTypeChanger<T>::change(r_ret);
-		validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(r_ret), p_args, BuildIndexSequence<sizeof...(P)>{});
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{});
-	}
-
-	static int get_argument_count() {
-		return sizeof...(P);
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return call_get_argument_type<P...>(p_arg);
-	}
-
-	static Variant::Type get_base_type() {
-		return GetTypeInfo<T>::VARIANT_TYPE;
-	}
-};
-
-class VariantConstructorObject {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		VariantInternal::clear(&r_ret);
-		if (p_args[0]->get_type() == Variant::NIL) {
-			VariantInternal::object_assign_null(&r_ret);
-			r_error.error = Callable::CallError::CALL_OK;
-		} else if (p_args[0]->get_type() == Variant::OBJECT) {
-			VariantInternal::object_assign(&r_ret, p_args[0]);
-			r_error.error = Callable::CallError::CALL_OK;
-		} else {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = Variant::OBJECT;
-		}
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantInternal::clear(r_ret);
-		VariantInternal::object_assign(r_ret, p_args[0]);
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<Object *>::construct(PtrToArg<Object *>::convert(p_args[0]), base);
-	}
-
-	static int get_argument_count() {
-		return 1;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::OBJECT;
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::OBJECT;
-	}
-};
-
-class VariantConstructorNilObject {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		if (p_args[0]->get_type() != Variant::NIL) {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = Variant::NIL;
-		}
-
-		VariantInternal::clear(&r_ret);
-		VariantInternal::object_assign_null(&r_ret);
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantInternal::clear(r_ret);
-		VariantInternal::object_assign_null(r_ret);
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<Object *>::construct(nullptr, base);
-	}
-
-	static int get_argument_count() {
-		return 1;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::NIL;
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::OBJECT;
-	}
-};
-
-class VariantConstructorCallableArgs {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		ObjectID object_id;
-		StringName method;
-
-		if (p_args[0]->get_type() == Variant::NIL) {
-			// leave as is
-		} else if (p_args[0]->get_type() == Variant::OBJECT) {
-			object_id = VariantInternal::get_object_id(p_args[0]);
-		} else {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = Variant::OBJECT;
-			return;
-		}
-
-		if (p_args[1]->get_type() == Variant::STRING_NAME) {
-			method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
-		} else if (p_args[1]->get_type() == Variant::STRING) {
-			method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
-		} else {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 1;
-			r_error.expected = Variant::STRING_NAME;
-			return;
-		}
-
-		VariantTypeChanger<Callable>::change(&r_ret);
-		*VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method);
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantTypeChanger<Callable>::change(r_ret);
-		*VariantGetInternalPtr<Callable>::get_ptr(r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<Callable>::construct(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
-	}
-
-	static int get_argument_count() {
-		return 2;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		if (p_arg == 0) {
-			return Variant::OBJECT;
-		} else {
-			return Variant::STRING_NAME;
-		}
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::CALLABLE;
-	}
-};
-
-class VariantConstructorSignalArgs {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		ObjectID object_id;
-		StringName method;
-
-		if (p_args[0]->get_type() == Variant::NIL) {
-			// leave as is
-		} else if (p_args[0]->get_type() == Variant::OBJECT) {
-			object_id = VariantInternal::get_object_id(p_args[0]);
-		} else {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = Variant::OBJECT;
-			return;
-		}
-
-		if (p_args[1]->get_type() == Variant::STRING_NAME) {
-			method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
-		} else if (p_args[1]->get_type() == Variant::STRING) {
-			method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
-		} else {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 1;
-			r_error.expected = Variant::STRING_NAME;
-			return;
-		}
-
-		VariantTypeChanger<Signal>::change(&r_ret);
-		*VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method);
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantTypeChanger<Signal>::change(r_ret);
-		*VariantGetInternalPtr<Signal>::get_ptr(r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<Signal>::construct(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
-	}
-
-	static int get_argument_count() {
-		return 2;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		if (p_arg == 0) {
-			return Variant::OBJECT;
-		} else {
-			return Variant::STRING_NAME;
-		}
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::SIGNAL;
-	}
-};
-
-template <class T>
-class VariantConstructorToArray {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = GetTypeInfo<T>::VARIANT_TYPE;
-			return;
-		}
-
-		VariantTypeChanger<Array>::change(&r_ret);
-		Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
-		const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
-
-		int size = src_arr.size();
-		dst_arr.resize(size);
-		for (int i = 0; i < size; i++) {
-			dst_arr[i] = src_arr[i];
-		}
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantTypeChanger<Array>::change(r_ret);
-		Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret);
-		const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
-
-		int size = src_arr.size();
-		dst_arr.resize(size);
-		for (int i = 0; i < size; i++) {
-			dst_arr[i] = src_arr[i];
-		}
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		Array dst_arr;
-		T src_arr = PtrToArg<T>::convert(p_args[0]);
-
-		int size = src_arr.size();
-		dst_arr.resize(size);
-		for (int i = 0; i < size; i++) {
-			dst_arr[i] = src_arr[i];
-		}
-
-		PtrConstruct<Array>::construct(dst_arr, base);
-	}
-
-	static int get_argument_count() {
-		return 1;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return GetTypeInfo<T>::VARIANT_TYPE;
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::ARRAY;
-	}
-};
-
-template <class T>
-class VariantConstructorFromArray {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		if (p_args[0]->get_type() != Variant::ARRAY) {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = Variant::ARRAY;
-			return;
-		}
-
-		VariantTypeChanger<T>::change(&r_ret);
-		const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
-		T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
-
-		int size = src_arr.size();
-		dst_arr.resize(size);
-		for (int i = 0; i < size; i++) {
-			dst_arr.write[i] = src_arr[i];
-		}
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantTypeChanger<T>::change(r_ret);
-		const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
-		T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(r_ret);
-
-		int size = src_arr.size();
-		dst_arr.resize(size);
-		for (int i = 0; i < size; i++) {
-			dst_arr.write[i] = src_arr[i];
-		}
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		Array src_arr = PtrToArg<Array>::convert(p_args[0]);
-		T dst_arr;
-
-		int size = src_arr.size();
-		dst_arr.resize(size);
-		for (int i = 0; i < size; i++) {
-			dst_arr.write[i] = src_arr[i];
-		}
-
-		PtrConstruct<T>::construct(dst_arr, base);
-	}
-
-	static int get_argument_count() {
-		return 1;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::ARRAY;
-	}
-
-	static Variant::Type get_base_type() {
-		return GetTypeInfo<T>::VARIANT_TYPE;
-	}
-};
-
-class VariantConstructorNil {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		if (p_args[0]->get_type() != Variant::NIL) {
-			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-			r_error.argument = 0;
-			r_error.expected = Variant::NIL;
-			return;
-		}
-
-		r_error.error = Callable::CallError::CALL_OK;
-		VariantInternal::clear(&r_ret);
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantInternal::clear(r_ret);
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<Variant>::construct(Variant(), base);
-	}
-
-	static int get_argument_count() {
-		return 1;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::NIL;
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::NIL;
-	}
-};
-
-template <class T>
-class VariantConstructNoArgs {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		VariantTypeChanger<T>::change_and_reset(&r_ret);
-		r_error.error = Callable::CallError::CALL_OK;
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantTypeChanger<T>::change_and_reset(r_ret);
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<T>::construct(T(), base);
-	}
-
-	static int get_argument_count() {
-		return 0;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::NIL;
-	}
-
-	static Variant::Type get_base_type() {
-		return GetTypeInfo<T>::VARIANT_TYPE;
-	}
-};
-
-class VariantConstructNoArgsNil {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		VariantInternal::clear(&r_ret);
-		r_error.error = Callable::CallError::CALL_OK;
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantInternal::clear(r_ret);
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		ERR_FAIL_MSG("can't ptrcall nil constructor");
-	}
-
-	static int get_argument_count() {
-		return 0;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::NIL;
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::NIL;
-	}
-};
-
-class VariantConstructNoArgsObject {
-public:
-	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
-		VariantInternal::clear(&r_ret);
-		VariantInternal::object_assign_null(&r_ret);
-		r_error.error = Callable::CallError::CALL_OK;
-	}
-
-	static void validated_construct(Variant *r_ret, const Variant **p_args) {
-		VariantInternal::clear(r_ret);
-		VariantInternal::object_assign_null(r_ret);
-	}
-	static void ptr_construct(void *base, const void **p_args) {
-		PtrConstruct<Object *>::construct(nullptr, base);
-	}
-
-	static int get_argument_count() {
-		return 0;
-	}
-
-	static Variant::Type get_argument_type(int p_arg) {
-		return Variant::NIL;
-	}
-
-	static Variant::Type get_base_type() {
-		return Variant::OBJECT;
-	}
-};
+#include "variant_construct.h"
 
 struct VariantConstructData {
 	void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error);

+ 572 - 0
core/variant/variant_construct.h

@@ -0,0 +1,572 @@
+/*************************************************************************/
+/*  variant_construct.h                                                  */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef VARIANT_CONSTRUCT_H
+#define VARIANT_CONSTRUCT_H
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/crypto/crypto_core.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/io/compression.h"
+#include "core/object/class_db.h"
+#include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/oa_hash_map.h"
+
+template <class T>
+struct PtrConstruct {};
+
+#define MAKE_PTRCONSTRUCT(m_type)                                                  \
+	template <>                                                                    \
+	struct PtrConstruct<m_type> {                                                  \
+		_FORCE_INLINE_ static void construct(const m_type &p_value, void *p_ptr) { \
+			memnew_placement(p_ptr, m_type(p_value));                              \
+		}                                                                          \
+	};
+
+MAKE_PTRCONSTRUCT(bool);
+MAKE_PTRCONSTRUCT(int64_t);
+MAKE_PTRCONSTRUCT(double);
+MAKE_PTRCONSTRUCT(String);
+MAKE_PTRCONSTRUCT(Vector2);
+MAKE_PTRCONSTRUCT(Vector2i);
+MAKE_PTRCONSTRUCT(Rect2);
+MAKE_PTRCONSTRUCT(Rect2i);
+MAKE_PTRCONSTRUCT(Vector3);
+MAKE_PTRCONSTRUCT(Vector3i);
+MAKE_PTRCONSTRUCT(Transform2D);
+MAKE_PTRCONSTRUCT(Plane);
+MAKE_PTRCONSTRUCT(Quaternion);
+MAKE_PTRCONSTRUCT(AABB);
+MAKE_PTRCONSTRUCT(Basis);
+MAKE_PTRCONSTRUCT(Transform3D);
+MAKE_PTRCONSTRUCT(Color);
+MAKE_PTRCONSTRUCT(StringName);
+MAKE_PTRCONSTRUCT(NodePath);
+MAKE_PTRCONSTRUCT(RID);
+
+template <>
+struct PtrConstruct<Object *> {
+	_FORCE_INLINE_ static void construct(Object *p_value, void *p_ptr) {
+		*((Object **)p_ptr) = p_value;
+	}
+};
+
+MAKE_PTRCONSTRUCT(Callable);
+MAKE_PTRCONSTRUCT(Signal);
+MAKE_PTRCONSTRUCT(Dictionary);
+MAKE_PTRCONSTRUCT(Array);
+MAKE_PTRCONSTRUCT(PackedByteArray);
+MAKE_PTRCONSTRUCT(PackedInt32Array);
+MAKE_PTRCONSTRUCT(PackedInt64Array);
+MAKE_PTRCONSTRUCT(PackedFloat32Array);
+MAKE_PTRCONSTRUCT(PackedFloat64Array);
+MAKE_PTRCONSTRUCT(PackedStringArray);
+MAKE_PTRCONSTRUCT(PackedVector2Array);
+MAKE_PTRCONSTRUCT(PackedVector3Array);
+MAKE_PTRCONSTRUCT(PackedColorArray);
+MAKE_PTRCONSTRUCT(Variant);
+
+template <class T, class... P>
+class VariantConstructor {
+	template <size_t... Is>
+	static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+		r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+		base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+		base = T(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+	}
+
+	template <size_t... Is>
+	static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) {
+		base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...);
+	}
+
+	template <size_t... Is>
+	static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) {
+		PtrConstruct<T>::construct(T(PtrToArg<P>::convert(p_args[Is])...), base);
+	}
+
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		r_error.error = Callable::CallError::CALL_OK;
+		VariantTypeChanger<T>::change(&r_ret);
+		construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantTypeChanger<T>::change(r_ret);
+		validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(r_ret), p_args, BuildIndexSequence<sizeof...(P)>{});
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{});
+	}
+
+	static int get_argument_count() {
+		return sizeof...(P);
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return call_get_argument_type<P...>(p_arg);
+	}
+
+	static Variant::Type get_base_type() {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+};
+
+class VariantConstructorObject {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		VariantInternal::clear(&r_ret);
+		if (p_args[0]->get_type() == Variant::NIL) {
+			VariantInternal::object_assign_null(&r_ret);
+			r_error.error = Callable::CallError::CALL_OK;
+		} else if (p_args[0]->get_type() == Variant::OBJECT) {
+			VariantInternal::object_assign(&r_ret, p_args[0]);
+			r_error.error = Callable::CallError::CALL_OK;
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::OBJECT;
+		}
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantInternal::clear(r_ret);
+		VariantInternal::object_assign(r_ret, p_args[0]);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<Object *>::construct(PtrToArg<Object *>::convert(p_args[0]), base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::OBJECT;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::OBJECT;
+	}
+};
+
+class VariantConstructorNilObject {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != Variant::NIL) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::NIL;
+		}
+
+		VariantInternal::clear(&r_ret);
+		VariantInternal::object_assign_null(&r_ret);
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantInternal::clear(r_ret);
+		VariantInternal::object_assign_null(r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<Object *>::construct(nullptr, base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::OBJECT;
+	}
+};
+
+class VariantConstructorCallableArgs {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		ObjectID object_id;
+		StringName method;
+
+		if (p_args[0]->get_type() == Variant::NIL) {
+			// leave as is
+		} else if (p_args[0]->get_type() == Variant::OBJECT) {
+			object_id = VariantInternal::get_object_id(p_args[0]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::OBJECT;
+			return;
+		}
+
+		if (p_args[1]->get_type() == Variant::STRING_NAME) {
+			method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
+		} else if (p_args[1]->get_type() == Variant::STRING) {
+			method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 1;
+			r_error.expected = Variant::STRING_NAME;
+			return;
+		}
+
+		VariantTypeChanger<Callable>::change(&r_ret);
+		*VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method);
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantTypeChanger<Callable>::change(r_ret);
+		*VariantGetInternalPtr<Callable>::get_ptr(r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<Callable>::construct(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
+	}
+
+	static int get_argument_count() {
+		return 2;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		if (p_arg == 0) {
+			return Variant::OBJECT;
+		} else {
+			return Variant::STRING_NAME;
+		}
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::CALLABLE;
+	}
+};
+
+class VariantConstructorSignalArgs {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		ObjectID object_id;
+		StringName method;
+
+		if (p_args[0]->get_type() == Variant::NIL) {
+			// leave as is
+		} else if (p_args[0]->get_type() == Variant::OBJECT) {
+			object_id = VariantInternal::get_object_id(p_args[0]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::OBJECT;
+			return;
+		}
+
+		if (p_args[1]->get_type() == Variant::STRING_NAME) {
+			method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
+		} else if (p_args[1]->get_type() == Variant::STRING) {
+			method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
+		} else {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 1;
+			r_error.expected = Variant::STRING_NAME;
+			return;
+		}
+
+		VariantTypeChanger<Signal>::change(&r_ret);
+		*VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method);
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantTypeChanger<Signal>::change(r_ret);
+		*VariantGetInternalPtr<Signal>::get_ptr(r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<Signal>::construct(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
+	}
+
+	static int get_argument_count() {
+		return 2;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		if (p_arg == 0) {
+			return Variant::OBJECT;
+		} else {
+			return Variant::STRING_NAME;
+		}
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::SIGNAL;
+	}
+};
+
+template <class T>
+class VariantConstructorToArray {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = GetTypeInfo<T>::VARIANT_TYPE;
+			return;
+		}
+
+		VariantTypeChanger<Array>::change(&r_ret);
+		Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
+		const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr[i] = src_arr[i];
+		}
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantTypeChanger<Array>::change(r_ret);
+		Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret);
+		const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr[i] = src_arr[i];
+		}
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		Array dst_arr;
+		T src_arr = PtrToArg<T>::convert(p_args[0]);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr[i] = src_arr[i];
+		}
+
+		PtrConstruct<Array>::construct(dst_arr, base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::ARRAY;
+	}
+};
+
+template <class T>
+class VariantConstructorFromArray {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != Variant::ARRAY) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::ARRAY;
+			return;
+		}
+
+		VariantTypeChanger<T>::change(&r_ret);
+		const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+		T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr.write[i] = src_arr[i];
+		}
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantTypeChanger<T>::change(r_ret);
+		const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+		T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(r_ret);
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr.write[i] = src_arr[i];
+		}
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		Array src_arr = PtrToArg<Array>::convert(p_args[0]);
+		T dst_arr;
+
+		int size = src_arr.size();
+		dst_arr.resize(size);
+		for (int i = 0; i < size; i++) {
+			dst_arr.write[i] = src_arr[i];
+		}
+
+		PtrConstruct<T>::construct(dst_arr, base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::ARRAY;
+	}
+
+	static Variant::Type get_base_type() {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+};
+
+class VariantConstructorNil {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		if (p_args[0]->get_type() != Variant::NIL) {
+			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = 0;
+			r_error.expected = Variant::NIL;
+			return;
+		}
+
+		r_error.error = Callable::CallError::CALL_OK;
+		VariantInternal::clear(&r_ret);
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantInternal::clear(r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<Variant>::construct(Variant(), base);
+	}
+
+	static int get_argument_count() {
+		return 1;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::NIL;
+	}
+};
+
+template <class T>
+class VariantConstructNoArgs {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		VariantTypeChanger<T>::change_and_reset(&r_ret);
+		r_error.error = Callable::CallError::CALL_OK;
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantTypeChanger<T>::change_and_reset(r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<T>::construct(T(), base);
+	}
+
+	static int get_argument_count() {
+		return 0;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return GetTypeInfo<T>::VARIANT_TYPE;
+	}
+};
+
+class VariantConstructNoArgsNil {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		VariantInternal::clear(&r_ret);
+		r_error.error = Callable::CallError::CALL_OK;
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantInternal::clear(r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		ERR_FAIL_MSG("can't ptrcall nil constructor");
+	}
+
+	static int get_argument_count() {
+		return 0;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::NIL;
+	}
+};
+
+class VariantConstructNoArgsObject {
+public:
+	static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+		VariantInternal::clear(&r_ret);
+		VariantInternal::object_assign_null(&r_ret);
+		r_error.error = Callable::CallError::CALL_OK;
+	}
+
+	static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
+		VariantInternal::clear(r_ret);
+		VariantInternal::object_assign_null(r_ret);
+	}
+	static void ptr_construct(void *base, const void **p_args) {
+		PtrConstruct<Object *>::construct(nullptr, base);
+	}
+
+	static int get_argument_count() {
+		return 0;
+	}
+
+	static Variant::Type get_argument_type(int p_arg) {
+		return Variant::NIL;
+	}
+
+	static Variant::Type get_base_type() {
+		return Variant::OBJECT;
+	}
+};
+
+#endif // VARIANT_CONSTRUCT_H

+ 1 - 1336
core/variant/variant_op.cpp

@@ -28,1342 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "variant.h"
-
-#include "core/core_string_names.h"
-#include "core/debugger/engine_debugger.h"
-#include "core/object/class_db.h"
-
-template <class R, class A, class B>
-class OperatorEvaluatorAdd {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a + b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) + *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) + PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorSub {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a - b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) - *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) - PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorMul {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a * b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) * *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) * PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorXForm {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a.xform(b);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<A>::get_ptr(left)->xform(*VariantGetInternalPtr<B>::get_ptr(right));
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left).xform(PtrToArg<B>::convert(right)), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorXFormInv {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = b.xform_inv(a);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<B>::get_ptr(right)->xform_inv(*VariantGetInternalPtr<A>::get_ptr(left));
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<B>::convert(right).xform_inv(PtrToArg<A>::convert(left)), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorDiv {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a / b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorDivNZ {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		if (b == 0) {
-			r_valid = false;
-			*r_ret = "Division by zero error";
-			return;
-		}
-		*r_ret = a / b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorMod {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a % b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorModNZ {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		if (b == 0) {
-			r_valid = false;
-			*r_ret = "Module by zero error";
-			return;
-		}
-		*r_ret = a % b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A>
-class OperatorEvaluatorNeg {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		*r_ret = -a;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = -*VariantGetInternalPtr<A>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(-PtrToArg<A>::convert(left), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A>
-class OperatorEvaluatorPos {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		*r_ret = a;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorShiftLeft {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-
-#if defined(DEBUG_ENABLED)
-		if (b < 0 || a < 0) {
-			*r_ret = "Invalid operands for bit shifting. Only positive operands are supported.";
-			r_valid = false;
-			return;
-		}
-#endif
-		*r_ret = a << b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) << *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) << PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorShiftRight {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-
-#if defined(DEBUG_ENABLED)
-		if (b < 0 || a < 0) {
-			*r_ret = "Invalid operands for bit shifting. Only positive operands are supported.";
-			r_valid = false;
-			return;
-		}
-#endif
-		*r_ret = a >> b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >> *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) >> PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorBitOr {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a | b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) | *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) | PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorBitAnd {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a & b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) & *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) & PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A, class B>
-class OperatorEvaluatorBitXor {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a ^ b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) ^ *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(PtrToArg<A>::convert(left) ^ PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class R, class A>
-class OperatorEvaluatorBitNeg {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		*r_ret = ~a;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<R>::change(r_ret);
-		*VariantGetInternalPtr<R>::get_ptr(r_ret) = ~*VariantGetInternalPtr<A>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<R>::encode(~PtrToArg<A>::convert(left), r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorEqual {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a == b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) == *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) == PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorEqualObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Object *a = p_left.get_validated_object();
-		const Object *b = p_right.get_validated_object();
-		*r_ret = a == b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Object *a = left->get_validated_object();
-		const Object *b = right->get_validated_object();
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == b;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == PtrToArg<Object *>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorEqualObjectNil {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Object *a = p_left.get_validated_object();
-		*r_ret = a == nullptr;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Object *a = left->get_validated_object();
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == nullptr;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorEqualNilObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Object *b = p_right.get_validated_object();
-		*r_ret = nullptr == b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Object *b = right->get_validated_object();
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr == b;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(nullptr == PtrToArg<Object *>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorNotEqual {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a != b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) != *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) != PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorNotEqualObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		Object *a = p_left.get_validated_object();
-		Object *b = p_right.get_validated_object();
-		*r_ret = a != b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		Object *a = left->get_validated_object();
-		Object *b = right->get_validated_object();
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != b;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != PtrToArg<Object *>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorNotEqualObjectNil {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		Object *a = p_left.get_validated_object();
-		*r_ret = a != nullptr;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		Object *a = left->get_validated_object();
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != nullptr;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != nullptr, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorNotEqualNilObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		Object *b = p_right.get_validated_object();
-		*r_ret = nullptr != b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		Object *b = right->get_validated_object();
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr != b;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(nullptr != PtrToArg<Object *>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorLess {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a < b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) < *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) < PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorLessEqual {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a <= b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) <= *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) <= PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorGreater {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a > b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) > *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) > PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorGreaterEqual {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a >= b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >= *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) >= PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorAnd {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a && b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) && *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) && PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorOr {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = a || b;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) || *VariantGetInternalPtr<B>::get_ptr(right);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) || PtrToArg<B>::convert(right), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-#define XOR_OP(m_a, m_b) (((m_a) || (m_b)) && !((m_a) && (m_b)))
-template <class A, class B>
-class OperatorEvaluatorXor {
-public:
-	_FORCE_INLINE_ static bool xor_op(const A &a, const B &b) {
-		return ((a) || (b)) && !((a) && (b));
-	}
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-		*r_ret = xor_op(a, b);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = xor_op(*VariantGetInternalPtr<A>::get_ptr(left), *VariantGetInternalPtr<B>::get_ptr(right));
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(xor_op(PtrToArg<A>::convert(left), PtrToArg<B>::convert(right)), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A>
-class OperatorEvaluatorNot {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		*r_ret = !a;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<A>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(!PtrToArg<A>::convert(left));
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-//// CUSTOM ////
-
-class OperatorEvaluatorAddArray {
-public:
-	_FORCE_INLINE_ static void _add_arrays(Array &sum, const Array &array_a, const Array &array_b) {
-		int asize = array_a.size();
-		int bsize = array_b.size();
-		sum.resize(asize + bsize);
-		for (int i = 0; i < asize; i++) {
-			sum[i] = array_a[i];
-		}
-		for (int i = 0; i < bsize; i++) {
-			sum[i + asize] = array_b[i];
-		}
-	}
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Array &array_a = *VariantGetInternalPtr<Array>::get_ptr(&p_left);
-		const Array &array_b = *VariantGetInternalPtr<Array>::get_ptr(&p_right);
-		Array sum;
-		_add_arrays(sum, array_a, array_b);
-		*r_ret = sum;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<Array>::change(r_ret);
-		_add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right));
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		Array ret;
-		_add_arrays(ret, PtrToArg<Array>::convert(left), PtrToArg<Array>::convert(right));
-		PtrToArg<Array>::encode(ret, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::ARRAY; }
-};
-
-template <class T>
-class OperatorEvaluatorAppendArray {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Vector<T> &array_a = *VariantGetInternalPtr<Vector<T>>::get_ptr(&p_left);
-		const Vector<T> &array_b = *VariantGetInternalPtr<Vector<T>>::get_ptr(&p_right);
-		Vector<T> sum = array_a;
-		sum.append_array(array_b);
-		*r_ret = sum;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<Vector<T>>::change(r_ret);
-		*VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector<T>>::get_ptr(left);
-		VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret)->append_array(*VariantGetInternalPtr<Vector<T>>::get_ptr(right));
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		Vector<T> sum = PtrToArg<Vector<T>>::convert(left);
-		sum.append_array(PtrToArg<Vector<T>>::convert(right));
-		PtrToArg<Vector<T>>::encode(sum, r_ret);
-	}
-	static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; }
-};
-
-class OperatorEvaluatorStringModNil {
-public:
-	_FORCE_INLINE_ static String do_mod(const String &s, bool *r_valid) {
-		Array values;
-		values.push_back(Variant());
-
-		String a = s.sprintf(values, r_valid);
-		if (r_valid) {
-			*r_valid = !*r_valid;
-		}
-		return a;
-	}
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
-		*r_ret = do_mod(a, &r_valid);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<String>::change(r_ret);
-		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), nullptr), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::STRING; }
-};
-
-class OperatorEvaluatorStringModArray {
-public:
-	_FORCE_INLINE_ static String do_mod(const String &s, const Array &p_values, bool *r_valid) {
-		String a = s.sprintf(p_values, r_valid);
-		if (r_valid) {
-			*r_valid = !*r_valid;
-		}
-		return a;
-	}
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
-		*r_ret = do_mod(a, *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<String>::change(r_ret);
-		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::STRING; }
-};
-
-class OperatorEvaluatorStringModObject {
-public:
-	_FORCE_INLINE_ static String do_mod(const String &s, const Object *p_object, bool *r_valid) {
-		Array values;
-		values.push_back(p_object);
-		String a = s.sprintf(values, r_valid);
-		if (r_valid) {
-			*r_valid = !*r_valid;
-		}
-
-		return a;
-	}
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
-		*r_ret = do_mod(a, p_right.get_validated_object(), &r_valid);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<String>::change(r_ret);
-		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::STRING; }
-};
-
-template <class T>
-class OperatorEvaluatorStringModT {
-public:
-	_FORCE_INLINE_ static String do_mod(const String &s, const T &p_value, bool *r_valid) {
-		Array values;
-		values.push_back(p_value);
-		String a = s.sprintf(values, r_valid);
-		if (r_valid) {
-			*r_valid = !*r_valid;
-		}
-		return a;
-	}
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
-		*r_ret = do_mod(a, *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<String>::change(r_ret);
-		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::STRING; }
-};
-
-template <Variant::Operator op, Variant::Type type_left, Variant::Type type_right>
-class OperatorEvaluatorAlwaysTrue {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		*r_ret = true;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = true;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(true, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <Variant::Operator op, Variant::Type type_left, Variant::Type type_right>
-class OperatorEvaluatorAlwaysFalse {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		*r_ret = false;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(false, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-///// OR ///////
-
-_FORCE_INLINE_ static bool _operate_or(bool p_left, bool p_right) {
-	return p_left || p_right;
-}
-
-_FORCE_INLINE_ static bool _operate_and(bool p_left, bool p_right) {
-	return p_left && p_right;
-}
-
-_FORCE_INLINE_ static bool _operate_xor(bool p_left, bool p_right) {
-	return (p_left || p_right) && !(p_left && p_right);
-}
-
-_FORCE_INLINE_ static bool _operate_get_nil(const Variant *p_ptr) {
-	return p_ptr->get_validated_object() != nullptr;
-}
-
-_FORCE_INLINE_ static bool _operate_get_bool(const Variant *p_ptr) {
-	return *VariantGetInternalPtr<bool>::get_ptr(p_ptr);
-}
-
-_FORCE_INLINE_ static bool _operate_get_int(const Variant *p_ptr) {
-	return *VariantGetInternalPtr<int64_t>::get_ptr(p_ptr) != 0;
-}
-
-_FORCE_INLINE_ static bool _operate_get_float(const Variant *p_ptr) {
-	return *VariantGetInternalPtr<double>::get_ptr(p_ptr) != 0.0;
-}
-
-_FORCE_INLINE_ static bool _operate_get_object(const Variant *p_ptr) {
-	return p_ptr->get_validated_object() != nullptr;
-}
-
-_FORCE_INLINE_ static bool _operate_get_ptr_nil(const void *p_ptr) {
-	return false;
-}
-
-_FORCE_INLINE_ static bool _operate_get_ptr_bool(const void *p_ptr) {
-	return PtrToArg<bool>::convert(p_ptr);
-}
-
-_FORCE_INLINE_ static bool _operate_get_ptr_int(const void *p_ptr) {
-	return PtrToArg<int64_t>::convert(p_ptr) != 0;
-}
-
-_FORCE_INLINE_ static bool _operate_get_ptr_float(const void *p_ptr) {
-	return PtrToArg<double>::convert(p_ptr) != 0.0;
-}
-
-_FORCE_INLINE_ static bool _operate_get_ptr_object(const void *p_ptr) {
-	return PtrToArg<Object *>::convert(p_ptr) != nullptr;
-}
-
-#define OP_EVALUATOR(m_class_name, m_left, m_right, m_op)                                                                    \
-	class m_class_name {                                                                                                     \
-	public:                                                                                                                  \
-		static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {                 \
-			*r_ret = m_op(_operate_get_##m_left(&p_left), _operate_get_##m_right(&p_right));                                 \
-			r_valid = true;                                                                                                  \
-		}                                                                                                                    \
-                                                                                                                             \
-		static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {                          \
-			VariantTypeChanger<bool>::change(r_ret);                                                                         \
-			*VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \
-		}                                                                                                                    \
-                                                                                                                             \
-		static void ptr_evaluate(const void *left, const void *right, void *r_ret) {                                         \
-			PtrToArg<bool>::encode(m_op(_operate_get_ptr_##m_left(left), _operate_get_ptr_##m_right(right)), r_ret);         \
-		}                                                                                                                    \
-                                                                                                                             \
-		static Variant::Type get_return_type() {                                                                             \
-			return Variant::BOOL;                                                                                            \
-		}                                                                                                                    \
-	};
-
-// OR
-
-// nil
-OP_EVALUATOR(OperatorEvaluatorNilXBoolOr, nil, bool, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorBoolXNilOr, bool, nil, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorNilXIntOr, nil, int, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorIntXNilOr, int, nil, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorNilXFloatOr, nil, float, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorFloatXNilOr, float, nil, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorObjectXNilOr, object, nil, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorNilXObjectOr, nil, object, _operate_or)
-
-// bool
-OP_EVALUATOR(OperatorEvaluatorBoolXBoolOr, bool, bool, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXIntOr, bool, int, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorIntXBoolOr, int, bool, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXFloatOr, bool, float, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorFloatXBoolOr, float, bool, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXObjectOr, bool, object, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorObjectXBoolOr, object, bool, _operate_or)
-
-// int
-OP_EVALUATOR(OperatorEvaluatorIntXIntOr, int, int, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorIntXFloatOr, int, float, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorFloatXIntOr, float, int, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorIntXObjectOr, int, object, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorObjectXIntOr, object, int, _operate_or)
-
-// float
-OP_EVALUATOR(OperatorEvaluatorFloatXFloatOr, float, float, _operate_or)
-
-OP_EVALUATOR(OperatorEvaluatorFloatXObjectOr, float, object, _operate_or)
-OP_EVALUATOR(OperatorEvaluatorObjectXFloatOr, object, float, _operate_or)
-
-// object
-OP_EVALUATOR(OperatorEvaluatorObjectXObjectOr, object, object, _operate_or)
-
-// AND
-
-// nil
-OP_EVALUATOR(OperatorEvaluatorNilXBoolAnd, nil, bool, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorBoolXNilAnd, bool, nil, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorNilXIntAnd, nil, int, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorIntXNilAnd, int, nil, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorNilXFloatAnd, nil, float, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorFloatXNilAnd, float, nil, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorObjectXNilAnd, object, nil, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorNilXObjectAnd, nil, object, _operate_and)
-
-// bool
-OP_EVALUATOR(OperatorEvaluatorBoolXBoolAnd, bool, bool, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXIntAnd, bool, int, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorIntXBoolAnd, int, bool, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXFloatAnd, bool, float, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorFloatXBoolAnd, float, bool, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXObjectAnd, bool, object, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorObjectXBoolAnd, object, bool, _operate_and)
-
-// int
-OP_EVALUATOR(OperatorEvaluatorIntXIntAnd, int, int, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorIntXFloatAnd, int, float, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorFloatXIntAnd, float, int, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorIntXObjectAnd, int, object, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorObjectXIntAnd, object, int, _operate_and)
-
-// float
-OP_EVALUATOR(OperatorEvaluatorFloatXFloatAnd, float, float, _operate_and)
-
-OP_EVALUATOR(OperatorEvaluatorFloatXObjectAnd, float, object, _operate_and)
-OP_EVALUATOR(OperatorEvaluatorObjectXFloatAnd, object, float, _operate_and)
-
-// object
-OP_EVALUATOR(OperatorEvaluatorObjectXObjectAnd, object, object, _operate_and)
-
-// XOR
-
-// nil
-OP_EVALUATOR(OperatorEvaluatorNilXBoolXor, nil, bool, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorBoolXNilXor, bool, nil, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorNilXIntXor, nil, int, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorIntXNilXor, int, nil, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorNilXFloatXor, nil, float, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorFloatXNilXor, float, nil, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorObjectXNilXor, object, nil, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorNilXObjectXor, nil, object, _operate_xor)
-
-// bool
-OP_EVALUATOR(OperatorEvaluatorBoolXBoolXor, bool, bool, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXIntXor, bool, int, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorIntXBoolXor, int, bool, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXFloatXor, bool, float, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorFloatXBoolXor, float, bool, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorBoolXObjectXor, bool, object, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorObjectXBoolXor, object, bool, _operate_xor)
-
-// int
-OP_EVALUATOR(OperatorEvaluatorIntXIntXor, int, int, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorIntXFloatXor, int, float, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorFloatXIntXor, float, int, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorIntXObjectXor, int, object, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorObjectXIntXor, object, int, _operate_xor)
-
-// float
-OP_EVALUATOR(OperatorEvaluatorFloatXFloatXor, float, float, _operate_xor)
-
-OP_EVALUATOR(OperatorEvaluatorFloatXObjectXor, float, object, _operate_xor)
-OP_EVALUATOR(OperatorEvaluatorObjectXFloatXor, object, float, _operate_xor)
-
-// object
-OP_EVALUATOR(OperatorEvaluatorObjectXObjectXor, object, object, _operate_xor)
-
-class OperatorEvaluatorNotBool {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		*r_ret = !*VariantGetInternalPtr<bool>::get_ptr(&p_left);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<bool>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(!PtrToArg<bool>::convert(left), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorNotInt {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		*r_ret = !*VariantGetInternalPtr<int64_t>::get_ptr(&p_left);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<int64_t>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(!PtrToArg<int64_t>::convert(left), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorNotFloat {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		*r_ret = !*VariantGetInternalPtr<double>::get_ptr(&p_left);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<double>::get_ptr(left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(!PtrToArg<double>::convert(left), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorNotObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		*r_ret = p_left.get_validated_object() == nullptr;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = left->get_validated_object() == nullptr;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-////
-
-class OperatorEvaluatorInStringFind {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const String &str_a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
-		const String &str_b = *VariantGetInternalPtr<String>::get_ptr(&p_right);
-
-		*r_ret = str_b.find(str_a) != -1;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left);
-		const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A, class B>
-class OperatorEvaluatorInArrayFind {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
-
-		*r_ret = b.find(a) != -1;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
-		const B &b = *VariantGetInternalPtr<B>::get_ptr(right);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(a) != -1;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<B>::convert(right).find(PtrToArg<A>::convert(left)) != -1, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorInArrayFindNil {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(&p_right);
-		*r_ret = b.find(Variant()) != -1;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(Variant()) != -1;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(Variant()) != -1, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorInArrayFindObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(&p_right);
-		*r_ret = b.find(p_left) != -1;
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(*left) != -1;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(PtrToArg<Object *>::convert(left)) != -1, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-template <class A>
-class OperatorEvaluatorInDictionaryHas {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right);
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
-
-		*r_ret = b.has(a);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
-		const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(a);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<A>::convert(left)), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorInDictionaryHasNil {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right);
-
-		*r_ret = b.has(Variant());
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(Variant());
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(Variant()), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorInDictionaryHasObject {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right);
-
-		*r_ret = b.has(p_left);
-		r_valid = true;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(*left);
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<Object *>::convert(left)), r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorObjectHasPropertyString {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		Object *b = p_right.get_validated_object();
-		if (!b) {
-			*r_ret = "Invalid base object for 'in'";
-			r_valid = false;
-			return;
-		}
-
-		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
-
-		b->get(a, &r_valid);
-		*r_ret = r_valid;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		Object *l = right->get_validated_object();
-		ERR_FAIL_COND(l == nullptr);
-		const String &a = *VariantGetInternalPtr<String>::get_ptr(left);
-
-		bool valid;
-		l->get(a, &valid);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		bool valid;
-		PtrToArg<Object *>::convert(right)->get(PtrToArg<String>::convert(left), &valid);
-		PtrToArg<bool>::encode(valid, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
-
-class OperatorEvaluatorObjectHasPropertyStringName {
-public:
-	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
-		Object *b = p_right.get_validated_object();
-		if (!b) {
-			*r_ret = "Invalid base object for 'in'";
-			r_valid = false;
-			return;
-		}
-
-		const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(&p_left);
-
-		b->get(a, &r_valid);
-		*r_ret = r_valid;
-	}
-	static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
-		Object *l = right->get_validated_object();
-		ERR_FAIL_COND(l == nullptr);
-		const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(left);
-
-		bool valid;
-		l->get(a, &valid);
-		VariantTypeChanger<bool>::change(r_ret);
-		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
-	}
-	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
-		bool valid;
-		PtrToArg<Object *>::convert(right)->get(PtrToArg<StringName>::convert(left), &valid);
-		PtrToArg<bool>::encode(valid, r_ret);
-	}
-	static Variant::Type get_return_type() { return Variant::BOOL; }
-};
+#include "variant_op.h"
 
 typedef void (*VariantEvaluatorFunction)(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid);
 

+ 1316 - 0
core/variant/variant_op.h

@@ -0,0 +1,1316 @@
+/*************************************************************************/
+/*  variant_op.h                                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef VARIANT_OP_H
+#define VARIANT_OP_H
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/object/class_db.h"
+
+template <class R, class A, class B>
+class OperatorEvaluatorAdd {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a + b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) + *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) + PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorSub {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a - b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) - *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) - PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorMul {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a * b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) * *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) * PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorXForm {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a.xform(b);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<A>::get_ptr(left)->xform(*VariantGetInternalPtr<B>::get_ptr(right));
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left).xform(PtrToArg<B>::convert(right)), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorXFormInv {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = b.xform_inv(a);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<B>::get_ptr(right)->xform_inv(*VariantGetInternalPtr<A>::get_ptr(left));
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<B>::convert(right).xform_inv(PtrToArg<A>::convert(left)), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorDiv {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a / b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorDivNZ {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		if (b == 0) {
+			r_valid = false;
+			*r_ret = "Division by zero error";
+			return;
+		}
+		*r_ret = a / b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorMod {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a % b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorModNZ {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		if (b == 0) {
+			r_valid = false;
+			*r_ret = "Module by zero error";
+			return;
+		}
+		*r_ret = a % b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A>
+class OperatorEvaluatorNeg {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		*r_ret = -a;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = -*VariantGetInternalPtr<A>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(-PtrToArg<A>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A>
+class OperatorEvaluatorPos {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		*r_ret = a;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorShiftLeft {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+
+#if defined(DEBUG_ENABLED)
+		if (b < 0 || a < 0) {
+			*r_ret = "Invalid operands for bit shifting. Only positive operands are supported.";
+			r_valid = false;
+			return;
+		}
+#endif
+		*r_ret = a << b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) << *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) << PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorShiftRight {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+
+#if defined(DEBUG_ENABLED)
+		if (b < 0 || a < 0) {
+			*r_ret = "Invalid operands for bit shifting. Only positive operands are supported.";
+			r_valid = false;
+			return;
+		}
+#endif
+		*r_ret = a >> b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >> *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) >> PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorBitOr {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a | b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) | *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) | PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorBitAnd {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a & b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) & *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) & PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A, class B>
+class OperatorEvaluatorBitXor {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a ^ b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) ^ *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(PtrToArg<A>::convert(left) ^ PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class R, class A>
+class OperatorEvaluatorBitNeg {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		*r_ret = ~a;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<R>::get_ptr(r_ret) = ~*VariantGetInternalPtr<A>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<R>::encode(~PtrToArg<A>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorEqual {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a == b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) == *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) == PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorEqualObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Object *a = p_left.get_validated_object();
+		const Object *b = p_right.get_validated_object();
+		*r_ret = a == b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Object *a = left->get_validated_object();
+		const Object *b = right->get_validated_object();
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == b;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == PtrToArg<Object *>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorEqualObjectNil {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Object *a = p_left.get_validated_object();
+		*r_ret = a == nullptr;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Object *a = left->get_validated_object();
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == nullptr;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorEqualNilObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Object *b = p_right.get_validated_object();
+		*r_ret = nullptr == b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Object *b = right->get_validated_object();
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr == b;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(nullptr == PtrToArg<Object *>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorNotEqual {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a != b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) != *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) != PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorNotEqualObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		Object *a = p_left.get_validated_object();
+		Object *b = p_right.get_validated_object();
+		*r_ret = a != b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		Object *a = left->get_validated_object();
+		Object *b = right->get_validated_object();
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != b;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != PtrToArg<Object *>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorNotEqualObjectNil {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		Object *a = p_left.get_validated_object();
+		*r_ret = a != nullptr;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		Object *a = left->get_validated_object();
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != nullptr;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != nullptr, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorNotEqualNilObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		Object *b = p_right.get_validated_object();
+		*r_ret = nullptr != b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		Object *b = right->get_validated_object();
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr != b;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(nullptr != PtrToArg<Object *>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorLess {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a < b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) < *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) < PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorLessEqual {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a <= b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) <= *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) <= PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorGreater {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a > b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) > *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) > PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorGreaterEqual {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a >= b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >= *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) >= PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorAnd {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a && b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) && *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) && PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorOr {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = a || b;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) || *VariantGetInternalPtr<B>::get_ptr(right);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<A>::convert(left) || PtrToArg<B>::convert(right), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+#define XOR_OP(m_a, m_b) (((m_a) || (m_b)) && !((m_a) && (m_b)))
+template <class A, class B>
+class OperatorEvaluatorXor {
+public:
+	_FORCE_INLINE_ static bool xor_op(const A &a, const B &b) {
+		return ((a) || (b)) && !((a) && (b));
+	}
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+		*r_ret = xor_op(a, b);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = xor_op(*VariantGetInternalPtr<A>::get_ptr(left), *VariantGetInternalPtr<B>::get_ptr(right));
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(xor_op(PtrToArg<A>::convert(left), PtrToArg<B>::convert(right)), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A>
+class OperatorEvaluatorNot {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		*r_ret = !a;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<A>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(!PtrToArg<A>::convert(left));
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+//// CUSTOM ////
+
+class OperatorEvaluatorAddArray {
+public:
+	_FORCE_INLINE_ static void _add_arrays(Array &sum, const Array &array_a, const Array &array_b) {
+		int asize = array_a.size();
+		int bsize = array_b.size();
+		sum.resize(asize + bsize);
+		for (int i = 0; i < asize; i++) {
+			sum[i] = array_a[i];
+		}
+		for (int i = 0; i < bsize; i++) {
+			sum[i + asize] = array_b[i];
+		}
+	}
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Array &array_a = *VariantGetInternalPtr<Array>::get_ptr(&p_left);
+		const Array &array_b = *VariantGetInternalPtr<Array>::get_ptr(&p_right);
+		Array sum;
+		_add_arrays(sum, array_a, array_b);
+		*r_ret = sum;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		_add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right));
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		Array ret;
+		_add_arrays(ret, PtrToArg<Array>::convert(left), PtrToArg<Array>::convert(right));
+		PtrToArg<Array>::encode(ret, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::ARRAY; }
+};
+
+template <class T>
+class OperatorEvaluatorAppendArray {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Vector<T> &array_a = *VariantGetInternalPtr<Vector<T>>::get_ptr(&p_left);
+		const Vector<T> &array_b = *VariantGetInternalPtr<Vector<T>>::get_ptr(&p_right);
+		Vector<T> sum = array_a;
+		sum.append_array(array_b);
+		*r_ret = sum;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector<T>>::get_ptr(left);
+		VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret)->append_array(*VariantGetInternalPtr<Vector<T>>::get_ptr(right));
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		Vector<T> sum = PtrToArg<Vector<T>>::convert(left);
+		sum.append_array(PtrToArg<Vector<T>>::convert(right));
+		PtrToArg<Vector<T>>::encode(sum, r_ret);
+	}
+	static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; }
+};
+
+class OperatorEvaluatorStringModNil {
+public:
+	_FORCE_INLINE_ static String do_mod(const String &s, bool *r_valid) {
+		Array values;
+		values.push_back(Variant());
+
+		String a = s.sprintf(values, r_valid);
+		if (r_valid) {
+			*r_valid = !*r_valid;
+		}
+		return a;
+	}
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+		*r_ret = do_mod(a, &r_valid);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), nullptr), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::STRING; }
+};
+
+class OperatorEvaluatorStringModArray {
+public:
+	_FORCE_INLINE_ static String do_mod(const String &s, const Array &p_values, bool *r_valid) {
+		String a = s.sprintf(p_values, r_valid);
+		if (r_valid) {
+			*r_valid = !*r_valid;
+		}
+		return a;
+	}
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+		*r_ret = do_mod(a, *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::STRING; }
+};
+
+class OperatorEvaluatorStringModObject {
+public:
+	_FORCE_INLINE_ static String do_mod(const String &s, const Object *p_object, bool *r_valid) {
+		Array values;
+		values.push_back(p_object);
+		String a = s.sprintf(values, r_valid);
+		if (r_valid) {
+			*r_valid = !*r_valid;
+		}
+
+		return a;
+	}
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+		*r_ret = do_mod(a, p_right.get_validated_object(), &r_valid);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::STRING; }
+};
+
+template <class T>
+class OperatorEvaluatorStringModT {
+public:
+	_FORCE_INLINE_ static String do_mod(const String &s, const T &p_value, bool *r_valid) {
+		Array values;
+		values.push_back(p_value);
+		String a = s.sprintf(values, r_valid);
+		if (r_valid) {
+			*r_valid = !*r_valid;
+		}
+		return a;
+	}
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+		*r_ret = do_mod(a, *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::STRING; }
+};
+
+template <Variant::Operator op, Variant::Type type_left, Variant::Type type_right>
+class OperatorEvaluatorAlwaysTrue {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		*r_ret = true;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = true;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(true, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <Variant::Operator op, Variant::Type type_left, Variant::Type type_right>
+class OperatorEvaluatorAlwaysFalse {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		*r_ret = false;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(false, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+///// OR ///////
+
+_FORCE_INLINE_ static bool _operate_or(bool p_left, bool p_right) {
+	return p_left || p_right;
+}
+
+_FORCE_INLINE_ static bool _operate_and(bool p_left, bool p_right) {
+	return p_left && p_right;
+}
+
+_FORCE_INLINE_ static bool _operate_xor(bool p_left, bool p_right) {
+	return (p_left || p_right) && !(p_left && p_right);
+}
+
+_FORCE_INLINE_ static bool _operate_get_nil(const Variant *p_ptr) {
+	return p_ptr->get_validated_object() != nullptr;
+}
+
+_FORCE_INLINE_ static bool _operate_get_bool(const Variant *p_ptr) {
+	return *VariantGetInternalPtr<bool>::get_ptr(p_ptr);
+}
+
+_FORCE_INLINE_ static bool _operate_get_int(const Variant *p_ptr) {
+	return *VariantGetInternalPtr<int64_t>::get_ptr(p_ptr) != 0;
+}
+
+_FORCE_INLINE_ static bool _operate_get_float(const Variant *p_ptr) {
+	return *VariantGetInternalPtr<double>::get_ptr(p_ptr) != 0.0;
+}
+
+_FORCE_INLINE_ static bool _operate_get_object(const Variant *p_ptr) {
+	return p_ptr->get_validated_object() != nullptr;
+}
+
+_FORCE_INLINE_ static bool _operate_get_ptr_nil(const void *p_ptr) {
+	return false;
+}
+
+_FORCE_INLINE_ static bool _operate_get_ptr_bool(const void *p_ptr) {
+	return PtrToArg<bool>::convert(p_ptr);
+}
+
+_FORCE_INLINE_ static bool _operate_get_ptr_int(const void *p_ptr) {
+	return PtrToArg<int64_t>::convert(p_ptr) != 0;
+}
+
+_FORCE_INLINE_ static bool _operate_get_ptr_float(const void *p_ptr) {
+	return PtrToArg<double>::convert(p_ptr) != 0.0;
+}
+
+_FORCE_INLINE_ static bool _operate_get_ptr_object(const void *p_ptr) {
+	return PtrToArg<Object *>::convert(p_ptr) != nullptr;
+}
+
+#define OP_EVALUATOR(m_class_name, m_left, m_right, m_op)                                                                    \
+	class m_class_name {                                                                                                     \
+	public:                                                                                                                  \
+		static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {                 \
+			*r_ret = m_op(_operate_get_##m_left(&p_left), _operate_get_##m_right(&p_right));                                 \
+			r_valid = true;                                                                                                  \
+		}                                                                                                                    \
+                                                                                                                             \
+		static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {                   \
+			*VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \
+		}                                                                                                                    \
+                                                                                                                             \
+		static void ptr_evaluate(const void *left, const void *right, void *r_ret) {                                         \
+			PtrToArg<bool>::encode(m_op(_operate_get_ptr_##m_left(left), _operate_get_ptr_##m_right(right)), r_ret);         \
+		}                                                                                                                    \
+                                                                                                                             \
+		static Variant::Type get_return_type() {                                                                             \
+			return Variant::BOOL;                                                                                            \
+		}                                                                                                                    \
+	};
+
+// OR
+
+// nil
+OP_EVALUATOR(OperatorEvaluatorNilXBoolOr, nil, bool, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorBoolXNilOr, bool, nil, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorNilXIntOr, nil, int, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorIntXNilOr, int, nil, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorNilXFloatOr, nil, float, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorFloatXNilOr, float, nil, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorObjectXNilOr, object, nil, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorNilXObjectOr, nil, object, _operate_or)
+
+// bool
+OP_EVALUATOR(OperatorEvaluatorBoolXBoolOr, bool, bool, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXIntOr, bool, int, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorIntXBoolOr, int, bool, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXFloatOr, bool, float, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorFloatXBoolOr, float, bool, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXObjectOr, bool, object, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorObjectXBoolOr, object, bool, _operate_or)
+
+// int
+OP_EVALUATOR(OperatorEvaluatorIntXIntOr, int, int, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorIntXFloatOr, int, float, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorFloatXIntOr, float, int, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorIntXObjectOr, int, object, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorObjectXIntOr, object, int, _operate_or)
+
+// float
+OP_EVALUATOR(OperatorEvaluatorFloatXFloatOr, float, float, _operate_or)
+
+OP_EVALUATOR(OperatorEvaluatorFloatXObjectOr, float, object, _operate_or)
+OP_EVALUATOR(OperatorEvaluatorObjectXFloatOr, object, float, _operate_or)
+
+// object
+OP_EVALUATOR(OperatorEvaluatorObjectXObjectOr, object, object, _operate_or)
+
+// AND
+
+// nil
+OP_EVALUATOR(OperatorEvaluatorNilXBoolAnd, nil, bool, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorBoolXNilAnd, bool, nil, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorNilXIntAnd, nil, int, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorIntXNilAnd, int, nil, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorNilXFloatAnd, nil, float, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorFloatXNilAnd, float, nil, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorObjectXNilAnd, object, nil, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorNilXObjectAnd, nil, object, _operate_and)
+
+// bool
+OP_EVALUATOR(OperatorEvaluatorBoolXBoolAnd, bool, bool, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXIntAnd, bool, int, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorIntXBoolAnd, int, bool, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXFloatAnd, bool, float, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorFloatXBoolAnd, float, bool, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXObjectAnd, bool, object, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorObjectXBoolAnd, object, bool, _operate_and)
+
+// int
+OP_EVALUATOR(OperatorEvaluatorIntXIntAnd, int, int, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorIntXFloatAnd, int, float, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorFloatXIntAnd, float, int, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorIntXObjectAnd, int, object, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorObjectXIntAnd, object, int, _operate_and)
+
+// float
+OP_EVALUATOR(OperatorEvaluatorFloatXFloatAnd, float, float, _operate_and)
+
+OP_EVALUATOR(OperatorEvaluatorFloatXObjectAnd, float, object, _operate_and)
+OP_EVALUATOR(OperatorEvaluatorObjectXFloatAnd, object, float, _operate_and)
+
+// object
+OP_EVALUATOR(OperatorEvaluatorObjectXObjectAnd, object, object, _operate_and)
+
+// XOR
+
+// nil
+OP_EVALUATOR(OperatorEvaluatorNilXBoolXor, nil, bool, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorBoolXNilXor, bool, nil, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorNilXIntXor, nil, int, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorIntXNilXor, int, nil, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorNilXFloatXor, nil, float, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorFloatXNilXor, float, nil, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorObjectXNilXor, object, nil, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorNilXObjectXor, nil, object, _operate_xor)
+
+// bool
+OP_EVALUATOR(OperatorEvaluatorBoolXBoolXor, bool, bool, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXIntXor, bool, int, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorIntXBoolXor, int, bool, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXFloatXor, bool, float, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorFloatXBoolXor, float, bool, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorBoolXObjectXor, bool, object, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorObjectXBoolXor, object, bool, _operate_xor)
+
+// int
+OP_EVALUATOR(OperatorEvaluatorIntXIntXor, int, int, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorIntXFloatXor, int, float, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorFloatXIntXor, float, int, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorIntXObjectXor, int, object, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorObjectXIntXor, object, int, _operate_xor)
+
+// float
+OP_EVALUATOR(OperatorEvaluatorFloatXFloatXor, float, float, _operate_xor)
+
+OP_EVALUATOR(OperatorEvaluatorFloatXObjectXor, float, object, _operate_xor)
+OP_EVALUATOR(OperatorEvaluatorObjectXFloatXor, object, float, _operate_xor)
+
+// object
+OP_EVALUATOR(OperatorEvaluatorObjectXObjectXor, object, object, _operate_xor)
+
+class OperatorEvaluatorNotBool {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		*r_ret = !*VariantGetInternalPtr<bool>::get_ptr(&p_left);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<bool>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(!PtrToArg<bool>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorNotInt {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		*r_ret = !*VariantGetInternalPtr<int64_t>::get_ptr(&p_left);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<int64_t>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(!PtrToArg<int64_t>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorNotFloat {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		*r_ret = !*VariantGetInternalPtr<double>::get_ptr(&p_left);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<double>::get_ptr(left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(!PtrToArg<double>::convert(left), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorNotObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		*r_ret = p_left.get_validated_object() == nullptr;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = left->get_validated_object() == nullptr;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+////
+
+class OperatorEvaluatorInStringFind {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const String &str_a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+		const String &str_b = *VariantGetInternalPtr<String>::get_ptr(&p_right);
+
+		*r_ret = str_b.find(str_a) != -1;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left);
+		const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A, class B>
+class OperatorEvaluatorInArrayFind {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
+
+		*r_ret = b.find(a) != -1;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
+		const B &b = *VariantGetInternalPtr<B>::get_ptr(right);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(a) != -1;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<B>::convert(right).find(PtrToArg<A>::convert(left)) != -1, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorInArrayFindNil {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(&p_right);
+		*r_ret = b.find(Variant()) != -1;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(Variant()) != -1;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(Variant()) != -1, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorInArrayFindObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(&p_right);
+		*r_ret = b.find(p_left) != -1;
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(*left) != -1;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(PtrToArg<Object *>::convert(left)) != -1, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+template <class A>
+class OperatorEvaluatorInDictionaryHas {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right);
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
+
+		*r_ret = b.has(a);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+		const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(a);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<A>::convert(left)), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorInDictionaryHasNil {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right);
+
+		*r_ret = b.has(Variant());
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(Variant());
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(Variant()), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorInDictionaryHasObject {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right);
+
+		*r_ret = b.has(p_left);
+		r_valid = true;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(*left);
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<Object *>::convert(left)), r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorObjectHasPropertyString {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		Object *b = p_right.get_validated_object();
+		if (!b) {
+			*r_ret = "Invalid base object for 'in'";
+			r_valid = false;
+			return;
+		}
+
+		const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left);
+
+		b->get(a, &r_valid);
+		*r_ret = r_valid;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		Object *l = right->get_validated_object();
+		ERR_FAIL_COND(l == nullptr);
+		const String &a = *VariantGetInternalPtr<String>::get_ptr(left);
+
+		bool valid;
+		l->get(a, &valid);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		bool valid;
+		PtrToArg<Object *>::convert(right)->get(PtrToArg<String>::convert(left), &valid);
+		PtrToArg<bool>::encode(valid, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+class OperatorEvaluatorObjectHasPropertyStringName {
+public:
+	static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
+		Object *b = p_right.get_validated_object();
+		if (!b) {
+			*r_ret = "Invalid base object for 'in'";
+			r_valid = false;
+			return;
+		}
+
+		const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(&p_left);
+
+		b->get(a, &r_valid);
+		*r_ret = r_valid;
+	}
+	static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+		Object *l = right->get_validated_object();
+		ERR_FAIL_COND(l == nullptr);
+		const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(left);
+
+		bool valid;
+		l->get(a, &valid);
+		*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
+	}
+	static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
+		bool valid;
+		PtrToArg<Object *>::convert(right)->get(PtrToArg<StringName>::convert(left), &valid);
+		PtrToArg<bool>::encode(valid, r_ret);
+	}
+	static Variant::Type get_return_type() { return Variant::BOOL; }
+};
+
+#endif // VARIANT_OP_H

+ 2 - 277
core/variant/variant_setget.cpp

@@ -28,282 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "variant.h"
-
-#include "core/core_string_names.h"
-#include "core/debugger/engine_debugger.h"
-#include "core/object/class_db.h"
-#include "core/templates/local_vector.h"
-#include "core/variant/variant_internal.h"
-
-/**** NAMED SETTERS AND GETTERS ****/
-
-#define SETGET_STRUCT(m_base_type, m_member_type, m_member)                                                                          \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                                \
-		static void get(const Variant *base, Variant *member) {                                                                      \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                        \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member;    \
-		}                                                                                                                            \
-		static void ptr_get(const void *base, void *member) {                                                                        \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member);                                  \
-		}                                                                                                                            \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                          \
-			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                     \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
-				valid = true;                                                                                                        \
-			} else {                                                                                                                 \
-				valid = false;                                                                                                       \
-			}                                                                                                                        \
-		}                                                                                                                            \
-		static void validated_set(Variant *base, const Variant *value) {                                                             \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value);     \
-		}                                                                                                                            \
-		static void ptr_set(void *base, const void *member) {                                                                        \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                    \
-			b.m_member = PtrToArg<m_member_type>::convert(member);                                                                   \
-			PtrToArg<m_base_type>::encode(b, base);                                                                                  \
-		}                                                                                                                            \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                         \
-	};
-
-#define SETGET_NUMBER_STRUCT(m_base_type, m_member_type, m_member)                                                                \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                             \
-		static void get(const Variant *base, Variant *member) {                                                                   \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                     \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
-		}                                                                                                                         \
-		static void ptr_get(const void *base, void *member) {                                                                     \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member);                               \
-		}                                                                                                                         \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                       \
-			if (value->get_type() == Variant::FLOAT) {                                                                            \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<double>::get_ptr(value);     \
-				valid = true;                                                                                                     \
-			} else if (value->get_type() == Variant::INT) {                                                                       \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<int64_t>::get_ptr(value);    \
-				valid = true;                                                                                                     \
-			} else {                                                                                                              \
-				valid = false;                                                                                                    \
-			}                                                                                                                     \
-		}                                                                                                                         \
-		static void validated_set(Variant *base, const Variant *value) {                                                          \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value);  \
-		}                                                                                                                         \
-		static void ptr_set(void *base, const void *member) {                                                                     \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                 \
-			b.m_member = PtrToArg<m_member_type>::convert(member);                                                                \
-			PtrToArg<m_base_type>::encode(b, base);                                                                               \
-		}                                                                                                                         \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                      \
-	};
-
-#define SETGET_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom)                                                         \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                                \
-		static void get(const Variant *base, Variant *member) {                                                                      \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                        \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom;    \
-		}                                                                                                                            \
-		static void ptr_get(const void *base, void *member) {                                                                        \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member);                                  \
-		}                                                                                                                            \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                          \
-			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                     \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
-				valid = true;                                                                                                        \
-			} else {                                                                                                                 \
-				valid = false;                                                                                                       \
-			}                                                                                                                        \
-		}                                                                                                                            \
-		static void validated_set(Variant *base, const Variant *value) {                                                             \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value);     \
-		}                                                                                                                            \
-		static void ptr_set(void *base, const void *member) {                                                                        \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                    \
-			b.m_custom = PtrToArg<m_member_type>::convert(member);                                                                   \
-			PtrToArg<m_base_type>::encode(b, base);                                                                                  \
-		}                                                                                                                            \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                         \
-	};
-
-#define SETGET_NUMBER_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom)                                               \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                             \
-		static void get(const Variant *base, Variant *member) {                                                                   \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                     \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
-		}                                                                                                                         \
-		static void ptr_get(const void *base, void *member) {                                                                     \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member);                               \
-		}                                                                                                                         \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                       \
-			if (value->get_type() == Variant::FLOAT) {                                                                            \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<double>::get_ptr(value);     \
-				valid = true;                                                                                                     \
-			} else if (value->get_type() == Variant::INT) {                                                                       \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<int64_t>::get_ptr(value);    \
-				valid = true;                                                                                                     \
-			} else {                                                                                                              \
-				valid = false;                                                                                                    \
-			}                                                                                                                     \
-		}                                                                                                                         \
-		static void validated_set(Variant *base, const Variant *value) {                                                          \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value);  \
-		}                                                                                                                         \
-		static void ptr_set(void *base, const void *member) {                                                                     \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                 \
-			b.m_custom = PtrToArg<m_member_type>::convert(member);                                                                \
-			PtrToArg<m_base_type>::encode(b, base);                                                                               \
-		}                                                                                                                         \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                      \
-	};
-
-#define SETGET_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter)                                                \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                               \
-		static void get(const Variant *base, Variant *member) {                                                                     \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                       \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
-		}                                                                                                                           \
-		static void ptr_get(const void *base, void *member) {                                                                       \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member);                               \
-		}                                                                                                                           \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                         \
-			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                    \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
-				valid = true;                                                                                                       \
-			} else {                                                                                                                \
-				valid = false;                                                                                                      \
-			}                                                                                                                       \
-		}                                                                                                                           \
-		static void validated_set(Variant *base, const Variant *value) {                                                            \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value));     \
-		}                                                                                                                           \
-		static void ptr_set(void *base, const void *member) {                                                                       \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                   \
-			b.m_setter(PtrToArg<m_member_type>::convert(member));                                                                   \
-			PtrToArg<m_base_type>::encode(b, base);                                                                                 \
-		}                                                                                                                           \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                        \
-	};
-
-#define SETGET_NUMBER_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter)                                         \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                               \
-		static void get(const Variant *base, Variant *member) {                                                                     \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                       \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
-		}                                                                                                                           \
-		static void ptr_get(const void *base, void *member) {                                                                       \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member);                               \
-		}                                                                                                                           \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                         \
-			if (value->get_type() == Variant::FLOAT) {                                                                              \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<double>::get_ptr(value));        \
-				valid = true;                                                                                                       \
-			} else if (value->get_type() == Variant::INT) {                                                                         \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<int64_t>::get_ptr(value));       \
-				valid = true;                                                                                                       \
-			} else {                                                                                                                \
-				valid = false;                                                                                                      \
-			}                                                                                                                       \
-		}                                                                                                                           \
-		static void validated_set(Variant *base, const Variant *value) {                                                            \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value));     \
-		}                                                                                                                           \
-		static void ptr_set(void *base, const void *member) {                                                                       \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                   \
-			b.m_setter(PtrToArg<m_member_type>::convert(member));                                                                   \
-			PtrToArg<m_base_type>::encode(b, base);                                                                                 \
-		}                                                                                                                           \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                        \
-	};
-
-#define SETGET_STRUCT_FUNC_INDEX(m_base_type, m_member_type, m_member, m_setter, m_getter, m_index)                                          \
-	struct VariantSetGet_##m_base_type##_##m_member {                                                                                        \
-		static void get(const Variant *base, Variant *member) {                                                                              \
-			VariantTypeAdjust<m_member_type>::adjust(member);                                                                                \
-			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(m_index);   \
-		}                                                                                                                                    \
-		static void ptr_get(const void *base, void *member) {                                                                                \
-			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(m_index), member);                                 \
-		}                                                                                                                                    \
-		static void set(Variant *base, const Variant *value, bool &valid) {                                                                  \
-			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                             \
-				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
-				valid = true;                                                                                                                \
-			} else {                                                                                                                         \
-				valid = false;                                                                                                               \
-			}                                                                                                                                \
-		}                                                                                                                                    \
-		static void validated_set(Variant *base, const Variant *value) {                                                                     \
-			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value));     \
-		}                                                                                                                                    \
-		static void ptr_set(void *base, const void *member) {                                                                                \
-			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                            \
-			b.m_setter(m_index, PtrToArg<m_member_type>::convert(member));                                                                   \
-			PtrToArg<m_base_type>::encode(b, base);                                                                                          \
-		}                                                                                                                                    \
-		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                                 \
-	};
-
-SETGET_NUMBER_STRUCT(Vector2, double, x)
-SETGET_NUMBER_STRUCT(Vector2, double, y)
-
-SETGET_NUMBER_STRUCT(Vector2i, int64_t, x)
-SETGET_NUMBER_STRUCT(Vector2i, int64_t, y)
-
-SETGET_NUMBER_STRUCT(Vector3, double, x)
-SETGET_NUMBER_STRUCT(Vector3, double, y)
-SETGET_NUMBER_STRUCT(Vector3, double, z)
-
-SETGET_NUMBER_STRUCT(Vector3i, int64_t, x)
-SETGET_NUMBER_STRUCT(Vector3i, int64_t, y)
-SETGET_NUMBER_STRUCT(Vector3i, int64_t, z)
-
-SETGET_STRUCT(Rect2, Vector2, position)
-SETGET_STRUCT(Rect2, Vector2, size)
-SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end)
-
-SETGET_STRUCT(Rect2i, Vector2i, position)
-SETGET_STRUCT(Rect2i, Vector2i, size)
-SETGET_STRUCT_FUNC(Rect2i, Vector2i, end, set_end, get_end)
-
-SETGET_STRUCT(AABB, Vector3, position)
-SETGET_STRUCT(AABB, Vector3, size)
-SETGET_STRUCT_FUNC(AABB, Vector3, end, set_end, get_end)
-
-SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, elements[0])
-SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, elements[1])
-SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, elements[2])
-
-SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, x, normal.x)
-SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, y, normal.y)
-SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, z, normal.z)
-SETGET_STRUCT(Plane, Vector3, normal)
-SETGET_NUMBER_STRUCT(Plane, double, d)
-
-SETGET_NUMBER_STRUCT(Quaternion, double, x)
-SETGET_NUMBER_STRUCT(Quaternion, double, y)
-SETGET_NUMBER_STRUCT(Quaternion, double, z)
-SETGET_NUMBER_STRUCT(Quaternion, double, w)
-
-SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_axis, get_axis, 0)
-SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_axis, get_axis, 1)
-SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_axis, get_axis, 2)
-
-SETGET_STRUCT(Transform3D, Basis, basis)
-SETGET_STRUCT(Transform3D, Vector3, origin)
-
-SETGET_NUMBER_STRUCT(Color, double, r)
-SETGET_NUMBER_STRUCT(Color, double, g)
-SETGET_NUMBER_STRUCT(Color, double, b)
-SETGET_NUMBER_STRUCT(Color, double, a)
-
-SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, r8, set_r8, get_r8)
-SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, g8, set_g8, get_g8)
-SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, b8, set_b8, get_b8)
-SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, a8, set_a8, get_a8)
-
-SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h)
-SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s)
-SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v)
+#include "variant_setget.h"
 
 struct VariantSetterGetterInfo {
 	void (*setter)(Variant *base, const Variant *value, bool &valid);
@@ -326,7 +51,7 @@ static void register_member(Variant::Type p_type, const StringName &p_member) {
 	sgi.ptr_setter = T::ptr_set;
 
 	sgi.getter = T::get;
-	sgi.validated_getter = T::get;
+	sgi.validated_getter = T::validated_get;
 	sgi.ptr_getter = T::ptr_get;
 
 	sgi.member_type = T::get_type();

+ 332 - 0
core/variant/variant_setget.h

@@ -0,0 +1,332 @@
+/*************************************************************************/
+/*  variant_setget.h                                                     */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef VARIANT_SETGET_H
+#define VARIANT_SETGET_H
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/object/class_db.h"
+#include "core/templates/local_vector.h"
+#include "core/variant/variant_internal.h"
+
+/**** NAMED SETTERS AND GETTERS ****/
+
+#define SETGET_STRUCT(m_base_type, m_member_type, m_member)                                                                          \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                                \
+		static void get(const Variant *base, Variant *member) {                                                                      \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                        \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member;    \
+		}                                                                                                                            \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                     \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member;    \
+		}                                                                                                                            \
+		static void ptr_get(const void *base, void *member) {                                                                        \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member);                                  \
+		}                                                                                                                            \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                          \
+			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                     \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
+				valid = true;                                                                                                        \
+			} else {                                                                                                                 \
+				valid = false;                                                                                                       \
+			}                                                                                                                        \
+		}                                                                                                                            \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                      \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value);     \
+		}                                                                                                                            \
+		static void ptr_set(void *base, const void *member) {                                                                        \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                    \
+			b.m_member = PtrToArg<m_member_type>::convert(member);                                                                   \
+			PtrToArg<m_base_type>::encode(b, base);                                                                                  \
+		}                                                                                                                            \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                         \
+	};
+
+#define SETGET_NUMBER_STRUCT(m_base_type, m_member_type, m_member)                                                                \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                             \
+		static void get(const Variant *base, Variant *member) {                                                                   \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                     \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
+		}                                                                                                                         \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                  \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \
+		}                                                                                                                         \
+		static void ptr_get(const void *base, void *member) {                                                                     \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member);                               \
+		}                                                                                                                         \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                       \
+			if (value->get_type() == Variant::FLOAT) {                                                                            \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<double>::get_ptr(value);     \
+				valid = true;                                                                                                     \
+			} else if (value->get_type() == Variant::INT) {                                                                       \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<int64_t>::get_ptr(value);    \
+				valid = true;                                                                                                     \
+			} else {                                                                                                              \
+				valid = false;                                                                                                    \
+			}                                                                                                                     \
+		}                                                                                                                         \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                   \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value);  \
+		}                                                                                                                         \
+		static void ptr_set(void *base, const void *member) {                                                                     \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                 \
+			b.m_member = PtrToArg<m_member_type>::convert(member);                                                                \
+			PtrToArg<m_base_type>::encode(b, base);                                                                               \
+		}                                                                                                                         \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                      \
+	};
+
+#define SETGET_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom)                                                         \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                                \
+		static void get(const Variant *base, Variant *member) {                                                                      \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                        \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom;    \
+		}                                                                                                                            \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                     \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom;    \
+		}                                                                                                                            \
+		static void ptr_get(const void *base, void *member) {                                                                        \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member);                                  \
+		}                                                                                                                            \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                          \
+			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                     \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \
+				valid = true;                                                                                                        \
+			} else {                                                                                                                 \
+				valid = false;                                                                                                       \
+			}                                                                                                                        \
+		}                                                                                                                            \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                      \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value);     \
+		}                                                                                                                            \
+		static void ptr_set(void *base, const void *member) {                                                                        \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                    \
+			b.m_custom = PtrToArg<m_member_type>::convert(member);                                                                   \
+			PtrToArg<m_base_type>::encode(b, base);                                                                                  \
+		}                                                                                                                            \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                         \
+	};
+
+#define SETGET_NUMBER_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom)                                               \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                             \
+		static void get(const Variant *base, Variant *member) {                                                                   \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                     \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
+		}                                                                                                                         \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                  \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \
+		}                                                                                                                         \
+		static void ptr_get(const void *base, void *member) {                                                                     \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member);                               \
+		}                                                                                                                         \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                       \
+			if (value->get_type() == Variant::FLOAT) {                                                                            \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<double>::get_ptr(value);     \
+				valid = true;                                                                                                     \
+			} else if (value->get_type() == Variant::INT) {                                                                       \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<int64_t>::get_ptr(value);    \
+				valid = true;                                                                                                     \
+			} else {                                                                                                              \
+				valid = false;                                                                                                    \
+			}                                                                                                                     \
+		}                                                                                                                         \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                   \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value);  \
+		}                                                                                                                         \
+		static void ptr_set(void *base, const void *member) {                                                                     \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                 \
+			b.m_custom = PtrToArg<m_member_type>::convert(member);                                                                \
+			PtrToArg<m_base_type>::encode(b, base);                                                                               \
+		}                                                                                                                         \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                      \
+	};
+
+#define SETGET_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter)                                                \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                               \
+		static void get(const Variant *base, Variant *member) {                                                                     \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                       \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
+		}                                                                                                                           \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                    \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
+		}                                                                                                                           \
+		static void ptr_get(const void *base, void *member) {                                                                       \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member);                               \
+		}                                                                                                                           \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                         \
+			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                    \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
+				valid = true;                                                                                                       \
+			} else {                                                                                                                \
+				valid = false;                                                                                                      \
+			}                                                                                                                       \
+		}                                                                                                                           \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                     \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value));     \
+		}                                                                                                                           \
+		static void ptr_set(void *base, const void *member) {                                                                       \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                   \
+			b.m_setter(PtrToArg<m_member_type>::convert(member));                                                                   \
+			PtrToArg<m_base_type>::encode(b, base);                                                                                 \
+		}                                                                                                                           \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                        \
+	};
+
+#define SETGET_NUMBER_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter)                                         \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                               \
+		static void get(const Variant *base, Variant *member) {                                                                     \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                       \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
+		}                                                                                                                           \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                    \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \
+		}                                                                                                                           \
+		static void ptr_get(const void *base, void *member) {                                                                       \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member);                               \
+		}                                                                                                                           \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                         \
+			if (value->get_type() == Variant::FLOAT) {                                                                              \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<double>::get_ptr(value));        \
+				valid = true;                                                                                                       \
+			} else if (value->get_type() == Variant::INT) {                                                                         \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<int64_t>::get_ptr(value));       \
+				valid = true;                                                                                                       \
+			} else {                                                                                                                \
+				valid = false;                                                                                                      \
+			}                                                                                                                       \
+		}                                                                                                                           \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                     \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value));     \
+		}                                                                                                                           \
+		static void ptr_set(void *base, const void *member) {                                                                       \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                   \
+			b.m_setter(PtrToArg<m_member_type>::convert(member));                                                                   \
+			PtrToArg<m_base_type>::encode(b, base);                                                                                 \
+		}                                                                                                                           \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                        \
+	};
+
+#define SETGET_STRUCT_FUNC_INDEX(m_base_type, m_member_type, m_member, m_setter, m_getter, m_index)                                          \
+	struct VariantSetGet_##m_base_type##_##m_member {                                                                                        \
+		static void get(const Variant *base, Variant *member) {                                                                              \
+			VariantTypeAdjust<m_member_type>::adjust(member);                                                                                \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(m_index);   \
+		}                                                                                                                                    \
+		static inline void validated_get(const Variant *base, Variant *member) {                                                             \
+			*VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(m_index);   \
+		}                                                                                                                                    \
+		static void ptr_get(const void *base, void *member) {                                                                                \
+			PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(m_index), member);                                 \
+		}                                                                                                                                    \
+		static void set(Variant *base, const Variant *value, bool &valid) {                                                                  \
+			if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) {                                                             \
+				VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value)); \
+				valid = true;                                                                                                                \
+			} else {                                                                                                                         \
+				valid = false;                                                                                                               \
+			}                                                                                                                                \
+		}                                                                                                                                    \
+		static inline void validated_set(Variant *base, const Variant *value) {                                                              \
+			VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value));     \
+		}                                                                                                                                    \
+		static void ptr_set(void *base, const void *member) {                                                                                \
+			m_base_type b = PtrToArg<m_base_type>::convert(base);                                                                            \
+			b.m_setter(m_index, PtrToArg<m_member_type>::convert(member));                                                                   \
+			PtrToArg<m_base_type>::encode(b, base);                                                                                          \
+		}                                                                                                                                    \
+		static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; }                                                 \
+	};
+
+SETGET_NUMBER_STRUCT(Vector2, double, x)
+SETGET_NUMBER_STRUCT(Vector2, double, y)
+
+SETGET_NUMBER_STRUCT(Vector2i, int64_t, x)
+SETGET_NUMBER_STRUCT(Vector2i, int64_t, y)
+
+SETGET_NUMBER_STRUCT(Vector3, double, x)
+SETGET_NUMBER_STRUCT(Vector3, double, y)
+SETGET_NUMBER_STRUCT(Vector3, double, z)
+
+SETGET_NUMBER_STRUCT(Vector3i, int64_t, x)
+SETGET_NUMBER_STRUCT(Vector3i, int64_t, y)
+SETGET_NUMBER_STRUCT(Vector3i, int64_t, z)
+
+SETGET_STRUCT(Rect2, Vector2, position)
+SETGET_STRUCT(Rect2, Vector2, size)
+SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end)
+
+SETGET_STRUCT(Rect2i, Vector2i, position)
+SETGET_STRUCT(Rect2i, Vector2i, size)
+SETGET_STRUCT_FUNC(Rect2i, Vector2i, end, set_end, get_end)
+
+SETGET_STRUCT(AABB, Vector3, position)
+SETGET_STRUCT(AABB, Vector3, size)
+SETGET_STRUCT_FUNC(AABB, Vector3, end, set_end, get_end)
+
+SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, elements[0])
+SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, elements[1])
+SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, elements[2])
+
+SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, x, normal.x)
+SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, y, normal.y)
+SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, z, normal.z)
+SETGET_STRUCT(Plane, Vector3, normal)
+SETGET_NUMBER_STRUCT(Plane, double, d)
+
+SETGET_NUMBER_STRUCT(Quaternion, double, x)
+SETGET_NUMBER_STRUCT(Quaternion, double, y)
+SETGET_NUMBER_STRUCT(Quaternion, double, z)
+SETGET_NUMBER_STRUCT(Quaternion, double, w)
+
+SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_axis, get_axis, 0)
+SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_axis, get_axis, 1)
+SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_axis, get_axis, 2)
+
+SETGET_STRUCT(Transform3D, Basis, basis)
+SETGET_STRUCT(Transform3D, Vector3, origin)
+
+SETGET_NUMBER_STRUCT(Color, double, r)
+SETGET_NUMBER_STRUCT(Color, double, g)
+SETGET_NUMBER_STRUCT(Color, double, b)
+SETGET_NUMBER_STRUCT(Color, double, a)
+
+SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, r8, set_r8, get_r8)
+SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, g8, set_g8, get_g8)
+SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, b8, set_b8, get_b8)
+SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, a8, set_a8, get_a8)
+
+SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h)
+SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s)
+SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v)
+
+#endif // VARIANT_SETGET_H