summaryrefslogtreecommitdiff
path: root/src/lib/eolian_cxx
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-06-06 02:54:36 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-06-06 02:54:36 -0300
commit2a3d7860dbc11458425e162cd69ee399e9025251 (patch)
tree84c5b21b644c4cf8806a8eee07b4ed81922c92b4 /src/lib/eolian_cxx
parent4d1b3191d94fcc70472552b1bb554984a9cb0288 (diff)
eolian-cxx: Rewrite to accomodate new features of the C++ binding
Diffstat (limited to 'src/lib/eolian_cxx')
-rw-r--r--src/lib/eolian_cxx/Eolian_Cxx.hh8
-rw-r--r--src/lib/eolian_cxx/eo_generate.hh23
-rw-r--r--src/lib/eolian_cxx/eo_types.hh350
-rw-r--r--src/lib/eolian_cxx/eo_validate.hh116
-rw-r--r--src/lib/eolian_cxx/grammar/address_of.hpp74
-rw-r--r--src/lib/eolian_cxx/grammar/alternative.hpp52
-rw-r--r--src/lib/eolian_cxx/grammar/attribute_conditional.hpp66
-rw-r--r--src/lib/eolian_cxx/grammar/attribute_reorder.hpp87
-rw-r--r--src/lib/eolian_cxx/grammar/attribute_replace.hpp63
-rw-r--r--src/lib/eolian_cxx/grammar/attributes.hpp185
-rw-r--r--src/lib/eolian_cxx/grammar/base_class_definition.hpp112
-rw-r--r--src/lib/eolian_cxx/grammar/c_type.hpp74
-rw-r--r--src/lib/eolian_cxx/grammar/case.hpp86
-rw-r--r--src/lib/eolian_cxx/grammar/class_declaration.hpp56
-rw-r--r--src/lib/eolian_cxx/grammar/class_definition.hpp176
-rw-r--r--src/lib/eolian_cxx/grammar/class_implementation.hpp56
-rw-r--r--src/lib/eolian_cxx/grammar/comment.hh45
-rw-r--r--src/lib/eolian_cxx/grammar/container.hpp46
-rw-r--r--src/lib/eolian_cxx/grammar/context.hpp46
-rw-r--r--src/lib/eolian_cxx/grammar/converting_argument.hpp47
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh603
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_events_generator.hh117
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh173
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_generator.hh265
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh65
-rw-r--r--src/lib/eolian_cxx/grammar/eo_header_generator.hh150
-rw-r--r--src/lib/eolian_cxx/grammar/eps.hpp24
-rw-r--r--src/lib/eolian_cxx/grammar/function_declaration.hpp39
-rw-r--r--src/lib/eolian_cxx/grammar/function_definition.hpp155
-rw-r--r--src/lib/eolian_cxx/grammar/generator.hpp50
-rw-r--r--src/lib/eolian_cxx/grammar/header.hpp38
-rw-r--r--src/lib/eolian_cxx/grammar/header_guards.hpp79
-rw-r--r--src/lib/eolian_cxx/grammar/header_include_directive.hpp34
-rw-r--r--src/lib/eolian_cxx/grammar/impl_header.hpp21
-rw-r--r--src/lib/eolian_cxx/grammar/implementation_include_directive.hpp39
-rw-r--r--src/lib/eolian_cxx/grammar/indentation.hpp50
-rw-r--r--src/lib/eolian_cxx/grammar/inheritance_base_generator.hh339
-rw-r--r--src/lib/eolian_cxx/grammar/keyword.hpp15
-rw-r--r--src/lib/eolian_cxx/grammar/klass_def.hpp704
-rw-r--r--src/lib/eolian_cxx/grammar/kleene.hpp47
-rw-r--r--src/lib/eolian_cxx/grammar/list.hpp52
-rw-r--r--src/lib/eolian_cxx/grammar/meta.hpp42
-rw-r--r--src/lib/eolian_cxx/grammar/namespace.hpp67
-rw-r--r--src/lib/eolian_cxx/grammar/namespace_generator.hh68
-rw-r--r--src/lib/eolian_cxx/grammar/parameter.hpp78
-rw-r--r--src/lib/eolian_cxx/grammar/parameters_generator.hh453
-rw-r--r--src/lib/eolian_cxx/grammar/qualifier_def.hpp178
-rw-r--r--src/lib/eolian_cxx/grammar/sequence.hpp136
-rw-r--r--src/lib/eolian_cxx/grammar/string.hpp185
-rw-r--r--src/lib/eolian_cxx/grammar/tab.hh30
-rw-r--r--src/lib/eolian_cxx/grammar/type.hpp40
-rw-r--r--src/lib/eolian_cxx/grammar/type_generator.hh266
-rw-r--r--src/lib/eolian_cxx/grammar/type_impl.hpp333
-rw-r--r--src/lib/eolian_cxx/grammar/type_traits.hpp63
-rw-r--r--src/lib/eolian_cxx/grammar/variant.hpp276
55 files changed, 3971 insertions, 3071 deletions
diff --git a/src/lib/eolian_cxx/Eolian_Cxx.hh b/src/lib/eolian_cxx/Eolian_Cxx.hh
index dfa748247e..5a8ea813c7 100644
--- a/src/lib/eolian_cxx/Eolian_Cxx.hh
+++ b/src/lib/eolian_cxx/Eolian_Cxx.hh
@@ -26,12 +26,4 @@ struct eolian_init
26 26
27} } 27} }
28 28
29#ifdef EFL_BETA_API_SUPPORT
30
31#include "eo_types.hh"
32#include "eo_validate.hh"
33#include "eo_generate.hh"
34
35#endif
36
37#endif // EOLIAN_CXX_LIB_HH 29#endif // EOLIAN_CXX_LIB_HH
diff --git a/src/lib/eolian_cxx/eo_generate.hh b/src/lib/eolian_cxx/eo_generate.hh
deleted file mode 100644
index 97e53bb9dc..0000000000
--- a/src/lib/eolian_cxx/eo_generate.hh
+++ /dev/null
@@ -1,23 +0,0 @@
1
2#ifndef EOLIAN_CXX_EO_GENERATE_HH
3#define EOLIAN_CXX_EO_GENERATE_HH
4
5#include <iosfwd>
6
7#include "eo_types.hh"
8#include "grammar/eo_header_generator.hh"
9
10namespace efl { namespace eolian {
11
12inline void
13generate(std::ostream& header_decl,
14 std::ostream& header_impl,
15 eo_class const& cls,
16 eo_generator_options const& opts)
17{
18 grammar::eo_headers_generator(header_decl, header_impl, cls, opts);
19}
20
21} }
22
23#endif // EOLIAN_CXX_EO_GENERATE_HH
diff --git a/src/lib/eolian_cxx/eo_types.hh b/src/lib/eolian_cxx/eo_types.hh
deleted file mode 100644
index 4431d3b44f..0000000000
--- a/src/lib/eolian_cxx/eo_types.hh
+++ /dev/null
@@ -1,350 +0,0 @@
1
2#ifndef EOLIAN_CXX_EO_TYPES_HH
3#define EOLIAN_CXX_EO_TYPES_HH
4
5#include <algorithm>
6#include <string>
7#include <vector>
8#include <cassert>
9
10namespace efl { namespace eolian {
11
12struct eo_constructor;
13struct eo_parameter;
14struct eo_function;
15struct eo_event;
16
17typedef std::vector<std::string> ancestors_container_type;
18typedef std::vector<std::string> includes_container_type;
19typedef std::vector<eo_constructor> constructors_container_type;
20typedef std::vector<eo_function> functions_container_type;
21typedef std::vector<eo_parameter> parameters_container_type;
22typedef std::vector<eo_event> events_container_type;
23
24
25enum class eolian_scope
26 {
27 public_, protected_, private_
28 };
29
30struct eolian_type
31{
32 enum category_type
33 {
34 unknown_, simple_, complex_, callback_
35 };
36
37 eolian_type()
38 : native("")
39 , category(unknown_)
40 , is_const(false)
41 , is_own(false)
42 , is_class(false)
43 , binding_requires_optional(false)
44 , binding()
45 , includes()
46 {}
47
48 eolian_type(std::string native_,
49 category_type category_,
50 bool is_const_,
51 bool is_own_,
52 bool is_class_,
53 bool binding_requires_optional_,
54 std::string binding_,
55 includes_container_type includes_)
56 : native(native_)
57 , category(category_)
58 , is_const(is_const_)
59 , is_own(is_own_)
60 , is_class(is_class_)
61 , binding_requires_optional(binding_requires_optional_)
62 , binding(binding_)
63 , includes(includes_)
64 {
65 assert(!native.empty());
66 assert(category != unknown_);
67 }
68
69 eolian_type(std::string native_,
70 category_type category_,
71 includes_container_type const& includes_)
72 : eolian_type(native_, category_, false, false, false, false, "", includes_)
73 {
74 assert(category == callback_);
75 }
76
77 std::string native;
78 category_type category;
79 bool is_const;
80 bool is_own;
81 bool is_class;
82 bool binding_requires_optional;
83 std::string binding;
84 includes_container_type includes;
85};
86
87typedef std::vector<eolian_type> eolian_type_container;
88
89struct eolian_type_instance
90{
91 eolian_type_instance()
92 : is_out(false)
93 , is_optional(false)
94 , parts()
95 {}
96
97 eolian_type_instance(std::initializer_list<eolian_type> il,
98 bool is_out_ = false,
99 bool is_optional_ = false)
100 : is_out(is_out_)
101 , is_optional(is_optional_)
102 , parts(il)
103 {}
104
105 explicit eolian_type_instance(std::size_t size)
106 : is_out(false)
107 , is_optional(false)
108 , parts(size)
109 {}
110
111 bool empty() const { return parts.empty(); }
112 std::size_t size() const { return parts.size(); }
113
114 eolian_type& front() { return parts.front(); }
115 eolian_type const& front() const { return parts.front(); }
116
117 bool is_out;
118 bool is_optional;
119 eolian_type_container parts;
120};
121
122const efl::eolian::eolian_type
123void_type { "void", efl::eolian::eolian_type::simple_, false, false, false, false, "", {} };
124
125inline bool
126type_is_void(eolian_type_instance const& type)
127{
128 return type.empty() || type.front().native.compare("void") == 0;
129}
130
131inline bool
132type_is_binding(eolian_type const& type)
133{
134 return !type.binding.empty();
135}
136
137inline bool
138type_is_binding(eolian_type_instance const& type)
139{
140 assert(!type.empty());
141 return type_is_binding(type.front());
142}
143
144inline bool
145type_is_out(eolian_type_instance const& type)
146{
147 return type.is_out;
148}
149
150inline bool
151type_is_class(eolian_type const& type)
152{
153 return type.is_class;
154}
155
156inline bool
157type_is_class(eolian_type_instance const& type)
158{
159 assert(!type.empty());
160 return type_is_class(type.front());
161}
162
163inline bool
164type_binding_requires_optional(eolian_type const& type)
165{
166 return type.binding_requires_optional;
167}
168
169inline bool
170type_binding_requires_optional(eolian_type_instance const& type)
171{
172 assert(!type.empty());
173 return type_binding_requires_optional(type.front());
174}
175
176inline bool
177type_is_optional(eolian_type_instance const& type)
178{
179 return type.is_optional;
180}
181
182inline eolian_type
183type_to_native(eolian_type const& type)
184{
185 eolian_type native(type);
186 native.binding.clear();
187 native.category = eolian_type::simple_;
188 native.is_class = false;
189 return native;
190}
191
192inline eolian_type
193type_to_native(eolian_type_instance const& type_ins)
194{
195 assert(!type_ins.empty());
196 return type_to_native(type_ins.front());
197}
198
199inline std::string
200type_to_native_str(eolian_type_instance const& type_ins)
201{
202 return type_to_native(type_ins).native;
203}
204
205inline bool
206type_is_complex(eolian_type const& type)
207{
208 return type.category == eolian_type::complex_;
209}
210
211inline bool
212type_is_complex(eolian_type_instance const& type_ins)
213{
214 assert(!type_ins.empty());
215 return type_is_complex(type_ins.front());
216}
217
218template <typename T>
219inline bool
220type_is_callback(T const&);
221
222template <>
223inline bool
224type_is_callback(eolian_type const& type)
225{
226 return type.category == eolian_type::callback_;
227}
228
229template <>
230inline bool
231type_is_callback(eolian_type_instance const& type_ins)
232{
233 return type_is_callback(type_ins.front());
234}
235
236struct eo_generator_options
237{
238 std::string header_decl_file_name;
239 std::string header_impl_file_name;
240 includes_container_type cxx_headers;
241 includes_container_type c_headers;
242};
243
244struct eo_class
245{
246 enum eo_class_type
247 {
248 regular_, regular_noninst_, interface_, mixin_
249 };
250
251 eo_class_type type;
252 std::string name;
253 std::string eo_name;
254 ancestors_container_type parents;
255 ancestors_container_type ancestors;
256 constructors_container_type constructors;
257 constructors_container_type optional_constructors;
258 constructors_container_type all_constructors;
259 functions_container_type functions;
260 events_container_type own_events;
261 events_container_type concrete_events;
262 std::string comment;
263 std::string name_space;
264};
265
266struct eo_parameter
267{
268 eolian_type_instance type;
269 std::string name;
270};
271
272struct eo_constructor
273{
274 std::string name;
275 std::string impl;
276 parameters_container_type params;
277 std::string comment;
278};
279
280struct eo_function
281{
282 enum eo_function_type
283 {
284 regular_, class_
285 };
286 eo_function_type type;
287 eolian_scope scope;
288 bool is_beta;
289 std::string name;
290 std::string impl;
291 eolian_type_instance ret;
292 parameters_container_type params;
293 std::string comment;
294};
295
296struct eo_event
297{
298 eo_event() : scope(eolian_scope::public_), is_beta(false), name(),
299 eo_name(), comment()
300 {}
301
302 eolian_scope scope;
303 bool is_beta;
304 std::string name;
305 std::string eo_name;
306 //parameters_container_type params; // XXX desirable.
307 std::string comment;
308
309 bool operator<(eo_event const& other) const { return name < other.name; }
310};
311
312
313inline bool
314function_is_void(eo_function const& func)
315{
316 return func.ret.empty() || func.ret.front().native.compare("void") == 0;
317}
318
319inline bool
320function_is_static(eo_function const& func)
321{
322 return func.type == eo_function::class_;
323}
324
325inline unsigned int
326parameters_count_callbacks(parameters_container_type const& parameters)
327{
328 unsigned int r = 0u;
329 for (auto first = parameters.begin(), last = parameters.end()
330 ; first != last ; ++first)
331 if(type_is_callback(first->type) && first + 1 != last)
332 ++r;
333 return r;
334}
335
336inline parameters_container_type::const_iterator
337parameters_find_callback(parameters_container_type const& parameters)
338{
339 for (auto it = parameters.cbegin(), last = parameters.cend();
340 it != last; ++it)
341 {
342 if (type_is_callback((*it).type) && it + 1 != last)
343 return it;
344 }
345 return parameters.cend();
346}
347
348} } // namespace efl { namespace eolian {
349
350#endif // EFL_EOLIAN_CXX_EO_TYPES_HH
diff --git a/src/lib/eolian_cxx/eo_validate.hh b/src/lib/eolian_cxx/eo_validate.hh
deleted file mode 100644
index 8ffa7dccd7..0000000000
--- a/src/lib/eolian_cxx/eo_validate.hh
+++ /dev/null
@@ -1,116 +0,0 @@
1
2#ifndef EOLIAN_CXX_EO_CLASS_VALIDATE_HH
3#define EOLIAN_CXX_EO_CLASS_VALIDATE_HH
4
5#include <algorithm>
6#include <string>
7#include <cassert>
8#include <cstdlib>
9#include "eo_types.hh"
10
11#include <iostream>
12
13namespace efl { namespace eolian {
14
15inline bool
16_is_valid(std::string const& value)
17{
18 return !value.empty() and (isalpha(value[0]) || value[0] == '_');
19}
20
21inline bool
22_is_valid(eolian_type_instance const& type)
23{
24 // if (type.empty() || (*type.rbegin()).category == eolian_type::complex_)
25 // return false;
26 for (auto rit = type.parts.rbegin(), last = type.parts.rend(); rit != last; ++rit)
27 {
28 if ((*rit).binding.empty() && (*rit).category == eolian_type::complex_)
29 return false;
30 // else if (rit != type.rbegin() && (*rit).category != eolian_type::complex_)
31 // {
32 // std::cout << "begin " << (rit != type.rbegin()) << std::endl;
33 // std::cout << "category " << rit->category << std::endl;
34 // return false;
35 // }
36 }
37 return true;
38}
39
40inline bool
41_is_valid(parameters_container_type const& parameters)
42{
43 unsigned int n_callbacks = parameters_count_callbacks(parameters);
44 return n_callbacks == 0 || n_callbacks == 1;
45}
46
47inline bool
48_is_valid(events_container_type const& events)
49{
50 for (eo_event event : events)
51 {
52 if (event.name.empty() || event.eo_name.empty())
53 return false;
54 }
55 return true;
56}
57
58template <typename T>
59inline void
60_validate(T const& val, eo_class const& cls)
61{
62 if(!_is_valid(val))
63 {
64 static_cast<void>(cls);
65 assert(false && "Failed identifier validation");
66 }
67}
68
69inline void
70eo_class_validate(const eo_class& cls)
71{
72 // class name and type
73 _validate(cls.name, cls);
74 assert(cls.type == eo_class::regular_ ||
75 cls.type == eo_class::regular_noninst_ ||
76 cls.type == eo_class::interface_ ||
77 cls.type == eo_class::mixin_);
78
79 // constructors
80 for (auto it = cls.constructors.cbegin(), last = cls.constructors.cend();
81 it != last; ++it)
82 {
83 _validate((*it).name, cls);
84 _validate((*it).params, cls);
85 // parameters
86 for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
87 it_p != last_p; ++it_p)
88 {
89 _validate((*it_p).name, cls);
90 _validate((*it_p).type, cls);
91 }
92 }
93 // functions
94 for (auto it = cls.functions.begin(), last = cls.functions.end();
95 it != last; ++it)
96 {
97 _validate((*it).name, cls);
98 _validate((*it).impl, cls);
99 _validate((*it).ret, cls);
100 _validate((*it).params, cls);
101 // parameters
102 for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
103 it_p != last_p; ++it_p)
104 {
105 _validate((*it_p).name, cls);
106 _validate((*it_p).type, cls);
107 }
108 }
109 // events
110 _validate(cls.own_events, cls);
111 _validate(cls.concrete_events, cls);
112}
113
114} } // namespace efl { namespace eolian {
115
116#endif // EOLIAN_CXX_EO_CLASS_VALIDATE_HH
diff --git a/src/lib/eolian_cxx/grammar/address_of.hpp b/src/lib/eolian_cxx/grammar/address_of.hpp
new file mode 100644
index 0000000000..41a027667c
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/address_of.hpp
@@ -0,0 +1,74 @@
1#ifndef EOLIAN_CXX_ADDRESS_OF_HH
2#define EOLIAN_CXX_ADDRESS_OF_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/function_declaration.hpp"
13#include "grammar/case.hpp"
14
15namespace efl { namespace eolian { namespace grammar {
16
17struct address_of_generator
18{
19 template <typename OutputIterator, typename Context>
20 bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
21 {
22 std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
23
24 if(!as_generator
25 (
26 scope_tab << " ::efl::eolian::address_of_operator<" << string
27 ).generate(sink, cls.cxx_name, context)) return false;
28
29 for(auto&& i : cls.inherits)
30 {
31 if(!as_generator(", " << *("::" << lower_case[string]) << "::" << string)
32 .generate(sink, std::make_tuple(attributes::cpp_namespaces(i.namespaces), i.eolian_name), context))
33 return false;
34 }
35
36 if(!as_generator
37 (
38 "> operator&() { return {this}; }\n"
39 ).generate(sink, attributes::unused, context)) return false;
40
41 if(!as_generator
42 (
43 scope_tab << " ::efl::eolian::address_of_operator<" << string << " const "
44 ).generate(sink, cls.cxx_name, context)) return false;
45
46 for(auto&& i : cls.inherits)
47 {
48 if(!as_generator(", " << *("::" << lower_case[string]) << "::" << string << " const ")
49 .generate(sink, std::make_tuple(attributes::cpp_namespaces(i.namespaces), i.eolian_name), context))
50 return false;
51 }
52
53 if(!as_generator
54 (
55 "> operator&() const { return {this}; }\n"
56 ).generate(sink, attributes::unused, context)) return false;
57
58 return true;
59 }
60};
61
62template <>
63struct is_eager_generator<address_of_generator> : std::true_type {};
64
65namespace type_traits {
66template <>
67struct attributes_needed<address_of_generator> : std::integral_constant<int, 1> {};
68}
69
70address_of_generator const address_of;
71
72} } }
73
74#endif
diff --git a/src/lib/eolian_cxx/grammar/alternative.hpp b/src/lib/eolian_cxx/grammar/alternative.hpp
new file mode 100644
index 0000000000..2d70052f45
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/alternative.hpp
@@ -0,0 +1,52 @@
1#ifndef EOLIAN_CXX_ALTERNATIVE_HH
2#define EOLIAN_CXX_ALTERNATIVE_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/meta.hpp"
6#include "grammar/variant.hpp"
7
8namespace efl { namespace eolian { namespace grammar {
9
10template <typename L, typename R>
11struct alternative_generator
12{
13 template <typename OutputIterator, typename...Args, typename Context>
14 bool generate(OutputIterator /*sink*/, attributes::variant<Args...> const& /*attribute*/, Context const& /*context*/) const
15 {
16 // return grammar::alternative_sequence(left, right, sink, attribute);
17 return false;
18 }
19 template <typename OutputIterator, typename Attribute, typename...Args, typename Context>
20 bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
21 {
22 if(!attributes::generate(as_generator(left), sink, attribute, context))
23 return attributes::generate(as_generator(right), sink, attribute, context);
24 else
25 return true;
26 }
27
28 L left;
29 R right;
30};
31
32template <typename L, typename R>
33struct is_eager_generator<alternative_generator<L, R> > : std::true_type {};
34
35namespace type_traits {
36template <typename L, typename R>
37struct attributes_needed<alternative_generator<L, R> > : std::integral_constant
38 <int, meta::max<attributes_needed<L>::value, attributes_needed<R>::value>::value> {};
39template <typename L, typename R>
40struct accepts_tuple<alternative_generator<L, R> > : std::true_type {};
41}
42
43template <typename L, typename R>
44typename std::enable_if<grammar::is_generator<L>::value && grammar::is_generator<R>::value, alternative_generator<L, R>>::type
45operator|(L l, R r)
46{
47 return alternative_generator<L, R>{l, r};
48}
49
50} } }
51
52#endif
diff --git a/src/lib/eolian_cxx/grammar/attribute_conditional.hpp b/src/lib/eolian_cxx/grammar/attribute_conditional.hpp
new file mode 100644
index 0000000000..1fab57d897
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/attribute_conditional.hpp
@@ -0,0 +1,66 @@
1#ifndef EOLIAN_CXX_ATTRIBUTE_CONDITIONAL_HH
2#define EOLIAN_CXX_ATTRIBUTE_CONDITIONAL_HH
3
4#include "grammar/generator.hpp"
5
6namespace efl { namespace eolian { namespace grammar {
7
8template <typename F, typename G>
9struct functional_attribute_conditional_generator
10{
11 template <typename OutputIterator, typename Attribute, typename Context>
12 bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
13 {
14 if(f(attribute))
15 return as_generator(g).generate(sink, attribute, ctx);
16 else
17 return false;
18 }
19
20 F f;
21 G g;
22};
23
24template <typename F, typename G>
25struct is_eager_generator<functional_attribute_conditional_generator<F, G>> : std::true_type {};
26
27template <typename F>
28struct functional_attribute_conditional_directive
29{
30 template <typename G>
31 functional_attribute_conditional_generator<F, G> operator[](G g) const
32 {
33 return {f, g};
34 }
35
36 template <typename OutputIterator, typename Attribute, typename Context>
37 bool generate(OutputIterator, Attribute const& attribute, Context const&) const
38 {
39 return f(attribute);
40 }
41
42 F f;
43};
44
45template <typename F>
46struct is_eager_generator<functional_attribute_conditional_directive<F>> : std::true_type {};
47
48struct attribute_conditional_terminal
49{
50 template <typename F>
51 functional_attribute_conditional_directive<F> operator()(F f) const
52 {
53 return {f};
54 }
55} const attribute_conditional;
56
57namespace type_traits {
58template <typename F, typename G>
59struct attributes_needed<functional_attribute_conditional_generator<F, G>> : attributes_needed<G> {};
60template <typename F>
61struct attributes_needed<functional_attribute_conditional_directive<F>> : std::integral_constant<int, 1> {};
62}
63
64} } }
65
66#endif
diff --git a/src/lib/eolian_cxx/grammar/attribute_reorder.hpp b/src/lib/eolian_cxx/grammar/attribute_reorder.hpp
new file mode 100644
index 0000000000..b3f8b3196b
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/attribute_reorder.hpp
@@ -0,0 +1,87 @@
1#ifndef EOLIAN_CXX_ATTRIBUTE_REORDER_HH
2#define EOLIAN_CXX_ATTRIBUTE_REORDER_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/attributes.hpp"
6
7namespace efl { namespace eolian { namespace grammar {
8
9template <typename Tuple, int...S>
10struct reorder_tuple
11{
12 Tuple* tuple;
13};
14
15namespace impl {
16
17template <int N, typename T>
18struct index_calc;
19
20template <int N, typename Tuple, int...S>
21struct index_calc<0, reorder_tuple<Tuple, N, S...>> : std::integral_constant<int, N> {};
22
23template <int I, int N, typename Tuple, int...S>
24struct index_calc<I, reorder_tuple<Tuple, N, S...>> : index_calc<I-1, reorder_tuple<Tuple, S...>> {};
25
26}
27namespace attributes {
28template <int N, typename Tuple, int...S>
29struct tuple_element<N, reorder_tuple<Tuple, S...>>
30{
31 template <typename T>
32 struct identity { typedef T type; };
33 typedef impl::index_calc<N, reorder_tuple<Tuple, S...>> index;
34 typedef typename std::conditional
35 <index::value == -1
36 , identity<Tuple>
37 , tuple_element<index::value, typename std::remove_const<Tuple>::type>>::type::type type;
38 static type const& get_impl(reorder_tuple<Tuple, S...> const& t
39 , std::integral_constant<int, -1>)
40 { return *t.tuple; }
41 template <int I>
42 static type const& get_impl(reorder_tuple<Tuple, S...> const& t
43 , std::integral_constant<int, I>)
44 { using std::get; return get<index::value>(*t.tuple); }
45 static type const& get(reorder_tuple<Tuple, S...> const& t)
46 { return get_impl(t, index{}); }
47};
48}
49template <int N, typename Tuple, int...S>
50typename attributes::tuple_element<N, reorder_tuple<Tuple, S...>>::type const& get(reorder_tuple<Tuple, S...>const& t)
51{
52 return attributes::tuple_element<N, reorder_tuple<Tuple, S...>>::get(t);
53}
54
55template <typename G, int...S>
56struct attribute_reorder_generator
57{
58 template <typename OutputIterator, typename Attribute, typename Context>
59 bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
60 {
61 return attributes::generate(as_generator(g), sink, reorder_tuple<Attribute const, S...>{&attribute}, ctx);
62 }
63
64 G g;
65};
66
67template <typename G, int...S>
68struct is_eager_generator<attribute_reorder_generator<G, S...>> : std::true_type {};
69
70template <int...S, typename G>
71attribute_reorder_generator<G, S...> attribute_reorder(G g)
72{
73 return {g};
74}
75
76namespace type_traits {
77template <typename G, int...S>
78struct attributes_needed<attribute_reorder_generator<G, S...>> : attributes_needed<G> {};
79template <int...S, typename Tuple>
80struct is_explicit_tuple<reorder_tuple<Tuple, S...>> : std::true_type {};
81template <int...S, typename Tuple>
82struct is_tuple<reorder_tuple<Tuple, S...>> : std::true_type {};
83}
84
85} } }
86
87#endif
diff --git a/src/lib/eolian_cxx/grammar/attribute_replace.hpp b/src/lib/eolian_cxx/grammar/attribute_replace.hpp
new file mode 100644
index 0000000000..448abc23b2
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/attribute_replace.hpp
@@ -0,0 +1,63 @@
1#ifndef EOLIAN_CXX_ATTRIBUTE_REPLACE_HH
2#define EOLIAN_CXX_ATTRIBUTE_REPLACE_HH
3
4#include "grammar/generator.hpp"
5
6namespace efl { namespace eolian { namespace grammar {
7
8template <typename F, typename G>
9struct functional_attribute_replace_generator
10{
11 template <typename OutputIterator, typename Attribute, typename Context>
12 bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
13 {
14 return as_generator(g).generate(sink, f(attribute), ctx);
15 }
16
17 F f;
18 G g;
19};
20
21template <typename F, typename G>
22struct is_eager_generator<functional_attribute_replace_generator<F, G>> : std::true_type {};
23
24template <typename F>
25struct functional_attribute_replace_directive
26{
27 template <typename G>
28 functional_attribute_replace_generator<F, G> operator[](G g) const
29 {
30 return {f, g};
31 }
32
33 template <typename OutputIterator, typename Attribute, typename Context>
34 bool generate(OutputIterator, Attribute const& attribute, Context const&) const
35 {
36 return f(attribute);
37 }
38
39 F f;
40};
41
42template <typename F>
43struct is_eager_generator<functional_attribute_replace_directive<F>> : std::true_type {};
44
45struct attribute_replace_terminal
46{
47 template <typename F>
48 functional_attribute_replace_directive<F> operator()(F f) const
49 {
50 return {f};
51 }
52} const attribute_replace;
53
54namespace type_traits {
55template <typename F, typename G>
56struct attributes_needed<functional_attribute_replace_generator<F, G>> : attributes_needed<G> {};
57template <typename F>
58struct attributes_needed<functional_attribute_replace_directive<F>> : std::integral_constant<int, 1> {};
59}
60
61} } }
62
63#endif
diff --git a/src/lib/eolian_cxx/grammar/attributes.hpp b/src/lib/eolian_cxx/grammar/attributes.hpp
new file mode 100644
index 0000000000..4e63676712
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/attributes.hpp
@@ -0,0 +1,185 @@
1#ifndef EOLIAN_CXX_ATTRIBUTES_HH
2#define EOLIAN_CXX_ATTRIBUTES_HH
3
4#include <tuple>
5#include <type_traits>
6#include "grammar/type_traits.hpp"
7
8namespace efl { namespace eolian { namespace grammar {
9
10namespace attributes {
11
12struct unused_type {};
13unused_type const unused;
14
15template <int N, typename Tuple, typename Enable = void>
16struct tuple_element;
17
18template <int N, typename Tuple>
19struct tuple_element<N, Tuple, typename std::enable_if
20 <type_traits::is_std_tuple<Tuple>::value>::type> : std::tuple_element<N, Tuple>
21{};
22
23template <int N, typename Tuple>
24typename tuple_element<N, typename std::remove_const<Tuple>::type>::type get_adl(Tuple& tuple)
25{
26 using std::get;
27 return get<N>(tuple);
28}
29
30template <int I, typename Tuple>
31struct lazy_offset_tuple
32{
33 lazy_offset_tuple(Tuple& tuple)
34 : tuple(tuple) {}
35
36 template <int N>
37 typename tuple_element<N+I, typename std::remove_const<Tuple>::type>::type get() const
38 {
39 return attributes::get_adl<N+I>(tuple);
40 }
41
42 Tuple& tuple;
43};
44
45}
46namespace type_traits {
47template <int N, typename T>
48struct is_tuple<attributes::lazy_offset_tuple<N, T>> : std::true_type {};
49template <int N, typename T>
50struct is_explicit_tuple<attributes::lazy_offset_tuple<N, T>> : std::true_type {};
51}
52namespace attributes {
53
54template <typename T>
55struct infinite_tuple
56{
57 T object;
58};
59
60template <typename T>
61infinite_tuple<T> make_infinite_tuple(T&& object)
62{
63 return infinite_tuple<T>{std::forward<T>(object)};
64}
65
66template <int N, typename T>
67struct tuple_element<N, infinite_tuple<T>>
68{
69 typedef T type;
70 static type& get(infinite_tuple<T>& tuple) { return tuple.object; }
71 static type const& get(infinite_tuple<T> const& tuple) { return tuple.object; }
72};
73template <int N, typename T>
74struct tuple_element<N, infinite_tuple<T> const> : tuple_element<N, infinite_tuple<T>> {};
75template <int N, typename T>
76typename tuple_element<N, infinite_tuple<T>>::type&
77get(infinite_tuple<T>& tuple)
78{
79 return tuple_element<N, infinite_tuple<T>>::get(tuple);
80}
81template <int N, typename T>
82typename tuple_element<N, infinite_tuple<T>>::type const&
83get(infinite_tuple<T> const& tuple)
84{
85 return tuple_element<N, infinite_tuple<T>>::get(tuple);
86}
87
88}
89
90namespace type_traits {
91template <typename T>
92struct is_tuple<attributes::infinite_tuple<T>> : std::true_type {};
93template <typename T>
94struct is_explicit_tuple<attributes::infinite_tuple<T>> : std::true_type {};
95}
96namespace attributes {
97
98template <int N, int I, typename Tuple>
99struct tuple_element<N, lazy_offset_tuple<I, Tuple>> : tuple_element<N+I, typename std::remove_const<Tuple>::type>
100{};
101template <int N, int I, typename Tuple>
102struct tuple_element<N, lazy_offset_tuple<I, Tuple> const> : tuple_element<N+I, typename std::remove_const<Tuple>::type>
103{};
104
105template <int N, int I, typename Tuple>
106typename tuple_element<N, lazy_offset_tuple<I, Tuple> const>::type
107 get(lazy_offset_tuple<I, Tuple> const& tuple)
108{
109 return tuple.template get<N>();
110}
111
112template <typename Tuple>
113lazy_offset_tuple<1, Tuple> pop_front(Tuple& tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value>::type* = 0)
114{
115 return lazy_offset_tuple<1, Tuple>(tuple);
116}
117
118template <int N, typename Tuple>
119lazy_offset_tuple<N + 1, Tuple> pop_front(lazy_offset_tuple<N, Tuple> tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value>::type* = 0)
120{
121 return lazy_offset_tuple<N + 1, Tuple>(tuple.tuple);
122}
123
124template <int I, typename Tuple>
125lazy_offset_tuple<I, Tuple> pop_front_n(Tuple& tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value && I>::type* = 0)
126{
127 return lazy_offset_tuple<I, Tuple>(tuple);
128}
129template <int I, typename Tuple>
130Tuple& pop_front_n(Tuple& tuple, typename std::enable_if<I == 0>::type* = 0)
131{
132 return tuple;
133}
134
135template <int I, int N, typename Tuple>
136lazy_offset_tuple<N + I, Tuple> pop_front_n(lazy_offset_tuple<N, Tuple> tuple, typename std::enable_if<type_traits::is_tuple<Tuple>::value>::type* = 0)
137{
138 return lazy_offset_tuple<N + I, Tuple>(tuple.tuple);
139}
140
141template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
142bool generate(Generator const& gen, OutputIterator sink, Attribute const& attribute, Context const& context
143 , typename std::enable_if
144 <type_traits::is_explicit_tuple<Attribute>::value
145 && !type_traits::accepts_tuple<Generator>::value
146 && type_traits::attributes_needed<Generator>::value != 0
147 >::type* = 0)
148{
149 return gen.generate(sink, get<0>(attribute), context);
150}
151
152template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
153bool generate(Generator const& gen, OutputIterator sink, Attribute const& attribute, Context const& context
154 , typename std::enable_if
155 <type_traits::is_explicit_tuple<Attribute>::value
156 && type_traits::accepts_tuple<Generator>::value
157 && type_traits::attributes_needed<Generator>::value != 0
158 >::type* = 0)
159{
160 return gen.generate(sink, attribute, context);
161}
162
163template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
164bool generate(Generator const& gen, OutputIterator sink, Attribute const&
165 , Context const& context
166 , typename std::enable_if
167 <type_traits::attributes_needed<Generator>::value == 0
168 >::type* = 0)
169{
170 return gen.generate(sink, unused, context);
171}
172
173template <typename Generator, typename OutputIterator, typename Attribute, typename Context>
174bool generate(Generator const& gen, OutputIterator sink, Attribute const& attribute, Context const& context
175 , typename std::enable_if
176 <!type_traits::is_explicit_tuple<Attribute>::value
177 && type_traits::attributes_needed<Generator>::value != 0
178 >::type* = 0)
179{
180 return gen.generate(sink, attribute, context);
181}
182
183} } } }
184
185#endif
diff --git a/src/lib/eolian_cxx/grammar/base_class_definition.hpp b/src/lib/eolian_cxx/grammar/base_class_definition.hpp
new file mode 100644
index 0000000000..29b68133f7
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/base_class_definition.hpp
@@ -0,0 +1,112 @@
1#ifndef EOLIAN_CXX_BASE_CLASS_DEFINITION_HH
2#define EOLIAN_CXX_BASE_CLASS_DEFINITION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/function_declaration.hpp"
13#include "grammar/namespace.hpp"
14#include "grammar/case.hpp"
15#include "grammar/address_of.hpp"
16
17namespace efl { namespace eolian { namespace grammar {
18
19struct base_class_definition_generator
20{
21 template <typename OutputIterator, typename Context>
22 bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
23 {
24 std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
25 // static_assert(std::is_same<OutputIterator, void>::value, "");
26 auto open_namespace = *("namespace " << string << " { ") << "\n";
27 if(!as_generator(open_namespace).generate
28 (sink, cpp_namespaces, add_lower_case_context(context))) return false;
29
30 if(!as_generator
31 (
32 "struct " << string << " {\n"
33 ).generate(sink, cls.cxx_name, context)) return false;
34
35 if(!as_generator(*(scope_tab << function_declaration))
36 .generate(sink, cls.functions, context)) return false;
37
38 // static Eo_Class const* _eo_class();
39 std::string suffix;
40 switch(cls.type)
41 {
42 case attributes::class_type::regular:
43 case attributes::class_type::abstract_:
44 suffix = "CLASS";
45 break;
46 case attributes::class_type::mixin:
47 suffix = "MIXIN";
48 break;
49 case attributes::class_type::interface_:
50 suffix = "INTERFACE";
51 break;
52 }
53
54 if(!as_generator
55 (
56 scope_tab << "static Eo_Class const* _eo_class()\n"
57 << scope_tab << "{\n"
58 << scope_tab << scope_tab << "return "
59 ).generate(sink, attributes::unused, context)) return false;
60 if(!as_generator
61 (*(lower_case[string] << "_") << string << "_" << string)
62 .generate(sink, std::make_tuple(cls.namespaces, cls.eolian_name, suffix), add_upper_case_context(context)))
63 return false;
64 if(!as_generator(";\n" << scope_tab << "}\n").generate(sink, attributes::unused, context)) return false;
65
66 if(!as_generator
67 (
68 scope_tab << "Eo* _eo_ptr() const { return *(Eo**)this; }\n"
69 ).generate(sink, attributes::unused, context)) return false;
70
71 // operator ::ns::Class_Name() const;
72 // operator ::ns::Class_Name&();
73 // operator ::ns::Class_Name const&() const;
74 if(!as_generator
75 (
76 scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "() const;\n"
77 << scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "&();\n"
78 << scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << " const&() const;\n"
79 ).generate(sink, std::make_tuple
80 (cpp_namespaces, cls.cxx_name, cpp_namespaces, cls.cxx_name, cpp_namespaces, cls.cxx_name)
81 , context))
82 return false;
83
84 // /// @cond LOCAL
85 if(!as_generator(scope_tab << "/// @cond LOCAL\n").generate(sink, attributes::unused, context)) return false;
86
87 if(!as_generator(address_of).generate(sink, cls, context)) return false;
88
89 // /// @endcond
90 if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, attributes::unused, context)) return false;
91
92 if(!as_generator("};\n").generate(sink, attributes::unused, context)) return false;
93 auto close_namespace = *(lit("} ")) << "\n";
94 if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
95
96 return true;
97 }
98};
99
100template <>
101struct is_eager_generator<base_class_definition_generator> : std::true_type {};
102
103namespace type_traits {
104template <>
105struct attributes_needed<base_class_definition_generator> : std::integral_constant<int, 1> {};
106}
107
108base_class_definition_generator const base_class_definition;
109
110} } }
111
112#endif
diff --git a/src/lib/eolian_cxx/grammar/c_type.hpp b/src/lib/eolian_cxx/grammar/c_type.hpp
new file mode 100644
index 0000000000..b963a77873
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/c_type.hpp
@@ -0,0 +1,74 @@
1#ifndef EOLIAN_CXX_C_TYPE_HH
2#define EOLIAN_CXX_C_TYPE_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/string.hpp"
7
8namespace efl { namespace eolian { namespace grammar { namespace attributes {
9
10struct c_type_visitor
11{
12 std::string const* c_type;
13 typedef std::string result_type;
14 std::string operator()(attributes::klass_name const& name) const
15 {
16 std::string n;
17 as_generator(" ::" << *(string << "_") << string << string << "*")
18 .generate(std::back_insert_iterator<std::string>(n)
19 , std::make_tuple(name.namespaces, name.eolian_name
20 , std::string{is_const(name.base_qualifier) ? " const" : ""})
21 , context_null {});
22 return n;
23 }
24 template <typename T>
25 std::string operator()(T const&) const
26 {
27 return *c_type;
28 }
29};
30
31inline std::string c_type(parameter_def const& param)
32{
33 switch(param.direction)
34 {
35 case parameter_direction::in:
36 return param.type.original_type.visit(c_type_visitor{&param.c_type});
37 case parameter_direction::out:
38 case parameter_direction::inout:
39 return param.type.original_type.visit(c_type_visitor{&param.c_type}) + "*";
40 default:
41 throw std::runtime_error("Unknown parameter direction");
42 };
43}
44
45}
46
47struct c_type_generator
48{
49 template <typename OutputIterator, typename Context>
50 bool generate(OutputIterator sink, attributes::parameter_def const& attribute, Context const& context) const
51 {
52 return as_generator(attributes::c_type(attribute)).generate(sink, attributes::unused, context);
53 }
54 template <typename OutputIterator, typename Context>
55 bool generate(OutputIterator sink, attributes::type_def const& attribute, Context const& context) const
56 {
57 return as_generator(attribute.original_type.visit(attributes::c_type_visitor{&attribute.c_type}))
58 .generate(sink, attributes::unused, context);
59 }
60};
61
62template <>
63struct is_eager_generator<c_type_generator> : std::true_type {};
64
65namespace type_traits {
66template <>
67struct attributes_needed<c_type_generator> : std::integral_constant<int, 1> {};
68}
69
70c_type_generator const c_type;
71
72} } }
73
74#endif
diff --git a/src/lib/eolian_cxx/grammar/case.hpp b/src/lib/eolian_cxx/grammar/case.hpp
new file mode 100644
index 0000000000..e6599910ec
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/case.hpp
@@ -0,0 +1,86 @@
1#ifndef EOLIAN_CXX_CASE_HH
2#define EOLIAN_CXX_CASE_HH
3
4#include "grammar/context.hpp"
5#include "grammar/generator.hpp"
6
7namespace efl { namespace eolian { namespace grammar {
8
9struct upper_case_tag {};
10struct lower_case_tag {};
11
12template <typename Context>
13context_cons<upper_case_tag, Context>
14add_upper_case_context(Context const& context)
15{
16 return context_add_tag(upper_case_tag{}, context);
17}
18
19template <typename Context>
20context_cons<lower_case_tag, Context>
21add_lower_case_context(Context const& context)
22{
23 return context_add_tag(lower_case_tag{}, context);
24}
25
26template <typename G>
27struct lower_case_generator
28{
29 lower_case_generator(G g) : g(g) {}
30
31 template <typename OutputIterator, typename Attribute, typename Context>
32 bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
33 {
34 return as_generator(g).generate(sink, attribute, add_lower_case_context(context));
35 }
36
37 G g;
38};
39
40template <typename G>
41struct upper_case_generator
42{
43 upper_case_generator(G g) : g(g) {}
44
45 template <typename OutputIterator, typename Attribute, typename Context>
46 bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
47 {
48 return as_generator(g).generate(sink, attribute, add_upper_case_context(context));
49 }
50
51 G g;
52};
53
54template <typename G>
55struct is_eager_generator<lower_case_generator<G>> : std::true_type {};
56template <typename G>
57struct is_eager_generator<upper_case_generator<G>> : std::true_type {};
58
59namespace type_traits {
60template <typename G>
61struct attributes_needed<lower_case_generator<G>> : attributes_needed<G> {};
62template <typename G>
63struct attributes_needed<upper_case_generator<G>> : attributes_needed<G> {};
64}
65
66struct lower_case_directive
67{
68 template <typename G>
69 lower_case_generator<G> operator[](G&& g) const
70 {
71 return lower_case_generator<G>{g};
72 }
73} const lower_case;
74
75struct upper_case_directive
76{
77 template <typename G>
78 upper_case_generator<G> operator[](G&& g) const
79 {
80 return upper_case_generator<G>{g};
81 }
82} const upper_case;
83
84} } }
85
86#endif
diff --git a/src/lib/eolian_cxx/grammar/class_declaration.hpp b/src/lib/eolian_cxx/grammar/class_declaration.hpp
new file mode 100644
index 0000000000..f117f1330d
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/class_declaration.hpp
@@ -0,0 +1,56 @@
1#ifndef EOLIAN_CXX_CLASS_DECLARATION_HH
2#define EOLIAN_CXX_CLASS_DECLARATION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/function_declaration.hpp"
13
14namespace efl { namespace eolian { namespace grammar {
15
16struct class_declaration_generator
17{
18 template <typename OutputIterator, typename Context>
19 bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
20 {
21 std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
22 auto open_namespace = *("namespace " << string << " { ") << "\n";
23 if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false;
24
25 if(!as_generator
26 (
27 "struct " << string << ";\n"
28 ).generate(sink, cls.cxx_name, context)) return false;
29
30 auto close_namespace = *(lit("} ")) << "\n";
31 if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
32
33 if(!as_generator
34 (
35 "namespace efl { namespace eo { template<> struct is_eolian_object< "
36 "::" << *(lower_case[string] << "::") << string << "> : ::std::true_type {}; } }\n"
37 ).generate(sink, std::make_tuple(cpp_namespaces, cls.cxx_name), context)) return false;
38
39
40 return true;
41 }
42};
43
44template <>
45struct is_eager_generator<class_declaration_generator> : std::true_type {};
46
47namespace type_traits {
48template <>
49struct attributes_needed<class_declaration_generator> : std::integral_constant<int, 1> {};
50}
51
52class_declaration_generator const class_declaration;
53
54} } }
55
56#endif
diff --git a/src/lib/eolian_cxx/grammar/class_definition.hpp b/src/lib/eolian_cxx/grammar/class_definition.hpp
new file mode 100644
index 0000000000..7473ae8ff0
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/class_definition.hpp
@@ -0,0 +1,176 @@
1#ifndef EOLIAN_CXX_CLASS_DEFINITION_HH
2#define EOLIAN_CXX_CLASS_DEFINITION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/function_declaration.hpp"
13#include "grammar/case.hpp"
14#include "grammar/address_of.hpp"
15#include "grammar/attribute_reorder.hpp"
16#include "grammar/attribute_conditional.hpp"
17#include "grammar/attribute_replace.hpp"
18
19namespace efl { namespace eolian { namespace grammar {
20
21struct class_definition_generator
22{
23 template <typename OutputIterator, typename Context>
24 bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
25 {
26 std::vector<std::string> cpp_namespaces = attributes::cpp_namespaces(cls.namespaces);
27 auto open_namespace = *("namespace " << string << " { ") << "\n";
28 if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false;
29
30 if(!as_generator
31 (
32 "struct " << string << " : ::efl::eo::concrete"
33 )
34 .generate(sink, cls.cxx_name, context))
35 return false;
36 for(auto&& i : cls.inherits)
37 {
38 if(!as_generator("\n" << scope_tab << ", EO_CXX_INHERIT(" << *(" ::" << lower_case[string]) << "::" << string << ")")
39 .generate(sink, std::make_tuple(attributes::cpp_namespaces(i.namespaces), i.eolian_name), context))
40 return false;
41 }
42 if(!as_generator("\n{\n").generate(sink, attributes::unused, context)) return false;
43
44 // constructors
45 if(!as_generator
46 (
47 scope_tab << "explicit " << string << "( ::Eo* eo)\n"
48 << scope_tab << scope_tab << ": ::efl::eo::concrete(eo) {}\n"
49 << scope_tab << "explicit " << string << "(std::nullptr_t)\n"
50 << scope_tab << scope_tab << ": ::efl::eo::concrete(nullptr) {}\n"
51 << scope_tab << string << "(" << string << " const& other) = default;\n"
52 << scope_tab << string << "(" << string << "&& other) = default;\n"
53 << scope_tab << string << "& operator=(" << string << " const& other) = default;\n"
54 << scope_tab << string << "& operator=(" << string << "&& other) = default;\n"
55 << scope_tab << string << "()\n"
56 << scope_tab << "{\n"
57 << scope_tab << scope_tab << "::efl::eolian::do_eo_add( ::efl::eo::concrete::_eo_raw, ::efl::eo::concrete{nullptr}, _eo_class());\n"
58 << scope_tab << "}\n"
59 << scope_tab << string << "( ::efl::eo::concrete parent)\n"
60 << scope_tab << "{\n"
61 << scope_tab << scope_tab << "::efl::eolian::do_eo_add( ::efl::eo::concrete::_eo_raw, parent, _eo_class());\n"
62 << scope_tab << "}\n"
63 << scope_tab << "template <typename F> " << string << "(F f, typename ::std::enable_if< ::efl::eolian::is_callable<F>::value>::type* = 0)\n"
64 << scope_tab << "{\n"
65 << scope_tab << scope_tab << "::efl::eolian::do_eo_add( ::efl::eo::concrete::_eo_raw, ::efl::eo::concrete{nullptr}, _eo_class(), f);\n"
66 << scope_tab << "}\n"
67 // << scope_tab << "explicit " << string << "( ::efl::eo::concrete const& parent)\n"
68 // << scope_tab << scope_tab << ": ::efl::eo::concrete( ::efl::eo::do_eo_add(parent)) {}\n"
69 // << scope_tab << "template <typename F>\n"
70 // << scope_tab << "explicit " << string << "( ::efl::eo::concrete const& parent, F f)\n"
71 // << scope_tab << scope_tab << ": ::efl::eo::concrete( ::efl::eo::do_eo_add(parent, f)) {}\n"
72 // << scope_tab << "template <typename F>\n"
73 // << scope_tab << "explicit " << string << "(F f)\n"
74 // << scope_tab << scope_tab << ": ::efl::eo::concrete( ::efl::eo::do_eo_add( ::efl::eo::concrete{nullptr}, f)) {}\n"
75 ).generate(sink, attributes::make_infinite_tuple(cls.cxx_name), context)) return false;
76
77 if(!as_generator(*(scope_tab << function_declaration))
78 .generate(sink, cls.functions, context)) return false;
79
80 // static Eo_Class const* _eo_class();
81 std::string suffix;
82 switch(cls.type)
83 {
84 case attributes::class_type::regular:
85 case attributes::class_type::abstract_:
86 suffix = "CLASS";
87 break;
88 case attributes::class_type::mixin:
89 suffix = "MIXIN";
90 break;
91 case attributes::class_type::interface_:
92 suffix = "INTERFACE";
93 break;
94 }
95
96 if(!as_generator
97 (
98 scope_tab << "static Eo_Class const* _eo_class()\n"
99 << scope_tab << "{\n"
100 << scope_tab << scope_tab << "return "
101 ).generate(sink, attributes::unused, context)) return false;
102 if(!as_generator
103 (*(string << "_") << string << "_" << string)
104 .generate(sink, std::make_tuple(cls.namespaces, cls.eolian_name, suffix), add_upper_case_context(context)))
105 return false;
106 if(!as_generator(";\n" << scope_tab << "}\n").generate(sink, attributes::unused, context)) return false;
107
108 if(!as_generator
109 (
110 scope_tab << "Eo* _eo_ptr() const { return *(Eo**)this; }\n"
111 ).generate(sink, attributes::unused, context)) return false;
112
113 // operator ::ns::Class_Name() const;
114 // operator ::ns::Class_Name&();
115 // operator ::ns::Class_Name const&() const;
116 if(!as_generator
117 (
118 scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "() const;\n"
119 << scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << "&();\n"
120 << scope_tab << "operator " << *("::" << lower_case[string]) << "::" << string << " const&() const;\n"
121 ).generate(sink, std::make_tuple(cpp_namespaces, cls.cxx_name, cpp_namespaces, cls.cxx_name
122 , cpp_namespaces, cls.cxx_name), context))
123 return false;
124
125 if(!as_generator
126 (
127 *attribute_reorder<1, 2, 0, 1>
128 ((scope_tab << "static struct " << string_replace(',', '_') << "_event\n"
129 << scope_tab << "{\n"
130 << scope_tab << scope_tab << "static Eo_Event_Description const* description()\n"
131 << scope_tab << scope_tab << "{ return " << string << "; }\n"
132 << scope_tab << scope_tab << "typedef "
133 << (attribute_conditional([] (eina::optional<attributes::type_def> t) { return !!t; })
134 [attribute_replace([] (eina::optional<attributes::type_def> t) { return *t; }) [type]]
135 | "void")
136 << " parameter_type;\n"
137 << scope_tab << "} const " << string_replace(',', '_') << "_event;\n"
138 ))).generate(sink, cls.events, context))
139 return false;
140
141 // /// @cond LOCAL
142 if(!as_generator(scope_tab << "/// @cond LOCAL\n").generate(sink, attributes::unused, context)) return false;
143
144 if(!as_generator(address_of).generate(sink, cls, context)) return false;
145
146 // /// @endcond
147 if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, attributes::unused, context)) return false;
148
149 if(!as_generator("};\n").generate(sink, attributes::unused, context)) return false;
150
151 // static asserts
152 if(!as_generator("static_assert(sizeof(" << string << ") == sizeof(Eo*), \"\");\n")
153 .generate(sink, cls.cxx_name, context)) return false;
154 if(!as_generator("static_assert(std::is_standard_layout<" << string << ">::value, \"\");\n")
155 .generate(sink, cls.cxx_name, context)) return false;
156
157 auto close_namespace = *(lit("} ")) << "\n";
158 if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
159
160 return true;
161 }
162};
163
164template <>
165struct is_eager_generator<class_definition_generator> : std::true_type {};
166
167namespace type_traits {
168template <>
169struct attributes_needed<class_definition_generator> : std::integral_constant<int, 1> {};
170}
171
172class_definition_generator const class_definition;
173
174} } }
175
176#endif
diff --git a/src/lib/eolian_cxx/grammar/class_implementation.hpp b/src/lib/eolian_cxx/grammar/class_implementation.hpp
new file mode 100644
index 0000000000..a3c1d01f54
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/class_implementation.hpp
@@ -0,0 +1,56 @@
1#ifndef EOLIAN_CXX_CLASS_IMPLEMENTATION_HH
2#define EOLIAN_CXX_CLASS_IMPLEMENTATION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/string.hpp"
8#include "grammar/indentation.hpp"
9#include "grammar/list.hpp"
10#include "grammar/alternative.hpp"
11#include "grammar/type.hpp"
12#include "grammar/parameter.hpp"
13#include "grammar/function_definition.hpp"
14#include "grammar/namespace.hpp"
15#include "grammar/type_impl.hpp"
16#include "grammar/attribute_reorder.hpp"
17
18namespace efl { namespace eolian { namespace grammar {
19
20struct class_implementation_generator
21{
22 template <typename OutputIterator, typename Context>
23 bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& ctx) const
24 {
25 return as_generator
26 (
27 (namespaces
28 [*function_definition(get_klass_name(cls))]
29 // << "namespace eo_cxx {\n"
30 // << namespaces
31 // [*function_definition(get_klass_name(cls))]
32 // << "}\n\n"
33 )).generate(sink, std::make_tuple(cls.namespaces, cls.functions), ctx)
34 && as_generator
35 (
36 "namespace eo_cxx {\n"
37 << namespaces
38 [*function_definition(get_klass_name(cls))]
39 << "}\n\n"
40 ).generate(sink, std::make_tuple(cls.namespaces, cls.functions), ctx);
41 }
42};
43
44template <>
45struct is_eager_generator<class_implementation_generator> : std::true_type {};
46
47namespace type_traits {
48template <>
49struct attributes_needed<class_implementation_generator> : std::integral_constant<int, 1> {};
50}
51
52class_implementation_generator const class_implementation;
53
54} } }
55
56#endif
diff --git a/src/lib/eolian_cxx/grammar/comment.hh b/src/lib/eolian_cxx/grammar/comment.hh
deleted file mode 100644
index 21fa3ea38d..0000000000
--- a/src/lib/eolian_cxx/grammar/comment.hh
+++ /dev/null
@@ -1,45 +0,0 @@
1
2#ifndef EOLIAN_CXX_STD_COMMENT_HH
3#define EOLIAN_CXX_STD_COMMENT_HH
4
5#include <string>
6#include <sstream>
7#include <iosfwd>
8#include <ostream>
9
10#include "tab.hh"
11
12namespace efl { namespace eolian { namespace grammar {
13
14using std::endl;
15
16const std::string comment_prefix("///");
17
18struct comment
19{
20 std::string _doc;
21 int _tab;
22 std::string _if_empty;
23 comment(std::string const& doc, int tab = 0, std::string const& if_empty = "")
24 : _doc(doc), _tab(tab), _if_empty(if_empty)
25 {}
26};
27
28inline std::ostream&
29operator<<(std::ostream& out, comment const& x)
30{
31 std::string const& doc = !x._doc.empty() ? x._doc : x._if_empty;
32 std::istringstream ss(doc);
33 std::string line;
34 while(std::getline(ss, line))
35 {
36 out << tab(x._tab) << comment_prefix
37 << (line.size() ? (" " + line) : "")
38 << endl;
39 }
40 return out;
41}
42
43} } } // namespace efl { namespace eolian { namespace grammar {
44
45#endif // EOLIAN_CXX_STD_COMMENT_HH
diff --git a/src/lib/eolian_cxx/grammar/container.hpp b/src/lib/eolian_cxx/grammar/container.hpp
new file mode 100644
index 0000000000..4612612360
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/container.hpp
@@ -0,0 +1,46 @@
1#ifndef EOLIAN_CXX_CONTAINER_HH
2#define EOLIAN_CXX_CONTAINER_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7#include "grammar/type.hpp"
8
9namespace efl { namespace eolian { namespace grammar {
10
11struct container_subtype_modify
12{
13 typedef void result_type;
14 void operator()(attributes::complex_type_def& /*x*/) const
15 {
16 }
17
18 void operator()(attributes::regular_type_def& x) const
19 {
20 if(x.base_type == "string")
21 remove_own(x.base_qualifier);
22 else if(!x.pointers.empty())
23 x.pointers.pop_back();
24 }
25
26 template <typename T>
27 void operator()(T& /*x*/) const
28 {
29 }
30};
31
32template <typename OutputIterator, typename Context>
33void generate_container(OutputIterator sink, attributes::complex_type_def const& complex, Context const& context
34 , std::string const& name)
35{
36 if(!complex.subtypes.empty())
37 {
38 attributes::type_def subtype = complex.subtypes[0];
39 subtype.original_type.visit(container_subtype_modify{});
40 as_generator(" "<< name << "<" << type << ">").generate(sink, subtype, context);
41 }
42}
43
44} } }
45
46#endif
diff --git a/src/lib/eolian_cxx/grammar/context.hpp b/src/lib/eolian_cxx/grammar/context.hpp
new file mode 100644
index 0000000000..9b5e164470
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/context.hpp
@@ -0,0 +1,46 @@
1#ifndef EOLIAN_CXX_CONTEXT_HH
2#define EOLIAN_CXX_CONTEXT_HH
3
4namespace efl { namespace eolian { namespace grammar {
5
6struct context_null {};
7
8template <typename Tag, typename Tail = context_null>
9struct context_cons
10{
11 Tag tag;
12 Tail const& tail;
13};
14
15template <typename Tag>
16struct context_cons<Tag, context_null>
17{
18 Tag tag;
19 context_null tail;
20};
21
22template <typename NewTag, typename Tag, typename Tail>
23context_cons<NewTag, context_cons<Tag, Tail>>
24context_add_tag(NewTag tag, context_cons<Tag, Tail> const& context)
25{
26 return context_cons<NewTag, context_cons<Tag, Tail>>{tag, context};
27}
28template <typename NewTag>
29context_cons<NewTag, context_null>
30context_add_tag(NewTag tag, context_null context)
31{
32 return context_cons<NewTag, context_null>{tag, context};
33}
34
35template <typename Tag, typename Context>
36struct tag_check;
37template <typename Tag, typename Tail>
38struct tag_check<Tag, context_cons<Tag, Tail>> : std::true_type {};
39template <typename Tag>
40struct tag_check<Tag, context_null> : std::false_type {};
41template <typename Tag, typename OtherTag, typename Context>
42struct tag_check<Tag, context_cons<OtherTag, Context>> : tag_check<Tag, Context> {};
43
44} } }
45
46#endif
diff --git a/src/lib/eolian_cxx/grammar/converting_argument.hpp b/src/lib/eolian_cxx/grammar/converting_argument.hpp
new file mode 100644
index 0000000000..0f512ca698
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/converting_argument.hpp
@@ -0,0 +1,47 @@
1#ifndef EOLIAN_CXX_CONVERTING_ARGUMENT_HH
2#define EOLIAN_CXX_CONVERTING_ARGUMENT_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/string.hpp"
8#include "grammar/indentation.hpp"
9#include "grammar/list.hpp"
10#include "grammar/alternative.hpp"
11#include "grammar/type.hpp"
12#include "grammar/parameter.hpp"
13#include "grammar/function_definition.hpp"
14#include "grammar/namespace.hpp"
15#include "grammar/c_type.hpp"
16#include "grammar/attribute_reorder.hpp"
17
18namespace efl { namespace eolian { namespace grammar {
19
20struct converting_argument_generator
21{
22 template <typename OutputIterator, typename Context>
23 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& ctx) const
24 {
25 return as_generator
26 (
27 attribute_reorder<1, -1, 2>
28 (
29 " ::efl::eolian::convert_to_c<" << c_type << ", " << parameter_type << ">(" << string << ")"
30 )
31 ).generate(sink, param, ctx);
32 }
33};
34
35template <>
36struct is_eager_generator<converting_argument_generator> : std::true_type {};
37
38namespace type_traits {
39template <>
40struct attributes_needed<converting_argument_generator> : std::integral_constant<int, 1> {};
41}
42
43converting_argument_generator const converting_argument;
44
45} } }
46
47#endif
diff --git a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
deleted file mode 100644
index 03d6283b0a..0000000000
--- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
+++ /dev/null
@@ -1,603 +0,0 @@
1
2#ifndef EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
3#define EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
4
5#include <iosfwd>
6#include <string>
7
8#include "eo_types.hh"
9#include "tab.hh"
10#include "comment.hh"
11#include "parameters_generator.hh"
12#include "namespace_generator.hh"
13
14namespace efl { namespace eolian { namespace grammar {
15
16struct class_name
17{
18 std::string _name;
19 class_name(std::string name)
20 : _name(name)
21 {}
22};
23
24inline std::ostream&
25operator<<(std::ostream& out, class_name const& x)
26{
27 out << x._name;
28 return out;
29}
30
31struct class_inheritance
32{
33 eo_class const& _cls;
34 class_inheritance(eo_class const& cls)
35 : _cls(cls)
36 {}
37};
38
39inline std::ostream&
40operator<<(std::ostream& out, class_inheritance const& x)
41{
42 eo_class const& cls = x._cls;
43
44 ancestors_container_type::const_iterator it,
45 first = cls.ancestors.cbegin(),
46 last = cls.ancestors.cend();
47 for (it = first; it != last; ++it)
48 {
49 out << tab(2) << ", EO_CXX_INHERIT(" << *it << ")" << endl;
50 }
51 return out;
52}
53
54struct constructor_functor_type_name
55{
56 eo_constructor const& _ctor;
57 constructor_functor_type_name(eo_constructor const& ctor)
58 : _ctor(ctor)
59 {}
60};
61
62inline std::ostream&
63operator<<(std::ostream& out, constructor_functor_type_name const& x)
64{
65 out << "_c_" << x._ctor.name;
66 return out;
67}
68
69struct constructor_functor_type_decl
70{
71 eo_constructor const& _ctor;
72 constructor_functor_type_decl(eo_constructor const& ctor)
73 : _ctor(ctor)
74 {}
75};
76
77inline std::ostream&
78operator<<(std::ostream& out, constructor_functor_type_decl const& x)
79{
80 out << constructor_functor_type_name(x._ctor);
81
82 if (parameters_count_callbacks(x._ctor.params) == 0)
83 return out;
84
85 bool comma = false;
86 out << "<";
87 auto first = x._ctor.params.cbegin(), last = x._ctor.params.cend();
88 for(auto it = first; it != last; ++it)
89 {
90 if (type_is_callback((*it).type) && it+1 != last)
91 {
92 if (comma)
93 out << ", ";
94 else
95 comma = true;
96 out << template_parameter_type((*it).type, (*it).name);
97 }
98 }
99 return out << ">";
100}
101
102struct functors_constructor_methods
103{
104 eo_class const& _cls;
105 functors_constructor_methods(eo_class const& cls) : _cls(cls) {}
106};
107
108inline std::ostream&
109operator<<(std::ostream& out, functors_constructor_methods const& x)
110{
111 constructors_container_type::const_iterator it,
112 first = x._cls.all_constructors.cbegin(),
113 last = x._cls.all_constructors.cend();
114 for (it = first; it != last; ++it)
115 {
116 eo_constructor const& c = *it;
117
118 // Hide documentation condition
119 out << comment("@cond LOCAL", 1);
120
121 // Struct declaration
122 out << template_parameters_declaration(c.params, 1)
123 << tab(1) << "struct " << constructor_functor_type_name(c) << endl
124 << tab(1) << "{" << endl;
125
126 // Callbacks typedefs
127 out << parameters_cxx_generic(c.params,
128 [](param_data d)
129 {
130 if (d.is_cb)
131 d.out << tab(2)
132 << parameter_remove_reference_typedef(d.type, d.name)
133 << endl;
134 }
135 )
136 << endl;
137
138 // Struct constructor
139 out << tab(2) << "explicit " << constructor_functor_type_name(c) << "("
140 << parameters_declaration(c.params) << ")"
141 << parameters_cxx_generic(c.params,
142 [](param_data d)
143 {
144 if(d.pos == 0u)
145 d.out << endl << tab(3) << ": ";
146 else
147 d.out << ", ";
148
149 if (d.is_cb)
150 d.out << callback_tmp(d.name) << "(new "
151 << template_parameter_type(d.type, d.name)
152 << "(" << parameter_forward(d.type, d.name) << "))";
153 else
154 d.out << d.name << "(" << parameter_forward(d.type, d.name) << ")";
155 }
156 )
157 << endl
158 << tab(2) << "{}" << endl;
159
160 // Struct operator()
161 out << tab(2) << "void operator()(Eo* _obj_eo_self)" << endl
162 << tab(2) << "{" << endl
163 << tab(3) << "::" << c.impl << "(_obj_eo_self" << (c.params.empty() ? "" : ", ")
164 << parameters_forward_to_c(c.params) << ");" << endl
165 << tab(2) << "}" << endl;
166
167 // Register event to free allocated callbacks when the Eo* is deleted
168 out << tab(2) << "void register_ev_del_free_callback(Eo* _eoptr)" << endl
169 << tab(2) << "{" << endl
170 << tab(3) << "(void) _eoptr;" << endl
171 << parameters_cxx_generic(c.params,
172 [](param_data d)
173 {
174 if (d.is_cb)
175 d.out << tab(3)
176 << "eo_event_callback_add(_eoptr, EO_EVENT_DEL, "
177 << "&::efl::eolian::free_callback_callback<"
178 << parameter_no_ref_type(d.type, d.name)
179 << ">, " << callback_tmp(d.name) << ");" << endl;
180 })
181 << tab(2) << "}" << endl;
182
183 // Struct member variables
184 out << endl
185 << parameters_cxx_generic(c.params,
186 [](param_data d)
187 {
188 d.out << tab(2);
189 if (d.is_cb)
190 d.out << parameter_no_ref_type(d.type, d.name) << "* "
191 << callback_tmp(d.name);
192 else
193 d.out << parameter_type(d.type, d.name) << " " << d.name;
194 d.out << ";" << endl;
195 }
196 );
197
198 // Close struct
199 out << tab(1) << "};" << endl;
200
201 // End documentation condition
202 out << comment("@endcond", 1) << endl;
203 }
204
205 return out;
206}
207
208struct constructor_method_function_declarations
209{
210 eo_class const& _cls;
211 constructor_method_function_declarations(eo_class const& cls) : _cls(cls) {}
212};
213
214inline std::ostream&
215operator<<(std::ostream& out, constructor_method_function_declarations const& x)
216{
217 constructors_container_type::const_iterator it,
218 first = x._cls.all_constructors.cbegin(),
219 last = x._cls.all_constructors.cend();
220 for (it = first; it != last; ++it)
221 {
222 eo_constructor const& c = *it;
223
224 // "eo_constructor" is already called in the eo_add_ref macro (used in
225 // _ctors_call).
226 // Creating a function with this name yields an error in the eo_add_ref
227 // macro expansion, because "eo_constructor" will refers to the class
228 // function instead of the Eo.Base function which is intended.
229 if (c.name == "eo_constructor")
230 {
231 continue;
232 }
233
234 out << comment(c.comment, 1)
235 << template_parameters_declaration(c.params, 1)
236 << tab(1) << "static " << constructor_functor_type_decl(c)
237 << " " << c.name << "("
238 << parameters_declaration(c.params) << ");" << endl << endl;
239 }
240
241 return out;
242}
243
244struct constructor_method_function_definitions
245{
246 eo_class const& _cls;
247 constructor_method_function_definitions(eo_class const& cls) : _cls(cls) {}
248};
249
250inline std::ostream&
251operator<<(std::ostream& out, constructor_method_function_definitions const& x)
252{
253 constructors_container_type::const_iterator it,
254 first = x._cls.all_constructors.cbegin(),
255 last = x._cls.all_constructors.cend();
256 for (it = first; it != last; ++it)
257 {
258 eo_constructor const& c = *it;
259
260 // Same explanation as the one in constructor_method_function_declarations
261 if (c.name == "eo_constructor")
262 {
263 continue;
264 }
265
266 out << template_parameters_declaration(c.params, 0)
267 << "inline " << full_name(x._cls)
268 << "::" << constructor_functor_type_decl(c) << " "
269 << full_name(x._cls, false) << "::" << c.name << "("
270 << parameters_declaration(c.params) << ")" << endl
271 << "{" << endl
272 << tab(1) << "return " << constructor_functor_type_decl(c) << "("
273 << parameters_forward(c.params) << ");" << endl
274 << "}" << endl << endl;
275 }
276
277 return out;
278}
279
280struct comment_constructor_with_constructor_methods
281{
282 eo_class const& _cls;
283 comment_constructor_with_constructor_methods(eo_class const& cls)
284 : _cls(cls)
285 {}
286};
287
288inline std::ostream&
289operator<<(std::ostream& out, comment_constructor_with_constructor_methods const& x)
290{
291 out << tab(1) << "/**" << endl
292 << tab(2) << "@brief Constructs a new " << full_name(x._cls, false) << " object." << endl
293 << endl
294 << tab(2) << "Constructs a new " << full_name(x._cls, false) << " object. If you want this object to be a child" << endl
295 << tab(2) << "of another Eo object, use an @ref efl::eo::parent expression, like the example." << endl
296 << endl;
297
298 if (x._cls.constructors.size())
299 {
300 bool singular = (x._cls.constructors.size() == 1);
301 out << tab(2) << "Since this class have " << (singular ? "a " : "")
302 << "necessary constructor method" << (singular ? "" : "s")
303 << ", you must call " << (singular ? "it" : "each one of them") << endl
304 << tab(2) << "in the right place within this constructor parameters." << endl
305 << endl;
306 }
307
308 if (!x._cls.optional_constructors.empty())
309 {
310 out << tab(2) << "Optional constructors may be called in any combination as the" << endl
311 << tab(2) << "last parameters." << endl
312 << endl;
313 }
314
315 out << tab(2) << "Example:" << endl
316 << tab(2) << "@code" << endl
317 << tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(efl::eo::parent = parent_object";
318
319 for (eo_constructor const& c : x._cls.all_constructors)
320 out << "," << endl
321 << tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")";
322
323 out << ");" << endl
324 << tab(2) << "@endcode" << endl
325 << endl;
326
327 for (eo_constructor const& c : x._cls.all_constructors)
328 out << tab(2) << "@see " << x._cls.name << "::" << c.name << endl;
329 out << tab(2) << "@see " << x._cls.name << "(Eo* eo)" << endl;
330
331 return out << tab(1) << "*/" << endl;
332}
333
334struct constructor_with_constructor_methods
335{
336 eo_class const& _cls;
337 bool _with_parent;
338 constructor_with_constructor_methods(eo_class const& cls, bool with_parent)
339 : _cls(cls)
340 , _with_parent(with_parent)
341 {}
342};
343
344inline std::ostream&
345operator<<(std::ostream& out, constructor_with_constructor_methods const& x)
346{
347 unsigned cb_count = 0;
348
349 constructors_container_type::const_iterator it,
350 first = x._cls.constructors.cbegin(),
351 last = x._cls.constructors.cend();
352 for (it = first; it != last; ++it)
353 {
354 cb_count += parameters_count_callbacks((*it).params);
355 }
356
357 if (cb_count != 0 || !x._cls.optional_constructors.empty())
358 {
359 out << tab(1) << "template <";
360 for (unsigned i = 0; i != cb_count; ++i)
361 {
362 if (i != 0)
363 out << ", ";
364 out << "typename F" << i;
365 }
366 if (!x._cls.optional_constructors.empty())
367 {
368 if (cb_count != 0)
369 out << ", ";
370 out << "typename... FOpts";
371 }
372 out << ">" << endl;
373 }
374
375 out << tab(1) << "explicit " << x._cls.name << "(";
376
377 if (x._with_parent)
378 out << "::efl::eo::parent_type _p";
379
380 {
381 unsigned cb_idx = 0;
382 for (it = first; it != last; ++it)
383 {
384 if (x._with_parent || it != first)
385 out << ", ";
386 out << constructor_functor_type_name(*it);
387
388 if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
389 {
390 out << "<"
391 << parameters_cxx_generic((*it).params,
392 [&cb_idx](param_data d)
393 {
394 if (d.is_cb)
395 d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
396 })
397 << ">";
398 }
399 out << " _c" << (it-first);
400 }
401 assert(cb_idx == cb_count);
402 }
403
404 if (!x._cls.optional_constructors.empty())
405 {
406 if (x._with_parent || first != last)
407 out << ", ";
408 out << "FOpts&&... _opts";
409 }
410
411 out << ")" << endl
412 << tab(2) << ": " << x._cls.name << "(_ctors_call("
413 << (x._with_parent ? "_p" : "::efl::eo::parent = nullptr");
414 for (it = first; it != last; ++it)
415 {
416 out << ", _c" << (it-first);
417 }
418 if (!x._cls.optional_constructors.empty())
419 {
420 out << ", std::forward<FOpts>(_opts)...";
421 }
422 out << "))" << endl
423 << tab(1) << "{}" << endl;
424
425 return out;
426}
427
428struct constructors_with_constructor_methods
429{
430 eo_class const& _cls;
431 constructors_with_constructor_methods(eo_class const& cls)
432 : _cls(cls)
433 {}
434};
435
436inline std::ostream&
437operator<<(std::ostream& out, constructors_with_constructor_methods const& x)
438{
439 out << tab(1) << "//@{" << endl
440 << comment_constructor_with_constructor_methods(x._cls)
441 << constructor_with_constructor_methods(x._cls, true) << endl
442 << constructor_with_constructor_methods(x._cls, false)
443 << tab(1) << "//@}" << endl << endl;
444 return out;
445}
446
447struct constructor_eo
448{
449 eo_class const& _cls;
450 constructor_eo(eo_class const& cls)
451 : _cls(cls)
452 {}
453};
454
455inline std::ostream&
456operator<<(std::ostream& out, constructor_eo const& x)
457{
458 std::string doc = "@brief Eo Constructor.\n\n"
459 "Constructs the object from an Eo* pointer stealing its ownership.\n\n"
460 "@param eo The Eo object pointer.\n\n";
461 out << comment(doc, 1)
462 << tab(1)
463 << "explicit " << x._cls.name << "(Eo* eo)" << endl
464 << tab(2) << ": ::efl::eo::concrete(eo)" << endl
465 << tab(1) << "{}" << endl << endl;
466
467 out << comment(
468 "@brief nullptr_t Constructor.\n\n"
469 "Constructs an empty (null) object.\n\n"
470 , 1
471 )
472 << tab(1)
473 << "explicit " << x._cls.name << "(std::nullptr_t)" << endl
474 << tab(2) << ": ::efl::eo::concrete(nullptr)" << endl
475 << tab(1) << "{}" << endl << endl;
476 return out;
477}
478
479struct copy_constructor
480{
481 eo_class const& _cls;
482 copy_constructor(eo_class const& cls)
483 : _cls(cls)
484 {}
485};
486
487inline std::ostream&
488operator<<(std::ostream& out, copy_constructor const& x)
489{
490 std::string doc = "@brief Copy Constructor.\n\n";
491 out << comment(doc, 1)
492 << tab(1)
493 << x._cls.name << "(" << x._cls.name << " const& other)" << endl
494 << tab(2) << ": " << x._cls.name
495 << "(eo_ref(other._eo_ptr()))" << endl
496 << tab(1) << "{}" << endl << endl;
497 return out;
498}
499
500struct destructor
501{
502 eo_class const& _cls;
503 destructor(eo_class const& cls)
504 : _cls(cls)
505 {}
506};
507
508inline std::ostream&
509operator<<(std::ostream& out, destructor const& x)
510{
511 out << tab(1)
512 << '~' << x._cls.name << "() {}" << endl << endl;
513 return out;
514}
515
516struct function_call_constructor_methods
517{
518 eo_class const& _cls;
519 function_call_constructor_methods(eo_class const& cls) : _cls(cls) {}
520};
521
522inline std::ostream&
523operator<<(std::ostream& out, function_call_constructor_methods const& x)
524{
525 out << comment("@internal", 1);
526
527 unsigned cb_count = 0;
528
529 constructors_container_type::const_iterator it,
530 first = x._cls.constructors.cbegin(),
531 last = x._cls.constructors.cend();
532 for (it = first; it != last; ++it)
533 {
534 cb_count += parameters_count_callbacks((*it).params);
535 }
536 if (cb_count != 0 || !x._cls.optional_constructors.empty())
537 {
538 out << tab(1) << "template <";
539 for (unsigned i = 0; i != cb_count; ++i)
540 {
541 if (i != 0)
542 out << ", ";
543 out << "typename F" << i;
544 }
545 if (!x._cls.optional_constructors.empty())
546 {
547 if (cb_count != 0)
548 out << ", ";
549 out << "typename... FOpts";
550 }
551 out << ">" << endl;
552 }
553
554 unsigned cb_idx = 0;
555 out << tab(1) << "static Eo* _ctors_call(::efl::eo::parent_type _p";
556 for (it = first; it != last; ++it)
557 {
558 out << ", " << constructor_functor_type_name(*it);
559
560 if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
561 {
562 out << "<"
563 << parameters_cxx_generic((*it).params,
564 [&cb_idx](param_data d)
565 {
566 if (d.is_cb)
567 d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
568 })
569 << ">";
570 }
571 out << " _c" << (it-first);
572 }
573 assert(cb_idx == cb_count);
574
575 if (!x._cls.optional_constructors.empty())
576 out << ", FOpts&&... _opts";
577
578 out << ")" << endl
579 << tab(1) << "{" << endl
580 << tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw";
581 for (it = first; it != last; ++it)
582 {
583 out << ", _c" << (it-first) << "(eo_self)";
584 }
585 if (!x._cls.optional_constructors.empty())
586 out << ", ::efl::eolian::call_ctors(eo_self, _opts...)";
587 out << ");" << endl << endl;
588
589 for (it = first; it != last; ++it)
590 out << tab(2) << "_c" << (it-first) << ".register_ev_del_free_callback(_ret_eo);" << endl;
591
592 if (!x._cls.optional_constructors.empty())
593 out << tab(2) << "::efl::eolian::register_ev_del_free_callback(_ret_eo, _opts...);" << endl;
594
595 out << tab(2) << "return _ret_eo;" << endl
596 << tab(1) << "}" << endl << endl;
597
598 return out;
599}
600
601} } } // namespace efl { namespace eolian { namespace grammar {
602
603#endif // EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
diff --git a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh
deleted file mode 100644
index 95e155ce58..0000000000
--- a/src/lib/eolian_cxx/grammar/eo_class_events_generator.hh
+++ /dev/null
@@ -1,117 +0,0 @@
1
2#ifndef EOLIAN_CXX_STD_EO_CLASS_EVENTS_GENERATOR_HH
3#define EOLIAN_CXX_STD_EO_CLASS_EVENTS_GENERATOR_HH
4
5#include <iosfwd>
6
7#include "type_generator.hh"
8#include "eo_class_scope_guard_generator.hh"
9#include "tab.hh"
10#include "comment.hh"
11
12namespace efl { namespace eolian { namespace grammar {
13
14struct add_cast_to_t
15{
16 add_cast_to_t(bool b)
17 : _b(b)
18 {
19 }
20
21 bool _b;
22};
23
24inline std::ostream&
25operator<<(std::ostream& out, add_cast_to_t x)
26{
27 if(x._b)
28 out << "static_cast<U*>(this)->";
29 return out;
30}
31
32struct event_callback_add
33{
34 eo_event const& _event;
35 eo_class const& _cls;
36 bool _add_cast_to_t;
37 event_callback_add(eo_event const& event, eo_class const& cls
38 , bool add_cast_to_t)
39 : _event(event), _cls(cls), _add_cast_to_t(add_cast_to_t)
40 {}
41};
42
43inline std::ostream&
44operator<<(std::ostream& out, event_callback_add const& x)
45{
46 out << comment(x._event.comment, 1)
47 << tab(1) << "template <typename F>" << endl
48 << tab(1) << "::efl::eo::signal_connection" << endl
49 << tab(1) << "callback_" << x._event.name << "_add(F && callback_," << endl
50 << tab(8) << "::efl::eo::callback_priority priority_ =" << endl
51 << tab(8) << "::efl::eo::callback_priorities::default_)" << endl
52 << tab(1) << "{" << endl
53 << tab(2) << "typedef typename std::remove_reference<F>::type function_type;" << endl
54 << tab(2) << "::std::unique_ptr<function_type> f ( new function_type(std::forward<F>(callback_)) );" << endl
55 << tab(2) << "eo_event_callback_priority_add(" << add_cast_to_t(x._add_cast_to_t) << "_concrete_eo_ptr()," << endl
56 << tab(2) << x._event.eo_name << ", priority_," << endl
57 << tab(2) << "&::efl::eo::_detail::event_callback<" << full_name(x._cls) << ", function_type>, f.get());" << endl
58 << tab(2) << "return ::efl::eo::make_signal_connection" << endl
59 << tab(3) << "(f, " << add_cast_to_t(x._add_cast_to_t)
60 << "_concrete_eo_ptr(), &::efl::eo::_detail::event_callback<"
61 << full_name(x._cls) << ", function_type>," << endl
62 << tab(3) << x._event.eo_name << " );" << endl
63 << tab(1) << "}" << endl;
64 return out;
65}
66
67struct event_callback_call
68{
69 eo_event const& _event;
70 bool _add_cast_to_t;
71 event_callback_call(eo_event const& event, bool add_cast_to_t)
72 : _event(event), _add_cast_to_t(add_cast_to_t)
73 {}
74};
75
76inline std::ostream&
77operator<<(std::ostream& out, event_callback_call const& x)
78{
79 out << comment(x._event.comment, 1)
80 << tab(1) << "template <typename T>" << endl
81 << tab(1) << "void" << endl
82 << tab(1) << "callback_" << x._event.name << "_call(T* info)" << endl
83 << tab(1) << "{" << endl
84 << tab(2) << "eo_event_callback_call" << endl
85 << tab(4) << "(" << add_cast_to_t(x._add_cast_to_t) << "_concrete_eo_ptr(), " << x._event.eo_name << ", info);" << endl
86 << tab(1) << "}" << endl;
87 return out;
88}
89
90struct events
91{
92 eo_class const& _cls;
93 events_container_type const& _events;
94 bool _add_cast_to_t;
95 events(eo_class const& cls, events_container_type const& evts, bool add_cast_to_t = false)
96 : _cls(cls), _events(evts), _add_cast_to_t(add_cast_to_t) {}
97};
98
99inline std::ostream&
100operator<<(std::ostream& out, events const& x)
101{
102 for (eo_event const& e : x._events)
103 {
104 out << scope_guard_head(x._cls, e);
105
106 out << event_callback_add(e, x._cls, x._add_cast_to_t) << endl
107 << event_callback_call(e, x._add_cast_to_t);
108
109 out << scope_guard_tail(x._cls, e) << endl;
110 }
111 out << endl;
112 return out;
113}
114
115} } }
116
117#endif // EOLIAN_CXX_STD_EO_CLASS_EVENTS_GENERATOR_HH
diff --git a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
deleted file mode 100644
index f99254c322..0000000000
--- a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
+++ /dev/null
@@ -1,173 +0,0 @@
1
2#ifndef EOLIAN_CXX_STD_EO_CLASS_FUNCTIONS_GENERATOR_HH
3#define EOLIAN_CXX_STD_EO_CLASS_FUNCTIONS_GENERATOR_HH
4
5#include <iosfwd>
6
7#include "eo_types.hh"
8#include "tab.hh"
9#include "comment.hh"
10#include "parameters_generator.hh"
11#include "type_generator.hh"
12#include "namespace_generator.hh"
13#include "eo_class_scope_guard_generator.hh"
14
15namespace efl { namespace eolian { namespace grammar {
16
17struct function_call
18{
19 eo_function const& _func;
20 function_call(eo_function const& func) : _func(func) {}
21};
22
23struct parameterized_obj_function_call
24{
25 eo_function const& _func;
26 std::string obj;
27 parameterized_obj_function_call(eo_function const& func, std::string obj) : _func(func), obj(obj) {}
28};
29
30inline std::ostream&
31operator<<(std::ostream& out, function_call const& x)
32{
33 bool is_void = function_is_void(x._func);
34 bool is_static = function_is_static(x._func);
35 return out << (!is_void ? "_tmp_ret = " : "")
36 << "::" << x._func.impl
37 << "("
38 << (is_static ? "const_cast<Eo*>(_eo_class())" : "_concrete_eo_ptr()")
39 << (x._func.params.empty() ? "" : ",")
40 << parameters_forward_to_c(x._func.params) << ")";
41}
42
43inline std::ostream&
44operator<<(std::ostream& out, parameterized_obj_function_call const& x)
45{
46 bool is_void = function_is_void(x._func);
47 return out << (!is_void ? "_tmp_ret = " : "")
48 << "::" << x._func.impl
49 << "("
50 << x.obj
51 << (x._func.params.empty() ? "" : ",")
52 << parameters_forward_to_c(x._func.params) << ")";
53}
54
55struct function_declaration
56{
57 eo_class const& _cls;
58 eo_function const& _func;
59 function_declaration(eo_class const& cls, eo_function const& func)
60 : _cls(cls), _func(func)
61 {}
62};
63
64inline std::ostream&
65operator<<(std::ostream& out, function_declaration const& x)
66{
67 eo_function const& func = x._func;
68
69 out << comment(x._func.comment, 1)
70 << template_parameters_declaration(func.params, 1)
71 << tab(1);
72
73 bool is_static = function_is_static(func);
74 if (is_static)
75 out << "static ";
76
77 out << reinterpret_type(func.ret) << " " << func.name << "("
78 << parameters_declaration(func.params)
79 << (is_static ? ");" : ") const;") << endl;
80
81 return out;
82}
83
84struct function_definition
85{
86 eo_class const& _cls;
87 eo_function const& _func;
88 bool _concrete;
89 function_definition(eo_class const& cls, eo_function const& func, bool concrete)
90 : _cls(cls), _func(func), _concrete(concrete)
91 {}
92};
93
94inline std::ostream&
95operator<<(std::ostream& out, function_definition const& x)
96{
97 eo_function const& func = x._func;
98
99 bool is_static = function_is_static(func);
100
101 out << template_parameters_declaration(func.params, 0)
102 << "inline " << reinterpret_type(func.ret) << " ";
103
104 if (x._concrete)
105 out << full_name(x._cls, false);
106 else
107 out << abstract_full_name(x._cls, false);
108
109 out << "::" << func.name << "("
110 << parameters_declaration(func.params)
111 << (is_static ? ")" : ") const") << endl
112 << "{" << endl;
113
114 if (!function_is_void(func))
115 out << tab(1)
116 << func.ret.front().native << " _tmp_ret;" << endl;
117
118 out << callbacks_heap_alloc("_concrete_eo_ptr()", func.params, is_static, 1);
119
120 out << tab(1) << function_call(x._func) << ";" << endl;
121
122 if (!function_is_void(func))
123 out << tab(1) << "return " << to_cxx(func.ret, "_tmp_ret") << ";" << endl;
124
125 out << "}" << endl;
126 return out;
127}
128
129struct function_declarations
130{
131 eo_class const& _cls;
132 function_declarations(eo_class const& cls)
133 : _cls(cls)
134 {}
135};
136
137inline std::ostream&
138operator<<(std::ostream& out, function_declarations const& x)
139{
140 for (eo_function const& f : x._cls.functions)
141 {
142 out << scope_guard_head(x._cls, f)
143 << function_declaration(x._cls, f)
144 << scope_guard_tail(x._cls, f) << endl;
145 }
146 return out;
147}
148
149struct function_definitions
150{
151 eo_class const& _cls;
152 bool _concrete;
153 function_definitions(eo_class const& cls, bool concrete)
154 : _cls(cls)
155 , _concrete(concrete)
156 {}
157};
158
159inline std::ostream&
160operator<<(std::ostream& out, function_definitions const& x)
161{
162 for (eo_function const& f : x._cls.functions)
163 {
164 out << scope_guard_head(x._cls, f)
165 << function_definition(x._cls, f, x._concrete)
166 << scope_guard_tail(x._cls, f) << endl;
167 }
168 return out;
169}
170
171} } } // namespace efl { namespace eolian { namespace grammar {
172
173#endif // EOLIAN_CXX_STD_EO_CLASS_FUNCTIONS_GENERATOR_HH
diff --git a/src/lib/eolian_cxx/grammar/eo_class_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_generator.hh
deleted file mode 100644
index e1545fc875..0000000000
--- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh
+++ /dev/null
@@ -1,265 +0,0 @@
1
2#ifndef EOLIAN_CXX_EO_CLASS_GENERATOR_HH
3#define EOLIAN_CXX_EO_CLASS_GENERATOR_HH
4
5#include <iosfwd>
6#include <string>
7
8#include "eo_types.hh"
9#include "tab.hh"
10#include "comment.hh"
11#include "namespace_generator.hh"
12#include "eo_class_constructors_generator.hh"
13#include "eo_class_functions_generator.hh"
14#include "eo_class_events_generator.hh"
15
16namespace efl { namespace eolian { namespace grammar {
17
18struct eo_class_getter
19{
20 eo_class const& _cls;
21 eo_class_getter(eo_class const& cls) : _cls(cls) {}
22};
23
24inline std::ostream&
25operator<<(std::ostream& out, eo_class_getter const& x)
26{
27 out << tab(1) << "static Eo_Class const* _eo_class()" << endl
28 << tab(1) << "{" << endl
29 << tab(2) << "return("<< x._cls.eo_name << ");" << endl
30 << tab(1) << "}" << endl << endl;
31 return out;
32}
33
34struct concrete_eo_ptr_getter
35{
36 eo_class const& _cls;
37 concrete_eo_ptr_getter(eo_class const& cls) : _cls(cls) {}
38};
39
40inline std::ostream&
41operator<<(std::ostream& out, concrete_eo_ptr_getter const&)
42{
43 out << comment("@internal", 1)
44 << tab(1) << "Eo* _concrete_eo_ptr() const" << endl
45 << tab(1) << "{" << endl
46 << tab(2) << "return static_cast<::efl::eo::concrete const*>(static_cast<void const*>(this))->_eo_ptr();" << endl
47 << tab(1) << "}" << endl << endl;
48 return out;
49}
50
51struct class_implicit_conversion_declaration
52{
53 eo_class const& _cls;
54 class_implicit_conversion_declaration(eo_class const& cls) : _cls(cls) {}
55};
56
57inline std::ostream&
58operator<<(std::ostream& out, class_implicit_conversion_declaration const& x)
59{
60 out << tab(1) << "operator " << full_name(x._cls) << "() const;" << endl;
61 out << tab(1) << "operator " << full_name(x._cls) << "&();" << endl;
62 out << tab(1) << "operator " << full_name(x._cls) << " const&() const;" << endl;
63 return out << endl;
64}
65
66struct class_implicit_conversion_definition
67{
68 eo_class const& _cls;
69 class_implicit_conversion_definition(eo_class const& cls) : _cls(cls) {}
70};
71
72inline std::ostream&
73operator<<(std::ostream& out, class_implicit_conversion_definition const& x)
74{
75 out << "inline " << abstract_full_name(x._cls) << "::operator "
76 << full_name(x._cls) << "() const" << endl
77 << "{" << endl
78 << tab(1) << "return *static_cast<" << full_name(x._cls)
79 << " const*>(static_cast<void const*>(this));" << endl
80 << "}" << endl << endl;
81
82 out << "inline " << abstract_full_name(x._cls) << "::operator "
83 << full_name(x._cls) << "&()" << endl
84 << "{" << endl
85 << tab(1) << "return *static_cast<" << full_name(x._cls)
86 << "*>(static_cast<void*>(this));" << endl
87 << "}" << endl << endl;
88
89 out << "inline " << abstract_full_name(x._cls) << "::operator "
90 << full_name(x._cls) << " const&() const" << endl
91 << "{" << endl
92 << tab(1) << "return *static_cast<" << full_name(x._cls)
93 << " const*>(static_cast<void const*>(this));" << endl
94 << "}" << endl << endl;
95
96 return out;
97}
98
99struct address_of_to_pointer
100{
101 eo_class const& _cls;
102 bool _is_const;
103 address_of_to_pointer(eo_class const& cls, bool is_const)
104 : _cls(cls), _is_const(is_const)
105 {}
106};
107
108inline std::ostream&
109operator<<(std::ostream& out, address_of_to_pointer const& x)
110{
111 out << "operator " << full_name(x._cls) << (x._is_const ? " const" : "")
112 << "*() const { return static_cast<" << full_name(x._cls)
113 << (x._is_const ? " const" : "")
114 << "*>(static_cast<D const*>(this)->p); }";
115 return out;
116}
117
118struct abstract_address_of
119{
120 eo_class const& _cls;
121 abstract_address_of(eo_class const& cls) : _cls(cls) {}
122};
123
124inline std::ostream&
125operator<<(std::ostream& out, abstract_address_of const& x)
126{
127 out << comment("@cond LOCAL", 1);
128
129 out << tab(1) << "template <typename D>" << endl
130 << tab(1) << "struct address_of" << endl
131 << tab(1) << "{" << endl
132 << tab(2) << address_of_to_pointer(x._cls, false) << endl
133 << tab(2) << address_of_to_pointer(x._cls, true) << endl
134 << tab(1) << "};" << endl << endl;
135
136 out << tab(1) << "template <typename D>" << endl
137 << tab(1) << "struct address_const_of" << endl
138 << tab(1) << "{" << endl
139 << tab(2) << address_of_to_pointer(x._cls, true) << endl
140 << tab(1) << "};" << endl;
141
142 out << comment("@endcond", 1) << endl;
143
144 return out;
145}
146
147struct address_of_inheritance
148{
149 eo_class const& _cls;
150 std::string _struct_name;
151 address_of_inheritance(eo_class const& cls, std::string const& struct_name)
152 : _cls(cls), _struct_name(struct_name)
153 {}
154};
155
156inline std::ostream&
157operator<<(std::ostream& out, address_of_inheritance const& x)
158{
159 for (std::string const& parent : x._cls.ancestors)
160 {
161 out << tab(2) << ", ::" << abstract_namespace << "::" << parent << "::"
162 << x._struct_name << "<" << x._struct_name << ">" << endl;
163 }
164 return out;
165}
166
167struct concrete_address_of
168{
169 eo_class const& _cls;
170 concrete_address_of(eo_class const& cls) : _cls(cls) {}
171};
172
173inline std::ostream&
174operator<<(std::ostream& out, concrete_address_of const& x)
175{
176 out << comment("@cond LOCAL", 1);
177 std::vector<std::string> names {"address_of", "address_const_of"};
178 for (int is_const = 0; is_const != 2; ++is_const)
179 {
180 std::string const& name = names[is_const];
181
182 out << tab(1) << "struct " << name << endl
183 << tab(2) << ": " << abstract_full_name(x._cls) << "::"
184 << name << "<" << name << ">" << endl
185 << address_of_inheritance(x._cls, name)
186 << tab(2) << ", ::efl::eo::detail::concrete_" << name << endl
187 << tab(1) << "{" << endl
188 << tab(2) << "explicit " << name << "(" << full_name(x._cls)
189 << (is_const ? " const" : "")
190 << "* p)" << endl
191 << tab(3) << ": ::efl::eo::detail::concrete_" << name << "(p)" << endl
192 << tab(2) << "{}" << endl
193 << tab(1) << "};" << endl
194 << tab(1) << name << " operator&()"
195 << (is_const ? " const" : "")
196 << " { return " << name << "(this); }" << endl << endl;
197 }
198 out << comment("@endcond", 1) << endl;
199
200 return out;
201}
202
203inline void
204eo_class_declarations_generator(std::ostream& out, eo_class const& cls)
205{
206 out << namespace_head(cls)
207 << "struct " << cls.name << ";" << endl << endl
208 << namespace_tail(cls)
209 << comment("@cond EO_CXX_ABSTRACT")
210 << "namespace " << abstract_namespace << " {" << endl << endl
211 << namespace_head(cls)
212 << comment(cls.comment)
213 << "struct " << cls.name << endl
214 << '{' << endl
215 << function_declarations(cls)
216 << events(cls, cls.own_events) << endl
217 << eo_class_getter(cls)
218 << class_implicit_conversion_declaration(cls)
219 << abstract_address_of(cls)
220 << "private:" << endl << endl
221 << concrete_eo_ptr_getter(cls)
222 << "};" << endl << endl
223 << namespace_tail(cls)
224 << "}" << endl
225 << comment("@endcond") << endl
226 << namespace_head(cls)
227 << comment(cls.comment, 0, "@brief Class " + cls.name)
228 << "struct " << cls.name << endl
229 << tab(2) << ": ::efl::eo::concrete" << endl
230 << class_inheritance(cls)
231 << '{' << endl
232 << functors_constructor_methods(cls)
233 << constructors_with_constructor_methods(cls)
234 << constructor_eo(cls)
235 << copy_constructor(cls)
236 << destructor(cls)
237 << constructor_method_function_declarations(cls)
238 << function_declarations(cls)
239 << events(cls, cls.concrete_events) << endl
240 << eo_class_getter(cls)
241 << concrete_address_of(cls)
242 << "private:" << endl << endl
243 << function_call_constructor_methods(cls)
244 << comment("@internal", 1)
245 << tab(1) << "Eo* _concrete_eo_ptr() const { return _eo_ptr(); }" << endl
246 << "};" << endl << endl
247 << "static_assert(sizeof(" << full_name(cls) << ") == sizeof(Eo*), \"\");" << endl
248 << "static_assert(std::is_standard_layout<" << full_name(cls) << ">::value, \"\");" << endl
249 << endl
250 << namespace_tail(cls)
251 << endl;
252}
253
254inline void
255eo_class_definitions_generator(std::ostream& out, eo_class const& cls)
256{
257 out << constructor_method_function_definitions(cls)
258 << function_definitions(cls, true)
259 << function_definitions(cls, false)
260 << class_implicit_conversion_definition(cls);
261}
262
263} } } // namespace efl { namespace eolian { namespace grammar {
264
265#endif // EOLIAN_CXX_EO_CLASS_GENERATOR_HH
diff --git a/src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh
deleted file mode 100644
index 5915c38beb..0000000000
--- a/src/lib/eolian_cxx/grammar/eo_class_scope_guard_generator.hh
+++ /dev/null
@@ -1,65 +0,0 @@
1#ifndef EOLIAN_CXX_STD_EO_CLASS_SCOPE_GUARD_GENERATOR_HH
2#define EOLIAN_CXX_STD_EO_CLASS_SCOPE_GUARD_GENERATOR_HH
3
4#include <cassert>
5
6#include "type_generator.hh"
7
8namespace efl { namespace eolian { namespace grammar {
9
10template <typename T>
11struct _scope_guard_head
12{
13 eo_class const& _cls;
14 T const& _e;
15 _scope_guard_head(eo_class const& cls, T const& e)
16 : _cls(cls), _e(e) {}
17};
18
19template <typename T>
20_scope_guard_head<T> scope_guard_head(eo_class const& cls, T const& e)
21{
22 return _scope_guard_head<T>(cls, e);
23}
24
25template <typename T>
26inline std::ostream&
27operator<<(std::ostream& out, _scope_guard_head<T> const& x)
28{
29 assert(x._e.scope != eolian_scope::private_);
30 if (x._e.scope == eolian_scope::protected_)
31 out << "#ifdef " << name_upper(x._cls) << "_PROTECTED" << endl;
32 if (x._e.is_beta)
33 out << "#ifdef " << name_upper(x._cls) << "_BETA" << endl;
34 return out;
35}
36
37template <typename T>
38struct _scope_guard_tail
39{
40 eo_class const& _cls;
41 T const& _e;
42 _scope_guard_tail(eo_class const& cls, T const& e)
43 : _cls(cls), _e(e) {}
44};
45
46template <typename T>
47struct _scope_guard_tail<T> scope_guard_tail(eo_class const& cls, T const& e)
48{
49 return _scope_guard_tail<T>(cls, e);
50}
51
52template <typename T>
53inline std::ostream&
54operator<<(std::ostream& out, _scope_guard_tail<T> const& x)
55{
56 if (x._e.scope == eolian_scope::protected_)
57 out << "#endif" << endl;
58 if (x._e.is_beta)
59 out << "#endif" << endl;
60 return out;
61}
62
63} } }
64
65#endif
diff --git a/src/lib/eolian_cxx/grammar/eo_header_generator.hh b/src/lib/eolian_cxx/grammar/eo_header_generator.hh
deleted file mode 100644
index 0b0fc55a36..0000000000
--- a/src/lib/eolian_cxx/grammar/eo_header_generator.hh
+++ /dev/null
@@ -1,150 +0,0 @@
1
2#ifndef EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
3#define EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
4
5#include <set>
6#include <algorithm>
7#include <string>
8#include <ostream>
9#include <iosfwd>
10#include <cctype>
11
12#include "eo_types.hh"
13#include "tab.hh"
14#include "eo_class_generator.hh"
15#include "inheritance_base_generator.hh"
16
17namespace {
18std::string
19_onceguard_key(efl::eolian::eo_class const& cls)
20{
21 std::string key;
22 if (cls.name_space != "")
23 {
24 std::string ns = cls.name_space;
25 size_t pos = 0;
26 while ((pos = ns.find("::")) != std::string::npos)
27 {
28 key += ns.substr(0, pos) + "_";
29 ns.erase(0, pos+2);
30 }
31 key += ns + "_";
32 }
33 key += cls.name;
34 std::transform(key.begin(), key.end(), key.begin(), ::toupper);
35 return key;
36}
37}
38
39namespace efl { namespace eolian { namespace grammar {
40
41struct include_dependencies
42{
43 eo_class const& _cls;
44 eo_generator_options const& _opts;
45 include_dependencies(eo_class const& cls, eo_generator_options const& opts)
46 : _cls(cls)
47 , _opts(opts)
48 {}
49};
50
51inline std::ostream&
52operator<<(std::ostream& out, include_dependencies const& x)
53{
54 std::set<std::string> headers;
55 eo_class const& cls = x._cls;
56
57 for (auto it = cls.constructors.cbegin(), last = cls.constructors.cend();
58 it != last; ++it)
59 for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
60 it_p != last_p; ++it_p)
61 for (eolian_type const& subtype : (*it_p).type.parts)
62 for (std::string header : subtype.includes)
63 if (header != x._opts.header_decl_file_name)
64 headers.insert(header);
65
66 for (auto it = cls.functions.begin(), last = cls.functions.end();
67 it != last; ++it)
68 for (auto it_p = (*it).params.begin(), last_p = (*it).params.end();
69 it_p != last_p; ++it_p)
70 for (eolian_type const& subtype : (*it_p).type.parts)
71 for (std::string header : subtype.includes)
72 if (header != x._opts.header_decl_file_name)
73 headers.insert(header);
74
75 for (std::string header : headers)
76 out << "#include <" << header << ">" << endl;
77
78 return out;
79}
80
81inline void
82onceguard_head(std::ostream& out, eo_class const& cls)
83{
84 std::string key = ::_onceguard_key(cls);
85 out << "#ifndef EFL_GENERATED_" << key << "_HH" << endl
86 << "#define EFL_GENERATED_" << key << "_HH" << endl << endl;
87}
88
89inline void
90onceguard_tail(std::ostream& out, eo_class const& cls)
91{
92 std::string key = ::_onceguard_key(cls);
93 out << "#endif // EFL_GENERATED_" << key << "_HH" << endl;
94}
95
96inline void
97include_headers(std::ostream& out,
98 eo_class const& cls EINA_UNUSED,
99 eo_generator_options const& opts)
100{
101 out << "extern \"C\"" << endl
102 << "{" << endl
103 << "#include <Efl.h>" << endl
104 << "}" << endl
105 << "#include <Eo.hh>" << endl << endl
106 << "#include <eo_cxx_interop.hh>" << endl << endl
107 << "extern \"C\"" << endl
108 << "{" << endl;
109 for (auto c_header : opts.c_headers)
110 {
111 out << "#include \"" << c_header << "\"" << endl;
112 }
113 out << "}" << endl << endl;
114 for (auto cxx_header : opts.cxx_headers)
115 {
116 out << "#include \"" << cxx_header << "\"" << endl;
117 }
118 out << include_dependencies(cls, opts) << endl;
119}
120
121inline void
122include_header_impl(std::ostream& out,
123 eo_class const& cls EINA_UNUSED,
124 eo_generator_options const& opts)
125{
126 out << "#include \"" << opts.header_impl_file_name << "\"" << endl << endl;
127}
128
129inline void
130eo_headers_generator(std::ostream& header_decl,
131 std::ostream& header_impl,
132 eo_class const& cls,
133 eo_generator_options const& opts)
134{
135 onceguard_head(header_decl, cls);
136 include_headers(header_decl, cls, opts);
137 eo_class_declarations_generator(header_decl, cls);
138 include_header_impl(header_decl, cls, opts);
139 onceguard_tail(header_decl, cls);
140 header_decl << endl;
141
142 header_impl << comment("@cond EO_CXX_EO_IMPL") << endl;
143 eo_class_definitions_generator(header_impl, cls);
144 eo_inheritance_detail_generator(header_impl, cls);
145 header_impl << endl << comment("@endcond") << endl;
146}
147
148} } } // namespace efl { namespace eolian { namespace grammar {
149
150#endif // EOLIAN_CXX_STD_EO_HEADER_GENERATOR_HH
diff --git a/src/lib/eolian_cxx/grammar/eps.hpp b/src/lib/eolian_cxx/grammar/eps.hpp
new file mode 100644
index 0000000000..e47d5f5499
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/eps.hpp
@@ -0,0 +1,24 @@
1#ifndef EOLIAN_CXX_EPS_HH
2#define EOLIAN_CXX_EPS_HH
3
4#include "grammar/generator.hpp"
5
6namespace efl { namespace eolian { namespace grammar {
7
8struct eps_generator
9{
10 template <typename OutputIterator, typename Attribute, typename Context>
11 bool generate(OutputIterator, Attribute const&, Context const&) const
12 {
13 return true;
14 }
15};
16
17template <>
18struct is_eager_generator<eps_generator> : std::true_type {};
19
20eps_generator const eps;
21
22} } }
23
24#endif
diff --git a/src/lib/eolian_cxx/grammar/function_declaration.hpp b/src/lib/eolian_cxx/grammar/function_declaration.hpp
new file mode 100644
index 0000000000..aabf8a2dba
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/function_declaration.hpp
@@ -0,0 +1,39 @@
1#ifndef EOLIAN_CXX_FUNCTION_DECLARATION_HH
2#define EOLIAN_CXX_FUNCTION_DECLARATION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/keyword.hpp"
13
14namespace efl { namespace eolian { namespace grammar {
15
16struct function_declaration_generator
17{
18 template <typename OutputIterator, typename Context>
19 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
20 {
21 return as_generator
22 (grammar::type << " " << string << "(" << (parameter % ", ") << ") const;\n")
23 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context);
24 }
25};
26
27template <>
28struct is_eager_generator<function_declaration_generator> : std::true_type {};
29
30namespace type_traits {
31template <>
32struct attributes_needed<function_declaration_generator> : std::integral_constant<int, 1> {};
33}
34
35function_declaration_generator const function_declaration;
36
37} } }
38
39#endif
diff --git a/src/lib/eolian_cxx/grammar/function_definition.hpp b/src/lib/eolian_cxx/grammar/function_definition.hpp
new file mode 100644
index 0000000000..8be8bba9e3
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/function_definition.hpp
@@ -0,0 +1,155 @@
1#ifndef EOLIAN_CXX_FUNCTION_DEFINITION_HH
2#define EOLIAN_CXX_FUNCTION_DEFINITION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6
7#include "grammar/string.hpp"
8#include "grammar/indentation.hpp"
9#include "grammar/list.hpp"
10#include "grammar/alternative.hpp"
11#include "grammar/type.hpp"
12#include "grammar/parameter.hpp"
13#include "grammar/function_declaration.hpp"
14#include "grammar/converting_argument.hpp"
15#include "grammar/case.hpp"
16#include "grammar/keyword.hpp"
17#include "grammar/attribute_conditional.hpp"
18#include "grammar/attribute_reorder.hpp"
19#include "grammar/type_impl.hpp"
20
21namespace efl { namespace eolian { namespace grammar {
22
23struct function_definition_generator
24{
25 function_definition_generator(attributes::klass_name const& name)
26 : _klass_name(name)
27 {}
28
29 template <typename OutputIterator, typename Context>
30 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& ctx) const
31 {
32 std::string suffix;
33 switch(_klass_name.type)
34 {
35 case attributes::class_type::regular:
36 case attributes::class_type::abstract_:
37 suffix = "CLASS";
38 break;
39 case attributes::class_type::mixin:
40 suffix = "MIXIN";
41 break;
42 case attributes::class_type::interface_:
43 suffix = "INTERFACE";
44 break;
45 }
46
47 if(f.is_beta &&
48 !as_generator("#ifdef " << *(string << "_") << string << "_" << string << "_BETA\n")
49 .generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name, suffix), add_upper_case_context(ctx)))
50 return false;
51 if(f.is_protected &&
52 !as_generator("#ifdef " << *(string << "_") << string << "_" << string << "_PROTECTED\n")
53 .generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name, suffix), add_upper_case_context(ctx)))
54 return false;
55
56 if(!as_generator
57 ("inline " << grammar::type << " " << string << "::" << string << "(" << (parameter % ", ") << ") const\n{\n")
58 .generate(sink, std::make_tuple(f.return_type, _klass_name.eolian_name, escape_keyword(f.name), f.parameters), ctx))
59 return false;
60
61 auto out_declaration =
62 attribute_conditional([] (attributes::parameter_def const& p) -> bool
63 { return p.direction == attributes::parameter_direction::out; })
64 [
65 attribute_reorder<1, 2>
66 (scope_tab << c_type << " __out_param_" << string << " = {};\n")
67 ]
68 | attribute_conditional([] (attributes::parameter_def const& p) -> bool
69 { return p.direction == attributes::parameter_direction::inout; })
70 [
71 attribute_reorder<1, 2, 1, 1, 2>
72 (scope_tab << c_type << " __out_param_" << string << " = ::efl::eolian::convert_inout<" << c_type
73 << ", " << type << ">(" << string << ");\n")
74 ]
75 | eps
76 ;
77 if(!as_generator(*(out_declaration))
78 .generate(sink, f.parameters, ctx)) return false;
79
80 if(!as_generator(scope_tab).generate(sink, attributes::unused, ctx)) return false;
81
82 if(f.return_type != attributes::void_
83 && !as_generator(attributes::c_type({attributes::parameter_direction::in, f.return_type, "", f.return_type.c_type})
84 << " __return_value = "
85 ).generate(sink, attributes::unused, ctx)) return false;
86
87 if(!as_generator
88 (" ::" << string << "(this->_eo_ptr()"
89 <<
90 *(
91 "\n" << scope_tab << scope_tab << ", "
92 <<
93 (
94 attribute_conditional([] (attributes::parameter_def const& p)
95 { return p.direction == attributes::parameter_direction::in; })
96 [converting_argument]
97 | ("& __out_param_" << attribute_reorder<2>(string))
98 )
99 )
100 << ");\n"
101 ).generate(sink, std::make_tuple(f.c_name, f.parameters), ctx))
102 return false;
103
104 auto out_assignments =
105 attribute_conditional([] (attributes::parameter_def const& p) -> bool
106 { return p.direction != attributes::parameter_direction::in; })
107 [
108 attribute_reorder<-1, 1, 2, 2>
109 (scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", " << c_type
110 << ">(" << string << ", __out_param_" << string << ");\n")
111 ]
112 | eps
113 ;
114 if(!as_generator(*(out_assignments))
115 .generate(sink, f.parameters, ctx)) return false;
116
117 if(f.return_type != attributes::void_
118 && !as_generator(scope_tab << "return ::efl::eolian::convert_to_return<"
119 << type<< ">(__return_value);\n"
120 ).generate(sink, f.return_type, ctx)) return false;
121
122 if(!as_generator("}\n").generate(sink, attributes::unused, ctx))
123 return false;
124
125 if(f.is_beta &&
126 !as_generator("#endif\n").generate(sink, attributes::unused, ctx))
127 return false;
128 if(f.is_protected &&
129 !as_generator("#endif\n").generate(sink, attributes::unused, ctx))
130 return false;
131 return true;
132 }
133
134 attributes::klass_name _klass_name;
135};
136
137template <>
138struct is_eager_generator<function_definition_generator> : std::true_type {};
139
140namespace type_traits {
141template <>
142struct attributes_needed<function_definition_generator> : std::integral_constant<int, 1> {};
143}
144
145struct function_definition_terminal
146{
147 function_definition_generator operator()(attributes::klass_name name) const
148 {
149 return function_definition_generator{name};
150 }
151} const function_definition;
152
153} } }
154
155#endif
diff --git a/src/lib/eolian_cxx/grammar/generator.hpp b/src/lib/eolian_cxx/grammar/generator.hpp
new file mode 100644
index 0000000000..1100befddf
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/generator.hpp
@@ -0,0 +1,50 @@
1#ifndef EOLIAN_CXX_GENERATOR_HH
2#define EOLIAN_CXX_GENERATOR_HH
3
4#include <type_traits>
5
6namespace efl { namespace eolian { namespace grammar {
7
8template <typename T, typename Enable = void>
9struct is_generator : std::false_type {};
10template <typename T, typename Enable = void>
11struct is_eager_generator : std::false_type {};
12
13template <typename T>
14struct is_generator<T&> : is_generator<T> {};
15template <typename T>
16struct is_eager_generator<T&> : is_eager_generator<T> {};
17template <typename T>
18struct is_generator<T const&> : is_generator<T> {};
19template <typename T>
20struct is_eager_generator<T const&> : is_eager_generator<T> {};
21template <typename T>
22struct is_generator<T const> : is_generator<T> {};
23template <typename T>
24struct is_eager_generator<T const> : is_eager_generator<T> {};
25template <typename T>
26struct is_generator<T volatile> : is_generator<T> {};
27template <typename T>
28struct is_eager_generator<T volatile> : is_eager_generator<T> {};
29template <typename T>
30struct is_generator<T volatile&> : is_generator<T> {};
31template <typename T>
32struct is_eager_generator<T volatile&> : is_eager_generator<T> {};
33template <typename T>
34struct is_generator<T volatile const> : is_generator<T> {};
35template <typename T>
36struct is_eager_generator<T volatile const> : is_eager_generator<T> {};
37template <typename T>
38struct is_generator<T volatile const&> : is_generator<T> {};
39template <typename T>
40struct is_eager_generator<T volatile const&> : is_eager_generator<T> {};
41template <typename T>
42struct is_generator<T> : is_eager_generator<T> {};
43
44template <typename G, typename Enable = typename std::enable_if<is_eager_generator<G>::value>::type>
45G as_generator(G&& g) { return g; }
46
47
48} } }
49
50#endif
diff --git a/src/lib/eolian_cxx/grammar/header.hpp b/src/lib/eolian_cxx/grammar/header.hpp
new file mode 100644
index 0000000000..96e123593c
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/header.hpp
@@ -0,0 +1,38 @@
1#ifndef EOLIAN_CXX_HEADER_HH
2#define EOLIAN_CXX_HEADER_HH
3
4#include "header_guards.hpp"
5#include "eps.hpp"
6#include "string.hpp"
7#include "sequence.hpp"
8#include "kleene.hpp"
9#include "header_include_directive.hpp"
10#include "base_class_definition.hpp"
11#include "class_definition.hpp"
12#include "class_declaration.hpp"
13#include "implementation_include_directive.hpp"
14
15namespace efl { namespace eolian { namespace grammar {
16
17auto class_header =
18 header_guards // class name
19 [
20 "#include <Eo.h>\n"
21 "\nextern \"C\" {\n"
22 << *header_include_directive // sequence<string>
23 << "}\n"
24 << "#include <Eina.hh>\n"
25 "#include <Eo.hh>\n"
26 << *header_include_directive // sequence<string>