jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=5901b4601e3a240f6286ab9396d1ea2967ca61bc

commit 5901b4601e3a240f6286ab9396d1ea2967ca61bc
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Mon Nov 27 19:52:44 2017 +0900

    cxx: Implement support for parts
    
    This generates methods like this:
    
      Part_Class part_name() const;
    
    Which can then be used like:
    
      slider.indicator().format_string_set("%1.1f");
---
 src/bin/eolian_cxx/eolian_cxx.cc                   |  8 +++
 src/examples/elementary/slider_cxx_example.cc      | 11 ++--
 .../eolian_cxx/grammar/base_class_definition.hpp   |  4 ++
 src/lib/eolian_cxx/grammar/class_definition.hpp    |  9 ++-
 .../eolian_cxx/grammar/class_implementation.hpp    | 11 ++--
 src/lib/eolian_cxx/grammar/klass_def.hpp           | 72 ++++++++++++++++++----
 src/lib/eolian_cxx/grammar/part_declaration.hpp    | 44 +++++++++++++
 src/lib/eolian_cxx/grammar/part_implementation.hpp | 72 ++++++++++++++++++++++
 8 files changed, 210 insertions(+), 21 deletions(-)

diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc
index 2df5b9ae2d..f3f3c36610 100644
--- a/src/bin/eolian_cxx/eolian_cxx.cc
+++ b/src/bin/eolian_cxx/eolian_cxx.cc
@@ -144,6 +144,14 @@ generate(const Eolian_Class* klass, 
eolian_cxx::options_type const& opts,
      };
    klass_function(klass);
 
+   for(efl::eina::iterator<Eolian_Part const> parts_itr ( 
::eolian_class_parts_get(klass))
+     , parts_last; parts_itr != parts_last; ++parts_itr)
+     {
+        Eolian_Class const* eolian_part_klass = 
::eolian_part_class_get(&*parts_itr);
+        efl::eolian::grammar::attributes::klass_def 
part_klass(eolian_part_klass, opts.unit);
+        forward_klasses.insert(part_klass);
+     }
+
    cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh"));
 
    std::string guard_name;
diff --git a/src/examples/elementary/slider_cxx_example.cc 
b/src/examples/elementary/slider_cxx_example.cc
index aa2360ff57..036dadcd1a 100644
--- a/src/examples/elementary/slider_cxx_example.cc
+++ b/src/examples/elementary/slider_cxx_example.cc
@@ -1,5 +1,7 @@
 // g++ -g `pkg-config --cflags --libs elementary-cxx efl-cxx eina-cxx eo-cxx 
ecore-cxx evas-cxx edje-cxx` slider_cxx_example.cc -o slider_cxx_example
 
+#define EFL_CXXPERIMENTAL
+
 #include <Elementary.hh>
 
 using efl::eo::instantiate;
@@ -51,13 +53,12 @@ efl_main(void *data EINA_UNUSED, const Efl_Event *ev 
EINA_UNUSED)
    bx.pack_end(sl4);
 
    efl::ui::Slider sl5(instantiate, win);
-
-   // FIXME: C++ part API needs special reference handling! This will show ERR!
-   efl::eo::downcast<efl::ui::slider::Part>(sl5.part("indicator"))
-         .format_string_set("%1.2f");
-
+   sl5.indicator().format_string_set("%1.0f rabbit(s)");
+   sl5.range_min_max_set(0, 100);
+   sl5.step_set(1);
    sl5.direction_set(EFL_UI_DIR_UP);
    sl5.hint_align_set(EFL_GFX_SIZE_HINT_FILL, 0.5);
+   sl5.hint_min_set({0, 120});
    bx.pack_end(sl5);
 
    efl::ui::Slider sl6(instantiate, win);
diff --git a/src/lib/eolian_cxx/grammar/base_class_definition.hpp 
b/src/lib/eolian_cxx/grammar/base_class_definition.hpp
index d5fa914b53..edc6afb86a 100644
--- a/src/lib/eolian_cxx/grammar/base_class_definition.hpp
+++ b/src/lib/eolian_cxx/grammar/base_class_definition.hpp
@@ -14,6 +14,7 @@
 #include "grammar/case.hpp"
 #include "grammar/address_of.hpp"
 #include "grammar/attribute_reorder.hpp"
+#include "grammar/part_declaration.hpp"
 
 namespace efl { namespace eolian { namespace grammar {
 
@@ -36,6 +37,9 @@ struct base_class_definition_generator
      if(!as_generator(*(scope_tab << 
function_declaration(get_klass_name(cls))))
         .generate(sink, cls.functions, context)) return false;
 
+     if(!as_generator(*(scope_tab << part_declaration << ";\n"))
+        .generate(sink, cls.parts, context)) return false;
+
      // static Efl_Class const* _eo_class();
      std::string suffix;
      switch(cls.type)
diff --git a/src/lib/eolian_cxx/grammar/class_definition.hpp 
b/src/lib/eolian_cxx/grammar/class_definition.hpp
index 30a9daf134..7367cf7ef0 100644
--- a/src/lib/eolian_cxx/grammar/class_definition.hpp
+++ b/src/lib/eolian_cxx/grammar/class_definition.hpp
@@ -15,6 +15,7 @@
 #include "grammar/attribute_reorder.hpp"
 #include "grammar/attribute_conditional.hpp"
 #include "grammar/attribute_replace.hpp"
+#include "grammar/part_declaration.hpp"
 
 namespace efl { namespace eolian { namespace grammar {
 
@@ -206,11 +207,17 @@ struct class_definition_generator
      // /// @endcond
      if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, 
attributes::unused, context)) return false;
 
+     // EXPERIMENTAL: Parts
+     if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, 
attributes::unused, context)) return false;
+     if(!as_generator(*(scope_tab << part_declaration << ";\n"))
+           .generate(sink, cls.parts, context)) return false;
+     if(!as_generator("#endif \n").generate(sink, attributes::unused, 
context)) return false;
+
      if(!as_generator(   scope_tab << "::efl::eo::wref<" << string << "> 
_get_wref() const { "
                          "return ::efl::eo::wref<" << string << ">(*this); }\n"
                      ).generate(sink, std::make_tuple(cls.cxx_name, 
cls.cxx_name), context)) return false;
 
-     // EXPERIMENTAL
+     // EXPERIMENTAL: wref and implicit conversion to Eo*
      if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, 
attributes::unused, context)) return false;
      // For easy wref, operator-> in wref needs to also return a pointer type
      if(!as_generator(   scope_tab << "const " << string << "* operator->() 
const { return this; }\n"
diff --git a/src/lib/eolian_cxx/grammar/class_implementation.hpp 
b/src/lib/eolian_cxx/grammar/class_implementation.hpp
index 373f04efef..60eb075073 100644
--- a/src/lib/eolian_cxx/grammar/class_implementation.hpp
+++ b/src/lib/eolian_cxx/grammar/class_implementation.hpp
@@ -14,6 +14,7 @@
 #include "grammar/namespace.hpp"
 #include "grammar/type_impl.hpp"
 #include "grammar/attribute_reorder.hpp"
+#include "grammar/part_implementation.hpp"
 
 namespace efl { namespace eolian { namespace grammar {
 
@@ -40,19 +41,21 @@ struct class_implementation_generator
 #ifndef USE_EOCXX_INHERIT_ONLY
      if(!as_generator(
         (namespaces
-         [*function_definition(get_klass_name(cls))]
+         [*function_definition(get_klass_name(cls))
+         << *part_implementation(cls.cxx_name)]
          << "\n"
-         )).generate(sink, std::make_tuple(cls.namespaces, cls.functions), 
ctx))
+         )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, 
cls.parts), ctx))
        return false;
 #endif
 
      if(!as_generator(
-        attribute_reorder<0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 
3, 2, 3>
+        attribute_reorder<0, 1, 4, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 
2, 3, 2, 3>
         (
          "namespace eo_cxx {\n"
          << namespaces
          [
           *function_definition(get_klass_name(cls))
+          << *part_implementation(cls.cxx_name)
           << "inline " << base_class_name << "::operator " << class_name << 
"() const { return *static_cast< "
             << class_name << " const*>(static_cast<void const*>(this)); }\n"
           << "inline " << base_class_name << "::operator " << class_name << 
"&() { return *static_cast< "
@@ -61,7 +64,7 @@ struct class_implementation_generator
             << class_name << " const*>(static_cast<void const*>(this)); }\n"
          ]
          << "}\n"
-         )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, 
cpp_namespaces, cls.cxx_name), ctx))
+         )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, 
cpp_namespaces, cls.cxx_name, cls.parts), ctx))
        return false;
 
      if(!as_generator("#endif\n").generate(sink, std::make_tuple(), ctx))
diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp 
b/src/lib/eolian_cxx/grammar/klass_def.hpp
index 739390ddc6..fc6d62d5b8 100644
--- a/src/lib/eolian_cxx/grammar/klass_def.hpp
+++ b/src/lib/eolian_cxx/grammar/klass_def.hpp
@@ -225,6 +225,11 @@ struct type_def
    }
    void set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, 
Eolian_C_Type_Type ctype);
    void set(Eolian_Expression_Type eolian_exp_type);
+
+   friend inline bool operator<(type_def const& lhs, type_def const& rhs)
+   {
+      return lhs.c_type < rhs.c_type;
+   }
 };
 
 struct get_qualifier_visitor
@@ -690,6 +695,32 @@ auto get(event_def& def) -> decltype(tuple_element<N, 
event_def>::get(def))
   return tuple_element<N, event_def>::get(def);
 }
 
+struct part_def
+{
+   klass_name klass;
+   std::string name;
+   //bool beta, protect; // can it be applied??
+
+   friend inline bool operator==(part_def const& lhs, part_def const& rhs)
+   {
+     return lhs.klass == rhs.klass
+       && lhs.name == rhs.name;
+   }
+   friend inline bool operator!=(part_def const& lhs, part_def const& rhs)
+   {
+     return !(lhs == rhs);
+   }
+   friend inline bool operator<(part_def const& lhs, part_def const& rhs)
+   {
+      return lhs.name < rhs.name ||
+            lhs.klass < rhs.klass;
+   }
+
+   part_def(Eolian_Part const* part, Eolian_Unit const*)
+      : klass(klass_name(::eolian_part_class_get(part), 
{attributes::qualifier_info::is_none, std::string()}))
+      , name(::eolian_part_name_get(part)) {}
+};
+
 inline Eolian_Class const* get_klass(klass_name const& klass_name_, 
Eolian_Unit const* unit);
 
 struct klass_def
@@ -703,6 +734,7 @@ struct klass_def
   class_type type;
   std::vector<event_def> events;
   std::set<klass_name, compare_klass_name_by_name> immediate_inherits;
+  std::set<part_def> parts;
 
   friend inline bool operator==(klass_def const& lhs, klass_def const& rhs)
   {
@@ -713,7 +745,8 @@ struct klass_def
       && lhs.functions == rhs.functions
       && lhs.inherits == rhs.inherits
       && lhs.type == rhs.type
-      && lhs.events == rhs.events;
+      && lhs.events == rhs.events
+      && lhs.parts == rhs.parts;
   }
   friend inline bool operator!=(klass_def const& lhs, klass_def const& rhs)
   {
@@ -723,7 +756,8 @@ struct klass_def
   {
      return lhs.eolian_name < rhs.eolian_name
        || lhs.cxx_name < rhs.cxx_name
-       || lhs.namespaces < rhs.namespaces;
+       || lhs.namespaces < rhs.namespaces
+       || lhs.parts < rhs.parts;
   }
 
   klass_def(std::string eolian_name, std::string cxx_name, std::string filename
@@ -737,6 +771,15 @@ struct klass_def
     , functions(functions), inherits(inherits), type(type)
     , immediate_inherits(immediate_inherits)
   {}
+  klass_def(std::string _eolian_name, std::string _cxx_name
+            , std::vector<std::string> _namespaces
+            , std::vector<function_def> _functions
+            , std::set<klass_name, compare_klass_name_by_name> _inherits
+            , class_type _type)
+    : eolian_name(_eolian_name), cxx_name(_cxx_name)
+    , namespaces(_namespaces)
+    , functions(_functions), inherits(_inherits), type(_type)
+  {}
   klass_def(Eolian_Class const* klass, Eolian_Unit const* unit)
   {
      for(efl::eina::iterator<const char> namespace_iterator( 
::eolian_class_namespaces_get(klass))
@@ -750,8 +793,8 @@ struct klass_def
        , functions_last; eolian_functions != functions_last; 
++eolian_functions)
        {
          Eolian_Function const* function = &*eolian_functions;
-         Eolian_Function_Type type = ::eolian_function_type_get(function);
-         if(type == EOLIAN_PROPERTY)
+         Eolian_Function_Type func_type = ::eolian_function_type_get(function);
+         if(func_type == EOLIAN_PROPERTY)
            {
              try {
                 if(! ::eolian_function_is_legacy_only(function, 
EOLIAN_PROP_GET)
@@ -766,9 +809,9 @@ struct klass_def
            }
          else
            try {
-             if(! ::eolian_function_is_legacy_only(function, type)
-                && ::eolian_function_scope_get(function, type) != 
EOLIAN_SCOPE_PRIVATE)
-               functions.push_back({function, type, unit});
+             if(! ::eolian_function_is_legacy_only(function, func_type)
+                && ::eolian_function_scope_get(function, func_type) != 
EOLIAN_SCOPE_PRIVATE)
+               functions.push_back({function, func_type, unit});
            } catch(std::exception const&) {}
        }
      for(efl::eina::iterator<Eolian_Function const> eolian_functions ( 
::eolian_class_functions_get(klass, EOLIAN_METHOD))
@@ -776,9 +819,9 @@ struct klass_def
        {
          try {
              Eolian_Function const* function = &*eolian_functions;
-             Eolian_Function_Type type = eolian_function_type_get(function);
+             Eolian_Function_Type func_type = 
eolian_function_type_get(function);
              if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD)
-                && ::eolian_function_scope_get(function, type) != 
EOLIAN_SCOPE_PRIVATE)
+                && ::eolian_function_scope_get(function, func_type) != 
EOLIAN_SCOPE_PRIVATE)
                functions.push_back({function, EOLIAN_METHOD, unit});
          } catch(std::exception const&) {}
        }
@@ -789,9 +832,9 @@ struct klass_def
          immediate_inherits.insert({inherit, {}});
        }
      std::function<void(Eolian_Class const*)> inherit_algo = 
-       [&] (Eolian_Class const* klass)
+       [&] (Eolian_Class const* inherit_klass)
        {
-         for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( 
::eolian_class_inherits_get(klass))
+         for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( 
::eolian_class_inherits_get(inherit_klass))
                , inherit_last; inherit_iterator != inherit_last; 
++inherit_iterator)
            {
              Eolian_Class const* inherit = &*inherit_iterator;
@@ -800,6 +843,13 @@ struct klass_def
            }
        };
      inherit_algo(klass);
+
+     for(efl::eina::iterator<Eolian_Part const> parts_itr ( 
::eolian_class_parts_get(klass))
+       , parts_last; parts_itr != parts_last; ++parts_itr)
+       {
+          parts.insert({&*parts_itr, unit});
+       }
+
      switch(eolian_class_type_get(klass))
        {
        case EOLIAN_CLASS_REGULAR:
diff --git a/src/lib/eolian_cxx/grammar/part_declaration.hpp 
b/src/lib/eolian_cxx/grammar/part_declaration.hpp
new file mode 100644
index 0000000000..383403c6bd
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/part_declaration.hpp
@@ -0,0 +1,44 @@
+#ifndef EOLIAN_CXX_PART_DECLARATION_HH
+#define EOLIAN_CXX_PART_DECLARATION_HH
+
+#include "grammar/generator.hpp"
+
+#include "grammar/string.hpp"
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "grammar/type.hpp"
+#include "grammar/parameter.hpp"
+#include "grammar/keyword.hpp"
+
+namespace efl { namespace eolian { namespace grammar {
+
+struct part_declaration_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::part_def const& part, 
Context const& ctx) const
+   {
+      if(!as_generator("::efl::eolian::return_traits<::" << *(string << "::"))
+            .generate(sink, part.klass.namespaces, 
add_lower_case_context(ctx)))
+        return false;
+      if(!as_generator(string << ">::type " << string << "() const")
+            .generate(sink, std::make_tuple(part.klass.eolian_name, 
part.name), ctx))
+        return false;
+
+      return true;
+   }
+};
+
+template <>
+struct is_eager_generator<part_declaration_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed<part_declaration_generator> : 
std::integral_constant<int, 1> {};
+}
+
+part_declaration_generator const part_declaration = {};
+
+} } }
+
+#endif
diff --git a/src/lib/eolian_cxx/grammar/part_implementation.hpp 
b/src/lib/eolian_cxx/grammar/part_implementation.hpp
new file mode 100644
index 0000000000..cee2fc7fa8
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/part_implementation.hpp
@@ -0,0 +1,72 @@
+#ifndef EOLIAN_CXX_PART_IMPLEMENTATION_HH
+#define EOLIAN_CXX_PART_IMPLEMENTATION_HH
+
+#include "grammar/generator.hpp"
+
+#include "grammar/string.hpp"
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "grammar/type.hpp"
+#include "grammar/parameter.hpp"
+#include "grammar/keyword.hpp"
+
+namespace efl { namespace eolian { namespace grammar {
+
+struct part_implementation_generator
+{
+   part_implementation_generator(std::string const& _klass_name)
+      : klass_name(_klass_name) {}
+
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::part_def const& part, 
Context const& ctx) const
+   {
+      if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, 
attributes::unused, ctx))
+        return false;
+
+      if(!as_generator("::efl::eolian::return_traits<::" << *(string << "::"))
+            .generate(sink, part.klass.namespaces, 
add_lower_case_context(ctx)))
+        return false;
+      // FIXME: part_def can't depend on klass_def so C type is not known :(
+      if(!as_generator(string << ">::type "<< string << "::" << string << "() 
const\n{\n"
+                       << scope_tab << "::Eo *__return_value = ::efl_part"
+                       << "(this->_eo_ptr(), \"" << string << "\");\n"
+                       << scope_tab << "::efl_auto_unref_set(__return_value, 
false);\n")
+            .generate(sink, std::make_tuple(part.klass.eolian_name, 
klass_name, part.name, part.name), ctx))
+        return false;
+      if(!as_generator(scope_tab << "return ::" << *(string << "::"))
+            .generate(sink, part.klass.namespaces, 
add_lower_case_context(ctx)))
+        return false;
+      if(!as_generator(string << "{__return_value};\n}\n")
+            .generate(sink, part.klass.eolian_name, ctx))
+        return false;
+
+      if(!as_generator("#endif\n").generate(sink, attributes::unused, ctx))
+        return false;
+
+      return true;
+   }
+
+private:
+   std::string klass_name;
+};
+
+template <>
+struct is_eager_generator<part_implementation_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed<part_implementation_generator> : 
std::integral_constant<int, 1> {};
+}
+
+struct part_implementation_terminal
+{
+  part_implementation_generator operator()(std::string klass_name) const
+  {
+    return part_implementation_generator{klass_name};
+  }
+} const part_implementation = {};
+
+} } }
+
+#endif

-- 


Reply via email to