eolian_cxx: Many changes for the C# bindings
authorLauro Moura <lauromoura@expertisesolutions.com.br>
Fri, 24 Nov 2017 00:47:25 +0000 (21:47 -0300)
committerLauro Moura <lauromoura@expertisesolutions.com.br>
Mon, 4 Dec 2017 18:47:49 +0000 (15:47 -0300)
- Added helper function to get all methods of a given class (local and
  inherited methods)
- Add filename information to klass
- Added new defs: enum, value (currently only integers), struct
- Generator refactoring
- Eolian C compatibility

30 files changed:
src/lib/eolian_cxx/grammar/address_of.hpp
src/lib/eolian_cxx/grammar/alternative.hpp
src/lib/eolian_cxx/grammar/attribute_conditional.hpp
src/lib/eolian_cxx/grammar/attribute_reorder.hpp
src/lib/eolian_cxx/grammar/attribute_replace.hpp
src/lib/eolian_cxx/grammar/base_class_definition.hpp
src/lib/eolian_cxx/grammar/c_type.hpp
src/lib/eolian_cxx/grammar/case.hpp
src/lib/eolian_cxx/grammar/class_declaration.hpp
src/lib/eolian_cxx/grammar/class_definition.hpp
src/lib/eolian_cxx/grammar/class_implementation.hpp
src/lib/eolian_cxx/grammar/context.hpp
src/lib/eolian_cxx/grammar/converting_argument.hpp
src/lib/eolian_cxx/grammar/eps.hpp
src/lib/eolian_cxx/grammar/function_declaration.hpp
src/lib/eolian_cxx/grammar/function_definition.hpp
src/lib/eolian_cxx/grammar/generator.hpp
src/lib/eolian_cxx/grammar/header_guards.hpp
src/lib/eolian_cxx/grammar/header_include_directive.hpp
src/lib/eolian_cxx/grammar/implementation_include_directive.hpp
src/lib/eolian_cxx/grammar/indentation.hpp
src/lib/eolian_cxx/grammar/integral.hpp [new file with mode: 0644]
src/lib/eolian_cxx/grammar/klass_def.hpp
src/lib/eolian_cxx/grammar/kleene.hpp
src/lib/eolian_cxx/grammar/list.hpp
src/lib/eolian_cxx/grammar/namespace.hpp
src/lib/eolian_cxx/grammar/parameter.hpp
src/lib/eolian_cxx/grammar/sequence.hpp
src/lib/eolian_cxx/grammar/string.hpp
src/lib/eolian_cxx/grammar/type.hpp

index 3fa48b0..6c6b977 100644 (file)
@@ -61,6 +61,8 @@ struct address_of_generator
 
 template <>
 struct is_eager_generator<address_of_generator> : std::true_type {};
+template <>
+struct is_generator<address_of_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 3ad3e6a..844f3d2 100644 (file)
@@ -30,6 +30,8 @@ struct alternative_generator
 
 template <typename L, typename R>
 struct is_eager_generator<alternative_generator<L, R> > : std::true_type {};
+template <typename L, typename R>
+struct is_generator<alternative_generator<L, R> > : std::true_type {};
 
 namespace type_traits {
 template  <typename  L, typename R>
index 2803f9f..5934564 100644 (file)
@@ -21,9 +21,6 @@ struct functional_attribute_conditional_generator
    G g;
 };
 
-template <typename F, typename G>
-struct is_eager_generator<functional_attribute_conditional_generator<F, G>> : std::true_type {};
-
 template <typename F>
 struct functional_attribute_conditional_directive
 {
@@ -42,9 +39,6 @@ struct functional_attribute_conditional_directive
   F f;
 };
 
-template <typename F>
-struct is_eager_generator<functional_attribute_conditional_directive<F>> : std::true_type {};
-      
 struct attribute_conditional_terminal
 {
   template <typename F>
@@ -54,6 +48,15 @@ struct attribute_conditional_terminal
   }
 } const attribute_conditional = {};
 
+template <typename F, typename G>
+struct is_eager_generator<functional_attribute_conditional_generator<F, G>> : std::true_type {};
+template <typename F>
+struct is_eager_generator<functional_attribute_conditional_directive<F>> : std::true_type {};
+template <typename F, typename G>
+struct is_generator<functional_attribute_conditional_generator<F, G>> : std::true_type {};
+template <typename F>
+struct is_generator<functional_attribute_conditional_directive<F>> : std::true_type {};
+      
 namespace type_traits {
 template <typename F, typename G>
 struct attributes_needed<functional_attribute_conditional_generator<F, G>>
index b3f8b31..a14e3a9 100644 (file)
@@ -66,6 +66,8 @@ struct attribute_reorder_generator
 
 template <typename G, int...S>
 struct is_eager_generator<attribute_reorder_generator<G, S...>> : std::true_type {};
+template <typename G, int...S>
+struct is_generator<attribute_reorder_generator<G, S...>> : std::true_type {};
 
 template <int...S, typename G>
 attribute_reorder_generator<G, S...> attribute_reorder(G g)
index e45fb9f..fee7328 100644 (file)
@@ -18,9 +18,6 @@ struct functional_attribute_replace_generator
    G g;
 };
 
-template <typename F, typename G>
-struct is_eager_generator<functional_attribute_replace_generator<F, G>> : std::true_type {};
-
 template <typename F>
 struct functional_attribute_replace_directive
 {
@@ -39,8 +36,14 @@ struct functional_attribute_replace_directive
   F f;
 };
 
+template <typename F, typename G>
+struct is_eager_generator<functional_attribute_replace_generator<F, G>> : std::true_type {};
 template <typename F>
 struct is_eager_generator<functional_attribute_replace_directive<F>> : std::true_type {};
+template <typename F, typename G>
+struct is_generator<functional_attribute_replace_generator<F, G>> : std::true_type {};
+template <typename F>
+struct is_generator<functional_attribute_replace_directive<F>> : std::true_type {};
       
 struct attribute_replace_terminal
 {
index 5a4a219..aa61334 100644 (file)
@@ -101,6 +101,8 @@ struct base_class_definition_generator
 
 template <>
 struct is_eager_generator<base_class_definition_generator> : std::true_type {};
+template <>
+struct is_generator<base_class_definition_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 6d814f8..e680b38 100644 (file)
@@ -35,10 +35,10 @@ inline std::string c_type(parameter_def const& param)
    switch(param.direction)
      {
      case parameter_direction::in:
-       return param.type.original_type.visit(c_type_visitor{&param.c_type});
+       return param.type.original_type.visit(c_type_visitor{&param.type.c_type});
      case parameter_direction::out:
      case parameter_direction::inout:
-       return param.type.original_type.visit(c_type_visitor{&param.c_type}) + "*";
+       return param.type.original_type.visit(c_type_visitor{&param.type.c_type}) + "*";
      default:
        throw std::runtime_error("Unknown parameter direction");
      };
@@ -63,6 +63,8 @@ struct c_type_generator
 
 template <>
 struct is_eager_generator<c_type_generator> : std::true_type {};
+template <>
+struct is_generator<c_type_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 8642136..c18d4ab 100644 (file)
@@ -55,6 +55,10 @@ template <typename G>
 struct is_eager_generator<lower_case_generator<G>> : std::true_type {};
 template <typename G>
 struct is_eager_generator<upper_case_generator<G>> : std::true_type {};
+template <typename G>
+struct is_generator<lower_case_generator<G>> : std::true_type {};
+template <typename G>
+struct is_generator<upper_case_generator<G>> : std::true_type {};
 
 namespace type_traits {
 template <typename G>
index d448c31..de9c4a6 100644 (file)
@@ -73,6 +73,8 @@ struct class_declaration_generator
 
 template <>
 struct is_eager_generator<class_declaration_generator> : std::true_type {};
+template <>
+struct is_generator<class_declaration_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 54df330..13349d4 100644 (file)
@@ -212,6 +212,8 @@ struct class_definition_generator
 
 template <>
 struct is_eager_generator<class_definition_generator> : std::true_type {};
+template <>
+struct is_generator<class_definition_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 3e9174f..0731e3d 100644 (file)
@@ -53,6 +53,8 @@ struct class_implementation_generator
 
 template <>
 struct is_eager_generator<class_implementation_generator> : std::true_type {};
+template <>
+struct is_generator<class_implementation_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 9b5e164..79e5417 100644 (file)
@@ -40,6 +40,26 @@ template <typename Tag>
 struct tag_check<Tag, context_null> : std::false_type {};
 template <typename Tag, typename OtherTag, typename Context>
 struct tag_check<Tag, context_cons<OtherTag, Context>> : tag_check<Tag, Context> {};
+
+template <typename Tag, typename SameTag, typename Tail> 
+Tag const& context_find_tag(context_cons<SameTag, Tail> const& context
+                            , typename std::enable_if<std::is_same<Tag, SameTag>::value>::type* = nullptr)
+{
+  return context.tag;
+}
+
+template <typename Tag, typename OtherTag, typename Tail> 
+Tag const& context_find_tag(context_cons<OtherTag, Tail> const& context
+                            , typename std::enable_if<!std::is_same<Tag, OtherTag>::value>::type* = nullptr)
+{
+  return context_find_tag<Tag>(context.tail);
+}
+
+template <typename Tag, typename OtherTag, typename Tail> 
+Tag const& context_find_tag(context_null const& context)
+{
+  throw std::logic_error("Context for generation not available");
+}
       
 } } }
 
index 0725580..230608f 100644 (file)
@@ -68,6 +68,8 @@ struct converting_argument_generator
 
 template <>
 struct is_eager_generator<converting_argument_generator> : std::true_type {};
+template <>
+struct is_generator<converting_argument_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 900df90..d396cbf 100644 (file)
@@ -16,6 +16,8 @@ struct eps_generator
 
 template <>
 struct is_eager_generator<eps_generator> : std::true_type {};
+template <>
+struct is_generator<eps_generator> : std::true_type {};
 
 eps_generator const eps = {};
 
index 431b4a2..e98fbf0 100644 (file)
@@ -57,6 +57,8 @@ struct function_declaration_generator
 
 template <>
 struct is_eager_generator<function_declaration_generator> : std::true_type {};
+template <>
+struct is_generator<function_declaration_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 1c7cf25..50bd997 100644 (file)
@@ -88,7 +88,7 @@ struct function_definition_generator
       if(!as_generator(scope_tab).generate(sink, attributes::unused, ctx)) return false;
       
       if(f.return_type != attributes::void_
-         && !as_generator(attributes::c_type({attributes::parameter_direction::in, f.return_type, "", f.return_type.c_type})
+         && !as_generator(attributes::c_type({attributes::parameter_direction::in, f.return_type, ""})
                           << " __return_value = "
                           ).generate(sink, attributes::unused, ctx)) return false;
       
@@ -154,6 +154,8 @@ struct function_definition_generator
 
 template <>
 struct is_eager_generator<function_definition_generator> : std::true_type {};
+template <>
+struct is_generator<function_definition_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 1100bef..130ee68 100644 (file)
@@ -38,8 +38,8 @@ template <typename T>
 struct is_generator<T volatile const&> : is_generator<T> {};
 template <typename T>
 struct is_eager_generator<T volatile const&> : is_eager_generator<T> {};
-template <typename T>
-struct is_generator<T> : is_eager_generator<T> {};
+// template <typename T>
+// struct is_generator<T> : is_eager_generator<T> {};
       
 template <typename G, typename Enable = typename std::enable_if<is_eager_generator<G>::value>::type>
 G as_generator(G&& g) { return g; }
index eab596d..a5a353b 100644 (file)
@@ -56,6 +56,8 @@ struct header_guards_generator
 
 template <typename G>
 struct is_eager_generator<header_guards_generator<G> > : std::true_type {};
+template <typename G>
+struct is_generator<header_guards_generator<G> > : std::true_type {};
 
 namespace type_traits {
 template  <typename G>
index 8fbc0eb..6b717b6 100644 (file)
@@ -21,6 +21,8 @@ struct header_include_directive_generator
 
 template <>
 struct is_eager_generator<header_include_directive_generator> : std::true_type {};
+template <>
+struct is_generator<header_include_directive_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index f82d84b..1fe50df 100644 (file)
@@ -32,6 +32,8 @@ struct implementation_include_directive_generator
 
 template <>
 struct is_eager_generator<implementation_include_directive_generator> : std::true_type {};
+template <>
+struct is_generator<implementation_include_directive_generator> : std::true_type {};
 
 namespace type_traits {
 template <>
index 615842e..897be03 100644 (file)
@@ -28,6 +28,8 @@ struct scope_tab_generator
 
 template <>
 struct is_eager_generator<scope_tab_generator> : std::true_type {};
+template <>
+struct is_generator<scope_tab_generator> : std::true_type {};
       
 struct scope_tab_terminal
 {
diff --git a/src/lib/eolian_cxx/grammar/integral.hpp b/src/lib/eolian_cxx/grammar/integral.hpp
new file mode 100644 (file)
index 0000000..95cb2f0
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef EOLIAN_CXX_INTEGRAL_HH
+#define EOLIAN_CXX_INTEGRAL_HH
+
+#include <cstdlib>
+#include <cstring>
+
+#include "grammar/generator.hpp"
+#include "grammar/attributes.hpp"
+#include "grammar/case.hpp"
+
+namespace efl { namespace eolian { namespace grammar {
+
+namespace detail {
+
+template <typename OutputIterator, typename T>
+void generate_integral(OutputIterator sink, T integer)
+{
+  std::stringstream stm;
+  stm << integer;
+  std::string string = stm.str();
+  std::copy(string.begin(), string.end(), sink);
+}
+
+}
+
+// literal
+template <typename T>
+struct literal_integral_generator
+{
+   T integral;
+
+   template <typename OutputIterator, typename Attribute, typename Context>
+   bool generate(OutputIterator sink, Attribute const&, Context const&) const
+   {
+      detail::generate_integral(sink, integral);
+      return true;
+   }
+};
+
+template <typename T, typename Enable = typename std::enable_if<std::is_integral<T>::value>::type>
+literal_integral_generator<T> as_generator(T&& literal) { return {std::forward<T>(literal)}; }
+literal_integral_generator<std::size_t> as_generator(std::size_t literal) { return {literal}; }
+
+struct integral_terminal {
+  template <typename T>
+  literal_integral_generator<T> operator()(T literal) const
+  {
+    return {literal};
+  }
+} const int_ = {};
+
+struct integral_generator
+{
+   template <typename OutputIterator, typename Attribute, typename Context>
+   bool generate(OutputIterator sink, Attribute const& attribute, Context const&) const
+   {
+      detail::generate_integral(sink, attribute);
+      return true;
+   }
+};
+
+integral_generator as_generator(integral_terminal) { return {}; }
+      
+template <typename T>
+struct is_eager_generator<literal_integral_generator<T>> : std::true_type {};
+template <>
+struct is_eager_generator<integral_generator> : std::true_type {};
+template <typename T>
+struct is_generator<literal_integral_generator<T>> : std::true_type {};
+template <>
+struct is_generator<integral_generator> : std::true_type {};
+template <typename T>
+struct is_generator<T, typename std::enable_if<std::is_integral<T>::value>::type> : std::true_type {};
+template <>
+struct is_generator<integral_terminal> : std::true_type {};
+
+namespace type_traits {
+template <typename T>
+struct attributes_needed<literal_integral_generator<T>> : std::integral_constant<int, 0> {};  
+template <>
+struct attributes_needed<integral_generator> : std::integral_constant<int, 1> {};  
+template <>
+struct attributes_needed<integral_terminal> : std::integral_constant<int, 1> {};  
+}      
+      
+} } }
+
+#endif
index 146bfbe..edfadc0 100644 (file)
@@ -212,16 +212,19 @@ struct type_def
    typedef eina::variant<klass_name, regular_type_def, complex_type_def> variant_type;
    variant_type original_type;
    std::string c_type;
+   bool has_own;
+   bool is_ptr;
 
    type_def() {}
-   type_def(variant_type original_type, std::string c_type)
-     : original_type(original_type), c_type(c_type) {}
+   type_def(variant_type original_type, std::string c_type, bool has_own)
+     : original_type(original_type), c_type(c_type), has_own(has_own) {}
 
    type_def(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype)
    {
      set(eolian_type, unit, ctype);
    }
    void set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype);
+   void set(Eolian_Expression_Type eolian_exp_type);
 };
 
 struct get_qualifier_visitor
@@ -247,17 +250,19 @@ inline bool operator!=(type_def const& lhs, type_def const& rhs)
   return !(lhs == rhs);
 }
         
-type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}}, "void"};
+type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}, false}, "void", false};
         
 inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype)
 {
    c_type = ::eolian_type_c_type_get(eolian_type, ctype);
    // ::eina_stringshare_del(stringshare); // this crashes
    Eolian_Type const* stp = eolian_type_base_type_get(eolian_type);
+   has_own = !!::eolian_type_is_owned(eolian_type);
+   is_ptr = !!::eolian_type_is_ptr(eolian_type);
    switch( ::eolian_type_type_get(eolian_type))
      {
      case EOLIAN_TYPE_VOID:
-       original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type), {}}, {}};
+       original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type), {}}, {}, false};
        break;
      case EOLIAN_TYPE_REGULAR:
        if (!stp)
@@ -305,6 +310,22 @@ inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* uni
      }
 }
 
+inline void type_def::set(Eolian_Expression_Type eolian_exp_type)
+{
+    switch(eolian_exp_type)
+      {
+      case EOLIAN_EXPR_INT:
+        original_type = attributes::regular_type_def{"int", {{}, {}}, {}, false};
+        c_type = "int";
+        break;
+      default:
+        // FIXME implement the remaining types
+        EINA_LOG_ERR("Unsupported expression type");
+        std::abort();
+        break;
+      }
+}
+
 enum class parameter_direction
 {
   in, inout, out
@@ -331,26 +352,23 @@ struct parameter_def
   parameter_direction direction;
   type_def type;
   std::string param_name;
-  std::string c_type;
 
   friend inline bool operator==(parameter_def const& lhs, parameter_def const& rhs)
   {
     return lhs.direction == rhs.direction
       && lhs.type == rhs.type
-      && lhs.param_name == rhs.param_name
-      && lhs.c_type == rhs.c_type;
+      && lhs.param_name == rhs.param_name;
   }
   friend inline bool operator!=(parameter_def const& lhs, parameter_def const& rhs)
   {
     return !(lhs == rhs);
   }
   
-  parameter_def(parameter_direction direction, type_def type, std::string param_name, std::string c_type)
-    : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)), c_type(std::move(c_type)) {}
+  parameter_def(parameter_direction direction, type_def type, std::string param_name)
+    : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)) {}
   parameter_def(Eolian_Function_Parameter const* param, Eolian_Unit const* unit)
     : type( ::eolian_parameter_type_get(param), unit, EOLIAN_C_TYPE_PARAM)
     , param_name( ::eolian_parameter_name_get(param))
-    , c_type( ::eolian_type_c_type_get(::eolian_parameter_type_get(param), EOLIAN_C_TYPE_PARAM))
   {
      Eolian_Parameter_Dir direction = ::eolian_parameter_direction_get(param);
      switch(direction)
@@ -396,8 +414,8 @@ template <>
 struct tuple_element<3ul, parameter_def>
 {
   typedef std::string type;
-  static type const& get(parameter_def const& p) { return p.c_type; }
-  static type& get(parameter_def& p) { return p.c_type; }
+  static type const& get(parameter_def const& p) { return p.type.c_type; }
+  static type& get(parameter_def& p) { return p.type.c_type; }
 };
 template <int I>
 typename tuple_element<I, parameter_def>::type const& get(parameter_def const& p)
@@ -412,6 +430,7 @@ struct function_def
   std::string name;
   std::vector<parameter_def> parameters;
   std::string c_name;
+  std::string filename;
   bool is_beta;
   bool is_protected;
 
@@ -421,6 +440,7 @@ struct function_def
       && lhs.name == rhs.name
       && lhs.parameters == rhs.parameters
       && lhs.c_name == rhs.c_name
+      && lhs.filename == rhs.filename
       && lhs.is_beta == rhs.is_beta
       && lhs.is_protected == rhs.is_protected;
   }
@@ -430,8 +450,8 @@ struct function_def
   }
   
   function_def(type_def return_type, std::string name, std::vector<parameter_def> parameters
-               , std::string c_name, bool is_beta)
-    : return_type(return_type), name(name), parameters(parameters), c_name(c_name), is_beta(is_beta) {}
+               , std::string c_name, std::string filename, bool is_beta)
+    : return_type(return_type), name(name), parameters(parameters), c_name(c_name), filename(filename), is_beta(is_beta) {}
   function_def() = default;
   function_def( ::Eolian_Function const* function, Eolian_Function_Type type, Eolian_Unit const* unit)
     : return_type(void_)
@@ -440,7 +460,7 @@ struct function_def
     name = ::eolian_function_name_get(function);
     if(r_type)
       return_type.set(r_type, unit, EOLIAN_C_TYPE_RETURN);
-     if(type == EOLIAN_METHOD)
+     if(type == EOLIAN_METHOD || type == EOLIAN_FUNCTION_POINTER)
        {
           for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator ( ::eolian_function_parameters_get(function))
             , param_last; param_iterator != param_last; ++param_iterator)
@@ -484,8 +504,18 @@ struct function_def
            parameters.insert(parameters.end(), values.begin(), values.end());
        }
      c_name = eolian_function_full_c_name_get(function, type, EINA_FALSE);
+     if (type != EOLIAN_FUNCTION_POINTER)
+       {
+          const Eolian_Class *klass = eolian_function_class_get(function);
+          filename = eolian_class_file_get(klass);
+       }
+     else
+       {
+          filename = "";
+       }
      is_beta = eolian_function_is_beta(function);
      is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED;
+     is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED;
   }
 };
 
@@ -606,20 +636,25 @@ auto get(event_def& def) -> decltype(tuple_element<N, event_def>::get(def))
   return tuple_element<N, event_def>::get(def);
 }
 
+inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit);
+
 struct klass_def
 {
   std::string eolian_name;
   std::string cxx_name;
+  std::string filename;
   std::vector<std::string> namespaces;
   std::vector<function_def> functions;
   std::set<klass_name, compare_klass_name_by_name> inherits;
   class_type type;
   std::vector<event_def> events;
+  std::set<klass_name, compare_klass_name_by_name> immediate_inherits;
 
   friend inline bool operator==(klass_def const& lhs, klass_def const& rhs)
   {
     return lhs.eolian_name == rhs.eolian_name
       && lhs.cxx_name == rhs.cxx_name
+      && lhs.filename == lhs.filename
       && lhs.namespaces == rhs.namespaces
       && lhs.functions == rhs.functions
       && lhs.inherits == rhs.inherits
@@ -631,14 +666,16 @@ struct klass_def
     return !(lhs == rhs);
   }
 
-  klass_def(std::string eolian_name, std::string cxx_name
+  klass_def(std::string eolian_name, std::string cxx_name, std::string filename
             , 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)
+            , class_type type
+            , std::set<klass_name, compare_klass_name_by_name> immediate_inherits)
+    : eolian_name(eolian_name), cxx_name(cxx_name), filename(filename)
     , namespaces(namespaces)
     , functions(functions), inherits(inherits), type(type)
+    , immediate_inherits(immediate_inherits)
   {}
   klass_def(Eolian_Class const* klass, Eolian_Unit const* unit)
   {
@@ -648,6 +685,7 @@ struct klass_def
           this->namespaces.push_back(&*namespace_iterator);
        }
      cxx_name = eolian_name = eolian_class_name_get(klass);
+     filename = eolian_class_file_get(klass);
      for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_PROPERTY))
        , functions_last; eolian_functions != functions_last; ++eolian_functions)
        {
@@ -684,6 +722,12 @@ struct klass_def
                functions.push_back({function, EOLIAN_METHOD, unit});
          } catch(std::exception const&) {}
        }
+     for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_inherits_get(klass))
+           , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
+       {
+         Eolian_Class const* inherit = &*inherit_iterator;
+         immediate_inherits.insert({inherit, {}});
+       }
      std::function<void(Eolian_Class const*)> inherit_algo = 
        [&] (Eolian_Class const* klass)
        {
@@ -722,6 +766,117 @@ struct klass_def
        }
   }
 
+  // TODO memoize the return?
+  std::vector<function_def> get_all_methods() const
+  {
+      std::vector<function_def> ret;
+
+      std::copy(functions.cbegin(), functions.cend(), std::back_inserter(ret));
+
+      for (auto inherit : inherits)
+       {
+          klass_def klass(get_klass(inherit, NULL), NULL);
+          std::copy(klass.functions.cbegin(), klass.functions.cend(),
+                    std::back_inserter(ret));
+       }
+
+      return ret;
+  }
+};
+
+struct value_def
+{
+  typedef eina::variant<int> variant_type; // FIXME support other types
+  variant_type value;
+  std::string literal;
+  type_def type;
+
+  value_def() {}
+  value_def(Eolian_Value value_obj)
+  {
+    type.set(value_obj.type);
+    value = value_obj.value.i;
+    literal = eolian_expression_value_to_literal(&value_obj);
+  }
+};
+
+struct enum_value_def
+{
+  value_def value;
+  std::string name;
+  std::string c_name;
+
+  enum_value_def(Eolian_Enum_Type_Field const* enum_field)
+  {
+      name = eolian_typedecl_enum_field_name_get(enum_field);
+      c_name = eolian_typedecl_enum_field_c_name_get(enum_field);
+      auto exp = eolian_typedecl_enum_field_value_get(enum_field, EINA_TRUE);
+      value = eolian_expression_eval(NULL, exp, EOLIAN_MASK_INT); // FIXME hardcoded int
+  }
+};
+
+struct enum_def
+{
+  std::string eolian_name;
+  std::string cxx_name;
+  std::vector<std::string> namespaces;
+  std::vector<enum_value_def> fields;
+
+  enum_def(Eolian_Typedecl const* enum_obj)
+  {
+     for(efl::eina::iterator<const char> namespace_iterator( ::eolian_typedecl_namespaces_get(enum_obj))
+           , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
+       {
+          this->namespaces.push_back((&*namespace_iterator));
+       }
+     cxx_name = eolian_name = eolian_typedecl_name_get(enum_obj);
+
+     for (efl::eina::iterator<const Eolian_Enum_Type_Field> field_iterator(::eolian_typedecl_enum_fields_get(enum_obj))
+             , field_last; field_iterator != field_last; ++field_iterator)
+       {
+          // Fill the types
+          this->fields.push_back(&*field_iterator);
+       }
+  }
+};
+
+struct struct_field_def
+{
+  type_def type;
+  std::string name;
+
+  struct_field_def(Eolian_Struct_Type_Field const* struct_field)
+  {
+     name = eolian_typedecl_struct_field_name_get(struct_field);
+     try {
+        type.set(eolian_typedecl_struct_field_type_get(struct_field), NULL, EOLIAN_C_TYPE_DEFAULT);
+     } catch(std::runtime_error const&) { /* Silently skip pointer fields*/ }
+  }
+
+};
+
+struct struct_def
+{
+  std::string eolian_name;
+  std::string cxx_name;
+  std::vector<std::string> namespaces;
+  std::vector<struct_field_def> fields;
+
+  struct_def(Eolian_Typedecl const* struct_obj)
+  {
+     for(efl::eina::iterator<const char> namespace_iterator( ::eolian_typedecl_namespaces_get(struct_obj))
+           , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
+       {
+          this->namespaces.push_back((&*namespace_iterator));
+       }
+     cxx_name = eolian_name = eolian_typedecl_name_get(struct_obj);
+
+     for(efl::eina::iterator<const Eolian_Struct_Type_Field> field_iterator(::eolian_typedecl_struct_fields_get(struct_obj))
+             , field_last; field_iterator != field_last; ++field_iterator)
+       {
+          this->fields.push_back(&*field_iterator);
+       }
+  }
 };
 
 inline klass_name get_klass_name(klass_def const& klass)
@@ -748,6 +903,80 @@ inline std::vector<std::string> cpp_namespaces(std::vector<std::string> namespac
   return namespaces;
 }
 
+inline bool has_events(klass_def const &klass)
+{
+    for (auto&& e : klass.events)
+      {
+         (void)e;
+         return true;
+      }
+
+    for (auto&& c : klass.inherits)
+      {
+        attributes::klass_def parent(get_klass(c, NULL), NULL);
+         for (auto&& e : parent.events)
+           {
+              (void)e;
+              return true;
+           }
+      }
+
+    return false;
+}
+
+template<typename T>
+inline bool has_type_return(klass_def const &klass, T visitor)
+{
+    for (auto&& f : klass.functions)
+      {
+         if (f.return_type.original_type.visit(visitor))
+           return true;
+      }
+
+    for (auto&& c : klass.inherits)
+      {
+        attributes::klass_def parent(get_klass(c, NULL), NULL);
+         if (has_type_return(parent, visitor))
+           return true;
+      }
+
+    return false;
+}
+
+struct string_return_visitor
+{
+    typedef string_return_visitor visitor_type;
+    typedef bool result_type;
+    template <typename T>
+    bool operator()(T const&) const { return false; }
+    bool operator()(regular_type_def const& regular) const
+    {
+        return regular.base_type == "string";
+    }
+};
+
+struct stringshare_return_visitor
+{
+    typedef stringshare_return_visitor visitor_type;
+    typedef bool result_type;
+    template <typename T>
+    bool operator()(T const&) const { return false; }
+    bool operator()(regular_type_def const& regular) const
+    {
+        return regular.base_type == "stringshare";
+    }
+};
+
+inline bool has_string_return(klass_def const &klass)
+{
+    return has_type_return(klass, string_return_visitor{});
+}
+
+inline bool has_stringshare_return(klass_def const &klass)
+{
+    return has_type_return(klass, stringshare_return_visitor{});
+}
+
 }
 namespace type_traits {
 
index 8c3088f..0aff2ba 100644 (file)
@@ -29,6 +29,8 @@ struct kleene_generator
 
 template <typename Generator>
 struct is_eager_generator<kleene_generator<Generator> > : std::true_type {};
+template <typename Generator>
+struct is_generator<kleene_generator<Generator> > : std::true_type {};
 
 namespace type_traits {
 template  <typename G>
index c8d9624..f87a771 100644 (file)
@@ -34,6 +34,8 @@ struct list_generator
 
 template <typename G, typename S>
 struct is_eager_generator<list_generator<G, S> > : std::true_type {};
+template <typename G, typename S>
+struct is_generator<list_generator<G, S> > : std::true_type {};
 
 namespace type_traits {
 template  <typename G, typename S>
index 5cef9ec..e16edca 100644 (file)
@@ -54,6 +54,8 @@ struct namespaces_directive
 
 template <typename G>
 struct is_eager_generator<namespaces_generator<G>> : std::true_type {};
+template <typename G>
+struct is_generator<namespaces_generator<G>> : std::true_type {};
 
 namespace type_traits {
 template <typename G>
index b29805e..f9e625a 100644 (file)
@@ -35,6 +35,8 @@ struct parameter_type_generator
 
 template <>
 struct is_eager_generator<parameter_type_generator> : std::true_type {};
+template <>
+struct is_generator<parameter_type_generator> : std::true_type {};
 namespace type_traits {
 template <>
 struct attributes_needed<parameter_type_generator> : std::integral_constant<int, 1> {};  
@@ -53,6 +55,8 @@ struct parameter_generator
 
 template <>
 struct is_eager_generator<parameter_generator> : std::true_type {};
+template <>
+struct is_generator<parameter_generator> : std::true_type {};
 namespace type_traits {
 template <>
 struct attributes_needed<parameter_generator> : std::integral_constant<int, 1> {};  
index 96fb467..dfffbf3 100644 (file)
@@ -115,6 +115,8 @@ struct sequence_generator
 
 template <typename L, typename R>
 struct is_eager_generator<sequence_generator<L, R> > : std::true_type {};
+template <typename L, typename R>
+struct is_generator<sequence_generator<L, R> > : std::true_type {};
 
 namespace type_traits {
 template  <typename  L, typename R>
index 77507ce..df4ae8f 100644 (file)
@@ -26,15 +26,6 @@ struct literal_generator
    const char* string;
 };
 
-template <>
-struct is_eager_generator<literal_generator> : std::true_type {};
-
-template <>
-struct is_generator<const char*> : std::true_type {};
-
-template <int N>
-struct is_generator<const char[N]> : std::true_type {};
-
 literal_generator as_generator(char const* literal) { return literal; }
 
 struct {
@@ -130,13 +121,6 @@ struct string_replace_generator
   char from, to;
 };
       
-template <>
-struct is_eager_generator<string_generator> : std::true_type {};
-template <>
-struct is_eager_generator<specific_string_generator> : std::true_type {};
-template <>
-struct is_eager_generator<string_replace_generator> : std::true_type {};
-
 struct string_generator_terminal
 {
   specific_string_generator operator[](std::string string) const
@@ -154,6 +138,28 @@ struct string_replace_terminal
 } const string_replace = {};
       
 template <>
+struct is_eager_generator<literal_generator> : std::true_type {};
+template <>
+struct is_generator<literal_generator> : std::true_type {};
+template <>
+struct is_generator<const char*> : std::true_type {};
+
+template <int N>
+struct is_generator<const char[N]> : std::true_type {};
+template <>
+struct is_eager_generator<string_generator> : std::true_type {};
+template <>
+struct is_eager_generator<specific_string_generator> : std::true_type {};
+template <>
+struct is_eager_generator<string_replace_generator> : std::true_type {};
+template <>
+struct is_generator<string_generator> : std::true_type {};
+template <>
+struct is_generator<specific_string_generator> : std::true_type {};
+template <>
+struct is_generator<string_replace_generator> : std::true_type {};
+
+template <>
 struct is_generator<string_generator_terminal> : std::true_type {};
 template <>
 struct is_generator<std::string> : std::true_type {};
index 8a09b6e..61e0e55 100644 (file)
@@ -23,7 +23,7 @@ struct type_generator
    template <typename OutputIterator, typename Context>
    bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
    {
-      return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.c_type
+      return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
             , param.direction != attributes::parameter_direction::in, false});
    }
 
@@ -46,6 +46,8 @@ type_generator const as_generator(type_terminal)
 template <>
 struct is_eager_generator<type_generator> : std::true_type {};
 template <>
+struct is_generator<type_generator> : std::true_type {};
+template <>
 struct is_generator<type_terminal> : std::true_type {};
 
 namespace type_traits {