diff --git a/.gitignore b/.gitignore index 4f048401f4..1da486ee1b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ tags *.eo.h *.eo.legacy.h *.eo.hh +*.eo.impl.hh *.eo.lua *.luac .dir-locals.el diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index f18cc4f77b..b4afaf42e7 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -667,7 +667,7 @@ EXCLUDE_PATTERNS = *_private* # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = eo_cxx::* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see @@ -1441,7 +1441,9 @@ PREDEFINED = EINA_MAGIC_DEBUG \ EAPI= \ EINA_PURE= \ EINA_CONST= \ - EINA_UNUSED= + EINA_UNUSED= \ + EFL_DOXYGEN=1 \ + "EO_CXX_INHERIT(name)=::name" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/src/Makefile_Ecore_Audio_Cxx.am b/src/Makefile_Ecore_Audio_Cxx.am index 498bcbf887..bf564d2c94 100644 --- a/src/Makefile_Ecore_Audio_Cxx.am +++ b/src/Makefile_Ecore_Audio_Cxx.am @@ -20,6 +20,13 @@ lib/ecore_audio/Ecore_Audio.hh: $(generated_ecore_audio_cxx_bindings) generated_ecore_audio_cxx_all = \ $(generated_ecore_audio_cxx_bindings) \ + lib/ecore_audio/ecore_audio.eo.impl.hh \ + lib/ecore_audio/ecore_audio_in.eo.impl.hh \ + lib/ecore_audio/ecore_audio_out.eo.impl.hh \ + lib/ecore_audio/ecore_audio_in_sndfile.eo.impl.hh \ + lib/ecore_audio/ecore_audio_out_sndfile.eo.impl.hh \ + lib/ecore_audio/ecore_audio_out_pulse.eo.impl.hh \ + lib/ecore_audio/ecore_audio_in_tone.eo.impl.hh \ lib/ecore_audio/Ecore_Audio.hh CLEANFILES += $(generated_ecore_audio_cxx_all) diff --git a/src/Makefile_Ecore_Cxx.am b/src/Makefile_Ecore_Cxx.am index d81651a6b1..b29a1c4868 100644 --- a/src/Makefile_Ecore_Cxx.am +++ b/src/Makefile_Ecore_Cxx.am @@ -22,6 +22,12 @@ lib/ecore/Ecore.eo.hh: $(generated_ecore_cxx_bindings) generated_ecore_cxx_all = \ $(generated_ecore_cxx_bindings) \ + lib/ecore/ecore_poller.eo.impl.hh \ + lib/ecore/ecore_job.eo.impl.hh \ + lib/ecore/ecore_idler.eo.impl.hh \ + lib/ecore/ecore_idle_exiter.eo.impl.hh \ + lib/ecore/ecore_animator.eo.impl.hh \ + lib/ecore/ecore_parent.eo.impl.hh \ lib/ecore/Ecore.eo.hh CLEANFILES += $(generated_ecore_cxx_all) diff --git a/src/Makefile_Edje_Cxx.am b/src/Makefile_Edje_Cxx.am index 8d6b068e98..0b308b0499 100644 --- a/src/Makefile_Edje_Cxx.am +++ b/src/Makefile_Edje_Cxx.am @@ -15,6 +15,8 @@ lib/edje/Edje.hh: $(generated_edje_cxx_bindings) generated_edje_cxx_all = \ $(generated_edje_cxx_bindings) \ + lib/edje/edje_object.eo.impl.hh \ + lib/edje/edje_edit.eo.impl.hh \ lib/edje/Edje.hh CLEANFILES += $(generated_edje_cxx_all) diff --git a/src/Makefile_Efl_Cxx.am b/src/Makefile_Efl_Cxx.am index 9df7c60bdd..c555015729 100644 --- a/src/Makefile_Efl_Cxx.am +++ b/src/Makefile_Efl_Cxx.am @@ -26,6 +26,12 @@ lib/efl/Efl.hh: $(generated_efl_cxx_bindings) generated_efl_cxx_all = \ $(generated_efl_cxx_bindings) \ + lib/efl/interfaces/efl_control.eo.impl.hh \ + lib/efl/interfaces/efl_file.eo.impl.hh \ + lib/efl/interfaces/efl_image.eo.impl.hh \ + lib/efl/interfaces/efl_player.eo.impl.hh \ + lib/efl/interfaces/efl_text.eo.impl.hh \ + lib/efl/interfaces/efl_text_properties.eo.impl.hh \ lib/efl/Efl.hh CLEANFILES += $(generated_efl_cxx_all) diff --git a/src/Makefile_Eo_Cxx.am b/src/Makefile_Eo_Cxx.am index 2f7dda6ada..b6315c8746 100644 --- a/src/Makefile_Eo_Cxx.am +++ b/src/Makefile_Eo_Cxx.am @@ -3,7 +3,9 @@ generated_eo_cxx_bindings = \ lib/eo/eo_base.eo.hh \ -lib/eo/eo_abstract_class.eo.hh +lib/eo/eo_base.eo.impl.hh \ +lib/eo/eo_abstract_class.eo.hh \ +lib/eo/eo_abstract_class.eo.impl.hh ### Library diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am index cd58e3e9c1..6dff2671df 100644 --- a/src/Makefile_Eolian_Cxx.am +++ b/src/Makefile_Eolian_Cxx.am @@ -15,6 +15,7 @@ lib/eolian_cxx/eo_validate.hh installed_eoliancxxgrammarheadersdir = $(includedir)/eolian-cxx-@VMAJ@/grammar/ dist_installed_eoliancxxgrammarheaders_DATA = \ lib/eolian_cxx/grammar/comment.hh \ +lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh \ lib/eolian_cxx/grammar/eo_class_constructors_generator.hh \ lib/eolian_cxx/grammar/eo_class_events_generator.hh \ lib/eolian_cxx/grammar/eo_class_functions_generator.hh \ @@ -95,10 +96,11 @@ tests/eolian_cxx/callback.eo.h \ tests/eolian_cxx/simple.eo.c \ tests/eolian_cxx/simple.eo.h \ tests/eolian_cxx/simple.eo.hh \ -tests/eolian_cxx/a.eo.hh tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h \ -tests/eolian_cxx/b.eo.hh tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h \ -tests/eolian_cxx/c.eo.hh tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h \ -tests/eolian_cxx/d.eo.hh tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h +tests/eolian_cxx/simple.eo.impl.hh \ +tests/eolian_cxx/a.eo.hh tests/eolian_cxx/a.eo.impl.hh tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h \ +tests/eolian_cxx/b.eo.hh tests/eolian_cxx/b.eo.impl.hh tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h \ +tests/eolian_cxx/c.eo.hh tests/eolian_cxx/c.eo.impl.hh tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h \ +tests/eolian_cxx/d.eo.hh tests/eolian_cxx/d.eo.impl.hh tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \ -I$(top_builddir)/src/lib/efl \ diff --git a/src/Makefile_Eolian_Cxx_Helper.am b/src/Makefile_Eolian_Cxx_Helper.am index cb54cc4c12..bb656c8f28 100644 --- a/src/Makefile_Eolian_Cxx_Helper.am +++ b/src/Makefile_Eolian_Cxx_Helper.am @@ -15,4 +15,7 @@ SUFFIXES += .eo.hh %.eo.hh: %.eo $(_EOLIAN_CXX_DEP) $(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -o $@ $< +%.eo.impl.hh: %.eo.hh $(_EOLIAN_CXX_DEP) + true $< + CLEANFILES += $(BUILT_SOURCES) diff --git a/src/Makefile_Evas_Cxx.am b/src/Makefile_Evas_Cxx.am index 96d5ab13b3..abe1aa6a9c 100644 --- a/src/Makefile_Evas_Cxx.am +++ b/src/Makefile_Evas_Cxx.am @@ -49,15 +49,48 @@ lib/evas/Evas.hh: $(generated_evas_canvas_cxx_bindings) @for i in $(generated_evas_canvas_cxx_bindings); do echo "#include " >> $(top_builddir)/src/lib/evas/Evas.hh; done @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/evas/Evas.hh -CLEANFILES += \ +generated_evas_canvas_cxx_all = \ $(generated_evas_canvas_cxx_bindings) \ +lib/evas/canvas/evas_line.eo.impl.hh \ +lib/evas/canvas/evas_polygon.eo.impl.hh \ +lib/evas/canvas/evas_rectangle.eo.impl.hh \ +lib/evas/canvas/evas_text.eo.impl.hh \ +lib/evas/canvas/evas_textblock.eo.impl.hh \ +lib/evas/canvas/evas_textgrid.eo.impl.hh \ +lib/evas/canvas/evas_signal_interface.eo.impl.hh \ +lib/evas/canvas/evas_object_smart.eo.impl.hh \ +lib/evas/canvas/evas_smart_clipped.eo.impl.hh \ +lib/evas/canvas/evas_table.eo.impl.hh \ +lib/evas/canvas/evas_common_interface.eo.impl.hh \ +lib/evas/canvas/evas_object.eo.impl.hh \ +lib/evas/canvas/evas_canvas.eo.impl.hh \ +lib/evas/canvas/evas_grid.eo.impl.hh \ +lib/evas/canvas/evas_image.eo.impl.hh \ +lib/evas/canvas/evas_out.eo.impl.hh \ +lib/evas/canvas/evas_draggable_interface.eo.impl.hh \ +lib/evas/canvas/evas_clickable_interface.eo.impl.hh \ +lib/evas/canvas/evas_scrollable_interface.eo.impl.hh \ +lib/evas/canvas/evas_selectable_interface.eo.impl.hh \ +lib/evas/canvas/evas_zoomable_interface.eo.impl.hh \ +lib/evas/canvas/evas_box.eo.impl.hh \ +lib/evas/canvas/evas_3d_camera.eo.impl.hh \ +lib/evas/canvas/evas_3d_light.eo.impl.hh \ +lib/evas/canvas/evas_3d_material.eo.impl.hh \ +lib/evas/canvas/evas_3d_mesh.eo.impl.hh \ +lib/evas/canvas/evas_3d_node.eo.impl.hh \ +lib/evas/canvas/evas_3d_object.eo.impl.hh \ +lib/evas/canvas/evas_3d_scene.eo.impl.hh \ +lib/evas/canvas/evas_3d_texture.eo.impl.hh \ lib/evas/Evas.hh +CLEANFILES += \ +$(generated_evas_canvas_cxx_all) + installed_evascxxmainheadersdir = $(includedir)/evas-cxx-@VMAJ@/ nodist_installed_evascxxmainheaders_DATA = lib/evas/Evas.hh installed_evascxxcanvasheadersdir = $(includedir)/evas-cxx-@VMAJ@/canvas -nodist_installed_evascxxcanvasheaders_DATA = $(generated_evas_canvas_cxx_bindings) +nodist_installed_evascxxcanvasheaders_DATA = $(generated_evas_canvas_cxx_all) ### Unit tests diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc index d029999411..22ee22f0e5 100644 --- a/src/bin/eolian_cxx/convert.cc +++ b/src/bin/eolian_cxx/convert.cc @@ -141,6 +141,7 @@ _convert_property_set_to_function(Eolian_Class const& klass, efl::eolian::eo_function set_ = { efl::eolian::eo_function::regular_, + function_scope(prop_), function_name(prop_) + "_set", function_impl(prop_) + "_set", function_return_type(prop_, eolian_cxx::setter), @@ -168,6 +169,7 @@ _convert_property_get_to_function(Eolian_Class const& klass, efl::eolian::eo_function get_ = { efl::eolian::eo_function::regular_, + function_scope(prop_), function_name(prop_) + "_get", function_impl(prop_) + "_get", function_return_type(prop_, eolian_cxx::getter), @@ -291,6 +293,7 @@ convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass) { cls.functions.push_back({ function_type(func), + function_scope(func), function_name(func), function_impl(func), function_return_type(func), diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc index 93e9e442ab..7afa10da10 100644 --- a/src/bin/eolian_cxx/eolian_cxx.cc +++ b/src/bin/eolian_cxx/eolian_cxx.cc @@ -119,30 +119,58 @@ generate(const Eolian_Class& klass, eolian_cxx::options_type const& opts) { efl::eolian::eo_class cls = eolian_cxx::convert_eolian_class(klass); efl::eolian::eo_generator_options gen_opts = generator_options(klass); - std::string outname = opts.out_file.empty() ? (class_base_file(klass) + ".hh") : opts.out_file; + std::string header_decl_file_name = opts.out_file.empty() ? (class_base_file(klass) + ".hh") : opts.out_file; + + std::string header_impl_file_name = header_decl_file_name; + std::size_t dot_pos = header_impl_file_name.rfind(".hh"); + if (dot_pos != std::string::npos) + header_impl_file_name.insert(dot_pos, ".impl"); + else + header_impl_file_name.insert(header_impl_file_name.size(), ".impl"); + + std::size_t slash_pos = header_decl_file_name.rfind('/'); + gen_opts.header_decl_file_name = (slash_pos == std::string::npos) ? + header_decl_file_name : + header_decl_file_name.substr(slash_pos+1); + + slash_pos = header_impl_file_name.rfind('/'); + gen_opts.header_impl_file_name = (slash_pos == std::string::npos) ? + header_impl_file_name : + header_impl_file_name.substr(slash_pos+1); + if (!opts.out_dir.empty()) { - outname = opts.out_dir + "/" + outname; + header_decl_file_name = opts.out_dir + "/" + header_decl_file_name; + header_impl_file_name = opts.out_dir + "/" + header_impl_file_name; } if(opts.out_file == "-") { - efl::eolian::generate(std::cout, cls, gen_opts); + efl::eolian::generate(std::cout, std::cout, cls, gen_opts); } else { - std::ofstream outfile; - outfile.open(outname); - if (outfile.good()) - { - efl::eolian::generate(outfile, cls, gen_opts); - outfile.close(); - } - else + std::ofstream header_decl; + header_decl.open(header_decl_file_name); + if (!header_decl.good()) { EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) - << "Can't open output file: " << outname << std::endl; + << "Can't open output file: " << header_decl_file_name << std::endl; return false; } + + std::ofstream header_impl; + header_impl.open(header_impl_file_name); + if (!header_impl.good()) + { + EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) + << "Can't open output file: " << header_impl_file_name << std::endl; + return false; + } + + efl::eolian::generate(header_decl, header_impl, cls, gen_opts); + + header_decl.close(); + header_impl.close(); } return true; } diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh index d1b28a6f5f..5cad7976c0 100644 --- a/src/bin/eolian_cxx/eolian_wrappers.hh +++ b/src/bin/eolian_cxx/eolian_wrappers.hh @@ -25,6 +25,15 @@ getter_t const getter = {}; struct method_t { static constexpr ::Eolian_Function_Type value = ::EOLIAN_METHOD; }; method_t const method = {}; +inline efl::eolian::eolian_scope +eolian_scope_cxx(Eolian_Object_Scope s) +{ + using efl::eolian::eolian_scope; + return s == EOLIAN_SCOPE_PRIVATE ? eolian_scope::private_ : + s == EOLIAN_SCOPE_PROTECTED ? eolian_scope::protected_ : + eolian_scope::public_; +} + inline const Eolian_Class* class_from_file(std::string const& file) { @@ -195,11 +204,18 @@ function_is_constructor(Eolian_Class const& cls, Eolian_Function const& func) return ::eolian_function_is_constructor(&func, &cls); } +inline efl::eolian::eolian_scope +function_scope(Eolian_Function const& func) +{ + return eolian_scope_cxx(::eolian_function_scope_get(&func)); +} + inline bool function_is_visible(Eolian_Function const& func, Eolian_Function_Type func_type) { - return (::eolian_function_scope_get(&func) == EOLIAN_SCOPE_PUBLIC && - ! ::eolian_function_is_legacy_only(&func, func_type)); + Eolian_Object_Scope s = ::eolian_function_scope_get(&func); + return ((s == EOLIAN_SCOPE_PUBLIC || s == EOLIAN_SCOPE_PROTECTED) && + !::eolian_function_is_legacy_only(&func, func_type)); } inline bool @@ -388,6 +404,7 @@ event_create(Eolian_Class const& klass, const Eolian_Event *event_) std::string name_ = safe_str(name); std::transform(name_.begin(), name_.end(), name_.begin(), [](int c) { return c != ',' ? c : '_'; }); + event.scope = eolian_scope_cxx(::eolian_event_scope_get(event_)); event.name = normalize_spaces(name_); event.eo_name = safe_upper (find_replace(class_full_name(klass), ".", "_") + "_EVENT_" + event.name); diff --git a/src/bin/eolian_cxx/type_lookup_table.cc b/src/bin/eolian_cxx/type_lookup_table.cc index 7fa085e9ba..dd005518fb 100644 --- a/src/bin/eolian_cxx/type_lookup_table.cc +++ b/src/bin/eolian_cxx/type_lookup_table.cc @@ -13,25 +13,25 @@ type_lookup_table {"Ecore_Task_Cb", eolian_type::callback_, {"Ecore.h"}}, {"Ecore_Timeline_Cb", eolian_type::callback_, {"Ecore.h"}}, {"Edje_Signal_Cb", eolian_type::callback_, {"Edje.h"}}, - {"Eina_Accessor *", eolian_type::complex_, false, false, true, "::efl::eina::accessor", {"eina-cxx/eina_accessor.hh"}}, - {"Eina_Bool", eolian_type::simple_, false, false, false, "bool", {}}, - {"Eina_Bool *", eolian_type::simple_, false, false, false, "bool*", {}}, - {"Eina_Inlist *", eolian_type::complex_, false, false, true, "::efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, - {"Eina_Inlist *", eolian_type::complex_, false, true, true, "::efl::eina::inlist", {"eina-cxx/eina_inlist.hh"}}, - {"Eina_Iterator *", eolian_type::complex_, false, false, true, "::efl::eina::iterator", {"eina-cxx/eina_iterator.hh"}}, - {"Eina_List *", eolian_type::complex_, false, false, true, "::efl::eina::range_list", {"eina-cxx/eina_list.hh"}}, - {"Eina_List *", eolian_type::complex_, false, true, true, "::efl::eina::list", {"eina-cxx/eina_list.hh"}}, - {"const Eina_List *", eolian_type::complex_, true, false, true, "::efl::eina::crange_list", {"eina-cxx/eina_list.hh"}}, + {"Eina_Accessor *", eolian_type::complex_, false, false, true, false, "::efl::eina::accessor", {"eina-cxx/eina_accessor.hh"}}, + {"Eina_Bool", eolian_type::simple_, false, false, false, false, "bool", {}}, + {"Eina_Bool *", eolian_type::simple_, false, false, false, false, "bool*", {}}, + {"Eina_Inlist *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, + {"Eina_Inlist *", eolian_type::complex_, false, true, true, true, "::efl::eina::inlist", {"eina-cxx/eina_inlist.hh"}}, + {"Eina_Iterator *", eolian_type::complex_, false, false, true, true, "::efl::eina::iterator", {"eina-cxx/eina_iterator.hh"}}, + {"Eina_List *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_list", {"eina-cxx/eina_list.hh"}}, + {"Eina_List *", eolian_type::complex_, false, true, true, true, "::efl::eina::list", {"eina-cxx/eina_list.hh"}}, + {"const Eina_List *", eolian_type::complex_, true, false, true, true, "::efl::eina::crange_list", {"eina-cxx/eina_list.hh"}}, {"Eio_Filter_Direct_Cb", eolian_type::callback_, {"Eio.h"}}, - {"Emodel *", eolian_type::simple_, false, false, true, "::emodel", {"Emodel.hh"}}, - {"Eo *", eolian_type::simple_, false, true, true, "::efl::eo::concrete", {"eo_concrete.hh"}}, - {"Eo *", eolian_type::simple_, false, false, true, "::efl::eo::concrete", {"eo_concrete.hh"}}, + {"Emodel *", eolian_type::simple_, false, false, true, false, "::emodel", {"Emodel.hh"}}, + {"Eo *", eolian_type::simple_, false, true, true, false, "::efl::eo::concrete", {"eo_concrete.hh"}}, + {"Eo *", eolian_type::simple_, false, false, true, false, "::efl::eo::concrete", {"eo_concrete.hh"}}, //{"Evas_Object_Box_Layout", eolian_type::callback_, {"Evas.h"}}, - {"Evas_Object *", eolian_type::simple_, false, false, true, "::evas::object", {"canvas/evas_object.eo.hh"}}, - {"char *", eolian_type::simple_, false, true, true, "std::unique_ptr", {"memory"}}, - {"const Eina_Inlist *", eolian_type::complex_, false, false, true, "::efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, - {"const Eina_List *", eolian_type::complex_, false, false, true, "::efl::eina::range_list", {"eina-cxx/eina_ptrlist.hh"}}, - {"const char *", eolian_type::simple_, false, false, true, "std::string", {"string"}}, + {"Evas_Object *", eolian_type::simple_, false, false, true, false, "::evas::object", {"canvas/evas_object.eo.hh"}}, + {"char *", eolian_type::simple_, false, true, true, false, "std::unique_ptr", {"memory"}}, + {"const Eina_Inlist *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_inlist", {"eina-cxx/eina_inlist.hh"}}, + {"const Eina_List *", eolian_type::complex_, false, false, true, true, "::efl::eina::range_list", {"eina-cxx/eina_ptrlist.hh"}}, + {"const char *", eolian_type::simple_, false, false, true, true, "::efl::eina::string_view", {"string"}}, }; } diff --git a/src/bindings/eo_cxx/eo_concrete.hh b/src/bindings/eo_cxx/eo_concrete.hh index 63029a14e7..9e328b1d92 100644 --- a/src/bindings/eo_cxx/eo_concrete.hh +++ b/src/bindings/eo_cxx/eo_concrete.hh @@ -21,6 +21,12 @@ #endif #endif +#if !defined(EFL_DOXYGEN) && !defined(EO_CXX_INHERIT) +# define EO_CXX_INHERIT(name) ::eo_cxx::name +#elif !defined(EO_CXX_INHERIT) +# define EO_CXX_INHERIT(name) ::name +#endif + namespace efl { namespace eo { /// @addtogroup Efl_Cxx_API diff --git a/src/bindings/eo_cxx/eo_cxx_interop.hh b/src/bindings/eo_cxx/eo_cxx_interop.hh index ba6a473fc6..08ca3005ba 100644 --- a/src/bindings/eo_cxx/eo_cxx_interop.hh +++ b/src/bindings/eo_cxx/eo_cxx_interop.hh @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -27,6 +28,20 @@ to_c(eina::optional const& x) return x->c_str(); } +inline const char* +to_c(eina::string_view const& x) +{ + return x.data(); +} + +inline const char* +to_c(eina::optional const& x) +{ + if (!x) + return nullptr; + return x->data(); +} + inline const char* to_c(efl::eina::stringshare const& x) { @@ -196,6 +211,20 @@ to_cxx(const char* x, std::tuple, tag, tag) +{ + return eina::string_view(x); +} + +inline eina::optional +to_cxx(const char* x, std::tuple, tag >) +{ + if (!x) + return nullptr; + return eina::string_view(x); +} + template struct traits { @@ -216,6 +245,13 @@ struct traits typedef const char* type; }; +template +struct traits + , T>::value>::type> +{ + typedef const char* type; +}; + template inline efl::eina::range_list to_cxx(const Eina_List* x, std::tuple, tag< efl::eina::range_list >) @@ -407,6 +443,22 @@ Eina_Bool free_callback_calback(void* data, Eo* obj EINA_UNUSED return EO_CALLBACK_CONTINUE; } +template +inline +std::vector& get_static_callback_vector() +{ + static std::vector vec; + return vec; +} + +template +inline +F* alloc_static_callback(F&& f) +{ + get_static_callback_vector().push_back(std::forward(f)); + return &(get_static_callback_vector().back()); +} + } } // namespace efl { namespace eolian { #endif // EFL_EOLIAN_INTEROP_HH diff --git a/src/examples/eolian_cxx/Makefile.am b/src/examples/eolian_cxx/Makefile.am index a0510f1d57..78420952a1 100644 --- a/src/examples/eolian_cxx/Makefile.am +++ b/src/examples/eolian_cxx/Makefile.am @@ -66,9 +66,11 @@ GENERATED = \ colourable.eo.c \ colourable.eo.h \ colourable.eo.hh \ + colourable.eo.impl.hh \ colourablesquare.eo.c \ colourablesquare.eo.h \ - colourablesquare.eo.hh + colourablesquare.eo.hh \ + colourablesquare.eo.impl.hh BUILT_SOURCES = $(GENERATED) CLEANFILES += $(BUILT_SOURCES) @@ -135,6 +137,9 @@ eolian_cxx_complex_types_01_SOURCES = eolian_cxx_complex_types_01.cc %.eo.hh: %.eo $(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -I${abs_srcdir} -o $@ $< +%.eo.impl.hh: %.eo.hh + true $< + %.eo.c: %.eo $(AM_V_EOL)$(EOLIAN_GEN) --eo --legacy $(EOLIAN_FLAGS) --gc -o $@ $< diff --git a/src/lib/eolian_cxx/eo_generate.hh b/src/lib/eolian_cxx/eo_generate.hh index a509201baa..97e53bb9dc 100644 --- a/src/lib/eolian_cxx/eo_generate.hh +++ b/src/lib/eolian_cxx/eo_generate.hh @@ -10,9 +10,12 @@ namespace efl { namespace eolian { inline void -generate(std::ostream& out, eo_class const& cls, eo_generator_options const& opts) +generate(std::ostream& header_decl, + std::ostream& header_impl, + eo_class const& cls, + eo_generator_options const& opts) { - grammar::eo_header_generator(out, cls, opts); + grammar::eo_headers_generator(header_decl, header_impl, cls, opts); } } } diff --git a/src/lib/eolian_cxx/eo_types.hh b/src/lib/eolian_cxx/eo_types.hh index 38f2d38127..b50e692ac1 100644 --- a/src/lib/eolian_cxx/eo_types.hh +++ b/src/lib/eolian_cxx/eo_types.hh @@ -21,6 +21,12 @@ typedef std::vector functions_container_type; typedef std::vector parameters_container_type; typedef std::vector events_container_type; + +enum class eolian_scope + { + public_, protected_, private_ + }; + struct eolian_type { enum category_type @@ -34,6 +40,7 @@ struct eolian_type , is_const(false) , is_own(false) , is_class(false) + , binding_requires_optional(false) , binding() , includes() {} @@ -43,6 +50,7 @@ struct eolian_type bool is_const_, bool is_own_, bool is_class_, + bool binding_requires_optional_, std::string binding_, includes_container_type includes_) : native(native_) @@ -50,6 +58,7 @@ struct eolian_type , is_const(is_const_) , is_own(is_own_) , is_class(is_class_) + , binding_requires_optional(binding_requires_optional_) , binding(binding_) , includes(includes_) { @@ -60,7 +69,7 @@ struct eolian_type eolian_type(std::string native_, category_type category_, includes_container_type const& includes_) - : eolian_type(native_, category_, false, false, false, "", includes_) + : eolian_type(native_, category_, false, false, false, false, "", includes_) { assert(category == callback_); } @@ -70,6 +79,7 @@ struct eolian_type bool is_const; bool is_own; bool is_class; + bool binding_requires_optional; std::string binding; includes_container_type includes; }; @@ -110,7 +120,7 @@ struct eolian_type_instance }; const efl::eolian::eolian_type -void_type { "void", efl::eolian::eolian_type::simple_, false, false, false, "", {} }; +void_type { "void", efl::eolian::eolian_type::simple_, false, false, false, false, "", {} }; inline bool type_is_void(eolian_type_instance const& type) @@ -150,6 +160,19 @@ type_is_class(eolian_type_instance const& type) return type_is_class(type.front()); } +inline bool +type_binding_requires_optional(eolian_type const& type) +{ + return type.binding_requires_optional; +} + +inline bool +type_binding_requires_optional(eolian_type_instance const& type) +{ + assert(!type.empty()); + return type_binding_requires_optional(type.front()); +} + inline bool type_is_nonull(eolian_type_instance const& type) { @@ -212,6 +235,8 @@ type_is_callback(eolian_type_instance const& type_ins) struct eo_generator_options { + std::string header_decl_file_name; + std::string header_impl_file_name; includes_container_type cxx_headers; includes_container_type c_headers; }; @@ -256,6 +281,7 @@ struct eo_function regular_, class_ }; eo_function_type type; + eolian_scope scope; std::string name; std::string impl; eolian_type_instance ret; @@ -265,6 +291,7 @@ struct eo_function struct eo_event { + eolian_scope scope; std::string name; std::string eo_name; //parameters_container_type params; // XXX desirable. diff --git a/src/lib/eolian_cxx/grammar/comment.hh b/src/lib/eolian_cxx/grammar/comment.hh index 92cc03f35a..21fa3ea38d 100644 --- a/src/lib/eolian_cxx/grammar/comment.hh +++ b/src/lib/eolian_cxx/grammar/comment.hh @@ -19,15 +19,17 @@ struct comment { std::string _doc; int _tab; - comment(std::string const& doc, int tab = 0) - : _doc(doc), _tab(tab) + std::string _if_empty; + comment(std::string const& doc, int tab = 0, std::string const& if_empty = "") + : _doc(doc), _tab(tab), _if_empty(if_empty) {} }; inline std::ostream& operator<<(std::ostream& out, comment const& x) { - std::istringstream ss(x._doc); + std::string const& doc = !x._doc.empty() ? x._doc : x._if_empty; + std::istringstream ss(doc); std::string line; while(std::getline(ss, line)) { 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 86a515edb9..268855284d 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh @@ -46,7 +46,7 @@ operator<<(std::ostream& out, class_inheritance const& x) last = cls.ancestors.cend(); for (it = first; it != last; ++it) { - out << tab(2) << ", ::" << abstract_namespace << "::" << *it << endl; + out << tab(2) << ", EO_CXX_INHERIT(" << *it << ")" << endl; } return out; } @@ -115,6 +115,9 @@ operator<<(std::ostream& out, functors_constructor_methods const& x) { eo_constructor const& c = *it; + // Hide documentation condition + out << comment("@cond LOCAL", 1); + // Struct declaration out << template_parameters_declaration(c.params, 1) << tab(1) << "struct " << constructor_functor_type_name(c) << endl @@ -176,7 +179,10 @@ operator<<(std::ostream& out, functors_constructor_methods const& x) ); // Close struct - out << tab(1) << "};" << endl << endl; + out << tab(1) << "};" << endl; + + // End documentation condition + out << comment("@endcond", 1) << endl; } return out; @@ -208,7 +214,7 @@ operator<<(std::ostream& out, constructor_method_function_declarations const& x) continue; } - out << comment(c.comment, 0) + out << comment(c.comment, 1) << template_parameters_declaration(c.params, 1) << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "(" << parameters_declaration(c.params) << ") const;" << endl << endl; @@ -253,6 +259,51 @@ operator<<(std::ostream& out, constructor_method_function_definitions const& x) return out; } +struct comment_constructor_with_constructor_methods +{ + eo_class const& _cls; + comment_constructor_with_constructor_methods(eo_class const& cls) + : _cls(cls) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, comment_constructor_with_constructor_methods const& x) +{ + out << tab(1) << "/**" << endl + << tab(2) << "@brief Constructs a new " << full_name(x._cls, false) << " object." << endl + << endl + << tab(2) << "Constructs a new " << full_name(x._cls, false) << " object. If you want this object to be a child" << endl + << tab(2) << "of another Eo object, use an @ref efl::eo::parent expression, like the example." << endl + << endl; + + if (x._cls.constructors.size()) + { + bool singular = (x._cls.constructors.size() == 1); + out << tab(2) << "Since this class have " << (singular ? "a " : "") << "constructor method" << (singular ? "" : "s") + << ", you must call " << (singular ? "it" : "each one of them") << endl + << tab(2) << "in the right place within this constructor parameters." << endl + << endl; + } + + out << tab(2) << "Example:" << endl + << tab(2) << "@code" << endl + << tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(" << endl; + + for (eo_constructor const& c : x._cls.constructors) + out << tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")," << endl; + + out << tab(3) << "efl::eo::parent = parent_object);" << endl + << tab(2) << "@endcode" << endl + << endl; + + for (eo_constructor const& c : x._cls.constructors) + out << tab(2) << "@see " << x._cls.name << "::" << c.name << endl; + out << tab(2) << "@see " << x._cls.name << "(Eo* eo)" << endl; + + return out << tab(1) << "*/" << endl; +} + struct constructor_with_constructor_methods { eo_class const& _cls; @@ -274,6 +325,8 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x) cb_count += parameters_count_callbacks((*it).params); } + out << comment_constructor_with_constructor_methods(x._cls); + if (cb_count != 0) { out << tab(1) << "template <"; @@ -398,6 +451,8 @@ struct function_call_constructor_methods inline std::ostream& operator<<(std::ostream& out, function_call_constructor_methods const& x) { + out << comment("@internal", 1); + unsigned cb_count = 0; constructors_container_type::const_iterator it, 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 4b7a9b3d4d..b86b4c4243 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh @@ -5,6 +5,7 @@ #include #include "type_generator.hh" +#include "eo_class_scope_guard_generator.hh" #include "tab.hh" #include "comment.hh" @@ -42,7 +43,8 @@ struct event_callback_add inline std::ostream& operator<<(std::ostream& out, event_callback_add const& x) { - out << tab(1) << "template " << endl + out << comment(x._event.comment, 1) + << tab(1) << "template " << endl << tab(1) << "::efl::eo::signal_connection" << endl << tab(1) << "callback_" << x._event.name << "_add(F && callback_," << endl << tab(8) << "::efl::eo::callback_priority priority_ =" << endl @@ -75,7 +77,8 @@ struct event_callback_call inline std::ostream& operator<<(std::ostream& out, event_callback_call const& x) { - out << tab(1) << "template " << endl + out << comment(x._event.comment, 1) + << tab(1) << "template " << endl << tab(1) << "void" << endl << tab(1) << "callback_" << x._event.name << "_call(T* info)" << endl << tab(1) << "{" << endl @@ -99,8 +102,12 @@ operator<<(std::ostream& out, events const& x) { for (eo_event const& e : x._events) { + out << scope_guard_head(x._cls, e); + out << event_callback_add(e, x._cls, x._add_cast_to_t) << endl << event_callback_call(e, x._add_cast_to_t); + + out << scope_guard_tail(x._cls, e) << endl; } out << endl; 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 56b450bada..1a64a8ca98 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh @@ -10,6 +10,7 @@ #include "parameters_generator.hh" #include "type_generator.hh" #include "namespace_generator.hh" +#include "eo_class_scope_guard_generator.hh" namespace efl { namespace eolian { namespace grammar { @@ -52,7 +53,7 @@ operator<<(std::ostream& out, function_declaration const& x) out << reinterpret_type(func.ret) << " " << func.name << "(" << parameters_declaration(func.params) - << (is_static ? ");" : ") const;") << endl << endl; + << (is_static ? ");" : ") const;") << endl; return out; } @@ -91,10 +92,7 @@ operator<<(std::ostream& out, function_definition const& x) out << tab(1) << func.ret.front().native << " _tmp_ret;" << endl; - if (!is_static) - out << callbacks_heap_alloc("_concrete_eo_ptr()", func.params, 1); - - // TODO : register free callback for static methods + out << callbacks_heap_alloc("_concrete_eo_ptr()", func.params, is_static, 1); out << tab(1) << "eo_do(" << (is_static ? "_eo_class(), " : "_concrete_eo_ptr(), ") @@ -103,7 +101,7 @@ operator<<(std::ostream& out, function_definition const& x) if (!function_is_void(func)) out << tab(1) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl; - out << "}" << endl << endl; + out << "}" << endl; return out; } @@ -120,7 +118,9 @@ operator<<(std::ostream& out, function_declarations const& x) { for (eo_function const& f : x._cls.functions) { - out << function_declaration(x._cls, f) << endl; + out << scope_guard_head(x._cls, f) + << function_declaration(x._cls, f) + << scope_guard_tail(x._cls, f) << endl; } return out; } @@ -140,7 +140,9 @@ operator<<(std::ostream& out, function_definitions const& x) { for (eo_function const& f : x._cls.functions) { - out << function_definition(x._cls, f, x._concrete) << endl; + out << scope_guard_head(x._cls, f) + << function_definition(x._cls, f, x._concrete) + << scope_guard_tail(x._cls, f) << 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 15850abfd3..c1d227cbcc 100644 --- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_class_generator.hh @@ -40,7 +40,8 @@ struct concrete_eo_ptr_getter inline std::ostream& operator<<(std::ostream& out, concrete_eo_ptr_getter const&) { - out << tab(1) << "Eo* _concrete_eo_ptr() const" << endl + out << comment("@internal", 1) + << tab(1) << "Eo* _concrete_eo_ptr() const" << endl << tab(1) << "{" << endl << tab(2) << "return static_cast<::efl::eo::concrete const*>(static_cast(this))->_eo_ptr();" << endl << tab(1) << "}" << endl << endl; @@ -123,6 +124,8 @@ struct abstract_address_of inline std::ostream& operator<<(std::ostream& out, abstract_address_of const& x) { + out << comment("@cond LOCAL", 1); + out << tab(1) << "template " << endl << tab(1) << "struct address_of" << endl << tab(1) << "{" << endl @@ -134,7 +137,9 @@ operator<<(std::ostream& out, abstract_address_of const& x) << tab(1) << "struct address_const_of" << endl << tab(1) << "{" << endl << tab(2) << address_of_to_pointer(x._cls, true) << endl - << tab(1) << "};" << endl << endl; + << tab(1) << "};" << endl; + + out << comment("@endcond", 1) << endl; return out; } @@ -168,6 +173,7 @@ struct concrete_address_of inline std::ostream& operator<<(std::ostream& out, concrete_address_of const& x) { + out << comment("@cond LOCAL", 1); std::vector names {"address_of", "address_const_of"}; for (int is_const = 0; is_const != 2; ++is_const) { @@ -189,16 +195,18 @@ operator<<(std::ostream& out, concrete_address_of const& x) << (is_const ? " const" : "") << " { return " << name << "(this); }" << endl << endl; } + out << comment("@endcond", 1) << endl; return out; } inline void -eo_class_generator(std::ostream& out, eo_class const& cls) +eo_class_declarations_generator(std::ostream& out, eo_class const& cls) { out << namespace_head(cls) << "struct " << cls.name << ";" << endl << endl << namespace_tail(cls) + << comment("@cond EO_CXX_ABSTRACT") << "namespace " << abstract_namespace << " {" << endl << endl << namespace_head(cls) << comment(cls.comment) @@ -209,12 +217,14 @@ eo_class_generator(std::ostream& out, eo_class const& cls) << eo_class_getter(cls) << class_implicit_conversion_declaration(cls) << abstract_address_of(cls) - << "private:" << endl + << "private:" << endl << endl << concrete_eo_ptr_getter(cls) << "};" << endl << endl << namespace_tail(cls) - << "}" << endl << endl + << "}" << endl + << comment("@endcond") << endl << namespace_head(cls) + << comment(cls.comment, 0, "@brief Class " + cls.name) << "struct " << cls.name << endl << tab(2) << ": ::efl::eo::concrete" << endl << class_inheritance(cls) @@ -229,15 +239,22 @@ eo_class_generator(std::ostream& out, eo_class const& cls) << events(cls, cls.concrete_events) << endl << eo_class_getter(cls) << concrete_address_of(cls) - << "private:" << endl + << "private:" << endl << endl << function_call_constructor_methods(cls) - << tab(2) << "Eo* _concrete_eo_ptr() const { return _eo_ptr(); }" << endl + << comment("@internal", 1) + << tab(1) << "Eo* _concrete_eo_ptr() const { return _eo_ptr(); }" << endl << "};" << endl << endl << "static_assert(sizeof(" << full_name(cls) << ") == sizeof(Eo*), \"\");" << endl << "static_assert(std::is_standard_layout<" << full_name(cls) << ">::value, \"\");" << endl << endl << namespace_tail(cls) - << constructor_method_function_definitions(cls) + << endl; +} + +inline void +eo_class_definitions_generator(std::ostream& out, eo_class const& cls) +{ + out << constructor_method_function_definitions(cls) << function_definitions(cls, true) << function_definitions(cls, false) << class_implicit_conversion_definition(cls); diff --git a/src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh new file mode 100644 index 0000000000..9d545c33b3 --- /dev/null +++ b/src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh @@ -0,0 +1,61 @@ +#ifndef EOLIAN_CXX_STD_EO_CLASS_SCOPE_GUARD_GENERATOR_HH +#define EOLIAN_CXX_STD_EO_CLASS_SCOPE_GUARD_GENERATOR_HH + +#include + +#include "type_generator.hh" + +namespace efl { namespace eolian { namespace grammar { + +template +struct _scope_guard_head +{ + eo_class const& _cls; + T const& _e; + _scope_guard_head(eo_class const& cls, T const& e) + : _cls(cls), _e(e) {} +}; + +template +_scope_guard_head scope_guard_head(eo_class const& cls, T const& e) +{ + return _scope_guard_head(cls, e); +} + +template +inline std::ostream& +operator<<(std::ostream& out, _scope_guard_head const& x) +{ + assert(x._e.scope != eolian_scope::private_); + if (x._e.scope == eolian_scope::protected_) + out << "#ifdef " << name_upper(x._cls) << "_PROTECTED" << endl; + return out; +} + +template +struct _scope_guard_tail +{ + eo_class const& _cls; + T const& _e; + _scope_guard_tail(eo_class const& cls, T const& e) + : _cls(cls), _e(e) {} +}; + +template +struct _scope_guard_tail scope_guard_tail(eo_class const& cls, T const& e) +{ + return _scope_guard_tail(cls, e); +} + +template +inline std::ostream& +operator<<(std::ostream& out, _scope_guard_tail const& x) +{ + if (x._e.scope == eolian_scope::protected_) + out << "#endif" << endl; + return out; +} + +} } } + +#endif diff --git a/src/lib/eolian_cxx/grammar/eo_header_generator.hh b/src/lib/eolian_cxx/grammar/eo_header_generator.hh index 56f4e28f97..9ec4a3b480 100644 --- a/src/lib/eolian_cxx/grammar/eo_header_generator.hh +++ b/src/lib/eolian_cxx/grammar/eo_header_generator.hh @@ -115,14 +115,30 @@ include_headers(std::ostream& out, } inline void -eo_header_generator(std::ostream& out, eo_class const& cls, eo_generator_options const& opts) +include_header_impl(std::ostream& out, + eo_class const& cls EINA_UNUSED, + eo_generator_options const& opts) { - onceguard_head(out, cls); - include_headers(out, cls, opts); - eo_class_generator(out, cls); - eo_inheritance_detail_generator(out, cls); - onceguard_tail(out, cls); - out << endl; + out << "#include \"" << opts.header_impl_file_name << "\"" << endl << endl; +} + +inline void +eo_headers_generator(std::ostream& header_decl, + std::ostream& header_impl, + eo_class const& cls, + eo_generator_options const& opts) +{ + onceguard_head(header_decl, cls); + include_headers(header_decl, cls, opts); + eo_class_declarations_generator(header_decl, cls); + include_header_impl(header_decl, cls, opts); + onceguard_tail(header_decl, cls); + header_decl << endl; + + header_impl << comment("@cond EO_CXX_EO_IMPL") << endl; + eo_class_definitions_generator(header_impl, cls); + eo_inheritance_detail_generator(header_impl, cls); + header_impl << endl << comment("@endcond") << endl; } } } } // namespace efl { namespace eolian { namespace grammar { diff --git a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh index 38382d5092..11b8f2a29e 100644 --- a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh +++ b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh @@ -30,9 +30,10 @@ _ns_as_prefix(eo_class const& cls) struct inheritance_operation { eo_class const& _cls; + eo_function const& _func; functions_container_type::size_type _idx; - inheritance_operation(eo_class const& cls, functions_container_type::size_type idx) - : _cls(cls), _idx(idx) + inheritance_operation(eo_class const& cls, eo_function const& func, functions_container_type::size_type idx) + : _cls(cls), _func(func), _idx(idx) {} }; @@ -40,7 +41,7 @@ inline std::ostream& operator<<(std::ostream& out, inheritance_operation const& x) { assert(x._idx < x._cls.functions.size()); - eo_function const& func = x._cls.functions[x._idx]; + eo_function const& func = x._func; out << tab(1) << "ops[" << x._idx << "].func = reinterpret_cast(& ::" << _ns_as_prefix(x._cls) << "_" @@ -74,17 +75,30 @@ operator<<(std::ostream& out, inheritance_operations_description const& x) << ", Eo_Op_Description* ops)" << endl << "{" << endl << tab(1) << "(void)ops;" << endl; - functions_container_type::size_type n_ops = x._cls.functions.size(); - for (functions_container_type::size_type i=0; i < n_ops; ++i) + + auto funcs = x._cls.functions; + auto part = std::stable_partition(funcs.begin(), funcs.end(), [](eo_function const& f){ return f.scope == eolian_scope::public_; }); + + functions_container_type::size_type op_idx = 0; + for (auto it = funcs.begin(); it != part; ++it, ++op_idx) { - out << inheritance_operation(x._cls, i); + out << inheritance_operation(x._cls, *it, op_idx); + } + + if (part != funcs.end()) + { + out << scope_guard_head(x._cls, *part); + for (auto it = part; it != funcs.end(); ++it, ++op_idx) + out << inheritance_operation(x._cls, *it, op_idx); + out << scope_guard_tail(x._cls, *part); } for (std::string const& parent : x._cls.parents) { out << tab(1) << "initialize_operation_description(::efl::eo::detail::tag<::" - << parent << ">(), &ops[" << x._cls.functions.size() << s << "]);" << endl; + << parent << ">(), &ops[operation_description_class_size< " + << full_name(x._cls) << " >::value" << s << "]);" << endl; s += " + operation_description_class_size<::" + parent + ">::value"; } @@ -110,6 +124,9 @@ operator<<(std::ostream& out, inheritance_wrappers const& x) for (it = first; it != last; ++it) { eo_function const& func = *it; + + out << scope_guard_head(x._cls, func); + out << "template " << endl << reinterpret_type(func.ret) << " " << _ns_as_prefix(x._cls) << "_" @@ -140,7 +157,9 @@ operator<<(std::ostream& out, inheritance_wrappers const& x) if (!function_is_void(func)) out << tab(1) << "return _tmp_ret;" << endl; - out << "}" << endl << endl; + out << "}" << endl; + + out << scope_guard_tail(x._cls, func) << endl; } return out; } @@ -148,8 +167,9 @@ operator<<(std::ostream& out, inheritance_wrappers const& x) struct inheritance_base_operations_size { eo_class const& _cls; - inheritance_base_operations_size(eo_class const& cls) - : _cls(cls) + functions_container_type const& _funcs; + inheritance_base_operations_size(eo_class const& cls, functions_container_type const& funcs) + : _cls(cls), _funcs(funcs) {} }; @@ -160,8 +180,8 @@ operator<<(std::ostream& out, inheritance_base_operations_size const& x) << endl << "struct operation_description_class_size< " << full_name(x._cls) << " >" << endl << "{" << endl - << tab(1) << "static const int value = " - << x._cls.functions.size(); + << tab(1) << "static constexpr int value = " + << x._funcs.size(); for (std::string const& parent : x._cls.parents) { @@ -175,6 +195,27 @@ operator<<(std::ostream& out, inheritance_base_operations_size const& x) return out; } +struct inheritance_base_operations_size_scopes +{ + eo_class const& _cls; + inheritance_base_operations_size_scopes(eo_class const& cls) + : _cls(cls) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, inheritance_base_operations_size_scopes const& x) +{ + auto funcs = x._cls.functions; + auto part = std::stable_partition(funcs.begin(), funcs.end(), [](eo_function const& f){ return f.scope == eolian_scope::public_; }); + + out << "#ifdef " << name_upper(x._cls) << "_PROTECTED" << endl + << inheritance_base_operations_size(x._cls, funcs) + << "#else" << endl + << inheritance_base_operations_size(x._cls, {funcs.begin(), part}) + << "#endif" << endl << endl; + return out; +} struct inheritance_base_operations_extensions { @@ -230,7 +271,7 @@ operator<<(std::ostream& out, inheritance_base_operations_function const& x) if (!is_void) out << tab(3) << func.ret.front().native << " _tmp_ret = {};" << endl; - out << callbacks_heap_alloc("dynamic_cast(this)->_eo_ptr()", func.params, 3) + out << callbacks_heap_alloc("dynamic_cast(this)->_eo_ptr()", func.params, function_is_static(x._func), 3) << endl; out << tab(3) @@ -241,7 +282,7 @@ operator<<(std::ostream& out, inheritance_base_operations_function const& x) if (!is_void) out << tab(4) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl; - return out << tab(2) << "}" << endl << endl; + return out << tab(2) << "}" << endl; } struct inheritance_base_operations @@ -265,7 +306,9 @@ operator<<(std::ostream& out, inheritance_base_operations const& x) last = x._cls.functions.end(); for (it = first; it != last; ++it) { + out << scope_guard_head(x._cls, *it); out << inheritance_base_operations_function(x._cls, *it); + out << scope_guard_tail(x._cls, *it) << endl; } out << tab(1) << "};" << endl << "};" << endl << endl; @@ -365,7 +408,7 @@ eo_inheritance_detail_generator(std::ostream& out, eo_class const& cls) out << inheritance_wrappers(cls) << "namespace efl { namespace eo { namespace detail {" << endl << endl << inheritance_base_operations(cls) << endl - << inheritance_base_operations_size(cls) + << inheritance_base_operations_size_scopes(cls) << inheritance_operations_description(cls) << inheritance_call_constructors(cls) << inheritance_eo_class_getter(cls) diff --git a/src/lib/eolian_cxx/grammar/parameters_generator.hh b/src/lib/eolian_cxx/grammar/parameters_generator.hh index 20f9e99c52..2d590f2b35 100644 --- a/src/lib/eolian_cxx/grammar/parameters_generator.hh +++ b/src/lib/eolian_cxx/grammar/parameters_generator.hh @@ -105,30 +105,6 @@ operator<<(std::ostream& out, callback_tmp const& x) return out << "_tmp_" << x._name; } -struct -callback_parameter_heap_alloc -{ - eolian_type_instance const& _type; - std::string const& _name; - int _tab; - callback_parameter_heap_alloc(eolian_type_instance const& type, std::string const& name, int tab) - : _type(type) - , _name(name) - , _tab(tab) - {} -}; - -inline std::ostream& -operator<<(std::ostream& out, callback_parameter_heap_alloc const& x) -{ - out << tab(x._tab) << parameter_remove_reference_typedef(x._type, x._name) << endl - << tab(x._tab) << parameter_no_ref_type(x._type, x._name) << "* " - << callback_tmp(x._name) << " = new " - << parameter_no_ref_type(x._type, x._name) << "(std::forward<" - << template_parameter_type(x._type, x._name) << ">(" << x._name << "));" << endl; - return out; -} - struct callback_parameter_free_ev_add { @@ -157,10 +133,12 @@ callbacks_heap_alloc { std::string const& _eo_raw_expr; parameters_container_type const& _params; + bool _is_static_func; int _tab; - callbacks_heap_alloc(std::string const& eo_raw_expr, parameters_container_type const& params, int tab) + callbacks_heap_alloc(std::string const& eo_raw_expr, parameters_container_type const& params, bool is_static_func, int tab) : _eo_raw_expr(eo_raw_expr) , _params(params) + , _is_static_func(is_static_func) , _tab(tab) {} }; @@ -171,12 +149,30 @@ operator<<(std::ostream& out, callbacks_heap_alloc const& x) auto first = x._params.cbegin(), last = x._params.cend(); for (auto it = first; it != last; ++it) { - if (type_is_callback((*it).type) && it+1 != last) + auto type = (*it).type; + auto name = (*it).name; + if (type_is_callback(type) && it+1 != last) { - out << callback_parameter_heap_alloc((*it).type, (*it).name, x._tab) - << tab(x._tab) - << callback_parameter_free_ev_add(x._eo_raw_expr, (*it).type, (*it).name) - << endl << endl; + + out << tab(x._tab) << parameter_remove_reference_typedef(type, name) << endl + << tab(x._tab) << parameter_no_ref_type(type, name) << "* " + << callback_tmp(name) << " = "; + + if (!x._is_static_func) + { + out << "new " << parameter_no_ref_type(type, name) + << "(std::forward< " + << template_parameter_type(type, name) << " >(" << name << "));" << endl + << tab(x._tab) + << callback_parameter_free_ev_add(x._eo_raw_expr, type, name) + << endl << endl; + } + else + { + out << "::efl::eolian::alloc_static_callback< " + << parameter_no_ref_type(type, name) << " >(std::forward< " + << template_parameter_type(type, name) << " >(" << name << "));" << endl; + } ++it; // skip next. } } @@ -272,6 +268,56 @@ operator<<(std::ostream& out, parameters_c_declaration const& x) return out; } +struct +parameters_names +{ + parameters_container_type const& _params; + parameters_names(parameters_container_type const& params) + : _params(params) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, parameters_names const& x) +{ + auto first = x._params.cbegin(), + last = x._params.cend(); + for (auto it = first; it != last; ++it) + { + if (it != first) + out << ", "; + + out << it->name; + + if (type_is_callback(it->type) && it+1 != last) + ++it; // skip next. + } + return out; +} + +struct +parameters_c_names +{ + parameters_container_type const& _params; + parameters_c_names(parameters_container_type const& params) + : _params(params) + {} +}; + +inline std::ostream& +operator<<(std::ostream& out, parameters_c_names const& x) +{ + auto first = x._params.cbegin(), + last = x._params.cend(); + for (auto it = first; it != last; ++it) + { + if (it != first) + out << ", "; + out << it->name; + } + return out; +} + struct parameters_types { diff --git a/src/lib/eolian_cxx/grammar/type_generator.hh b/src/lib/eolian_cxx/grammar/type_generator.hh index 5913330b42..193d2ea88a 100644 --- a/src/lib/eolian_cxx/grammar/type_generator.hh +++ b/src/lib/eolian_cxx/grammar/type_generator.hh @@ -46,6 +46,21 @@ operator<<(std::ostream& out, abstract_full_name const& x) return out << abstract_namespace << full_name(x._cls); } +struct name_upper +{ + eo_class const& _cls; + name_upper(eo_class const& cls) + : _cls(cls) {} +}; + +inline std::ostream& +operator<<(std::ostream& out, name_upper const& x) +{ + std::string key = x._cls.name; + std::transform(key.begin(), key.end(), key.begin(), ::toupper); + return out << key; +} + struct c_type { eolian_type_instance const& _list; @@ -91,10 +106,13 @@ operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x) } assert(!res.empty()); - if (x._type.is_out && type_is_binding(x._type.front())) - res += "*"; - else if (!x._type.is_nonull && x._type.front().is_class) - res = "::efl::eina::optional< " + res + " >"; + if (type_is_binding(x._type.front())) + { + if (x._type.is_out) + res += "*"; + else if (!x._type.is_nonull && x._type.front().binding_requires_optional) + res = "::efl::eina::optional< " + res + " >"; + } return out << res; } diff --git a/src/tests/eolian_cxx/callback.c b/src/tests/eolian_cxx/callback.c index 5192fa0a01..ef978fbcbe 100644 --- a/src/tests/eolian_cxx/callback.c +++ b/src/tests/eolian_cxx/callback.c @@ -48,5 +48,11 @@ static void _callback_twocallback(Eo *obj EINA_UNUSED, Callback_Data *pd EINA_UN cb(data); } +static void _callback_test_global_callbacks(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED + , Ecore_Cb cb, void *data) +{ + cb(data); +} + #include "callback.eo.c" diff --git a/src/tests/eolian_cxx/callback.eo b/src/tests/eolian_cxx/callback.eo index 16dd76ee6f..50583064af 100644 --- a/src/tests/eolian_cxx/callback.eo +++ b/src/tests/eolian_cxx/callback.eo @@ -16,6 +16,12 @@ class Callback (Eo.Base) @in Ecore_Cb cb2; } } + test_global_callbacks @class { + params { + @in Ecore_Cb cb; + @in void* data; + } + } } implements { Eo.Base.constructor; diff --git a/src/tests/eolian_cxx/eolian_cxx_test_callback.cc b/src/tests/eolian_cxx/eolian_cxx_test_callback.cc index 5c5d95f035..2acfd09e63 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_callback.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_callback.cc @@ -109,10 +109,23 @@ START_TEST(eolian_cxx_test_callback_event_del) } END_TEST +START_TEST(eolian_cxx_test_global_callback) +{ + efl::eo::eo_init i; + + bool called = false; + + callback::test_global_callbacks(std::bind([&called] { called = true; })); + + fail_if(!called); +} +END_TEST + void eolian_cxx_test_callback(TCase* tc) { tcase_add_test(tc, eolian_cxx_test_callback_method); tcase_add_test(tc, eolian_cxx_test_callback_event_add); tcase_add_test(tc, eolian_cxx_test_callback_event_del); + tcase_add_test(tc, eolian_cxx_test_global_callback); }