diff --git a/src/Makefile_Eo_Cxx.am b/src/Makefile_Eo_Cxx.am index 2acdc054f1..ffb0e1ddb4 100644 --- a/src/Makefile_Eo_Cxx.am +++ b/src/Makefile_Eo_Cxx.am @@ -16,6 +16,7 @@ bindings/eo_cxx/eo_inherit.hh \ bindings/eo_cxx/eo_ops.hh \ bindings/eo_cxx/eo_private.hh \ bindings/eo_cxx/eo_inherit_bindings.hh \ -bindings/eo_cxx/Eo.hh +bindings/eo_cxx/Eo.hh \ +bindings/eo_cxx/eo_cxx_interop.hh endif diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am index af89d12244..6bfc6c1b8f 100644 --- a/src/Makefile_Eolian_Cxx.am +++ b/src/Makefile_Eolian_Cxx.am @@ -22,6 +22,7 @@ lib/eolian_cxx/grammar/eo_class_generator.hh \ lib/eolian_cxx/grammar/eo_header_generator.hh \ lib/eolian_cxx/grammar/inheritance_base_generator.hh \ lib/eolian_cxx/grammar/parameters_generator.hh \ +lib/eolian_cxx/grammar/type_generator.hh \ lib/eolian_cxx/grammar/tab.hh ### Binary @@ -35,7 +36,8 @@ bin_eolian_cxx_eolian_cxx_SOURCES = \ bin/eolian_cxx/convert.hh \ bin/eolian_cxx/eolian_wrappers.hh \ bin/eolian_cxx/safe_strings.hh \ - bin/eolian_cxx/type_lookup.hh \ + bin/eolian_cxx/type_lookup.hh \ + bin/eolian_cxx/type_lookup_table.cc \ bin/eolian_cxx/eolian_cxx.cc bin_eolian_cxx_eolian_cxx_CXXFLAGS = -I$(top_builddir)/src/lib/efl \ @@ -82,11 +84,4 @@ tests_eolian_cxx_eolian_cxx_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@ endif -EXTRA_DIST += \ -tests/eolian_cxx/data/base.eo \ -tests/eolian_cxx/data/class_simple.eo \ -tests/eolian_cxx/data/scope.eo \ -tests/eolian_cxx/data/ctor_dtor.eo \ -tests/eolian_cxx/data/complex_type.eo - endif diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc index 873068dac2..f52affa7db 100644 --- a/src/bin/eolian_cxx/convert.cc +++ b/src/bin/eolian_cxx/convert.cc @@ -116,7 +116,7 @@ convert_eolian_property_to_functions(Eolian_Class const& klass) { efl::eolian::eolian_type getter_param_type = type_to_native(param.type); - getter_param_type/*.native*/ += "*"; // XXX implement complex types + getter_param_type.native += "*"; return efl::eolian::eo_parameter { { getter_param_type }, param.name }; }); diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh index e9a9ab99d6..79544286c6 100644 --- a/src/bin/eolian_cxx/eolian_wrappers.hh +++ b/src/bin/eolian_cxx/eolian_wrappers.hh @@ -180,8 +180,7 @@ function_type(Eolian_Function const& func) inline efl::eolian::eolian_type_instance function_return_type(Eolian_Function const& func, Eolian_Function_Type func_type = method_t::value) { - return type_lookup - (::eolian_function_return_type_get(&func, func_type)); + return type_lookup(::eolian_function_return_type_get(&func, func_type)); } inline efl::eolian::eolian_type_instance @@ -286,11 +285,17 @@ parameter_type(Eolian_Function_Parameter const& parameter, efl::eolian::eolian_type_instance type (type_lookup(::eolian_parameter_type_get(¶meter))); assert(!type.empty()); - // XXX implement complex types. if (parameter_is_out(parameter)) - type = { type_to_native(type) + "*" }; + { + type = { efl::eolian::type_to_native(type) }; + type.front().native += "*"; + } if (parameter_is_const(parameter, func_type)) - type.insert(0, "const "); + { + type[0].native.insert(0, "const "); + if (!type[0].binding.empty()) + type[0].binding.insert(0, "const "); + } return type; } @@ -311,7 +316,9 @@ event_create(Eolian_Class const& klass, const Eolian_Event *event_) { efl::eolian::eo_event event; const char *name, *comment; - if(::eolian_class_event_information_get(event_, &name, NULL, &comment)) + const Eolian_Type *type; + static_cast(type); // XXX + if(::eolian_class_event_information_get(event_, &name, &type, &comment)) { std::string name_ = safe_str(name); std::transform(name_.begin(), name_.end(), name_.begin(), diff --git a/src/bin/eolian_cxx/type_lookup.hh b/src/bin/eolian_cxx/type_lookup.hh index 4ac5057981..b5c7cfa144 100644 --- a/src/bin/eolian_cxx/type_lookup.hh +++ b/src/bin/eolian_cxx/type_lookup.hh @@ -12,6 +12,8 @@ #include #include +#include + #include #include "eo_types.hh" @@ -19,18 +21,46 @@ namespace eolian_cxx { -inline std::string -type_lookup(const Eolian_Type *type) +typedef std::vector lookup_table_type; +extern const lookup_table_type type_lookup_table; + +inline efl::eolian::eolian_type +type_from_eolian(Eolian_Type const& type) { - if (type == NULL) - return "void"; - // XXX add complex types implementation. - const char *tps = eolian_type_c_type_get(type); - std::string ret = safe_str(tps); - ::eina_stringshare_del(tps); - return ret; + efl::eolian::eolian_type x; + x.native = normalize_spaces(safe_str(type.name)); + x.is_own = type.is_own; + return x; } +template +inline const efl::eolian::eolian_type& +type_find(Iterator first, Iterator last, efl::eolian::eolian_type const& type) +{ + auto res = std::find_if + (first, last, + [&type] (efl::eolian::eolian_type const& x) + { + return (x.native == type.native && x.is_own == type.is_own); + }); + return (res != last) ? *res : type; +} + +inline efl::eolian::eolian_type_instance +type_lookup(const Eolian_Type* type, + lookup_table_type const& lut = type_lookup_table) +{ + if (type == NULL) return { efl::eolian::void_type }; + size_t n = ::eina_list_count(type->subtypes) + 1; + assert(n > 0); + efl::eolian::eolian_type_instance v(n); + for (size_t i=0; i", {"memory"}}, + {"const Eina_Inlist *", eolian_type::complex_, false, "efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, + {"const Eina_List *", eolian_type::complex_, false, "efl::eina::range_ptr_list", {"eina-cxx/eina_ptrlist.hh"}}, + {"const char *", eolian_type::simple_, false, "std::string", {"string"}} +}; + +} diff --git a/src/bindings/eo_cxx/eo_base.hh b/src/bindings/eo_cxx/eo_base.hh index 4f8cca0d1b..3953fb9a58 100644 --- a/src/bindings/eo_cxx/eo_base.hh +++ b/src/bindings/eo_cxx/eo_base.hh @@ -12,6 +12,7 @@ #include #include "eo_ops.hh" +#include "eo_event.hh" namespace efl { namespace eo { diff --git a/src/bindings/eo_cxx/eo_cxx_interop.hh b/src/bindings/eo_cxx/eo_cxx_interop.hh new file mode 100644 index 0000000000..4a159495fc --- /dev/null +++ b/src/bindings/eo_cxx/eo_cxx_interop.hh @@ -0,0 +1,237 @@ + +#ifndef EFL_EOLIAN_INTEROP_HH +#define EFL_EOLIAN_INTEROP_HH + +#include +#include +#include + +#include +#include + +namespace efl { namespace eolian { + +//// From C++ to C + +inline Eo* +to_c(efl::eo::base const& x) +{ + return ::eo_ref(x._eo_ptr()); +} + +inline const char* +to_c(std::string const& x) +{ + return x.c_str(); +} + +inline const char* +to_c(efl::eina::stringshare const& x) +{ + return x.c_str(); +} + +inline Eina_Bool +to_c(bool x) +{ + return x ? EINA_TRUE : EINA_FALSE; +} + +//// From C to C++ + +template +struct tag {}; + +template +T to_cxx(U object, O o); + +// XXX +inline void* +to_cxx(void *x, std::tuple, tag) +{ + return x; +} + +// XXX +inline const void* +to_cxx(const void *x, std::tuple, tag) +{ + return x; +} + +template +inline T +to_cxx(Eo* x, std::tuple, tag) +{ + return T(x); +} + +template +inline T +to_cxx(Eo* x, std::tuple, tag) +{ + return T(::eo_ref(x)); +} + +#ifdef _EVAS_H +template +Evas_Object_Textblock_Node_Format * +to_cxx(Evas_Object_Textblock_Node_Format* x, std::tuple, tag) +{ + return x; // XXX +} +#endif + +inline bool +to_cxx(Eina_Bool x, std::tuple, tag) +{ + return !!x; +} + +inline std::string +to_cxx(const char* x, std::tuple, tag) +{ + return std::string(x); +} + +template +struct traits +{ + typedef T type; +}; + +template +struct traits + ::value>::type> +{ + typedef Eo* type; +}; + +template +struct traits + , T>::value>::type> +{ + typedef const char* type; +}; + +template +inline efl::eina::range_ptr_list +to_cxx(const Eina_List* x, std::tuple, tag< efl::eina::range_ptr_list >) +{ + efl::eina::ptr_list list; + const Eina_List *l; + void *val; + EINA_LIST_FOREACH(x, l, val) + { + typedef typename traits::type type; + list.push_back(new T (to_cxx(static_cast(val), std::tuple() + , tag()))); + } + return list; +} + +template +inline efl::eina::range_ptr_list +to_cxx(Eina_List* x, std::tuple, tag< efl::eina::range_ptr_list >) +{ + efl::eina::ptr_list list; + Eina_List *l; + void *val; + EINA_LIST_FOREACH(x, l, val) + { + typedef typename traits::type type; + list.push_back(new T (to_cxx(static_cast(val), std::tuple() + , tag()))); + } + eina_list_free(x); + return list; +} + +template +inline efl::eina::ptr_list +to_cxx(Eina_List* x, std::tuple, tag< efl::eina::ptr_list >) +{ + efl::eina::ptr_list list; + Eina_List *l; + void *val; + EINA_LIST_FOREACH(x, l, val) + { + typedef typename traits::type type; + list.push_back(new T (to_cxx(static_cast(val), std::tuple() + , tag()))); + } + eina_list_free(x); + return list; +} + +inline eina::stringshare +to_cxx(Eina_Stringshare const* x, const std::false_type, tag) +{ + return ::eina_stringshare_ref(x); +} + +template +inline efl::eina::accessor +to_cxx(Eina_Accessor* x, std::tuple, tag< efl::eina::accessor >) +{ + return efl::eina::accessor(x); +} + +template +inline efl::eina::iterator +to_cxx(Eina_Iterator* x, std::tuple, tag< efl::eina::iterator >) +{ + return efl::eina::iterator(x); +} + +template +T to_cxx(U object, O o) +{ + return to_cxx(object, o, tag()); +} + +//// Callbacks + +template +R funcall(V* data, Args... args) +{ + F const* f = static_cast(data); + return (*f)(args...); +} + +template +struct callback_result_type; + +template +struct callback_result_type +{ + typedef R type; +}; + +template +struct callback_args_type; + +template +struct callback_args_type +{ + typedef std::tuple type; +}; + +template +C get_callback_impl(tag >) +{ + static_assert(std::is_same::type>::value, + "First argument of callback should be void* or const void*"); + return static_cast(&eolian::funcall); +} + +template +C get_callback() +{ + return get_callback_impl::type> + (tag::type>()); +} + +} } // namespace efl { namespace eolian { + +#endif // EFL_EOLIAN_INTEROP_HH diff --git a/src/bindings/eo_cxx/eo_event.hh b/src/bindings/eo_cxx/eo_event.hh new file mode 100644 index 0000000000..4d990ce39c --- /dev/null +++ b/src/bindings/eo_cxx/eo_event.hh @@ -0,0 +1,130 @@ + +/// +/// @file eo_event.hh +/// + +#ifndef EFL_CXX_EO_EVENT_HH +#define EFL_CXX_EO_EVENT_HH + +#include + +#include +#include + +namespace efl { namespace eo { + +typedef ::Eo_Callback_Priority callback_priority; +namespace callback_priorities +{ +static const callback_priority before = -100; +static const callback_priority default_ = 0; +static const callback_priority after = 100; +} + +struct signal_connection +{ + signal_connection(std::function deleter) + : _deleter(deleter) {} + void disconnect() + { + if(_deleter) + { + _deleter(); + _deleter = std::function(); + } + } +private: + std::function _deleter; + friend struct scoped_signal_connection; +}; + +struct scoped_signal_connection +{ + scoped_signal_connection(signal_connection const& other) + : _deleter(other._deleter) + { + } + ~scoped_signal_connection() + { + disconnect(); + } + void disconnect() + { + if(_deleter) + { + _deleter(); + _deleter = std::function(); + } + } + scoped_signal_connection(scoped_signal_connection&& other) + : _deleter(other._deleter) + { + other._deleter = std::function(); + } +private: + std::function _deleter; + + scoped_signal_connection& operator=(scoped_signal_connection const&) = delete; + scoped_signal_connection(scoped_signal_connection const&) = delete; +}; + +template +struct _event_deleter +{ + _event_deleter(F* data, Eo* eo, ::Eo_Event_Cb cb, Eo_Event_Description const* description) + : _data(data), _eo( ::eo_ref(eo)), _cb(cb), _description(description) + { + } + ~_event_deleter() + { + ::eo_unref(_eo); + } + _event_deleter(_event_deleter const& other) + : _data(other._data), _eo( ::eo_ref(other._eo)), _cb(other._cb), _description(other._description) + {} + _event_deleter& operator=(_event_deleter const& other) + { + ::eo_unref( _eo); + _data = other._data; + _eo = ::eo_ref(other._eo); + _cb = other._cb; + _description = other._description; + return *this; + } + + void operator()() const + { + eo_do(_eo, ::eo_event_callback_del(_description, _cb, _data)); + delete _data; + } + + F* _data; + Eo* _eo; + ::Eo_Event_Cb _cb; + Eo_Event_Description const* _description; +}; + +template +signal_connection make_signal_connection(std::unique_ptr& data, Eo* eo, ::Eo_Event_Cb cb, Eo_Event_Description const* description) +{ + signal_connection c(_event_deleter(data.get(), eo, cb, description)); + data.release(); + return std::move(c); +} + +namespace _detail { + +template +Eina_Bool +event_callback(void *data, Eo *obj, Eo_Event_Description const* desc, void *info) +{ + T wrapper(::eo_ref(obj)); + F *f = static_cast(data); + return (*f)(wrapper, *desc, info); +} + +} + +} } + +#endif diff --git a/src/lib/eolian_cxx/eo_types.hh b/src/lib/eolian_cxx/eo_types.hh index 4fba083430..bd6e7d9536 100644 --- a/src/lib/eolian_cxx/eo_types.hh +++ b/src/lib/eolian_cxx/eo_types.hh @@ -21,6 +21,142 @@ typedef std::vector functions_container_type; typedef std::vector parameters_container_type; typedef std::vector events_container_type; +struct eolian_type +{ + enum category_type + { + unknown_, simple_, complex_, callback_ + }; + + eolian_type() + : native("") + , category(unknown_) + , is_own(false) + , binding() + , includes() + {} + + eolian_type(std::string native_, + category_type category_, + bool is_own_, + std::string binding_, + includes_container_type includes_) + : native(native_) + , category(category_) + , is_own(is_own_) + , binding(binding_) + , includes(includes_) + { + assert(!native.empty()); + assert(category != unknown_); + } + + eolian_type(std::string native_, + category_type category_, + includes_container_type const& includes_) + : eolian_type(native_, category_, false, "", includes_) + { + assert(category == callback_); + } + + ~eolian_type() {} + + eolian_type(eolian_type const& other) + : native(other.native) + , category(other.category) + , is_own(other.is_own) + , binding(other.binding) + , includes(other.includes) + {} + + eolian_type& + operator=(eolian_type const& rhs) + { + native = rhs.native; + category = rhs.category; + is_own = rhs.is_own; + binding = rhs.binding; + includes = rhs.includes; + return *this; + } + + std::string native; + category_type category; + bool is_own; + std::string binding; + includes_container_type includes; +}; + +typedef std::vector eolian_type_instance; + +const efl::eolian::eolian_type +void_type { "void", efl::eolian::eolian_type::simple_, false, "", {} }; + +inline bool +type_is_void(eolian_type_instance const& type) +{ + return type.empty() || type[0].native.compare("void") == 0; +} + +inline bool +type_is_binding(eolian_type const& type) +{ + return !type.binding.empty(); +} + +inline bool +type_is_binding(eolian_type_instance const& type) +{ + assert(!type.empty()); + return type_is_binding(type.front()); +} + +inline eolian_type +type_to_native(eolian_type const& type) +{ + eolian_type native = type; + native.binding.clear(); + native.category = eolian_type::simple_; + return native; +} + +inline eolian_type +type_to_native(eolian_type_instance const& type_ins) +{ + assert(!type_ins.empty()); + return type_to_native(type_ins.front()); +} + +inline std::string +type_to_native_str(eolian_type_instance const& type_ins) +{ + return type_to_native(type_ins).native; +} + +inline bool +type_is_complex(eolian_type const& type) +{ + return type.category == eolian_type::complex_; +} + +template +inline bool +type_is_callback(T const&); + +template <> +inline bool +type_is_callback(eolian_type const& type) +{ + return type.category == eolian_type::callback_; +} + +template <> +inline bool +type_is_callback(eolian_type_instance const& type_ins) +{ + return type_is_callback(type_ins.front()); +} + struct eo_generator_options { includes_container_type cxx_headers; @@ -48,7 +184,7 @@ struct eo_class struct eo_parameter { - std::string type; + eolian_type_instance type; std::string name; }; @@ -68,15 +204,24 @@ struct eo_function eo_function_type type; std::string name; std::string impl; - std::string ret; + eolian_type_instance ret; parameters_container_type params; std::string comment; }; +struct eo_event +{ + std::string name; + std::string eo_name; + //parameters_container_type params; // XXX desirable. + std::string comment; +}; + + inline bool function_is_void(eo_function const& func) { - return func.ret.empty() || func.ret.compare("void") == 0; + return func.ret.empty() || func.ret[0].native.compare("void") == 0; } inline bool @@ -85,31 +230,28 @@ function_is_static(eo_function const& func) return func.type == eo_function::class_; } -struct eo_event +inline unsigned int +parameters_count_callbacks(parameters_container_type const& parameters) { - std::string name; - std::string eo_name; - std::string comment; -}; - - -// XXX mocked implementation. waiting for complex types... -typedef std::string eolian_type_instance; -typedef std::string eolian_type; -inline bool -type_is_void(eolian_type_instance const& type) -{ - return type.empty() || type.compare("void") == 0; + unsigned int r = 0u; + for (eo_parameter const& param : parameters) + if(type_is_callback(param.type)) + ++r; + return r; } -} } - -namespace eolian_cxx { -inline efl::eolian::eolian_type -type_to_native(efl::eolian::eolian_type const& type) +inline parameters_container_type::const_iterator +parameters_find_callback(parameters_container_type const& parameters) { - return type; + for (auto it = parameters.cbegin(), last = parameters.cend(); + it != last; ++it) + { + if (type_is_callback((*it).type)) + return it; } + return parameters.cend(); } +} } // namespace efl { namespace eolian { + #endif // EFL_EOLIAN_CXX_EO_TYPES_HH diff --git a/src/lib/eolian_cxx/eo_validate.hh b/src/lib/eolian_cxx/eo_validate.hh index 801c0e0d68..e317f8fde2 100644 --- a/src/lib/eolian_cxx/eo_validate.hh +++ b/src/lib/eolian_cxx/eo_validate.hh @@ -16,6 +16,39 @@ _is_valid(std::string const& value) return !value.empty() and isalpha(value[0]); } +inline bool +_is_valid(eolian_type_instance const& type) +{ + if (type.empty() || (*type.rbegin()).category == eolian_type::complex_) + return false; + for (auto rit = ++type.rbegin(), last = type.rend(); rit != last; ++rit) + { + if ((*rit).binding.empty() || (*rit).category != eolian_type::complex_) + return false; + else if (rit != type.rbegin() && (*rit).category != eolian_type::complex_) + return false; + } + return true; +} + +inline bool +_is_valid(parameters_container_type const& parameters) +{ + unsigned int n_callbacks = parameters_count_callbacks(parameters); + return n_callbacks == 0 || n_callbacks == 1; +} + +inline bool +_is_valid(events_container_type const& events) +{ + for (eo_event event : events) + { + if (event.name.empty() || event.eo_name.empty()) + return false; + } + return true; +} + template inline void _validate(T val, const eo_class& cls) @@ -44,6 +77,7 @@ eo_class_validate(const eo_class& cls) it != last; ++it) { _validate((*it).name, cls); + _validate((*it).params, cls); // parameters for (auto it_p = (*it).params.begin(), last_p = (*it).params.end(); it_p != last_p; ++it_p) @@ -59,6 +93,7 @@ eo_class_validate(const eo_class& cls) _validate((*it).name, cls); _validate((*it).impl, cls); _validate((*it).ret, cls); + _validate((*it).params, cls); // parameters for (auto it_p = (*it).params.begin(), last_p = (*it).params.end(); it_p != last_p; ++it_p) @@ -67,6 +102,8 @@ eo_class_validate(const eo_class& cls) _validate((*it_p).type, cls); } } + // events + _validate(cls.events, cls); } } } // namespace efl { namespace eolian { diff --git a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh index f434c560d0..f25a9a99af 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh @@ -114,14 +114,16 @@ operator<<(std::ostream& out, constructors const& x) for (it = first; it != last; ++it) { eo_constructor const& ctor = *it; - out << comment(ctor.comment, 1) - << tab(1) + out << comment(ctor.comment, 1); + if (parameters_count_callbacks(ctor.params)) + out << tab(1) << "template " << endl; + out << tab(1) << x._cls.name << '(' << parameters_declaration(ctor.params) << (ctor.params.size() > 0 ? ", " : "") << "efl::eo::parent_type _p = (efl::eo::parent = nullptr))" << endl << tab(2) << ": " << class_name(x._cls.name) - << "(_c" << (it - first) << "(" << parameters_list(ctor.params) + << "(_c" << (it - first) << "(" << parameters_cxx_list(ctor.params) << (ctor.params.size() > 0 ? ", " : "") << "_p))" << endl << tab(1) << "{}" << endl << endl; @@ -180,14 +182,26 @@ operator<<(std::ostream& out, eo_class_constructors const& x) last = x._cls.constructors.end(); for (it = first; it != last; ++it) { + if (parameters_count_callbacks((*it).params)) + out << tab(1) << "template " << endl; out << tab(1) << "static Eo* _c" << (it - first) << "(" << parameters_declaration((*it).params) << ((*it).params.size() > 0 ? ", " : "") << "efl::eo::parent_type _p" << ')' << endl - << tab(1) << "{" << endl - << tab(2) << "return eo_add_custom(" + << tab(1) << "{" << endl; + + parameters_container_type::const_iterator callback_iter = + parameters_find_callback((*it).params); + if (callback_iter != (*it).params.cend()) + { + out << tab(2) + << "F* _tmp_f = new F(std::move(" + << (*callback_iter).name << "));" + << endl; + } + out << tab(2) << "return eo_add_custom(" << x._cls.eo_name << ", _p._eo_raw, " << (*it).name << "(" << parameters_list((*it).params) << "));" << endl << tab(1) << "}" << endl << endl; diff --git a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh index fdb3a317b7..da796ae600 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh @@ -4,88 +4,76 @@ #include -#include // std::transform() -#include // ::toupper() - #include "eo_types.hh" #include "tab.hh" #include "comment.hh" -#include "parameters_generator.hh" namespace efl { namespace eolian { namespace grammar { struct event_callback_add { eo_event const& _event; - std::string const& _ev_name; - event_callback_add(eo_event const& event, std::string const& ev_name) - : _event(event), - _ev_name(ev_name) + eo_class const& _cls; + event_callback_add(eo_event const& event, eo_class const& cls) + : _event(event), _cls(cls) {} }; inline std::ostream& operator<<(std::ostream& out, event_callback_add const& x) { - // TODO implement - return out; -} - -struct event_callback_del -{ - eo_event const& _event; - std::string const& _ev_name; - event_callback_del(eo_event const& event, std::string const& ev_name) - : _event(event), - _ev_name(ev_name) - {} -}; - -inline std::ostream& -operator<<(std::ostream& out, event_callback_del const& x) -{ - // TODO: implement + out << tab(1) << "template " << endl + << tab(1) << "::efl::eo::signal_connection" << endl + << tab(1) << "event_" << x._event.name << "_callback_add(F && callback_," << endl + << tab(11) << "::efl::eo::callback_priority priority_ =" << endl + << tab(11) << "::efl::eo::callback_priorities::default_)" << endl + << tab(1) << "{" << endl + << tab(2) << "::std::unique_ptr f ( new F(std::move(callback_)) );" << endl + << tab(2) << "eo_do(_eo_ptr()," << endl + << tab(4) << "eo_event_callback_priority_add" << endl + << tab(4) << "(" << x._event.eo_name << ", priority_," << endl + << tab(4) << "&efl::eo::_detail::event_callback<" << x._cls.name << ", F>, f.get()));" << endl + << tab(2) << "return ::efl::eo::make_signal_connection" << endl + << tab(3) << "(f, this->_eo_ptr(), &efl::eo::_detail::event_callback<" << x._cls.name << ", F>," << endl + << tab(3) << x._event.eo_name << " );" << endl + << tab(1) << "}" << endl; return out; } struct event_callback_call { eo_event const& _event; - std::string const& _ev_name; - event_callback_call(eo_event const& event, std::string const& ev_name) - : _event(event), - _ev_name(ev_name) + event_callback_call(eo_event const& event) + : _event(event) {} }; inline std::ostream& operator<<(std::ostream& out, event_callback_call const& x) { - // TODO implement + out << tab(1) << "template " << endl + << tab(1) << "void" << endl + << tab(1) << "event_" << x._event.name << "_callback_call(T* info)" << endl + << tab(1) << "{" << endl + << tab(2) << "eo_do(_eo_ptr(), eo_event_callback_call" << endl + << tab(4) << "(" << x._event.eo_name << ", info));" << endl + << tab(1) << "}" << endl; return out; } struct events { - events_container_type const& _events; - events(events_container_type const& events) : _events(events) {} + eo_class const& _cls; + events(eo_class const& cls) : _cls(cls) {} }; inline std::ostream& operator<<(std::ostream& out, events const& x) { - std::string prefix = x._cls.name + "_EVENT_"; - std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper()); - events_container_type::const_iterator it, - first = x._events.begin(), - last = x._events.end(); - for (it = first; it != last; ++it) + for (eo_event const& e : x._cls.events) { - std::string ev_name = (*it).name; - std::transform(ev_name.begin(), ev_name.end(), ev_name.begin(), ::toupper()); - out << event_callback_add((*it), prefix+ev_name) - << event_callback_del((*it), prefix+ev_name) - << event_callback_call((*it), prefix+ev_name); + out << event_callback_add(e, x._cls) << endl + << event_callback_call(e); } return out; } diff --git a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh index 55675f36e6..015edf5371 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh @@ -8,6 +8,7 @@ #include "tab.hh" #include "comment.hh" #include "parameters_generator.hh" +#include "type_generator.hh" namespace efl { namespace eolian { namespace grammar { @@ -21,10 +22,9 @@ inline std::ostream& operator<<(std::ostream& out, function_call const& x) { bool is_void = function_is_void(x._func); - out << (!is_void ? "_tmp_ret = " : "") - << "::" << x._func.impl - << "(" << parameters_list(x._func.params) << ")"; - return out; + return out << (!is_void ? "_tmp_ret = " : "") + << "::" << x._func.impl + << "(" << parameters_list(x._func.params) << ")"; } struct function @@ -37,25 +37,30 @@ inline std::ostream& operator<<(std::ostream& out, function const& x) { eo_function const& func = x._func; - bool is_void = function_is_void(func); - out << comment(x._func.comment, 1) - << tab(1) - << ( func.type == eo_function::class_ ? "static " : "" ) - << func.ret << " " << func.name << "(" + + out << comment(x._func.comment, 1); + if (parameters_count_callbacks(x._func.params) == 1) + out << tab(1) << "template " << endl; + + if (function_is_static(func)) + out << tab(1) << "static "; + + out << tab(1) + << reinterpret_type(func.ret) << " " << func.name << "(" << parameters_declaration(func.params) << ") const" << endl << tab(1) << "{" << endl; - if (!is_void) - { - out << tab(2) << func.ret << " _tmp_ret;" << endl; - } - out << tab(2) << "eo_do(_eo_ptr(), " - << function_call(x._func) - << ");" << endl; - if (!is_void) - { - out << tab(2) << "return _tmp_ret;" << endl; - } + + if (!function_is_void(func)) + out << tab(2) + << func.ret.front().native << " _tmp_ret;" << endl; + + out << tab(2) + << "eo_do(_eo_ptr(), " << function_call(x._func) << ");" << endl; + + if (!function_is_void(func)) + out << tab(2) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl; + out << tab(1) << "}" << endl; return out; } diff --git a/src/lib/eolian_cxx/grammar/eo_class_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_generator.hh index af92bb41a9..2b2233bdb7 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_generator.hh @@ -10,6 +10,7 @@ #include "comment.hh" #include "eo_class_constructors_generator.hh" #include "eo_class_functions_generator.hh" +#include "eo_class_events_generator.hh" namespace efl { namespace eolian { namespace grammar { @@ -41,6 +42,7 @@ eo_class_generator(std::ostream& out, eo_class const& cls) << copy_constructor(cls) << destructor(cls) << functions(cls.functions) + << events(cls) << eo_class_getter(cls) << "private:" << endl << eo_class_constructors(cls) diff --git a/src/lib/eolian_cxx/grammar/eo_header_generator.hh b/src/lib/eolian_cxx/grammar/eo_header_generator.hh index f1a0fd8b88..3228f03692 100644 --- a/src/lib/eolian_cxx/grammar/eo_header_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_header_generator.hh @@ -38,6 +38,42 @@ _onceguard_key(efl::eolian::eo_class const& cls) namespace efl { namespace eolian { namespace grammar { +struct include_dependencies +{ + eo_class const& _cls; + include_dependencies(eo_class const& cls) + : _cls(cls) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, include_dependencies const& x) +{ + std::set headers; + eo_class const& cls = x._cls; + + for (auto it = cls.constructors.cbegin(), last = cls.constructors.cend(); + it != last; ++it) + for (auto it_p = (*it).params.begin(), last_p = (*it).params.end(); + it_p != last_p; ++it_p) + for (eolian_type const& subtype : (*it_p).type) + for (std::string header : subtype.includes) + headers.insert(header); + + for (auto it = cls.functions.begin(), last = cls.functions.end(); + it != last; ++it) + for (auto it_p = (*it).params.begin(), last_p = (*it).params.end(); + it_p != last_p; ++it_p) + for (eolian_type const& subtype : (*it_p).type) + for (std::string header : subtype.includes) + headers.insert(header); + + for (std::string header : headers) + out << "#include <" << header << ">" << endl; + + return out; +} + inline void onceguard_head(std::ostream& out, eo_class const& cls) { @@ -91,6 +127,7 @@ include_headers(std::ostream& out, eo_generator_options const& opts) { out << "#include " << endl << endl + << "#include " << endl << endl << "extern \"C\"" << endl << "{" << endl; for (auto c_header : opts.c_headers) @@ -102,6 +139,7 @@ include_headers(std::ostream& out, { out << "#include \"" << cxx_header << "\"" << endl; } + out << include_dependencies(cls) << endl; } inline void diff --git a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh index 2bc9a0e755..8f426a50c0 100644 --- a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh +++ b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh @@ -96,7 +96,7 @@ inline std::ostream& operator<<(std::ostream& out, inheritance_wrapper const& x) { out << "template " << endl - << x._func.ret << " " + << reinterpret_type(x._func.ret) << " " << _ns_as_prefix(x._cls) << "_" << x._cls.name << "_" << x._func.name << "_wrapper(Eo* objid EINA_UNUSED, " @@ -130,7 +130,7 @@ operator<<(std::ostream& out, inheritance_wrappers const& x) { eo_function const& func = *it; out << "template " << endl - << func.ret << " " + << reinterpret_type(func.ret) << " " << _ns_as_prefix(x._cls) << "_" << x._cls.name << "_" << func.name << "_wrapper(Eo* objid EINA_UNUSED, " @@ -186,13 +186,13 @@ operator<<(std::ostream& out, inheritance_base_operations_function const& x) eo_function const& func = x._func; bool is_void = function_is_void(func); - out << tab(2) << "virtual " << func.ret << " " + out << tab(2) << "virtual " << reinterpret_type(func.ret) << " " << func.name << "(" << parameters_declaration(func.params) << ")" << endl << tab(2) << "{" << endl; if (!is_void) { - out << tab(3) << func.ret << " _tmp_ret = {};" << endl; + out << tab(3) << reinterpret_type(func.ret) << " _tmp_ret = {};" << endl; } out << tab(3) << "eo_do_super(static_cast(this)->_eo_ptr()" << endl @@ -301,7 +301,7 @@ operator<<(std::ostream& out, inheritance_extension_function const& x) { bool is_void = function_is_void(x._func); out << tab(2) - << x._func.ret << " " + << reinterpret_type(x._func.ret) << " " << x._func.name << "(" << parameters_declaration(x._func.params) << ")" << endl @@ -309,7 +309,7 @@ operator<<(std::ostream& out, inheritance_extension_function const& x) if (!is_void) { - out << tab(3) << x._func.ret << " _tmp_ret = {};" << endl; + out << tab(3) << reinterpret_type(x._func.ret) << " _tmp_ret = {};" << endl; } out << tab(3) << "eo_do(static_cast(this)->_eo_ptr(), " diff --git a/src/lib/eolian_cxx/grammar/parameters_generator.hh b/src/lib/eolian_cxx/grammar/parameters_generator.hh index 644c1a58c9..9f6f3e5e0b 100644 --- a/src/lib/eolian_cxx/grammar/parameters_generator.hh +++ b/src/lib/eolian_cxx/grammar/parameters_generator.hh @@ -6,6 +6,7 @@ #include "tab.hh" #include "eo_types.hh" +#include "type_generator.hh" namespace efl { namespace eolian { namespace grammar { @@ -21,12 +22,20 @@ parameters_declaration inline std::ostream& operator<<(std::ostream& out, parameters_declaration const& x) { - parameters_container_type::const_iterator it, first = x._params.cbegin(); - parameters_container_type::const_iterator last = x._params.cend(); - for (it = first; it != last; ++it) + auto first = x._params.cbegin(), + last = x._params.cend(); + for (auto it = first; it != last; ++it) { - if (it != first) out << ", "; - out << (*it).type << " " << (*it).name; + if (it != first) + out << ", "; + if (type_is_callback((*it).type)) + { + out << "F && " << (*it).name; + assert(it+1 != last); + ++it; // skip next. + } + else + out << reinterpret_type((*it).type) << " " << (*it).name; } return out; } @@ -49,7 +58,7 @@ operator<<(std::ostream& out, parameters_types const& x) for (it = first; it != last; ++it) { if(it != first) out << ", "; - out << (*it).type; + out << reinterpret_type((*it).type); } return out; } @@ -66,16 +75,52 @@ parameters_list inline std::ostream& operator<<(std::ostream& out, parameters_list const& x) { - parameters_container_type::const_iterator it, first = x._params.cbegin(); - parameters_container_type::const_iterator last = x._params.cend(); - for (it = first; it != last; ++it) + auto first = x._params.cbegin(), last = x._params.cend(); + for (auto it = first; it != last; ++it) { - if (it != first) out << ", "; - out << (*it).name; + if (it != first) + out << ", "; + out << to_c((*it).type, (*it).name); + if (type_is_callback((*it).type)) + { + out << ", _tmp_f"; + ++it; // skip next + } } return out; } +struct +parameters_cxx_list +{ + parameters_container_type const& _params; + parameters_cxx_list(parameters_container_type const& params) + : _params(params) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, parameters_cxx_list const& x) +{ + auto first = x._params.cbegin(), + last = x._params.cend(); + for (auto it = first; it != last; ++it) + { + if (it != first) + out << ", "; + if (type_is_callback((*it).type)) + { + out << "std::move(" << (*it).name << ")"; + assert(it+1 != last); + ++it; // skip next. + } + else + out << (*it).name; + } + return out; +} + + } } } // namespace efl { namespace eolian { namespace grammar { diff --git a/src/lib/eolian_cxx/grammar/type_generator.hh b/src/lib/eolian_cxx/grammar/type_generator.hh new file mode 100644 index 0000000000..1ca5a6631a --- /dev/null +++ b/src/lib/eolian_cxx/grammar/type_generator.hh @@ -0,0 +1,106 @@ + +#ifndef EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH +#define EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH + +#include +#include + +#include "eo_types.hh" + +namespace efl { namespace eolian { namespace grammar { + +using std::endl; + +struct reinterpret_type +{ + eolian_type_instance const& _list; + reinterpret_type(eolian_type_instance const& list) + : _list(list) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x) +{ + assert(x._list.size() > 0); + std::string res; + for (auto rit = x._list.rbegin(), last = x._list.rend(); rit != last; ++rit) + { + if (type_is_complex(*rit)) + res = (*rit).binding + "< " + res + " >"; + else + res = type_is_binding(*rit) ? (*rit).binding : (*rit).native; + } + assert(!res.empty()); + return out << res; +} + +struct type_ownership +{ + eolian_type_instance const& _type; + type_ownership(eolian_type_instance const& type) + : _type(type) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, type_ownership const& x) +{ + out << "std::tuple<"; + for (auto it=x._type.begin(), last=x._type.end(); it != last; ++it) + { + if (it != x._type.begin()) + out << ", "; + out << ((*it).is_own ? "std::true_type" : "std::false_type"); + } + return out << ">()"; +} + +struct to_cxx +{ + eolian_type_instance const& _type; + std::string const& _varname; + to_cxx(eolian_type_instance const& type, std::string const& varname) + : _type(type), _varname(varname) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, to_cxx const& x) +{ + if (type_is_binding(x._type)) + { + out << "efl::eolian::to_cxx<" + << reinterpret_type(x._type) + << ">(" << x._varname + << ", " << type_ownership(x._type) << ");"; + } + else + out << "_ret"; + return out; +} + +struct to_c +{ + eolian_type_instance const& _type; + std::string const& _varname; + to_c(eolian_type_instance const& type, std::string const& varname) + : _type(type), _varname(varname) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, to_c const& x) +{ + if (type_is_callback(x._type)) + out << "efl::eolian::get_callback<" << type_to_native_str(x._type) << ", F>()"; + else if (type_is_binding(x._type)) + out << "efl::eolian::to_c(" << x._varname << ")"; + else + out << x._varname; + return out; +} + +} } } + +#endif // EOLIAN_CXX_GRAMMAR_TYPE_GENERATOR_HH