1 /*
2  * Copyright 2019 by its authors. See AUTHORS.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef EOLIAN_CXX_KLASS_DEF_HH
17 #define EOLIAN_CXX_KLASS_DEF_HH
18 
19 #include "grammar/type_traits.hpp"
20 #include "grammar/attributes.hpp"
21 #include "grammar/qualifier_def.hpp"
22 #include "grammar/string.hpp"
23 #include "grammar/sequence.hpp"
24 #include "grammar/kleene.hpp"
25 #include "grammar/case.hpp"
26 
27 #include <Eolian.h>
28 
29 #include <Eina.hh>
30 
31 #include <vector>
32 #include <memory>
33 #include <set>
34 #include <iosfwd>
35 #include <string>
36 
37 namespace efl { namespace eolian { namespace grammar {
38 
39 namespace attributes {
40 
41 struct complex_type_def;
42 
43 }
44 
45 namespace attributes {
46 
47 template <typename...Args, std::size_t I>
lexicographical_compare_impl(std::tuple<Args...> const &,std::tuple<Args...> const &,std::integral_constant<std::size_t,I>,std::true_type)48 bool lexicographical_compare_impl(std::tuple<Args...> const&
49                                   , std::tuple<Args...> const&
50                                   , std::integral_constant<std::size_t, I>
51                                   , std::true_type)
52 {
53   return true;
54 }
55 template <typename...Args, std::size_t I>
lexicographical_compare_impl(std::tuple<Args...> const & lhs,std::tuple<Args...> const & rhs,std::integral_constant<std::size_t,I>,std::false_type)56 bool lexicographical_compare_impl(std::tuple<Args...> const& lhs
57                                   , std::tuple<Args...> const& rhs
58                                   , std::integral_constant<std::size_t, I>
59                                   , std::false_type)
60 {
61   return std::get<I>(lhs) < std::get<I>(rhs)
62       || (!(std::get<I>(rhs) < std::get<I>(lhs))
63           && lexicographical_compare_impl(lhs, rhs, std::integral_constant<std::size_t, I+1>()
64                                           , std::integral_constant<bool, I + 1 == sizeof...(Args)>())
65          )
66     ;
67 }
68 template <typename...Args>
lexicographical_compare(std::tuple<Args...> const & lhs,std::tuple<Args...> const & rhs)69 bool lexicographical_compare(std::tuple<Args...> const& lhs
70                              , std::tuple<Args...> const& rhs)
71 {
72   return lexicographical_compare_impl(lhs, rhs, std::integral_constant<std::size_t, 0ul>(), std::false_type());
73 }
74 template <typename T, typename U>
lexicographical_compare(std::tuple<T,U> const & lhs,std::tuple<T,U> const & rhs)75 bool lexicographical_compare(std::tuple<T, U> const& lhs
76                              , std::tuple<T, U> const& rhs)
77 {
78   return std::get<0>(lhs) < std::get<0>(rhs)
79        || (!(std::get<0>(rhs) < std::get<0>(lhs))
80           && std::get<1>(lhs) < std::get<1>(rhs));
81 }
82 
83 enum class typedecl_type
84 {
85   unknown,
86   struct_,
87   struct_opaque,
88   enum_,
89   alias,
90   function_ptr,
91 };
92 
operator <<(std::ostream & s,typedecl_type dec)93 inline std::ostream& operator<<(std::ostream& s, typedecl_type dec)
94 {
95   switch(dec)
96   {
97   case typedecl_type::unknown:
98     return s << "unknown";
99   case typedecl_type::struct_:
100     return s << "struct_";
101   case typedecl_type::struct_opaque:
102     return s << "struct_opaque";
103   case typedecl_type::enum_:
104     return s << "enum_";
105   case typedecl_type::alias:
106     return s << "alias";
107   case typedecl_type::function_ptr:
108     return s << "function_ptr";
109   };
110   return s;
111 }
112 
typedecl_type_get(Eolian_Typedecl const * decl)113 inline typedecl_type typedecl_type_get(Eolian_Typedecl const* decl)
114 {
115   if (!decl)
116     return typedecl_type::unknown;
117 
118   Eolian_Typedecl_Type t = eolian_typedecl_type_get(decl);
119   switch (t)
120   {
121   case EOLIAN_TYPEDECL_UNKNOWN: return typedecl_type::unknown;
122   case EOLIAN_TYPEDECL_STRUCT: return typedecl_type::struct_;
123   case EOLIAN_TYPEDECL_STRUCT_OPAQUE: return typedecl_type::struct_opaque;
124   case EOLIAN_TYPEDECL_ENUM: return typedecl_type::enum_;
125   case EOLIAN_TYPEDECL_ALIAS: return typedecl_type::alias;
126   case EOLIAN_TYPEDECL_FUNCTION_POINTER: return typedecl_type::function_ptr;
127   default: return typedecl_type::unknown;
128   }
129 }
130 
131 
132 struct type_def;
133 bool operator==(type_def const& lhs, type_def const& rhs);
134 bool operator!=(type_def const& lhs, type_def const& rhs);
135 
136 enum class class_type
137 {
138   regular, abstract_, mixin, interface_
139 };
140 
operator <<(std::ostream & s,class_type t)141 inline std::ostream& operator<<(std::ostream& s, class_type t)
142 {
143   switch(t)
144   {
145   case class_type::regular:
146     return s << "regular";
147   case class_type::abstract_:
148     return s << "abstract_";
149   case class_type::mixin:
150     return s << "mixin";
151   case class_type::interface_:
152     return s << "interface_";
153   };
154   return s;
155 }
156 
157 struct klass_name
158 {
159    std::vector<std::string> namespaces;
160    std::string eolian_name;
161    qualifier_def base_qualifier;
162    class_type type;
163    std::string klass_get_name;
164    bool is_beta;
165 
operator <<(std::ostream & s,klass_name const & name)166    friend inline std::ostream& operator<<(std::ostream& s, klass_name const& name)
167    {
168      s << "[ namespaces: {";
169      std::copy(name.namespaces.begin(), name.namespaces.end(), std::ostream_iterator<std::string>(s, ","));
170      return s << "}, eolian_name: " << name.eolian_name << " base_qualifier: " << name.base_qualifier
171               << " type: " << name.type << " klass_get_name: " << name.klass_get_name << "]";
172    }
173 
klass_nameefl::eolian::grammar::attributes::klass_name174    klass_name() {
175    }
176 
klass_nameefl::eolian::grammar::attributes::klass_name177    klass_name(std::vector<std::string> namespaces
178               , std::string eolian_name, qualifier_def base_qualifier
179               , class_type type, std::string klass_get_name, bool is_beta)
180      : namespaces(namespaces), eolian_name(eolian_name), base_qualifier(base_qualifier)
181      , type(type), klass_get_name(klass_get_name), is_beta(is_beta) {}
klass_nameefl::eolian::grammar::attributes::klass_name182    klass_name(Eolian_Class const* klass, qualifier_def base_qualifier)
183      : eolian_name( ::eolian_class_short_name_get(klass))
184               , base_qualifier(base_qualifier)
185               , klass_get_name( ::eolian_class_c_get_function_name_get(klass))
186               , is_beta(::eolian_object_is_beta(EOLIAN_OBJECT(klass)))
187    {
188      for(efl::eina::iterator<const char> namespace_iterator ( ::eolian_class_namespaces_get(klass))
189            , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
190        {
191          namespaces.push_back(&*namespace_iterator);
192        }
193      switch(eolian_class_type_get(klass))
194        {
195        case EOLIAN_CLASS_REGULAR:
196          type = class_type::regular;
197          break;
198        case EOLIAN_CLASS_ABSTRACT:
199          type = class_type::abstract_;
200          break;
201        case EOLIAN_CLASS_MIXIN:
202          type = class_type::mixin;
203          break;
204        case EOLIAN_CLASS_INTERFACE:
205          type = class_type::interface_;
206          break;
207        default:
208          throw std::runtime_error("Class with unknown type");
209        }
210    }
211 };
212 
operator ==(klass_name const & lhs,klass_name const & rhs)213 inline bool operator==(klass_name const& lhs, klass_name const& rhs)
214 {
215   return lhs.namespaces == rhs.namespaces && lhs.eolian_name == rhs.eolian_name
216     && lhs.base_qualifier == rhs.base_qualifier/* && lhs.pointers == rhs.pointers*/;
217 }
operator !=(klass_name const & lhs,klass_name const & rhs)218 inline bool operator!=(klass_name const& lhs, klass_name const& rhs)
219 {
220   return !(lhs == rhs);
221 }
operator <(klass_name const & lhs,klass_name const & rhs)222 inline bool operator<(klass_name const& lhs, klass_name const& rhs)
223 {
224   typedef std::tuple<std::vector<std::string>const&
225                      , std::string const&
226                      , qualifier_def const&
227                      , class_type
228                      > tuple_type;
229   return lexicographical_compare(tuple_type(lhs.namespaces, lhs.eolian_name
230                                             , lhs.base_qualifier
231                                             , lhs.type)
232                                  , tuple_type(rhs.namespaces, rhs.eolian_name
233                                               , rhs.base_qualifier
234                                               , rhs.type));
235 }
236 
237 struct documentation_def
238 {
239    std::string summary;
240    std::string description;
241    std::string since;
242    std::vector<std::string> desc_paragraphs;
243    std::string full_text;
244 
245    documentation_def() = default;
documentation_defefl::eolian::grammar::attributes::documentation_def246    documentation_def(std::string summary, std::string description, std::string since, std::string full_text)
247      : summary(summary), description(description), since(since), full_text(full_text)
248    {}
documentation_defefl::eolian::grammar::attributes::documentation_def249    documentation_def(Eolian_Documentation const* eolian_doc)
250    {
251       const char *str;
252 
253       if (!eolian_doc)
254         return;
255 
256       str = eolian_documentation_summary_get(eolian_doc);
257       if (str)
258         full_text = summary = str;
259 
260       str = eolian_documentation_description_get(eolian_doc);
261       if (str) {
262         description = str;
263         // Separate summary from description with a blank line
264         full_text += "\n\n" + description;
265       }
266 
267       str = eolian_documentation_since_get(eolian_doc);
268       if (str) {
269         since = str;
270       }
271 
272       efl::eina::ptr_list<const char, efl::eina::malloc_clone_allocator>
273         l(eolian_documentation_string_split(description.c_str()));
274       for (auto&& i : l)
275         desc_paragraphs.push_back({&i});
276    }
277 
operator ==(documentation_def const & lhs,documentation_def const & rhs)278    friend inline bool operator==(documentation_def const& lhs, documentation_def const& rhs)
279    {
280       return lhs.summary == rhs.summary
281         && lhs.description == rhs.description
282         && lhs.since == rhs.since;
283    }
284 };
285 
286 template <>
287 struct tuple_element<0ul, klass_name>
288 {
289   typedef std::vector<std::string> type;
getefl::eolian::grammar::attributes::tuple_element290   static type& get(klass_name& klass) { return klass.namespaces; }
getefl::eolian::grammar::attributes::tuple_element291   static type const& get(klass_name const& klass) { return klass.namespaces; }
292 };
293 template <>
294 struct tuple_element<1ul, klass_name>
295 {
296   typedef std::string type;
getefl::eolian::grammar::attributes::tuple_element297   static type& get(klass_name& klass) { return klass.eolian_name; }
getefl::eolian::grammar::attributes::tuple_element298   static type const& get(klass_name const& klass) { return klass.eolian_name; }
299 };
300 template <int N>
301 struct tuple_element<N, klass_name const> : tuple_element<N, klass_name> {};
302 
303 template <int N>
304 typename tuple_element<N, klass_name>::type&
get(klass_name & klass)305 get(klass_name& klass)
306 {
307   return tuple_element<N, klass_name>::get(klass);
308 }
309 template <int N>
310 typename tuple_element<N, klass_name>::type const&
get(klass_name const & klass)311 get(klass_name const& klass)
312 {
313   return tuple_element<N, klass_name>::get(klass);
314 }
315 
316 struct regular_type_def
317 {
regular_type_defefl::eolian::grammar::attributes::regular_type_def318    regular_type_def() : type_type(typedecl_type::unknown), is_undefined(false) {}
regular_type_defefl::eolian::grammar::attributes::regular_type_def319    regular_type_def(std::string base_type, qualifier_def qual, std::vector<std::string> namespaces
320                     , typedecl_type type_type = typedecl_type::unknown, bool is_undefined = false)
321      : base_type(std::move(base_type)), base_qualifier(qual), namespaces(std::move(namespaces))
322      , type_type(type_type), is_undefined(is_undefined) {}
323 
is_typeefl::eolian::grammar::attributes::regular_type_def324    bool is_type(typedecl_type tt) const { return type_type == tt; }
is_unknownefl::eolian::grammar::attributes::regular_type_def325    bool is_unknown() const { return is_type(typedecl_type::unknown); }
is_structefl::eolian::grammar::attributes::regular_type_def326    bool is_struct() const { return is_type(typedecl_type::struct_); }
is_struct_opaqueefl::eolian::grammar::attributes::regular_type_def327    bool is_struct_opaque() const { return is_type(typedecl_type::struct_opaque); }
is_enumefl::eolian::grammar::attributes::regular_type_def328    bool is_enum() const { return is_type(typedecl_type::enum_); }
is_aliasefl::eolian::grammar::attributes::regular_type_def329    bool is_alias() const { return is_type(typedecl_type::alias); }
is_function_ptrefl::eolian::grammar::attributes::regular_type_def330    bool is_function_ptr() const { return is_type(typedecl_type::function_ptr); }
331 
operator <<(std::ostream & s,regular_type_def const & def)332    friend inline std::ostream& operator<<(std::ostream& s, regular_type_def const& def)
333    {
334      s << "[ base_type: " << def.base_type << " base_qualifier: " << def.base_qualifier
335        << " namespaces: ";
336      std::copy(def.namespaces.begin(), def.namespaces.end(), std::ostream_iterator<std::string>(s, ", "));
337      return s << " type_type: " << def.type_type << " is_undefined " << def.is_undefined << "]";
338    }
339 
340    std::string base_type;
341    qualifier_def base_qualifier;
342    std::vector<std::string> namespaces;
343    typedecl_type type_type;
344    bool is_undefined;
345 };
346 
operator ==(regular_type_def const & rhs,regular_type_def const & lhs)347 inline bool operator==(regular_type_def const& rhs, regular_type_def const& lhs)
348 {
349   return rhs.base_type == lhs.base_type && rhs.base_qualifier == lhs.base_qualifier;
350 }
operator !=(regular_type_def const & rhs,regular_type_def const & lhs)351 inline bool operator!=(regular_type_def const& rhs, regular_type_def const& lhs)
352 {
353   return !(rhs == lhs);
354 }
355 
356 struct complex_type_def
357 {
358    regular_type_def outer;
359    std::vector<type_def> subtypes;
360 
operator <<(std::ostream & s,complex_type_def const & def)361    friend inline std::ostream& operator<<(std::ostream& s, complex_type_def const& def)
362    {
363      s << "[ outer " << def.outer << " subtypes: {";
364      std::copy(def.subtypes.begin(), def.subtypes.end(), std::ostream_iterator<type_def>(s, ", "));
365      return s << "}]";
366    }
367 };
368 
operator ==(complex_type_def const & lhs,complex_type_def const & rhs)369 inline bool operator==(complex_type_def const& lhs, complex_type_def const& rhs)
370 {
371   return lhs.outer == rhs.outer && lhs.subtypes == rhs.subtypes;
372 }
operator !=(complex_type_def const & lhs,complex_type_def const & rhs)373 inline bool operator!=(complex_type_def const& lhs, complex_type_def const& rhs)
374 {
375   return !(lhs == rhs);
376 }
377 
378 namespace value_ownership
379 {
380     const bool moved = true;
381     const bool unmoved = false;
382 };
383 
384 namespace is_by
385 {
386     const bool reference = true;
387     const bool value = false;
388 };
389 
390 // type_def represents a type where it is used, like a method parameter or a struc field, in contrast to more
391 // specifict types like struct_def, class_def, function_def, which represents a declaration of a type.
392 struct type_def
393 {
394    typedef eina::variant<klass_name, regular_type_def, complex_type_def> variant_type;
395    variant_type original_type;
396    std::string c_type;
397    bool has_own;
398    bool is_ptr;
399    bool is_beta;
400    std::string doc_summary;
401    bool is_value_type;
402 
403    type_def() = default;
type_defefl::eolian::grammar::attributes::type_def404    type_def(variant_type original_type, std::string c_type, bool has_own, bool is_ptr, bool is_beta, std::string doc_summary)
405      : original_type(original_type), c_type(c_type), has_own(has_own), is_ptr(is_ptr), is_beta(is_beta), doc_summary(doc_summary) {}
406 
type_defefl::eolian::grammar::attributes::type_def407    type_def(Eolian_Type const* eolian_type, Eolian_Unit const* unit, std::string const& ctype, bool is_moved, bool is_reference)
408    {
409      set(eolian_type, unit, ctype, is_moved, is_reference);
410    }
411    void set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, std::string const & ctype, bool is_moved, bool is_reference);
412    void set(Eolian_Expression_Type eolian_exp_type);
413 
operator <(type_def const & lhs,type_def const & rhs)414    friend inline bool operator<(type_def const& lhs, type_def const& rhs)
415    {
416       return lhs.c_type < rhs.c_type;
417    }
operator <<(std::ostream & s,type_def const & rhs)418    friend inline std::ostream& operator<<(std::ostream& s, type_def const& rhs)
419    {
420       return s << "[ original: " << rhs.original_type << " c_type "
421                << rhs.c_type << " has_own " << rhs.has_own << " is_ptr "
422                << rhs.is_ptr << "]";
423    }
424 
425 private:
426    void set(const char* regular_name, const char* c_type);
427 };
428 
429 struct get_qualifier_visitor
430 {
431   typedef qualifier_def result_type;
432   template <typename T>
operator ()efl::eolian::grammar::attributes::get_qualifier_visitor433   qualifier_def operator()(T const& object) const
434   {
435      return object.base_qualifier;
436   }
operator ()efl::eolian::grammar::attributes::get_qualifier_visitor437   qualifier_def operator()(complex_type_def const& complex) const
438   {
439     return complex.outer.base_qualifier;
440   }
441 };
442 
operator ==(type_def const & lhs,type_def const & rhs)443 inline bool operator==(type_def const& lhs, type_def const& rhs)
444 {
445   return lhs.original_type == rhs.original_type && lhs.c_type == rhs.c_type;
446 }
operator !=(type_def const & lhs,type_def const & rhs)447 inline bool operator!=(type_def const& lhs, type_def const& rhs)
448 {
449   return !(lhs == rhs);
450 }
451 
452 type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}}, "void", false, false, false, ""};
453 
set(Eolian_Type const * eolian_type,Eolian_Unit const * unit,std::string const & ctype,bool is_moved,bool is_reference)454 inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, std::string const& ctype, bool is_moved, bool is_reference)
455 {
456    c_type = ctype;
457    is_value_type = ('*' != c_type.back());
458    // ::eina_stringshare_del(stringshare); // this crashes
459    Eolian_Type const* stp = eolian_type_base_type_get(eolian_type);
460    has_own = is_moved;
461 
462    is_ptr = is_reference || eolian_type_is_ptr(eolian_type);
463 
464    Eolian_Typedecl const* decl = eolian_type_typedecl_get(eolian_type);
465    is_beta = decl && eolian_object_is_beta(EOLIAN_OBJECT(decl));
466    if (decl)
467      {
468         documentation_def documentation = eolian_typedecl_documentation_get(decl);
469         doc_summary = documentation.summary;
470      }
471    switch( ::eolian_type_type_get(eolian_type))
472      {
473      case EOLIAN_TYPE_VOID:
474        original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type, is_moved, is_ptr), {}}, {}};
475        break;
476      case EOLIAN_TYPE_REGULAR:
477        if (!stp)
478          {
479            bool is_undefined = false;
480            Eolian_Typedecl const* decl = eolian_type_typedecl_get(eolian_type);
481            typedecl_type type_type = (decl ? typedecl_type_get(decl) : typedecl_type::unknown);
482            if(decl && eolian_typedecl_type_get(decl) == EOLIAN_TYPEDECL_ALIAS)
483              {
484                Eolian_Type const* aliased = eolian_typedecl_base_type_get(decl);
485                if(aliased && eolian_type_type_get(aliased) == EOLIAN_TYPE_UNDEFINED)
486                  {
487                    is_undefined = true;
488                  }
489              }
490            if(c_type == "va_list *")
491              throw std::runtime_error("");
492            std::vector<std::string> namespaces;
493            for(efl::eina::iterator<const char> namespace_iterator( ::eolian_type_namespaces_get(eolian_type))
494                  , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
495              namespaces.push_back(&*namespace_iterator);
496            original_type = {regular_type_def{ ::eolian_type_short_name_get(eolian_type), {qualifiers(eolian_type, is_moved, is_ptr), {}}, namespaces, type_type, is_undefined}};
497          }
498        else
499          {
500            complex_type_def complex
501             {{::eolian_type_short_name_get(eolian_type), {qualifiers(eolian_type, is_moved, is_ptr), {}}, {}}, {}};
502            while (stp)
503              {
504                 complex.subtypes.push_back({stp
505                                             , unit
506                                             , ::eolian_type_c_type_get(stp)
507                                             , static_cast<bool>(eolian_type_is_move(stp))
508                                             , is_by::value});
509                 stp = eolian_type_next_type_get(stp);
510              }
511            original_type = complex;
512          }
513        break;
514      case EOLIAN_TYPE_CLASS:
515        {
516           Eolian_Class const* klass = eolian_type_class_get(eolian_type);
517           original_type = klass_name(klass, {qualifiers(eolian_type, is_moved, is_ptr), {}});
518        }
519        break;
520      default:
521        throw std::runtime_error("Type not supported");
522        break;
523      }
524 }
525 
set(Eolian_Expression_Type eolian_exp_type)526 inline void type_def::set(Eolian_Expression_Type eolian_exp_type)
527 {
528     switch(eolian_exp_type)
529       {
530       case EOLIAN_EXPR_INT:
531         set("int", "int");
532         break;
533       case EOLIAN_EXPR_UINT:
534         set("uint", "unsigned int");
535         break;
536       case EOLIAN_EXPR_FLOAT:
537         set("float", "float");
538         break;
539       case EOLIAN_EXPR_DOUBLE:
540         set("double", "double");
541         break;
542       case EOLIAN_EXPR_STRING:
543         set("string", "const char *");
544         break;
545       case EOLIAN_EXPR_BOOL:
546         set("bool", "Eina_Bool");
547         break;
548       case EOLIAN_EXPR_NULL:
549         set("null", "void *");
550         break;
551       default:
552         // FIXME implement the remaining types
553         EINA_LOG_ERR("Unsupported expression type : %d", eolian_exp_type);
554         std::abort();
555         break;
556       }
557 }
558 
set(const char * regular_name,const char * c_type)559 inline void type_def::set(const char* regular_name, const char* c_type)
560 {
561     original_type = attributes::regular_type_def{regular_name, {{}, {}}, {}};
562     this->c_type = c_type;
563 }
564 
565 struct alias_def
566 {
567   std::string eolian_name;
568   std::string cxx_name;
569   std::vector<std::string> namespaces;
570   bool is_undefined;
571   type_def base_type {};
572   documentation_def documentation;
573   bool is_beta;
574 
alias_defefl::eolian::grammar::attributes::alias_def575   alias_def(Eolian_Typedecl const* alias_obj, Eolian_Unit const* unit)
576       : is_beta(::eolian_typedecl_is_beta(alias_obj))
577   {
578      cxx_name = eolian_name = ::eolian_typedecl_short_name_get(alias_obj);
579 
580      for(efl::eina::iterator<const char> namespace_iterator( ::eolian_typedecl_namespaces_get(alias_obj))
581           , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
582        {
583           this->namespaces.push_back((&*namespace_iterator));
584        }
585 
586      Eolian_Type const* bt = ::eolian_typedecl_base_type_get(alias_obj);
587      if (eolian_type_type_get(bt) == EOLIAN_TYPE_UNDEFINED)
588        is_undefined = true;
589      else
590        {
591           auto eolian_type = ::eolian_typedecl_base_type_get(alias_obj);
592           base_type = type_def(eolian_type
593                                , unit
594                                , ::eolian_type_c_type_get(eolian_type)
595                                , value_ownership::unmoved
596                                , is_by::value);
597           is_undefined = false;
598        }
599 
600      documentation = ::eolian_typedecl_documentation_get(alias_obj);
601   }
602 };
603 
604 enum class parameter_direction
605 {
606   unknown, in, inout, out
607 };
608 
609 namespace detail {
610 struct add_optional_qualifier_visitor
611 {
612   typedef void result_type;
613   template <typename T>
operator ()efl::eolian::grammar::attributes::detail::add_optional_qualifier_visitor614   void operator()(T&  object) const
615   {
616     object.base_qualifier.qualifier |= qualifier_info::is_optional;
617   }
operator ()efl::eolian::grammar::attributes::detail::add_optional_qualifier_visitor618   void operator()(complex_type_def& complex) const
619   {
620     (*this)(complex.outer);
621   }
622 };
623 }
624 
625 struct value_def
626 {
627   typedef eina::variant<int> variant_type; // FIXME support other types
628   variant_type value;
629   std::string literal;
630   type_def type;
631 
632   value_def() = default;
value_defefl::eolian::grammar::attributes::value_def633   value_def(Eolian_Value value_obj)
634   {
635     type.set(value_obj.type);
636     value = value_obj.value.i;
637     literal = eolian_expression_value_to_literal(&value_obj);
638   }
639 };
640 
641 
642 struct expression_def
643 {
644   value_def value;
645   std::string serialized;
646   // We store this explicitly as evaluating the value reduces a name reference
647   // to a plain string value.
648   bool is_name_ref;
649 
operator ==(expression_def const & lhs,expression_def const & rhs)650   friend inline bool operator==(expression_def const& lhs, expression_def const& rhs)
651   {
652     return lhs.serialized == rhs.serialized;
653   }
operator !=(expression_def const & lhs,expression_def const & rhs)654   friend inline bool operator!=(expression_def const& lhs, expression_def const& rhs)
655   {
656     return !(lhs == rhs);
657   }
658 
expression_defefl::eolian::grammar::attributes::expression_def659   expression_def(Eolian_Expression const* expression) : value(::eolian_expression_eval(expression, EOLIAN_MASK_ALL))
660                                                 , serialized()
661                                                 , is_name_ref(::eolian_expression_type_get(expression) == EOLIAN_EXPR_NAME)
662   {
663     auto serialized_s = ::eolian_expression_serialize(expression);
664     serialized = serialized_s;
665     ::eina_stringshare_del(serialized_s);
666   }
667 };
668 
669 struct parameter_def
670 {
671   parameter_direction direction;
672   type_def type;
673   std::string param_name;
674   documentation_def documentation;
675   eina::optional<expression_def> default_value;
676   Eolian_Unit const* unit;
677 
operator ==(parameter_def const & lhs,parameter_def const & rhs)678   friend inline bool operator==(parameter_def const& lhs, parameter_def const& rhs)
679   {
680     return lhs.direction == rhs.direction
681       && lhs.type == rhs.type
682       && lhs.param_name == rhs.param_name
683       && lhs.documentation == rhs.documentation
684       && lhs.default_value == rhs.default_value;
685   }
operator !=(parameter_def const & lhs,parameter_def const & rhs)686   friend inline bool operator!=(parameter_def const& lhs, parameter_def const& rhs)
687   {
688     return !(lhs == rhs);
689   }
690 
parameter_defefl::eolian::grammar::attributes::parameter_def691   parameter_def(parameter_direction direction, type_def type, std::string param_name,
692                 documentation_def documentation, Eolian_Unit const* unit)
693     : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)), documentation(documentation), unit(unit) {}
parameter_defefl::eolian::grammar::attributes::parameter_def694   parameter_def(Eolian_Function_Parameter const* param, Eolian_Unit const* _unit)
695     : type( ::eolian_parameter_type_get(param)
696             , _unit
697             , eolian_parameter_c_type_get(param, EINA_FALSE)
698             , eolian_parameter_is_move(param)
699             , eolian_parameter_is_by_ref(param))
700     , param_name( ::eolian_parameter_name_get(param))
701     , default_value(::eolian_parameter_default_value_get(param) ?
702                         ::eolian_parameter_default_value_get(param) :
703                         eina::optional<expression_def>{})
704     , unit(_unit)
705   {
706      Eolian_Parameter_Direction direction = ::eolian_parameter_direction_get(param);
707      switch(direction)
708        {
709        case EOLIAN_PARAMETER_UNKNOWN:
710        case EOLIAN_PARAMETER_IN:
711          this->direction = parameter_direction::in;
712          break;
713        case EOLIAN_PARAMETER_INOUT:
714          this->direction = parameter_direction::inout;
715          break;
716        case EOLIAN_PARAMETER_OUT:
717          this->direction = parameter_direction::out;
718          break;
719        }
720      if( ::eolian_parameter_is_optional(param))
721        type.original_type.visit(detail::add_optional_qualifier_visitor{});
722 
723      documentation = eolian_parameter_documentation_get(param);
724   }
725 };
726 
727 template <>
728 struct tuple_element<0ul, parameter_def>
729 {
730   typedef parameter_direction type;
getefl::eolian::grammar::attributes::tuple_element731   static type const& get(parameter_def const& p) { return p.direction; }
getefl::eolian::grammar::attributes::tuple_element732   static type& get(parameter_def& p) { return p.direction; }
733 };
734 template <>
735 struct tuple_element<1ul, parameter_def>
736 {
737   typedef type_def type;
getefl::eolian::grammar::attributes::tuple_element738   static type const& get(parameter_def const& p) { return p.type; }
getefl::eolian::grammar::attributes::tuple_element739   static type& get(parameter_def& p) { return p.type; }
740 };
741 template <>
742 struct tuple_element<2ul, parameter_def>
743 {
744   typedef std::string type;
getefl::eolian::grammar::attributes::tuple_element745   static type const& get(parameter_def const& p) { return p.param_name; }
getefl::eolian::grammar::attributes::tuple_element746   static type& get(parameter_def& p) { return p.param_name; }
747 };
748 template <>
749 struct tuple_element<3ul, parameter_def>
750 {
751   typedef std::string type;
getefl::eolian::grammar::attributes::tuple_element752   static type const& get(parameter_def const& p) { return p.type.c_type; }
getefl::eolian::grammar::attributes::tuple_element753   static type& get(parameter_def& p) { return p.type.c_type; }
754 };
755 template <int I>
get(parameter_def const & p)756 typename tuple_element<I, parameter_def>::type const& get(parameter_def const& p)
757 { return tuple_element<I, parameter_def>::get(p); }
758 template <int I>
get(parameter_def & p)759 typename tuple_element<I, parameter_def>::type& get(parameter_def& p)
760 { return tuple_element<I, parameter_def>::get(p); }
761 
762 enum class function_type
763 {
764   unresolved,
765   property,
766   prop_set,
767   prop_get,
768   method,
769   function_pointer
770 };
771 
772 enum class member_scope
773 {
774    scope_unknown,
775    scope_public,
776    scope_private,
777    scope_protected,
778 };
779 
780 struct function_def
781 {
782   // Klass information for function_def as method
783   klass_name klass;
784   // Eolian name of the function
785   std::string name;
786 
787   // Actual return type as expected in the C version of this function.
788   // For property getters, this could be the type of the single
789   // value it holds
790   type_def return_type;
791   // Parameters of this function as the C implementation of it
792   std::vector<parameter_def> parameters;
793 
794   // Original return type as declared in the Eo.
795   type_def explicit_return_type;
796   // Original Eolian keys of this function. Used only for properties
797   std::vector<parameter_def> keys;
798   // Original Eolian values of this function. Used only for properties
799   std::vector<parameter_def> values;
800 
801   // Name of this function in the C api
802   std::string c_name;
803   std::string filename;
804   // Namespaces for top-level function pointers
805   std::vector<std::string> namespaces;
806 
807   documentation_def documentation;
808   documentation_def return_documentation;
809   documentation_def property_documentation;
810 
811   function_type type;
812   member_scope scope;
813   bool is_beta;
814   bool is_protected;
815   bool is_static;
816   Eolian_Unit const* unit;
817 
operator ==(function_def const & lhs,function_def const & rhs)818   friend inline bool operator==(function_def const& lhs, function_def const& rhs)
819   {
820     return lhs.klass == rhs.klass
821       && lhs.return_type == rhs.return_type
822       && lhs.name == rhs.name
823       && lhs.parameters == rhs.parameters
824       && lhs.keys == rhs.keys
825       && lhs.values == rhs.values
826       && lhs.c_name == rhs.c_name
827       && lhs.filename == rhs.filename
828       && lhs.namespaces == rhs.namespaces
829       && lhs.documentation == rhs.documentation
830       && lhs.return_documentation == rhs.return_documentation
831       && lhs.property_documentation == rhs.property_documentation
832       && lhs.type == rhs.type
833       && lhs.scope == rhs.scope
834       && lhs.is_beta == rhs.is_beta
835       && lhs.is_protected == rhs.is_protected
836       && lhs.is_static == rhs.is_static;
837   }
operator !=(function_def const & lhs,function_def const & rhs)838   friend inline bool operator!=(function_def const& lhs, function_def const& rhs)
839   {
840     return !(lhs == rhs);
841   }
842   function_def() = default;
843 
function_defefl::eolian::grammar::attributes::function_def844   function_def( ::Eolian_Function const* function, Eolian_Function_Type type, Eolian_Typedecl const* tp, Eolian_Unit const* unit)
845     : return_type(void_), explicit_return_type(void_), unit(unit)
846   {
847      Eolian_Type const* r_type = ::eolian_function_return_type_get(function, type);
848      name = ::eolian_function_name_get(function);
849      return_documentation = eolian_function_return_documentation_get(function, type);
850      scope = static_cast<member_scope>(eolian_function_scope_get(function, type));
851 
852      if(r_type)
853        {
854           return_type.set(r_type
855                          , unit
856                          , eolian_function_return_c_type_get(function, type)
857                          , eolian_function_return_is_move(function, type)
858                          , eolian_function_return_is_by_ref(function, type));
859           explicit_return_type = return_type;
860        }
861 
862      if(type == EOLIAN_METHOD || type == EOLIAN_FUNCTION_POINTER)
863        {
864           for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator ( ::eolian_function_parameters_get(function))
865             , param_last; param_iterator != param_last; ++param_iterator)
866             {
867                parameters.push_back({&*param_iterator, unit});
868             }
869        }
870      else if(type == EOLIAN_PROP_GET || type == EOLIAN_PROP_SET)
871        {
872          if(type == EOLIAN_PROP_GET)
873            name += "_get";
874          else
875            name += "_set";
876          for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator
877                ( ::eolian_property_keys_get(function, type))
878                , param_last; param_iterator != param_last; ++param_iterator)
879            {
880               parameter_def param = {&*param_iterator, unit};
881               parameters.push_back(param);
882               keys.push_back(param);
883            }
884          for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator
885                ( ::eolian_property_values_get(function, type))
886                , param_last; param_iterator != param_last; ++param_iterator)
887            {
888               values.push_back({&*param_iterator, unit});
889            }
890 
891          if(!r_type && type == EOLIAN_PROP_GET && values.size() == 1)
892            {
893              return_type = values[0].type;
894              if (return_documentation.summary.empty())
895                return_documentation = values[0].documentation;
896 
897            }
898          else if(type == EOLIAN_PROP_GET)
899            {
900              for(auto&& v : values)
901                {
902                  v.direction = parameter_direction::out;
903                  parameters.push_back(v);
904                }
905            }
906          else
907            parameters.insert(parameters.end(), values.begin(), values.end());
908        }
909      c_name = eolian_function_full_c_name_get(function, type);
910      if (type != EOLIAN_FUNCTION_POINTER)
911        {
912           const Eolian_Class *eolian_klass = eolian_function_class_get(function);
913           filename = eolian_object_file_get((const Eolian_Object *)eolian_klass);
914           klass = klass_name(eolian_klass,
915               {attributes::qualifier_info::is_none, std::string()});
916           is_beta = eolian_function_is_beta(function) || klass.is_beta;
917        }
918      else
919        {
920           is_beta = tp && eolian_object_is_beta(EOLIAN_OBJECT(tp));
921           filename = "";
922 
923           if (tp)
924             {
925                for (efl::eina::iterator<const char> ns_iterator(::eolian_typedecl_namespaces_get(tp)), ns_last;
926                     ns_iterator != ns_last;
927                     ns_iterator++)
928                  namespaces.push_back(&*ns_iterator);
929             }
930        }
931      is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED;
932      is_static = eolian_function_is_static(function);
933 
934      Eolian_Implement const* implement = eolian_function_implement_get(function);
935      if (!implement)
936        return;
937 
938      documentation = eolian_implement_documentation_get(implement, type);
939 
940 
941      if (type == EOLIAN_PROP_GET || type == EOLIAN_PROP_SET)
942        property_documentation = eolian_implement_documentation_get(implement, EOLIAN_PROPERTY);
943 
944      switch (type)
945        {
946        case EOLIAN_UNRESOLVED:
947          this->type = function_type::unresolved;
948          break;
949        case EOLIAN_PROPERTY:
950          this->type = function_type::property;
951          break;
952        case EOLIAN_PROP_GET:
953          this->type = function_type::prop_get;
954          break;
955        case EOLIAN_PROP_SET:
956          this->type = function_type::prop_set;
957          break;
958        case EOLIAN_METHOD:
959          this->type = function_type::method;
960          break;
961        case EOLIAN_FUNCTION_POINTER:
962          this->type = function_type::function_pointer;
963          break;
964        }
965   }
966 
template_statementefl::eolian::grammar::attributes::function_def967   std::string template_statement() const
968   {
969      std::string statement;
970      char template_typename = 'F';
971      for (auto const& param : this->parameters)
972        {
973           attributes::regular_type_def const* typ =
974                 efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
975           if (typ && typ->is_function_ptr())
976             {
977                char typenam[2] = { 0, };
978                typenam[0] = template_typename++;
979                if (statement.empty())
980                  statement = std::string("template <typename ") + typenam;
981                else
982                  statement += std::string(", typename ") + typenam;
983             }
984        }
985      if (statement.empty()) return statement;
986      else return statement + ">";
987   }
988 
opening_statementsefl::eolian::grammar::attributes::function_def989   std::vector<std::string> opening_statements() const
990   {
991      std::vector<std::string> statements;
992      char template_typename = 'F';
993      for (auto const& param : this->parameters)
994        {
995           attributes::regular_type_def const* typ =
996                 efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
997           if (typ && typ->is_function_ptr())
998             {
999                char typenam[2] = { 0, };
1000                typenam[0] = template_typename++;
1001                std::string statement = "auto fw_" + param.param_name + " = new ::efl::eolian::function_wrapper<";
1002                statement += param.type.c_type + ", " + typenam + ", ::efl::eolian::" + param.type.c_type + "__function_tag>(" + param.param_name + ");";
1003                statements.push_back(statement);
1004             }
1005        }
1006      return statements;
1007   }
1008 };
1009 
1010 template <>
1011 struct tuple_element<0ul, function_def>
1012 {
1013    typedef type_def type;
getefl::eolian::grammar::attributes::tuple_element1014    static type& get(function_def& f) { return f.return_type; }
getefl::eolian::grammar::attributes::tuple_element1015    static type const& get(function_def const& f) { return f.return_type; }
1016 };
1017 
1018 template <>
1019 struct tuple_element<1ul, function_def>
1020 {
1021    typedef std::string type;
getefl::eolian::grammar::attributes::tuple_element1022    static type& get(function_def& f) { return f.name; }
getefl::eolian::grammar::attributes::tuple_element1023    static type const& get(function_def const& f) { return f.name; }
1024 };
1025 
1026 template <>
1027 struct tuple_element<2ul, function_def>
1028 {
1029    typedef std::vector<parameter_def> type;
getefl::eolian::grammar::attributes::tuple_element1030    static type& get(function_def& f) { return f.parameters; }
getefl::eolian::grammar::attributes::tuple_element1031    static type const& get(function_def const& f) { return f.parameters; }
1032 };
1033 
1034 struct property_def
1035 {
1036   klass_name klass;
1037   std::string name;
1038   documentation_def documentation;
1039 
1040   efl::eina::optional<function_def> getter;
1041   efl::eina::optional<function_def> setter;
1042 
operator ==(property_def const & lhs,property_def const & rhs)1043   friend inline bool operator==(property_def const& lhs, property_def const& rhs)
1044   {
1045     return lhs.klass == rhs.klass
1046       && lhs.name == rhs.name
1047       && lhs.documentation == rhs.documentation
1048       && lhs.getter == rhs.getter
1049       && lhs.setter == rhs.setter;
1050   }
1051 
operator !=(property_def const & lhs,property_def const & rhs)1052   friend inline bool operator!=(property_def const& lhs, property_def const& rhs)
1053   {
1054     return !(lhs == rhs);
1055   }
1056 
1057   property_def() = default;
property_defefl::eolian::grammar::attributes::property_def1058   property_def(Eolian_Function const *function, efl::eina::optional<function_def> getter
1059               , efl::eina::optional<function_def> setter, Eolian_Unit const*)
1060               : getter(getter), setter(setter)
1061   {
1062     name = ::eolian_function_name_get(function);
1063 
1064     const Eolian_Class *eolian_klass = eolian_function_class_get(function);
1065     klass = klass_name(eolian_klass, {attributes::qualifier_info::is_none, std::string()});
1066 
1067     Eolian_Implement const* implement = ::eolian_function_implement_get(function);
1068     if (!implement)
1069       return;
1070 
1071     Eolian_Function_Type type = ::eolian_function_type_get(function);
1072     if (type == EOLIAN_PROP_GET || type == EOLIAN_PROP_SET || type == EOLIAN_PROPERTY)
1073       {
1074          documentation = eolian_implement_documentation_get(implement, EOLIAN_PROPERTY);
1075          // If property-level documentation is empty, use the getter- or setter-level
1076          // docs as fallback (if present).
1077          if (documentation.summary.empty())
1078            documentation = eolian_implement_documentation_get(implement, EOLIAN_PROP_GET);
1079          if (documentation.summary.empty())
1080            documentation = eolian_implement_documentation_get(implement, EOLIAN_PROP_SET);
1081       }
1082   }
1083 };
1084 
1085 struct constant_def
1086 {
1087   std::string name;
1088   std::string full_name;
1089   type_def base_type;
1090   documentation_def documentation;
1091   std::vector<std::string> namespaces;
1092   Eolian_Value expression_value;
1093   bool is_extern : 1;
1094 
operator ==(constant_def const & lhs,constant_def const & rhs)1095   friend inline bool operator==(constant_def const& lhs, constant_def const& rhs)
1096   {
1097     return lhs.name == rhs.name
1098       && lhs.full_name == rhs.full_name
1099       && lhs.base_type == rhs.base_type
1100       && lhs.documentation == rhs.documentation
1101       && lhs.namespaces == rhs.namespaces
1102       && lhs.expression_value.type == rhs.expression_value.type
1103       && lhs.expression_value.value.ll == rhs.expression_value.value.ll
1104       && lhs.is_extern == rhs.is_extern;
1105   }
1106 
operator !=(constant_def const & lhs,constant_def const & rhs)1107   friend inline bool operator!=(constant_def const& lhs, constant_def const& rhs)
1108   {
1109     return !(lhs == rhs);
1110   }
1111 
1112   constant_def() = default;
constant_defefl::eolian::grammar::attributes::constant_def1113   constant_def(Eolian_Constant const* constant, Eolian_Unit const* unit)
1114         : name(::eolian_constant_short_name_get(constant))
1115         , full_name(::eolian_constant_name_get(constant))
1116         , base_type(::eolian_constant_type_get(constant)
1117                     , unit
1118                     , ::eolian_type_c_type_get(eolian_constant_type_get(constant))
1119                     , value_ownership::unmoved
1120                     , is_by::value)
1121         , documentation(::eolian_constant_documentation_get(constant))
1122         , expression_value()
1123         , is_extern(::eolian_constant_is_extern(constant))
1124   {
1125      for(efl::eina::iterator<const char> namespace_iterator( ::eolian_constant_namespaces_get(constant))
1126           , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
1127        {
1128           this->namespaces.push_back((&*namespace_iterator));
1129        }
1130 
1131      auto expr = ::eolian_constant_value_get(constant);
1132      if (!expr)
1133        throw std::runtime_error("Could not get constant variable value expression");
1134 
1135      this->expression_value = ::eolian_expression_eval(expr, ::EOLIAN_MASK_ALL);
1136   }
1137 };
1138 
1139 
1140 // template <int N>
1141 // struct tuple_element<N, function_def const> : tuple_element<N, function_def> {};
1142 // template <int N>
1143 // struct tuple_element<N, function_def&> : tuple_element<N, function_def> {};
1144 // template <int N>
1145 // struct tuple_element<N, function_def const&> : tuple_element<N, function_def> {};
1146 
1147 // template <std::size_t I>
1148 // typename tuple_element<I, function_def>::type const&
1149 // get(function_def const& f)
1150 // {
1151 //   return tuple_element<I, function_def>::get(f);
1152 // }
1153 
1154 // template <std::size_t I>
1155 // typename tuple_element<I, function_def>::type&
1156 // get(function_def& f)
1157 // {
1158 //   return tuple_element<I, function_def>::get(f);
1159 // }
1160 
1161 struct compare_klass_name_by_name
1162 {
operator ()efl::eolian::grammar::attributes::compare_klass_name_by_name1163   bool operator()(klass_name const& lhs, klass_name const& rhs) const
1164   {
1165     return lhs.namespaces < rhs.namespaces
1166         || (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name);
1167   }
1168 };
1169 
1170 struct event_def
1171 {
1172   klass_name klass;
1173   eina::optional<type_def> type;
1174   std::string name, c_name;
1175   bool is_beta, is_protected;
1176   documentation_def documentation;
1177 
operator ==(event_def const & lhs,event_def const & rhs)1178   friend inline bool operator==(event_def const& lhs, event_def const& rhs)
1179   {
1180     return lhs.klass == rhs.klass
1181       && lhs.type == rhs.type
1182       && lhs.name == rhs.name
1183       && lhs.c_name == rhs.c_name
1184       && lhs.is_beta == rhs.is_beta
1185       && lhs.is_protected == rhs.is_protected
1186       && lhs.documentation == rhs.documentation;
1187   }
operator !=(event_def const & lhs,event_def const & rhs)1188   friend inline bool operator!=(event_def const& lhs, event_def const& rhs)
1189   {
1190     return !(lhs == rhs);
1191   }
1192 
event_defefl::eolian::grammar::attributes::event_def1193   event_def(klass_name _klass, type_def type, std::string name, std::string c_name,
1194           bool is_beta, bool is_protected, documentation_def documentation)
1195     : klass(_klass), type(type), name(name), c_name(c_name), is_beta(is_beta), is_protected(is_protected)
1196     , documentation(documentation) {}
1197 
event_defefl::eolian::grammar::attributes::event_def1198   event_def(Eolian_Event const* event, Eolian_Class const* cls, Eolian_Unit const* unit)
1199     : klass(cls, {attributes::qualifier_info::is_none, std::string()})
1200     , type( ::eolian_event_type_get(event) ? eina::optional<type_def>{{::eolian_event_type_get(event)
1201                                                                        , unit
1202                                                                        , ::eolian_type_c_type_get(::eolian_event_type_get(event))
1203                                                                        , value_ownership::unmoved
1204                                                                        , is_by::value}
1205              } : eina::optional<type_def>{})
1206     , name( ::eolian_event_name_get(event))
1207     , c_name( ::eolian_event_c_macro_get(event))
1208     , is_beta( ::eolian_event_is_beta(event) || klass.is_beta)
1209     , is_protected( ::eolian_event_scope_get(event) == EOLIAN_SCOPE_PROTECTED)
1210     , documentation( ::eolian_event_documentation_get(event)) {}
1211 };
1212 
1213 template <>
1214 struct tuple_element<0, event_def>
1215 {
1216   typedef eina::optional<type_def> type;
getefl::eolian::grammar::attributes::tuple_element1217   static type& get(event_def& def) { return def.type; }
getefl::eolian::grammar::attributes::tuple_element1218   static type const& get(event_def const& def) { return def.type; }
1219 };
1220 template <>
1221 struct tuple_element<1, event_def>
1222 {
1223   typedef std::string type;
getefl::eolian::grammar::attributes::tuple_element1224   static type& get(event_def& def) { return def.name; }
getefl::eolian::grammar::attributes::tuple_element1225   static type const& get(event_def const& def) { return def.name; }
1226 };
1227 template <>
1228 struct tuple_element<2, event_def>
1229 {
1230   typedef std::string type;
getefl::eolian::grammar::attributes::tuple_element1231   static type& get(event_def& def) { return def.c_name; }
getefl::eolian::grammar::attributes::tuple_element1232   static type const& get(event_def const& def) { return def.c_name; }
1233 };
1234 template <int N>
1235 struct tuple_element<N, event_def const> : tuple_element<N, event_def> {};
1236 template <int N>
get(event_def const & def)1237 auto get(event_def const& def) -> decltype(tuple_element<N, event_def>::get(def))
1238 {
1239   return tuple_element<N, event_def>::get(def);
1240 }
1241 template <int N>
get(event_def & def)1242 auto get(event_def& def) -> decltype(tuple_element<N, event_def>::get(def))
1243 {
1244   return tuple_element<N, event_def>::get(def);
1245 }
1246 
1247 struct part_def
1248 {
1249    klass_name klass;
1250    std::string name;
1251    documentation_def documentation;
1252    //bool beta, protect; // can it be applied??
1253 
operator ==(part_def const & lhs,part_def const & rhs)1254    friend inline bool operator==(part_def const& lhs, part_def const& rhs)
1255    {
1256      return lhs.klass == rhs.klass
1257        && lhs.name == rhs.name;
1258    }
operator !=(part_def const & lhs,part_def const & rhs)1259    friend inline bool operator!=(part_def const& lhs, part_def const& rhs)
1260    {
1261      return !(lhs == rhs);
1262    }
operator <(part_def const & lhs,part_def const & rhs)1263    friend inline bool operator<(part_def const& lhs, part_def const& rhs)
1264    {
1265       return lhs.name < rhs.name ||
1266             lhs.klass < rhs.klass;
1267    }
1268 
part_defefl::eolian::grammar::attributes::part_def1269    part_def(Eolian_Part const* part, Eolian_Unit const*)
1270       : klass(klass_name(::eolian_part_class_get(part), {attributes::qualifier_info::is_none, std::string()}))
1271       , name(::eolian_part_name_get(part))
1272       , documentation(::eolian_part_documentation_get(part)) {}
1273 };
1274 
1275 struct constructor_def
1276 {
1277     std::string name;
1278     klass_name klass;
1279     function_def function;
1280     bool is_optional;
1281 
operator ==(constructor_def const & lhs,constructor_def const & rhs)1282     friend inline bool operator==(constructor_def const& lhs, constructor_def const& rhs)
1283     {
1284       return lhs.name == rhs.name
1285         && lhs.klass == rhs.klass
1286         && lhs.function == rhs.function
1287         && lhs.is_optional == rhs.is_optional;
1288     }
1289 
operator !=(constructor_def const & lhs,constructor_def const & rhs)1290     friend inline bool operator!=(constructor_def const& lhs, constructor_def const& rhs)
1291     {
1292       return !(lhs == rhs);
1293     }
1294 
constructor_defefl::eolian::grammar::attributes::constructor_def1295     constructor_def(Eolian_Constructor const* constructor, Eolian_Unit const* unit)
1296         : name(::eolian_constructor_name_get(constructor))
1297         , klass(::eolian_constructor_class_get(constructor), {})
1298         , is_optional(::eolian_constructor_is_optional(constructor))
1299     {
1300          Eolian_Function const* eo_function = ::eolian_constructor_function_get(constructor);
1301          Eolian_Function_Type eo_func_type = ::eolian_function_type_get(eo_function);
1302          if (eo_func_type == ::EOLIAN_PROPERTY)
1303            eo_func_type = ::EOLIAN_PROP_SET;
1304          function = function_def(eo_function, eo_func_type, NULL, unit);
1305     }
1306 };
1307 
1308 inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit);
1309 
1310 struct klass_def
1311 {
1312   std::string eolian_name;
1313   std::string cxx_name;
1314   std::string filename;
1315   documentation_def documentation;
1316   std::vector<std::string> namespaces;
1317   std::vector<function_def> functions;
1318   std::vector<property_def> properties;
1319   std::vector<constructor_def> constructors;
1320   std::set<klass_name, compare_klass_name_by_name> inherits;
1321   class_type type;
1322   std::vector<event_def> events;
1323   std::set<klass_name, compare_klass_name_by_name> immediate_inherits;
1324   eina::optional<klass_name> parent;
1325   std::set<klass_name, compare_klass_name_by_name> extensions;
1326   std::string klass_get_name;
1327   bool is_beta;
1328 
1329   std::set<part_def> parts;
1330   Eolian_Unit const* unit;
1331 
operator ==(klass_def const & lhs,klass_def const & rhs)1332   friend inline bool operator==(klass_def const& lhs, klass_def const& rhs)
1333   {
1334     return lhs.eolian_name == rhs.eolian_name
1335       && lhs.cxx_name == rhs.cxx_name
1336       && lhs.filename == rhs.filename
1337       && lhs.namespaces == rhs.namespaces
1338       && lhs.functions == rhs.functions
1339       && lhs.properties == rhs.properties
1340       && lhs.inherits == rhs.inherits
1341       && lhs.type == rhs.type
1342       && lhs.events == rhs.events
1343       && lhs.parts == rhs.parts
1344       && lhs.klass_get_name == rhs.klass_get_name
1345       && lhs.is_beta == rhs.is_beta;
1346   }
operator !=(klass_def const & lhs,klass_def const & rhs)1347   friend inline bool operator!=(klass_def const& lhs, klass_def const& rhs)
1348   {
1349     return !(lhs == rhs);
1350   }
operator <(klass_def const & lhs,klass_def const & rhs)1351   friend inline bool operator<(klass_def const& lhs, klass_def const& rhs)
1352   {
1353      return lhs.eolian_name < rhs.eolian_name
1354        || lhs.cxx_name < rhs.cxx_name
1355        || lhs.namespaces < rhs.namespaces
1356        || lhs.parts < rhs.parts;
1357   }
1358 
operator ==(klass_def const & lhs,klass_name const & rhs)1359   friend inline bool operator==(klass_def const& lhs, klass_name const& rhs)
1360   {
1361      return lhs.namespaces == rhs.namespaces
1362          && lhs.eolian_name == rhs.eolian_name
1363          && lhs.type == rhs.type;
1364   }
operator ==(klass_name const & lhs,klass_def const & rhs)1365   friend inline bool operator==(klass_name const& lhs, klass_def const& rhs)
1366   {
1367       return rhs == lhs;
1368   }
operator !=(klass_def const & lhs,klass_name const & rhs)1369   friend inline bool operator!=(klass_def const& lhs, klass_name const& rhs)
1370   {
1371       return !(lhs == rhs);
1372   }
operator !=(klass_name const & lhs,klass_def const & rhs)1373   friend inline bool operator!=(klass_name const& lhs, klass_def const& rhs)
1374   {
1375       return !(rhs == lhs);
1376   }
1377 
1378 
klass_defefl::eolian::grammar::attributes::klass_def1379   klass_def(std::string eolian_name, std::string cxx_name, std::string filename
1380             , documentation_def documentation
1381             , std::vector<std::string> namespaces
1382             , std::vector<function_def> functions
1383             , std::vector<property_def> properties
1384             , std::set<klass_name, compare_klass_name_by_name> inherits
1385             , class_type type
1386             , std::set<klass_name, compare_klass_name_by_name> immediate_inherits
1387             , std::string klass_get_name
1388             , bool is_beta
1389             , Eolian_Unit const* unit)
1390     : eolian_name(eolian_name), cxx_name(cxx_name), filename(filename)
1391     , documentation(documentation)
1392     , namespaces(namespaces)
1393     , functions(functions), properties(properties), inherits(inherits), type(type)
1394     , immediate_inherits(immediate_inherits)
1395     , klass_get_name(klass_get_name)
1396     , is_beta(is_beta)
1397     , unit(unit)
1398   {}
klass_defefl::eolian::grammar::attributes::klass_def1399   klass_def(std::string _eolian_name, std::string _cxx_name
1400             , std::vector<std::string> _namespaces
1401             , std::vector<function_def> _functions
1402             , std::vector<property_def> _properties
1403             , std::set<klass_name, compare_klass_name_by_name> _inherits
1404             , class_type _type, Eolian_Unit const* unit
1405             , std::string klass_get_name
1406             , bool is_beta)
1407     : eolian_name(_eolian_name), cxx_name(_cxx_name)
1408     , namespaces(_namespaces)
1409     , functions(_functions), properties(_properties), inherits(_inherits), type(_type)
1410     , klass_get_name(klass_get_name), is_beta(is_beta), unit(unit)
1411   {}
klass_defefl::eolian::grammar::attributes::klass_def1412   klass_def(Eolian_Class const* klass, Eolian_Unit const* unit)
1413     : klass_get_name( ::eolian_class_c_get_function_name_get(klass))
1414     , is_beta(::eolian_class_is_beta(klass))
1415     , unit(unit)
1416   {
1417      for(efl::eina::iterator<const char> namespace_iterator( ::eolian_class_namespaces_get(klass))
1418            , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
1419        {
1420           this->namespaces.push_back(&*namespace_iterator);
1421        }
1422      cxx_name = eolian_name = eolian_class_short_name_get(klass);
1423      filename = eolian_object_file_get((const Eolian_Object *)klass);
1424      for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_PROPERTY))
1425        , functions_last; eolian_functions != functions_last; ++eolian_functions)
1426        {
1427          Eolian_Function const* function = &*eolian_functions;
1428          Eolian_Function_Type func_type = ::eolian_function_type_get(function);
1429          if(func_type == EOLIAN_PROPERTY)
1430            {
1431              efl::eina::optional<function_def> getter(nullptr);
1432              efl::eina::optional<function_def> setter(nullptr);
1433              try {
1434                 if(::eolian_function_scope_get(function, EOLIAN_PROP_GET) != EOLIAN_SCOPE_PRIVATE)
1435                   {
1436                      function_def f(function, EOLIAN_PROP_GET, NULL, unit);
1437                      functions.push_back(f);
1438                      getter = efl::eina::optional<function_def>(f);
1439                   }
1440              } catch(std::exception const&) {}
1441              try {
1442                 if(::eolian_function_scope_get(function, EOLIAN_PROP_SET) != EOLIAN_SCOPE_PRIVATE)
1443                   {
1444                      function_def f(function, EOLIAN_PROP_SET, NULL, unit);
1445                      functions.push_back(f);
1446                      setter = efl::eina::optional<function_def>(f);
1447                   }
1448              } catch(std::exception const&) {}
1449              if (getter.is_engaged() || setter.is_engaged())
1450                properties.push_back({function, getter, setter, unit});
1451            }
1452          else
1453            try {
1454              if(::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE)
1455                {
1456                   efl::eina::optional<function_def> getter(nullptr);
1457                   efl::eina::optional<function_def> setter(nullptr);
1458                   function_def f(function, func_type, NULL, unit);
1459                   if (func_type == EOLIAN_PROP_GET)
1460                     getter = efl::eina::optional<function_def>(f);
1461                   else if (func_type == EOLIAN_PROP_SET)
1462                     setter = efl::eina::optional<function_def>(f);
1463                   functions.push_back(f);
1464                   if (func_type == EOLIAN_PROP_GET || func_type == EOLIAN_PROP_SET)
1465                     properties.push_back({function, getter, setter, unit});
1466                }
1467            } catch(std::exception const&) {}
1468        }
1469      for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD))
1470        , functions_last; eolian_functions != functions_last; ++eolian_functions)
1471        {
1472          try {
1473              Eolian_Function const* function = &*eolian_functions;
1474              Eolian_Function_Type func_type = eolian_function_type_get(function);
1475              if(::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE)
1476                functions.push_back({function, EOLIAN_METHOD, NULL, unit});
1477          } catch(std::exception const&) {}
1478        }
1479      if(::eolian_class_parent_get(klass))
1480        {
1481           parent = eina::optional<klass_name>({::eolian_class_parent_get(klass), {}});
1482           immediate_inherits.insert(*parent);
1483        }
1484      for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_extensions_get(klass))
1485            , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
1486        {
1487          Eolian_Class const* inherit = &*inherit_iterator;
1488          klass_name extension(inherit, {});
1489          immediate_inherits.insert(extension);
1490          extensions.insert(extension);
1491        }
1492      std::function<void(Eolian_Class const*)> inherit_algo =
1493        [&] (Eolian_Class const* inherit_klass)
1494        {
1495          if(::eolian_class_parent_get(inherit_klass))
1496            {
1497              Eolian_Class const* inherit = ::eolian_class_parent_get(inherit_klass);
1498              inherits.insert({inherit, {}});
1499              inherit_algo(inherit);
1500            }
1501          for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_extensions_get(inherit_klass))
1502                , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
1503            {
1504              Eolian_Class const* inherit = &*inherit_iterator;
1505              inherits.insert({inherit, {}});
1506              inherit_algo(inherit);
1507            }
1508        };
1509      inherit_algo(klass);
1510 
1511      for(efl::eina::iterator<Eolian_Part const> parts_itr ( ::eolian_class_parts_get(klass))
1512        , parts_last; parts_itr != parts_last; ++parts_itr)
1513        {
1514           parts.insert({&*parts_itr, unit});
1515        }
1516 
1517      switch(eolian_class_type_get(klass))
1518        {
1519        case EOLIAN_CLASS_REGULAR:
1520          type = class_type::regular;
1521          break;
1522        case EOLIAN_CLASS_ABSTRACT:
1523          type = class_type::abstract_;
1524          break;
1525        case EOLIAN_CLASS_MIXIN:
1526          type = class_type::mixin;
1527          break;
1528        case EOLIAN_CLASS_INTERFACE:
1529          type = class_type::interface_;
1530          break;
1531        default:
1532          throw std::runtime_error("Class with unknown type");
1533        }
1534      for(efl::eina::iterator<Eolian_Event const> event_iterator( ::eolian_class_events_get(klass))
1535            , event_last; event_iterator != event_last; ++event_iterator)
1536        {
1537          try {
1538            events.push_back({&*event_iterator, klass, unit});
1539          } catch(std::exception const&) {}
1540        }
1541 
1542      for(efl::eina::iterator<Eolian_Constructor const> constructor_iterator(::eolian_class_constructors_get(klass))
1543              , constructor_last; constructor_iterator != constructor_last; ++constructor_iterator)
1544          constructors.push_back({&*constructor_iterator, unit});
1545 
1546      documentation = eolian_class_documentation_get(klass);
1547   }
1548 
1549   // TODO memoize the return?
get_all_methodsefl::eolian::grammar::attributes::klass_def1550   std::vector<function_def> get_all_methods() const
1551   {
1552       std::vector<function_def> ret;
1553 
1554       std::copy(functions.cbegin(), functions.cend(), std::back_inserter(ret));
1555 
1556       for (auto inherit : inherits)
1557        {
1558           klass_def klass(get_klass(inherit, unit), unit);
1559           std::copy(klass.functions.cbegin(), klass.functions.cend(),
1560                     std::back_inserter(ret));
1561        }
1562 
1563       return ret;
1564   }
1565 
get_all_partsefl::eolian::grammar::attributes::klass_def1566   std::vector<part_def> get_all_parts() const
1567   {
1568       std::vector<part_def> ret;
1569 
1570       std::copy(parts.cbegin(), parts.cend(), std::back_inserter(ret));
1571 
1572       for (auto inherit : inherits)
1573         {
1574            klass_def klass(get_klass(inherit, unit), unit);
1575            std::copy(klass.parts.cbegin(), klass.parts.cend(),
1576                      std::back_inserter(ret));
1577         }
1578 
1579       return ret;
1580   }
1581 
get_all_eventsefl::eolian::grammar::attributes::klass_def1582   std::vector<event_def> get_all_events() const
1583   {
1584       std::vector<event_def> ret;
1585 
1586       std::copy(events.cbegin(), events.cend(), std::back_inserter(ret));
1587 
1588       for (auto inherit : inherits)
1589         {
1590            klass_def klass(get_klass(inherit, unit), unit);
1591            std::copy(klass.events.cbegin(), klass.events.cend(),
1592                      std::back_inserter(ret));
1593         }
1594 
1595       return ret;
1596   }
1597 
get_all_constructorsefl::eolian::grammar::attributes::klass_def1598   std::vector<constructor_def> get_all_constructors() const
1599   {
1600       std::vector<constructor_def> ret;
1601 
1602       std::copy(constructors.cbegin(), constructors.cend(), std::back_inserter(ret));
1603 
1604       for (auto inherit : inherits)
1605         {
1606            klass_def klass(get_klass(inherit, unit), unit);
1607            std::copy(klass.constructors.cbegin(), klass.constructors.cend(),
1608                      std::back_inserter(ret));
1609         }
1610 
1611       return ret;
1612   }
1613 };
1614 
1615 struct enum_value_def
1616 {
1617   value_def value;
1618   std::string name;
1619   std::string c_name;
1620   documentation_def documentation;
1621 
enum_value_defefl::eolian::grammar::attributes::enum_value_def1622   enum_value_def(Eolian_Enum_Type_Field const* enum_field, Eolian_Unit const*)
1623   {
1624       name = eolian_typedecl_enum_field_name_get(enum_field);
1625       c_name = eolian_typedecl_enum_field_c_constant_get(enum_field);
1626       auto exp = eolian_typedecl_enum_field_value_get(enum_field, EINA_TRUE);
1627       value = eolian_expression_eval(exp, EOLIAN_MASK_INT); // FIXME hardcoded int
1628       documentation = eolian_typedecl_enum_field_documentation_get(enum_field);
1629   }
1630 };
1631 
1632 struct enum_def
1633 {
1634   std::string eolian_name;
1635   std::string cxx_name;
1636   std::vector<std::string> namespaces;
1637   std::vector<enum_value_def> fields;
1638   documentation_def documentation;
1639   bool is_beta;
1640 
enum_defefl::eolian::grammar::attributes::enum_def1641   enum_def(Eolian_Typedecl const* enum_obj, Eolian_Unit const* unit)
1642   {
1643      for(efl::eina::iterator<const char> namespace_iterator( ::eolian_typedecl_namespaces_get(enum_obj))
1644            , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
1645        {
1646           this->namespaces.push_back((&*namespace_iterator));
1647        }
1648      cxx_name = eolian_name = eolian_typedecl_short_name_get(enum_obj);
1649 
1650      for (efl::eina::iterator<const Eolian_Enum_Type_Field> field_iterator(::eolian_typedecl_enum_fields_get(enum_obj))
1651              , field_last; field_iterator != field_last; ++field_iterator)
1652        {
1653           // Fill the types
1654           enum_value_def field_def(&*field_iterator, unit);
1655           this->fields.push_back(field_def);
1656        }
1657      is_beta = eolian_object_is_beta(EOLIAN_OBJECT(enum_obj));
1658 
1659      documentation = ::eolian_typedecl_documentation_get(enum_obj);
1660   }
1661 };
1662 
1663 struct struct_field_def
1664 {
1665   type_def type;
1666   std::string name;
1667   documentation_def documentation;
1668 
struct_field_defefl::eolian::grammar::attributes::struct_field_def1669   struct_field_def(Eolian_Struct_Type_Field const* struct_field, Eolian_Unit const* unit)
1670   {
1671      name = eolian_typedecl_struct_field_name_get(struct_field);
1672      try {
1673         type.set(eolian_typedecl_struct_field_type_get(struct_field)
1674                 , unit
1675                 , eolian_typedecl_struct_field_c_type_get(struct_field)
1676                 , eolian_typedecl_struct_field_is_move(struct_field)
1677                 , eolian_typedecl_struct_field_is_by_ref(struct_field));
1678      } catch(std::runtime_error const&) { /* Silently skip pointer fields*/ }
1679      documentation = ::eolian_typedecl_struct_field_documentation_get(struct_field);
1680   }
1681 
1682 };
1683 
1684 struct struct_def
1685 {
1686   std::string eolian_name;
1687   std::string cxx_name;
1688   std::vector<std::string> namespaces;
1689   std::vector<struct_field_def> fields;
1690   bool is_beta;
1691   documentation_def documentation;
1692 
struct_defefl::eolian::grammar::attributes::struct_def1693   struct_def(Eolian_Typedecl const* struct_obj, Eolian_Unit const* unit)
1694   {
1695      for(efl::eina::iterator<const char> namespace_iterator( ::eolian_typedecl_namespaces_get(struct_obj))
1696            , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
1697        {
1698           this->namespaces.push_back((&*namespace_iterator));
1699        }
1700      cxx_name = eolian_name = eolian_typedecl_short_name_get(struct_obj);
1701 
1702      for(efl::eina::iterator<const Eolian_Struct_Type_Field> field_iterator(::eolian_typedecl_struct_fields_get(struct_obj))
1703              , field_last; field_iterator != field_last; ++field_iterator)
1704        {
1705           struct_field_def field_def(&*field_iterator, unit);
1706           this->fields.push_back(field_def);
1707        }
1708 
1709      is_beta = eolian_object_is_beta(EOLIAN_OBJECT(struct_obj));
1710 
1711      documentation = ::eolian_typedecl_documentation_get(struct_obj);
1712   }
1713 };
1714 
get_klass_name(klass_def const & klass)1715 inline klass_name get_klass_name(klass_def const& klass)
1716 {
1717   return {klass.namespaces, klass.eolian_name, {qualifier_info::is_none, {}}, klass.type, klass.klass_get_name, klass.is_beta};
1718 }
1719 
get_klass(klass_name const & klass_name_,Eolian_Unit const * unit)1720 inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit)
1721 {
1722   std::string klass_name;
1723   if(!as_generator(*(string << ".") << string)
1724      .generate(std::back_insert_iterator<std::string>(klass_name)
1725                , std::make_tuple(klass_name_.namespaces, klass_name_.eolian_name)
1726                , context_null{}))
1727     return nullptr;
1728   else
1729     return ::eolian_unit_class_by_name_get(unit, klass_name.c_str());
1730 }
1731 
cpp_namespaces(std::vector<std::string> namespaces)1732 inline std::vector<std::string> cpp_namespaces(std::vector<std::string> namespaces)
1733 {
1734   if(namespaces.empty())
1735     namespaces.push_back("nonamespace");
1736   return namespaces;
1737 }
1738 
has_events(klass_def const & klass)1739 inline bool has_events(klass_def const &klass)
1740 {
1741     for (auto&& e : klass.events)
1742       {
1743          (void)e;
1744          return true;
1745       }
1746 
1747     for (auto&& c : klass.inherits)
1748       {
1749         attributes::klass_def parent(get_klass(c, klass.unit), klass.unit);
1750          for (auto&& e : parent.events)
1751            {
1752               (void)e;
1753               return true;
1754            }
1755       }
1756 
1757     return false;
1758 }
1759 
1760 template<typename T>
has_type_return(klass_def const & klass,T visitor)1761 inline bool has_type_return(klass_def const &klass, T visitor)
1762 {
1763     for (auto&& f : klass.functions)
1764       {
1765          if (f.return_type.original_type.visit(visitor))
1766            return true;
1767       }
1768 
1769     for (auto&& c : klass.inherits)
1770       {
1771         attributes::klass_def parent(get_klass(c, klass.unit), klass.unit);
1772          if (has_type_return(parent, visitor))
1773            return true;
1774       }
1775 
1776     return false;
1777 }
1778 
1779 struct string_return_visitor
1780 {
1781     typedef string_return_visitor visitor_type;
1782     typedef bool result_type;
1783     template <typename T>
operator ()efl::eolian::grammar::attributes::string_return_visitor1784     bool operator()(T const&) const { return false; }
operator ()efl::eolian::grammar::attributes::string_return_visitor1785     bool operator()(regular_type_def const& regular) const
1786     {
1787         return regular.base_type == "string";
1788     }
1789 };
1790 
1791 struct stringshare_return_visitor
1792 {
1793     typedef stringshare_return_visitor visitor_type;
1794     typedef bool result_type;
1795     template <typename T>
operator ()efl::eolian::grammar::attributes::stringshare_return_visitor1796     bool operator()(T const&) const { return false; }
operator ()efl::eolian::grammar::attributes::stringshare_return_visitor1797     bool operator()(regular_type_def const& regular) const
1798     {
1799         return regular.base_type == "stringshare";
1800     }
1801 };
1802 
has_string_return(klass_def const & klass)1803 inline bool has_string_return(klass_def const &klass)
1804 {
1805     return has_type_return(klass, string_return_visitor{});
1806 }
1807 
has_stringshare_return(klass_def const & klass)1808 inline bool has_stringshare_return(klass_def const &klass)
1809 {
1810     return has_type_return(klass, stringshare_return_visitor{});
1811 }
1812 
1813 }
1814 namespace type_traits {
1815 
1816 template <>
1817 struct is_tuple<attributes::parameter_def> : std::true_type {};
1818 template <>
1819 struct is_tuple<attributes::event_def> : std::true_type {};
1820 
1821 }
1822 
1823 } } }
1824 
1825 #endif
1826