diff options
author | Ignacio Etcheverry <ignalfonsore@gmail.com> | 2017-08-09 11:54:27 +0200 |
---|---|---|
committer | Ignacio Etcheverry <ignalfonsore@gmail.com> | 2017-08-10 07:17:44 +0200 |
commit | 46fdf163991f6f6893e00b301267c6ef2380008e (patch) | |
tree | 103e1b6f5bd5dfd3918a912286fefd6fdbdad12f /core | |
parent | 1536cc438128fe4036fa7da5ec305513a781d3c8 (diff) |
Improves method bind detection of signature types
Diffstat (limited to 'core')
-rw-r--r-- | core/class_db.cpp | 19 | ||||
-rw-r--r-- | core/class_db.h | 9 | ||||
-rw-r--r-- | core/make_binders.py | 24 | ||||
-rw-r--r-- | core/method_bind.cpp | 34 | ||||
-rw-r--r-- | core/method_bind.h | 19 | ||||
-rw-r--r-- | core/reference.h | 18 | ||||
-rw-r--r-- | core/type_info.h | 203 | ||||
-rw-r--r-- | core/variant.h | 10 |
8 files changed, 296 insertions, 40 deletions
diff --git a/core/class_db.cpp b/core/class_db.cpp index 24d71f86b0..f4ae1f3c52 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -1082,12 +1082,6 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c StringName mdname = StaticCString::create(method_name); #endif - StringName rettype; - if (mdname.operator String().find(":") != -1) { - rettype = mdname.operator String().get_slice(":", 1); - mdname = mdname.operator String().get_slice(":", 0); - } - OBJTYPE_WLOCK; ERR_FAIL_COND_V(!p_bind, NULL); p_bind->set_name(mdname); @@ -1106,7 +1100,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c if (!type) { ERR_PRINTS("Couldn't bind method '" + mdname + "' for instance: " + instance_type); memdelete(p_bind); - ERR_FAIL_COND_V(!type, NULL); + ERR_FAIL_V(NULL); } if (type->method_map.has(mdname)) { @@ -1115,11 +1109,20 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c ERR_EXPLAIN("Method already bound: " + instance_type + "::" + mdname); ERR_FAIL_V(NULL); } + #ifdef DEBUG_METHODS_ENABLED + + if (method_name.args.size() > p_bind->get_argument_count()) { + memdelete(p_bind); + ERR_EXPLAIN("Method definition provides more arguments than the method actually has: " + instance_type + "::" + mdname); + ERR_FAIL_V(NULL); + } + p_bind->set_argument_names(method_name.args); - p_bind->set_return_type(rettype); + type->method_order.push_back(mdname); #endif + type->method_map[mdname] = p_bind; Vector<Variant> defvals; diff --git a/core/class_db.h b/core/class_db.h index 02eac0dbbc..ea747ebc37 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -436,12 +436,6 @@ public: MethodBind *bind = create_vararg_method_bind(p_method, p_info); ERR_FAIL_COND_V(!bind, NULL); - String rettype; - if (p_name.operator String().find(":") != -1) { - rettype = p_name.operator String().get_slice(":", 1); - p_name = p_name.operator String().get_slice(":", 0); - } - bind->set_name(p_name); bind->set_default_arguments(p_default_args); @@ -461,8 +455,7 @@ public: } type->method_map[p_name] = bind; #ifdef DEBUG_METHODS_ENABLED - if (!rettype.empty()) - bind->set_return_type(rettype); + bind->set_return_type("Variant"); type->method_order.push_back(p_name); #endif diff --git a/core/make_binders.py b/core/make_binders.py index 74b5e9fda3..a5cdb78443 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -11,11 +11,18 @@ public: #ifdef DEBUG_METHODS_ENABLED virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return Variant::get_type_for<R>();$ - $arg if (p_argument==(@-1)) return Variant::get_type_for<P@>(); + $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$ + $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE; $ return Variant::NIL; } + virtual StringName _gen_argument_type_name(int p_arg) const { return _gen_argument_type_hint(p_arg); } + StringName _gen_argument_type_hint(int p_argument) const { + $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_name();$ + $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_name(); + $ + return StringName(); + } #endif virtual String get_instance_class() const { return T::get_class_static(); @@ -91,11 +98,20 @@ public: virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return Variant::get_type_for<R>();$ - $arg if (p_argument==(@-1)) return Variant::get_type_for<P@>(); + $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$ + $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE; $ return Variant::NIL; } + + virtual StringName _gen_argument_type_name(int p_arg) const { return _gen_argument_type_hint(p_arg); } + + StringName _gen_argument_type_hint(int p_argument) const { + $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_name();$ + $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_name(); + $ + return StringName(); + } #endif virtual String get_instance_class() const { return type_name; diff --git a/core/method_bind.cpp b/core/method_bind.cpp index 51c0e72bc7..6792b62703 100644 --- a/core/method_bind.cpp +++ b/core/method_bind.cpp @@ -38,12 +38,16 @@ PropertyInfo MethodBind::get_argument_info(int p_argument) const { if (p_argument >= 0) { - String name = (p_argument < arg_names.size()) ? String(arg_names[p_argument]) : String("arg" + itos(p_argument)); + String name = p_argument < arg_names.size() ? String(arg_names[p_argument]) : String("arg" + itos(p_argument)); PropertyInfo pi(get_argument_type(p_argument), name); - if ((pi.type == Variant::OBJECT) && name.find(":") != -1) { - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = name.get_slicec(':', 1); - pi.name = name.get_slicec(':', 0); + + if (!is_vararg() && pi.type == Variant::OBJECT) { + StringName type_hint = arg_type_hints[p_argument]; + + if (type_hint != StringName()) { + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = type_hint.operator String(); + } } return pi; @@ -87,6 +91,16 @@ Vector<StringName> MethodBind::get_argument_names() const { return arg_names; } +void MethodBind::set_argument_type_hints(const Vector<StringName> &p_type_hints) { + + arg_type_hints = p_type_hints; +} + +Vector<StringName> MethodBind::get_argument_type_hints() const { + + return arg_type_hints; +} + #endif void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) { @@ -98,11 +112,19 @@ void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) { void MethodBind::_generate_argument_types(int p_count) { set_argument_count(p_count); + Variant::Type *argt = memnew_arr(Variant::Type, p_count + 1); - argt[0] = _gen_argument_type(-1); + + arg_type_hints.resize(p_count); + + argt[0] = _gen_argument_type(-1); // return type + set_return_type(_gen_argument_type_hint(-1)); + for (int i = 0; i < p_count; i++) { argt[i + 1] = _gen_argument_type(i); + arg_type_hints[i] = _gen_argument_type_hint(i); } + set_argument_types(argt); } diff --git a/core/method_bind.h b/core/method_bind.h index dbc9cca082..3b4ff96a19 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -44,6 +44,8 @@ #define DEBUG_METHODS_ENABLED #endif +#include "type_info.h" + enum MethodFlags { METHOD_FLAG_NORMAL = 1, @@ -87,12 +89,10 @@ struct VariantCaster<const T &> { #define _VC(m_idx) \ (VariantCaster<P##m_idx>::cast((m_idx - 1) >= p_arg_count ? get_default_argument(m_idx - 1) : *p_args[m_idx - 1])) -//SIMPLE_NUMERIC_TYPE is used to avoid a warning on Variant::get_type_for - #ifdef PTRCALL_ENABLED #define VARIANT_ENUM_CAST(m_enum) \ - SIMPLE_NUMERIC_TYPE(m_enum); \ + MAKE_ENUM_TYPE_INFO(m_enum) \ template <> \ struct VariantCaster<m_enum> { \ \ @@ -113,7 +113,7 @@ struct VariantCaster<const T &> { #else #define VARIANT_ENUM_CAST(m_enum) \ - SIMPLE_NUMERIC_TYPE(m_enum); \ + MAKE_ENUM_TYPE_INFO(m_enum) \ template <> \ struct VariantCaster<m_enum> { \ \ @@ -165,6 +165,7 @@ class MethodBind { int argument_count; #ifdef DEBUG_METHODS_ENABLED Vector<StringName> arg_names; + Vector<StringName> arg_type_hints; Variant::Type *argument_types; StringName ret_type; #endif @@ -176,6 +177,7 @@ protected: void _set_returns(bool p_returns); #ifdef DEBUG_METHODS_ENABLED virtual Variant::Type _gen_argument_type(int p_arg) const = 0; + virtual StringName _gen_argument_type_hint(int p_arg) const = 0; void _generate_argument_types(int p_count); void set_argument_types(Variant::Type *p_types) { argument_types = p_types; } #endif @@ -220,6 +222,9 @@ public: void set_argument_names(const Vector<StringName> &p_names); Vector<StringName> get_argument_names() const; + + void set_argument_type_hints(const Vector<StringName> &p_type_hints); + Vector<StringName> get_argument_type_hints() const; #endif void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); } @@ -282,11 +287,17 @@ public: return Variant::NIL; } + virtual StringName _gen_argument_type_hint(int p_arg) const { + + return "Variant"; + } + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Variant::CallError &r_error) { T *instance = static_cast<T *>(p_object); return (instance->*call_method)(p_args, p_arg_count, r_error); } + void set_method_info(const MethodInfo &p_info) { set_argument_count(p_info.arguments.size()); diff --git a/core/reference.h b/core/reference.h index 90f2791f4b..7f48f8323e 100644 --- a/core/reference.h +++ b/core/reference.h @@ -374,5 +374,23 @@ struct PtrToArg<const RefPtr &> { } }; +template <class T> +struct GetTypeInfo<Ref<T> > { + enum { VARIANT_TYPE = Variant::OBJECT }; + + static inline StringName get_class_name() { + return T::get_class_static(); + } +}; + +template <class T> +struct GetTypeInfo<const Ref<T> &> { + enum { VARIANT_TYPE = Variant::OBJECT }; + + static inline StringName get_class_name() { + return T::get_class_static(); + } +}; + #endif #endif // REFERENCE_H diff --git a/core/type_info.h b/core/type_info.h new file mode 100644 index 0000000000..10912fd074 --- /dev/null +++ b/core/type_info.h @@ -0,0 +1,203 @@ +#ifndef GET_TYPE_INFO_H +#define GET_TYPE_INFO_H + +template <bool C, typename T = void> +struct EnableIf { + + typedef T type; +}; + +template <typename T> +struct EnableIf<false, T> { +}; + +template <typename, typename> +struct TypesAreSame { + + static bool const value = false; +}; + +template <typename A> +struct TypesAreSame<A, A> { + + static bool const value = true; +}; + +template <typename B, typename D> +struct TypeInherits { + + static D *get_d(); + + static char (&test(B *))[1]; + static char (&test(...))[2]; + + static bool const value = sizeof(test(get_d())) == sizeof(char) && + !TypesAreSame<B volatile const, void volatile const>::value; +}; + +template <class T, typename = void> +struct GetTypeInfo { + enum { VARIANT_TYPE = Variant::NIL }; + + static inline StringName get_class_name() { + ERR_PRINT("Fallback type info. Bug!"); + return ""; // Not "Nil", this is an error + } +}; + +#define MAKE_TYPE_INFO(m_type, m_var_type) \ + template <> \ + struct GetTypeInfo<m_type> { \ + enum { VARIANT_TYPE = m_var_type }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; \ + template <> \ + struct GetTypeInfo<const m_type &> { \ + enum { VARIANT_TYPE = m_var_type }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; + +MAKE_TYPE_INFO(bool, Variant::BOOL) +MAKE_TYPE_INFO(uint8_t, Variant::INT) +MAKE_TYPE_INFO(int8_t, Variant::INT) +MAKE_TYPE_INFO(uint16_t, Variant::INT) +MAKE_TYPE_INFO(int16_t, Variant::INT) +MAKE_TYPE_INFO(uint32_t, Variant::INT) +MAKE_TYPE_INFO(int32_t, Variant::INT) +MAKE_TYPE_INFO(int64_t, Variant::INT) +MAKE_TYPE_INFO(uint64_t, Variant::INT) +MAKE_TYPE_INFO(float, Variant::REAL) +MAKE_TYPE_INFO(double, Variant::REAL) + +MAKE_TYPE_INFO(String, Variant::STRING) +MAKE_TYPE_INFO(Vector2, Variant::VECTOR2) +MAKE_TYPE_INFO(Rect2, Variant::RECT2) +MAKE_TYPE_INFO(Vector3, Variant::VECTOR3) +MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D) +MAKE_TYPE_INFO(Plane, Variant::PLANE) +MAKE_TYPE_INFO(Quat, Variant::QUAT) +MAKE_TYPE_INFO(Rect3, Variant::RECT3) +MAKE_TYPE_INFO(Basis, Variant::BASIS) +MAKE_TYPE_INFO(Transform, Variant::TRANSFORM) +MAKE_TYPE_INFO(Color, Variant::COLOR) +MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH) +MAKE_TYPE_INFO(RID, Variant::_RID) +MAKE_TYPE_INFO(Dictionary, Variant::DICTIONARY) +MAKE_TYPE_INFO(Array, Variant::ARRAY) +MAKE_TYPE_INFO(PoolByteArray, Variant::POOL_BYTE_ARRAY) +MAKE_TYPE_INFO(PoolIntArray, Variant::POOL_INT_ARRAY) +MAKE_TYPE_INFO(PoolRealArray, Variant::POOL_REAL_ARRAY) +MAKE_TYPE_INFO(PoolStringArray, Variant::POOL_STRING_ARRAY) +MAKE_TYPE_INFO(PoolVector2Array, Variant::POOL_VECTOR2_ARRAY) +MAKE_TYPE_INFO(PoolVector3Array, Variant::POOL_VECTOR3_ARRAY) +MAKE_TYPE_INFO(PoolColorArray, Variant::POOL_COLOR_ARRAY) + +MAKE_TYPE_INFO(StringName, Variant::STRING) +MAKE_TYPE_INFO(IP_Address, Variant::STRING) + +class BSP_Tree; +MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY) + +#define MAKE_TYPE_INFO_WITH_NAME(m_type, m_var_type, m_class_name) \ + template <> \ + struct GetTypeInfo<m_type> { \ + enum { VARIANT_TYPE = m_var_type }; \ + static inline StringName get_class_name() { \ + return m_class_name; \ + } \ + }; \ + template <> \ + struct GetTypeInfo<const m_type &> { \ + enum { VARIANT_TYPE = m_var_type }; \ + static inline StringName get_class_name() { \ + return m_class_name; \ + } \ + }; + +MAKE_TYPE_INFO_WITH_NAME(RefPtr, Variant::OBJECT, "Reference") +MAKE_TYPE_INFO_WITH_NAME(Variant, Variant::NIL, "Variant") + +#define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \ + template <> \ + struct GetTypeInfo<m_template<m_type> > { \ + enum { VARIANT_TYPE = m_var_type }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; \ + template <> \ + struct GetTypeInfo<const m_template<m_type> &> { \ + enum { VARIANT_TYPE = m_var_type }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; + +MAKE_TEMPLATE_TYPE_INFO(Vector, uint8_t, Variant::POOL_BYTE_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, int, Variant::POOL_INT_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, float, Variant::POOL_REAL_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, String, Variant::POOL_STRING_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Vector2, Variant::POOL_VECTOR2_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Vector3, Variant::POOL_VECTOR3_ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Color, Variant::POOL_COLOR_ARRAY) + +MAKE_TEMPLATE_TYPE_INFO(Vector, Variant, Variant::ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, RID, Variant::ARRAY) +MAKE_TEMPLATE_TYPE_INFO(Vector, Plane, Variant::ARRAY) + +MAKE_TEMPLATE_TYPE_INFO(PoolVector, Plane, Variant::ARRAY) +MAKE_TEMPLATE_TYPE_INFO(PoolVector, Face3, Variant::POOL_VECTOR3_ARRAY) + +#define MAKE_ENUM_TYPE_INFO(m_enum) \ + template <> \ + struct GetTypeInfo<m_enum> { \ + enum { VARIANT_TYPE = Variant::INT }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; \ + template <> \ + struct GetTypeInfo<m_enum const> { \ + enum { VARIANT_TYPE = Variant::INT }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; \ + template <> \ + struct GetTypeInfo<m_enum &> { \ + enum { VARIANT_TYPE = Variant::INT }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; \ + template <> \ + struct GetTypeInfo<const m_enum &> { \ + enum { VARIANT_TYPE = Variant::INT }; \ + static inline StringName get_class_name() { \ + return Variant::get_type_name((Variant::Type)VARIANT_TYPE); \ + } \ + }; + +template <typename T> +struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { + enum { VARIANT_TYPE = Variant::OBJECT }; + + static inline StringName get_class_name() { + return T::get_class_static(); + } +}; + +template <typename T> +struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> { + enum { VARIANT_TYPE = Variant::OBJECT }; + + static inline StringName get_class_name() { + return T::get_class_static(); + } +}; + +#endif // GET_TYPE_INFO_H diff --git a/core/variant.h b/core/variant.h index 95782d9619..40de1a9bce 100644 --- a/core/variant.h +++ b/core/variant.h @@ -49,7 +49,6 @@ #include "rect3.h" #include "ref_ptr.h" #include "rid.h" -#include "simple_type.h" #include "transform.h" #include "ustring.h" #include "vector3.h" @@ -154,15 +153,6 @@ public: static bool can_convert(Type p_type_from, Type p_type_to); static bool can_convert_strict(Type p_type_from, Type p_type_to); - template <class T> - static Type get_type_for() { - - GetSimpleType<T> t; - Variant v(t.type); - Type r = v.get_type(); - return r; - } - bool is_ref() const; _FORCE_INLINE_ bool is_num() const { return type == INT || type == REAL; }; _FORCE_INLINE_ bool is_array() const { return type >= ARRAY; }; |