eolian_cxx: Add protected methods and events to C++ wrappers and fixes
authorVitor Sousa <vitorsousasilva@gmail.com>
Mon, 12 Jan 2015 14:00:59 +0000 (12:00 -0200)
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Tue, 14 Apr 2015 04:06:57 +0000 (01:06 -0300)
Using eina::string_view in eolian generated interfaces (instead of
std::string) to allow lightweight passing of both C strings and C++
std::string.

Also, No longer using eina::optional in generated headers for types
that already implements the concept of null state (like Eo wrappers
and eina_accessor).

Also fix allocating callback objects require by class methods
(i.e. static) in static vectors so the memory will be freed when the
programs exit.

Added a new test case for testing callbacks on class methods.

Moved method definitions and supplementary code from generated C++
wrappers to auxiliary header file (.eo.impl.hh) generated together
with the main ".eo.hh" file. Updated Makefiles to list such files in
the compilation and cleanup processes. Updated .gitignore to include
these new generated files.

Made general adjustments on the documentation of generated C++ wrappers

Added "PREDEFINED" preprocessor macro definition in the Doxyfile.in in
order to make some adjustments for better documentation in the C++
generated headers.  Excluding generation of documentation for classes
in the "eo_cxx" namespace (the namespace for "abstract" eolian C++
wrappers).  Now generating the documentation for the events too.
Hiding some auxiliary code from being documented. Some aesthetic
adjustments for generated white space. Generate documentation for the
main constructor of C++ wrappers and added auxiliary grammars to list
parameters names.

32 files changed:
.gitignore
doc/Doxyfile.in
src/Makefile_Ecore_Audio_Cxx.am
src/Makefile_Ecore_Cxx.am
src/Makefile_Edje_Cxx.am
src/Makefile_Efl_Cxx.am
src/Makefile_Eo_Cxx.am
src/Makefile_Eolian_Cxx.am
src/Makefile_Eolian_Cxx_Helper.am
src/Makefile_Evas_Cxx.am
src/bin/eolian_cxx/convert.cc
src/bin/eolian_cxx/eolian_cxx.cc
src/bin/eolian_cxx/eolian_wrappers.hh
src/bin/eolian_cxx/type_lookup_table.cc
src/bindings/eo_cxx/eo_concrete.hh
src/bindings/eo_cxx/eo_cxx_interop.hh
src/examples/eolian_cxx/Makefile.am
src/lib/eolian_cxx/eo_generate.hh
src/lib/eolian_cxx/eo_types.hh
src/lib/eolian_cxx/grammar/comment.hh
src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
src/lib/eolian_cxx/grammar/eo_class_events_generator.hh
src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
src/lib/eolian_cxx/grammar/eo_class_generator.hh
src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh [new file with mode: 0644]
src/lib/eolian_cxx/grammar/eo_header_generator.hh
src/lib/eolian_cxx/grammar/inheritance_base_generator.hh
src/lib/eolian_cxx/grammar/parameters_generator.hh
src/lib/eolian_cxx/grammar/type_generator.hh
src/tests/eolian_cxx/callback.c
src/tests/eolian_cxx/callback.eo
src/tests/eolian_cxx/eolian_cxx_test_callback.cc

index 4f04840..1da486e 100644 (file)
@@ -32,6 +32,7 @@ tags
 *.eo.h
 *.eo.legacy.h
 *.eo.hh
+*.eo.impl.hh
 *.eo.lua
 *.luac
 .dir-locals.el
index f18cc4f..b4afaf4 100644 (file)
@@ -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.
index 498bcbf..bf564d2 100644 (file)
@@ -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)
index d81651a..b29a1c4 100644 (file)
@@ -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)
index 8d6b068..0b308b0 100644 (file)
@@ -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)
index 9df7c60..c555015 100644 (file)
@@ -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)
index 2f7dda6..b6315c8 100644 (file)
@@ -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
 
index cd58e3e..6dff267 100644 (file)
@@ -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 \
index cb54cc4..bb656c8 100644 (file)
@@ -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)
index 96d5ab1..abe1aa6 100644 (file)
@@ -49,15 +49,48 @@ lib/evas/Evas.hh: $(generated_evas_canvas_cxx_bindings)
        @for i in $(generated_evas_canvas_cxx_bindings); do echo "#include <canvas/$$(basename $$i)>" >> $(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
 
index d029999..22ee22f 100644 (file)
@@ -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),
index 93e9e44..7afa10d 100644 (file)
@@ -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())
+        std::ofstream header_decl;
+        header_decl.open(header_decl_file_name);
+        if (!header_decl.good())
           {
-             efl::eolian::generate(outfile, cls, gen_opts);
-             outfile.close();
+             EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
+               << "Can't open output file: " << header_decl_file_name << std::endl;
+             return false;
           }
-        else
+
+        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: " << outname << std::endl;
+               << "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;
 }
index d1b28a6..5cad797 100644 (file)
@@ -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);
index 7fa085e..dd00551 100644 (file)
@@ -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<char*>", {"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<char*>", {"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"}},
 };
 
 }
index 63029a1..9e328b1 100644 (file)
 #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
index ba6a473..08ca300 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <string>
 #include <tuple>
+#include <utility>
 #include <type_traits>
 
 #include <Eina.hh>
@@ -28,6 +29,20 @@ to_c(eina::optional<std::string> const& x)
 }
 
 inline const char*
+to_c(eina::string_view const& x)
+{
+   return x.data();
+}
+
+inline const char*
+to_c(eina::optional<eina::string_view> const& x)
+{
+   if (!x)
+     return nullptr;
+   return x->data();
+}
+
+inline const char*
 to_c(efl::eina::stringshare const& x)
 {
    return x.c_str();
@@ -196,6 +211,20 @@ to_cxx(const char* x, std::tuple<std::false_type>, tag<eina::optional<std::strin
    return std::string(x);
 }
 
+inline eina::string_view
+to_cxx(const char* x, std::tuple<std::false_type>, tag<eina::string_view>)
+{
+   return eina::string_view(x);
+}
+
+inline eina::optional<eina::string_view>
+to_cxx(const char* x, std::tuple<std::false_type>, tag<eina::optional<eina::string_view> >)
+{
+   if (!x)
+     return nullptr;
+   return eina::string_view(x);
+}
+
 template <typename T, typename Enable = void>
 struct traits
 {
@@ -216,6 +245,13 @@ struct traits
    typedef const char* type;
 };
 
+template <typename T>
+struct traits
+ <T, typename std::enable_if<std::is_base_of<::efl::eina::basic_string_view<char>, T>::value>::type>
+{
+   typedef const char* type;
+};
+
 template <typename T, typename ...Args>
 inline efl::eina::range_list<T const>
 to_cxx(const Eina_List* x, std::tuple<std::false_type, Args...>, tag< efl::eina::range_list<T> >)
@@ -407,6 +443,22 @@ Eina_Bool free_callback_calback(void* data, Eo* obj EINA_UNUSED
    return EO_CALLBACK_CONTINUE;
 }
 
+template <typename F>
+inline
+std::vector<F>& get_static_callback_vector()
+{
+   static std::vector<F> vec;
+   return vec;
+}
+
+template <typename F>
+inline
+F* alloc_static_callback(F&& f)
+{
+   get_static_callback_vector<F>().push_back(std::forward<F>(f));
+   return &(get_static_callback_vector<F>().back());
+}
+
 } } // namespace efl { namespace eolian {
 
 #endif // EFL_EOLIAN_INTEROP_HH
index a0510f1..7842095 100644 (file)
@@ -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 $@ $<
 
index a509201..97e53bb 100644 (file)
 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);
 }
 
 } }
index 38f2d38..b50e692 100644 (file)
@@ -21,6 +21,12 @@ typedef std::vector<eo_function> functions_container_type;
 typedef std::vector<eo_parameter> parameters_container_type;
 typedef std::vector<eo_event> 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)
@@ -151,6 +161,19 @@ type_is_class(eolian_type_instance const& type)
 }
 
 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)
 {
    return type.is_nonull;
@@ -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.
index 92cc03f..21fa3ea 100644 (file)
@@ -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))
      {
index 86a515e..2688552 100644 (file)
@@ -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,
index 4b7a9b3..b86b4c4 100644 (file)
@@ -5,6 +5,7 @@
 #include <iosfwd>
 
 #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 <typename F>" << endl
+   out << comment(x._event.comment, 1)
+       << tab(1) << "template <typename F>" << 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 <typename T>" << endl
+   out << comment(x._event.comment, 1)
+       << tab(1) << "template <typename T>" << 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;
index 56b450b..1a64a8c 100644 (file)
@@ -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;
 }
index 15850ab..c1d227c 100644 (file)
@@ -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<void const*>(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 <typename D>" << 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<std::string> 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 (file)
index 0000000..9d545c3
--- /dev/null
@@ -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 <cassert>
+
+#include "type_generator.hh"
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <typename T>
+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 <typename T>
+_scope_guard_head<T> scope_guard_head(eo_class const& cls, T const& e)
+{
+   return _scope_guard_head<T>(cls, e);
+}
+
+template <typename T>
+inline std::ostream&
+operator<<(std::ostream& out, _scope_guard_head<T> 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 <typename T>
+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 <typename T>
+struct _scope_guard_tail<T> scope_guard_tail(eo_class const& cls, T const& e)
+{
+   return _scope_guard_tail<T>(cls, e);
+}
+
+template <typename T>
+inline std::ostream&
+operator<<(std::ostream& out, _scope_guard_tail<T> const& x)
+{
+   if (x._e.scope == eolian_scope::protected_)
+     out << "#endif" << endl;
+   return out;
+}
+
+} } }
+
+#endif
index 56f4e28..9ec4a3b 100644 (file)
@@ -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)
+{
+   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(out, cls);
-   include_headers(out, cls, opts);
-   eo_class_generator(out, cls);
-   eo_inheritance_detail_generator(out, cls);
-   onceguard_tail(out, cls);
-   out << endl;
+   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 {
index 38382d5..11b8f2a 100644 (file)
@@ -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<void*>(& ::"
        << _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<T>(::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 <typename T>" << 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<T*>(this)->_eo_ptr()", func.params, 3)
+   out << callbacks_heap_alloc("dynamic_cast<T*>(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)
index 20f9e99..2d590f2 100644 (file)
@@ -106,30 +106,6 @@ operator<<(std::ostream& out, callback_tmp const& x)
 }
 
 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
 {
    std::string const& _eo_raw_expr;
@@ -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.
           }
      }
@@ -273,6 +269,56 @@ operator<<(std::ostream& out, parameters_c_declaration const& x)
 }
 
 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
 {
    parameters_container_type const& _params;
index 5913330..193d2ea 100644 (file)
@@ -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;
 }
index 5192fa0..ef978fb 100644 (file)
@@ -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"
 
index 16dd76e..5058306 100644 (file)
@@ -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;
index 5c5d95f..2acfd09 100644 (file)
@@ -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);
 }