summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-11-22 16:54:57 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-12-05 10:14:03 +0900
commit5425baa9061753356d450a3c736669341e1b1570 (patch)
treea008cad3e6be4c7d5a2f5e79425ddf27cc6a6a68 /src
parenta597084db7b3a8a4bc7320b68aee7cbb34c6da43 (diff)
cxx: Add support for function pointers
This was tested on the function pointer Efl.Ui.Format_Func_Cb
Diffstat (limited to '')
-rw-r--r--src/bin/eolian_cxx/eolian_cxx.cc115
-rw-r--r--src/bindings/cxx/eo_cxx/eo_cxx_interop.hh20
-rw-r--r--src/lib/eolian_cxx/grammar/converting_argument.hpp24
-rw-r--r--src/lib/eolian_cxx/grammar/function_declaration.hpp8
-rw-r--r--src/lib/eolian_cxx/grammar/function_definition.hpp19
-rw-r--r--src/lib/eolian_cxx/grammar/header.hpp1
-rw-r--r--src/lib/eolian_cxx/grammar/klass_def.hpp60
-rw-r--r--src/lib/eolian_cxx/grammar/parameter.hpp29
-rw-r--r--src/lib/eolian_cxx/grammar/type_function_declaration.hpp121
-rw-r--r--src/lib/eolian_cxx/grammar/types_definition.hpp38
10 files changed, 386 insertions, 49 deletions
diff --git a/src/bin/eolian_cxx/eolian_cxx.cc b/src/bin/eolian_cxx/eolian_cxx.cc
index 3fab179cae..b67d0442b9 100644
--- a/src/bin/eolian_cxx/eolian_cxx.cc
+++ b/src/bin/eolian_cxx/eolian_cxx.cc
@@ -25,6 +25,7 @@
25#include "grammar/klass_def.hpp" 25#include "grammar/klass_def.hpp"
26#include "grammar/header.hpp" 26#include "grammar/header.hpp"
27#include "grammar/impl_header.hpp" 27#include "grammar/impl_header.hpp"
28#include "grammar/types_definition.hpp"
28 29
29namespace eolian_cxx { 30namespace eolian_cxx {
30 31
@@ -58,7 +59,8 @@ opts_check(eolian_cxx::options_type const& opts)
58} 59}
59 60
60static bool 61static bool
61generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts) 62generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts,
63 std::string const& cpp_types_header)
62{ 64{
63 std::string header_decl_file_name = opts.out_file.empty() 65 std::string header_decl_file_name = opts.out_file.empty()
64 ? (::eolian_class_file_get(klass) + std::string(".hh")) : opts.out_file; 66 ? (::eolian_class_file_get(klass) + std::string(".hh")) : opts.out_file;
@@ -143,9 +145,9 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
143 } 145 }
144 }; 146 };
145 klass_function(klass); 147 klass_function(klass);
146 148
147 cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh")); 149 cpp_headers.erase(eolian_class_file_get(klass) + std::string(".hh"));
148 150
149 std::string guard_name; 151 std::string guard_name;
150 as_generator(*(efl::eolian::grammar::string << "_") << efl::eolian::grammar::string << "_EO_HH") 152 as_generator(*(efl::eolian::grammar::string << "_") << efl::eolian::grammar::string << "_EO_HH")
151 .generate(std::back_insert_iterator<std::string>(guard_name) 153 .generate(std::back_insert_iterator<std::string>(guard_name)
@@ -153,12 +155,13 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
153 , efl::eolian::grammar::context_null{}); 155 , efl::eolian::grammar::context_null{});
154 156
155 std::tuple<std::string, std::set<std::string>&, std::set<std::string>& 157 std::tuple<std::string, std::set<std::string>&, std::set<std::string>&
158 , std::string const&
156 , std::vector<efl::eolian::grammar::attributes::klass_def>& 159 , std::vector<efl::eolian::grammar::attributes::klass_def>&
157 , std::vector<efl::eolian::grammar::attributes::klass_def>& 160 , std::vector<efl::eolian::grammar::attributes::klass_def>&
158 , std::vector<efl::eolian::grammar::attributes::klass_def>& 161 , std::vector<efl::eolian::grammar::attributes::klass_def>&
159 , std::vector<efl::eolian::grammar::attributes::klass_def>& 162 , std::vector<efl::eolian::grammar::attributes::klass_def>&
160 > attributes 163 > attributes
161 {guard_name, c_headers, cpp_headers, klasses, forward_klasses, klasses, klasses}; 164 {guard_name, c_headers, cpp_headers, cpp_types_header, klasses, forward_klasses, klasses, klasses};
162 165
163 if(opts.out_file == "-") 166 if(opts.out_file == "-")
164 { 167 {
@@ -205,19 +208,117 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
205 return true; 208 return true;
206} 209}
207 210
211static bool
212types_generate(std::string const& fname, options_type const& opts,
213 std::string& cpp_types_header)
214{
215 using namespace efl::eolian::grammar::attributes;
216
217 std::vector<function_def> functions;
218 Eina_Iterator *itr = eolian_declarations_get_by_file(fname.c_str());
219 /* const */ Eolian_Declaration *decl;
220
221 // Build list of functions with their parameters
222 while(::eina_iterator_next(itr, reinterpret_cast<void**>(&decl)))
223 {
224 Eolian_Declaration_Type dt = eolian_declaration_type_get(decl);
225 if (dt != EOLIAN_DECL_ALIAS)
226 continue;
227
228 const Eolian_Typedecl *tp = eolian_declaration_data_type_get(decl);
229 if (!tp || eolian_typedecl_is_extern(tp))
230 continue;
231
232 if (::eolian_typedecl_type_get(tp) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
233 continue;
234
235 const Eolian_Function *func = eolian_typedecl_function_pointer_get(tp);
236 if (!func) return false;
237
238 Eina_Iterator *param_itr = eolian_function_parameters_get(func);
239 std::vector<parameter_def> params;
240
241 /* const */ Eolian_Function_Parameter *param;
242 while (::eina_iterator_next(param_itr, reinterpret_cast<void **>(&param)))
243 {
244 parameter_direction param_dir;
245 switch (eolian_parameter_direction_get(param))
246 {
247 /* Note: Inverted on purpose, as the direction objects are
248 * passed is inverted (from C to C++ for function pointers).
249 * FIXME: This is probably not right in all cases. */
250 case EOLIAN_IN_PARAM: param_dir = parameter_direction::out; break;
251 case EOLIAN_INOUT_PARAM: param_dir = parameter_direction::inout; break;
252 case EOLIAN_OUT_PARAM: param_dir = parameter_direction::in; break;
253 default: return false;
254 }
255
256 const Eolian_Type *param_type_eolian = eolian_parameter_type_get(param);
257 type_def param_type(param_type_eolian, opts.unit, EOLIAN_C_TYPE_PARAM);
258 std::string param_name = eolian_parameter_name_get(param);
259 std::string param_c_type = eolian_type_c_type_get(param_type_eolian, EOLIAN_C_TYPE_PARAM);
260 parameter_def param_def(param_dir, param_type, param_name, param_c_type);
261 params.push_back(std::move(param_def));
262 }
263 ::eina_iterator_free(param_itr);
264
265 const Eolian_Type *ret_type_eolian = eolian_function_return_type_get(func, EOLIAN_FUNCTION_POINTER);
266
267 type_def ret_type = void_;
268 if (ret_type_eolian)
269 ret_type = type_def(ret_type_eolian, opts.unit, EOLIAN_C_TYPE_RETURN);
270
271 /*
272 // List namespaces. Not used as function_wrapper lives in efl::eolian.
273 std::vector<std::string> namespaces;
274 Eina_Iterator *ns_itr = eolian_typedecl_namespaces_get(tp);
275 char *ns;
276 while (::eina_iterator_next(ns_itr, reinterpret_cast<void**>(&ns)))
277 namespaces.push_back(std::string(ns));
278 ::eina_iterator_free(ns_itr);
279 */
280
281 std::string name = eolian_function_name_get(func);
282 std::string c_name = eolian_typedecl_full_name_get(tp);
283 std::replace(c_name.begin(), c_name.end(), '.', '_');
284 bool beta = eolian_function_is_beta(func);
285
286 function_def def(ret_type, name, params, c_name, beta, false, true);
287 functions.push_back(std::move(def));
288 }
289 ::eina_iterator_free(itr);
290
291 if (functions.empty())
292 return true;
293
294 std::stringstream sink;
295
296 sink.write("\n", 1);
297 if (!efl::eolian::grammar::types_definition
298 .generate(std::ostream_iterator<char>(sink),
299 functions, efl::eolian::grammar::context_null()))
300 return false;
301
302 cpp_types_header = sink.str();
303
304 return true;
305}
306
208static void 307static void
209run(options_type const& opts) 308run(options_type const& opts)
210{ 309{
211 if(!opts.main_header) 310 if(!opts.main_header)
212 { 311 {
213 const Eolian_Class *klass = NULL; 312 const Eolian_Class *klass = nullptr;
214 char* dup = strdup(opts.in_files[0].c_str()); 313 char* dup = strdup(opts.in_files[0].c_str());
215 char* base = basename(dup); 314 char* base = basename(dup);
216 klass = ::eolian_class_get_by_file(NULL, base); 315 std::string cpp_types_header;
316 klass = ::eolian_class_get_by_file(nullptr, base);
217 free(dup); 317 free(dup);
218 if (klass) 318 if (klass)
219 { 319 {
220 if (!generate(klass, opts)) 320 if (!types_generate(base, opts, cpp_types_header) ||
321 !generate(klass, opts, cpp_types_header))
221 { 322 {
222 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain) 323 EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
223 << "Error generating: " << ::eolian_class_name_get(klass) 324 << "Error generating: " << ::eolian_class_name_get(klass)
diff --git a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
index 662e5a7d55..9181c11875 100644
--- a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
+++ b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
@@ -61,6 +61,8 @@ template <>
61struct out_traits<void*> { typedef void*& type; }; 61struct out_traits<void*> { typedef void*& type; };
62template <typename T> 62template <typename T>
63struct out_traits<efl::shared_future<T>> { typedef efl::shared_future<T>& type; }; 63struct out_traits<efl::shared_future<T>> { typedef efl::shared_future<T>& type; };
64template <>
65struct out_traits<efl::eina::strbuf> { typedef efl::eina::strbuf_wrapper& type; };
64 66
65template <typename T> 67template <typename T>
66struct inout_traits { typedef T& type; }; 68struct inout_traits { typedef T& type; };
@@ -291,23 +293,7 @@ auto convert_inout(V& object) -> decltype(impl::convert_inout_impl(object, impl:
291template <typename T, typename U, bool Own = false, typename V> 293template <typename T, typename U, bool Own = false, typename V>
292T convert_to_c(V&& object); 294T convert_to_c(V&& object);
293 295
294template <typename F, typename T> 296template <typename U, typename F, typename V=void> struct function_wrapper;
295void* data_function_ptr_to_c(T)
296{
297 return nullptr;
298}
299
300template <typename F, typename T>
301F function_ptr_to_c()
302{
303 return nullptr;
304}
305
306template <typename F, typename T>
307Eina_Free_Cb free_function_ptr_to_c()
308{
309 return nullptr;
310}
311 297
312namespace impl { 298namespace impl {
313 299
diff --git a/src/lib/eolian_cxx/grammar/converting_argument.hpp b/src/lib/eolian_cxx/grammar/converting_argument.hpp
index 230608ffc3..eb7ef57376 100644
--- a/src/lib/eolian_cxx/grammar/converting_argument.hpp
+++ b/src/lib/eolian_cxx/grammar/converting_argument.hpp
@@ -33,24 +33,12 @@ struct converting_argument_generator
33 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& ctx) const 33 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& ctx) const
34 { 34 {
35 attributes::qualifier_def qualifier = param.type.original_type.visit(attributes::get_qualifier_visitor{}); 35 attributes::qualifier_def qualifier = param.type.original_type.visit(attributes::get_qualifier_visitor{});
36 bool is_function_ptr = param.type.original_type.visit(this->is_function_ptr); 36 if (param.type.original_type.visit(this->is_function_ptr))
37 if(is_function_ptr) 37 {
38 return as_generator 38 // FIXME: This supports only one function pointer.
39 ( 39 return as_generator("fw->data_to_c(), fw->func_to_c(), fw->free_to_c()")
40 attribute_reorder<-1, -1, 2, -1, -1, -1, -1> 40 .generate(sink, param, ctx);
41 ( 41 }
42 " ::efl::eolian::data_function_ptr_to_c<" << c_type
43 << ", " << parameter_type
44 << ">(" << string << ")"
45
46 ", ::efl::eolian::function_ptr_to_c<" << c_type
47 << ", " << parameter_type
48 << ">()"
49 ", ::efl::eolian::free_function_ptr_to_c<" << c_type
50 << ", " << parameter_type
51 << ">()"
52 )
53 ).generate(sink, param, ctx);
54 else 42 else
55 return as_generator 43 return as_generator
56 ( 44 (
diff --git a/src/lib/eolian_cxx/grammar/function_declaration.hpp b/src/lib/eolian_cxx/grammar/function_declaration.hpp
index e98fbf0a3a..641ae6560c 100644
--- a/src/lib/eolian_cxx/grammar/function_declaration.hpp
+++ b/src/lib/eolian_cxx/grammar/function_declaration.hpp
@@ -1,3 +1,4 @@
1
1#ifndef EOLIAN_CXX_FUNCTION_DECLARATION_HH 2#ifndef EOLIAN_CXX_FUNCTION_DECLARATION_HH
2#define EOLIAN_CXX_FUNCTION_DECLARATION_HH 3#define EOLIAN_CXX_FUNCTION_DECLARATION_HH
3 4
@@ -42,6 +43,13 @@ struct function_declaration_generator
42 !as_generator("#ifdef " << *(string << "_") << string << "_" << string << "_BETA\n") 43 !as_generator("#ifdef " << *(string << "_") << string << "_" << string << "_BETA\n")
43 .generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name, suffix), add_upper_case_context(ctx))) 44 .generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name, suffix), add_upper_case_context(ctx)))
44 return false; 45 return false;
46
47 std::string template_statement(f.template_statement());
48 if (!template_statement.empty() &&
49 !as_generator(template_statement << " ")
50 .generate(sink, attributes::unused, ctx))
51 return false;
52
45 if(!as_generator 53 if(!as_generator
46 ("::efl::eolian::return_traits<" << grammar::type(true) << ">::type " << string << "(" << (parameter % ", ") << ") const;\n") 54 ("::efl::eolian::return_traits<" << grammar::type(true) << ">::type " << string << "(" << (parameter % ", ") << ") const;\n")
47 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), ctx)) 55 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), ctx))
diff --git a/src/lib/eolian_cxx/grammar/function_definition.hpp b/src/lib/eolian_cxx/grammar/function_definition.hpp
index 50bd9970c5..55f56216fd 100644
--- a/src/lib/eolian_cxx/grammar/function_definition.hpp
+++ b/src/lib/eolian_cxx/grammar/function_definition.hpp
@@ -17,6 +17,7 @@
17#include "grammar/attribute_conditional.hpp" 17#include "grammar/attribute_conditional.hpp"
18#include "grammar/attribute_reorder.hpp" 18#include "grammar/attribute_reorder.hpp"
19#include "grammar/type_impl.hpp" 19#include "grammar/type_impl.hpp"
20#include "grammar/eps.hpp"
20 21
21namespace efl { namespace eolian { namespace grammar { 22namespace efl { namespace eolian { namespace grammar {
22 23
@@ -52,12 +53,24 @@ struct function_definition_generator
52 !as_generator("#ifdef " << *(string << "_") << string << "_PROTECTED\n") 53 !as_generator("#ifdef " << *(string << "_") << string << "_PROTECTED\n")
53 .generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name), add_upper_case_context(ctx))) 54 .generate(sink, std::make_tuple(_klass_name.namespaces, _klass_name.eolian_name), add_upper_case_context(ctx)))
54 return false; 55 return false;
55 56
57 std::string template_statement(f.template_statement());
58 if (!template_statement.empty() &&
59 !as_generator(template_statement << "\n")
60 .generate(sink, attributes::unused, ctx))
61 return false;
62
56 if(!as_generator 63 if(!as_generator
57 ("inline ::efl::eolian::return_traits<" << grammar::type(true) << ">::type " << string << "::" << string << "(" << (parameter % ", ") << ") const\n{\n") 64 ("inline ::efl::eolian::return_traits<" << grammar::type(true) << ">::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)) 65 .generate(sink, std::make_tuple(f.return_type, _klass_name.eolian_name, escape_keyword(f.name), f.parameters), ctx))
59 return false; 66 return false;
60 67
68 std::vector<std::string> opening_statements(f.opening_statements());
69 if (!opening_statements.empty() &&
70 !as_generator(scope_tab << *(string) << "\n")
71 .generate(sink, std::make_tuple(opening_statements), ctx))
72 return false;
73
61 auto out_declaration = 74 auto out_declaration =
62 attribute_conditional([] (attributes::parameter_def const& p) -> bool 75 attribute_conditional([] (attributes::parameter_def const& p) -> bool
63 { return p.direction == attributes::parameter_direction::out; }) 76 { return p.direction == attributes::parameter_direction::out; })
@@ -118,8 +131,8 @@ struct function_definition_generator
118 scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", " << c_type 131 scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", " << c_type
119 << 132 <<
120 ( 133 (
121 attribute_conditional([] (attributes::type_def const& type) 134 attribute_conditional([] (attributes::type_def const& typ)
122 { return type.original_type.visit(attributes::get_qualifier_visitor{}) & qualifier_info::is_own; }) 135 { return typ.original_type.visit(attributes::get_qualifier_visitor{}) & qualifier_info::is_own; })
123 [ 136 [
124 ", true" 137 ", true"
125 ] | eps 138 ] | eps
diff --git a/src/lib/eolian_cxx/grammar/header.hpp b/src/lib/eolian_cxx/grammar/header.hpp
index 63a6095949..4f1df9233f 100644
--- a/src/lib/eolian_cxx/grammar/header.hpp
+++ b/src/lib/eolian_cxx/grammar/header.hpp
@@ -24,6 +24,7 @@ auto class_header =
24 << "#include <Eina.hh>\n" 24 << "#include <Eina.hh>\n"
25 "#include <Eo.hh>\n" 25 "#include <Eo.hh>\n"
26 << *header_include_directive // sequence<string> 26 << *header_include_directive // sequence<string>
27 << string // extra header <string>
27 << *class_declaration // sequence<class> | class 28 << *class_declaration // sequence<class> | class
28 << *class_forward_declaration // sequence<class> | class 29 << *class_forward_declaration // sequence<class> | class
29 << "\nnamespace eo_cxx {\n" 30 << "\nnamespace eo_cxx {\n"
diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp
index edfadc05bb..f7b12af578 100644
--- a/src/lib/eolian_cxx/grammar/klass_def.hpp
+++ b/src/lib/eolian_cxx/grammar/klass_def.hpp
@@ -433,6 +433,7 @@ struct function_def
433 std::string filename; 433 std::string filename;
434 bool is_beta; 434 bool is_beta;
435 bool is_protected; 435 bool is_protected;
436 bool is_function_pointer;
436 437
437 friend inline bool operator==(function_def const& lhs, function_def const& rhs) 438 friend inline bool operator==(function_def const& lhs, function_def const& rhs)
438 { 439 {
@@ -442,17 +443,27 @@ struct function_def
442 && lhs.c_name == rhs.c_name 443 && lhs.c_name == rhs.c_name
443 && lhs.filename == rhs.filename 444 && lhs.filename == rhs.filename
444 && lhs.is_beta == rhs.is_beta 445 && lhs.is_beta == rhs.is_beta
445 && lhs.is_protected == rhs.is_protected; 446 && lhs.is_protected == rhs.is_protected
447 && lhs.is_function_pointer == rhs.is_function_pointer;
446 } 448 }
447 friend inline bool operator!=(function_def const& lhs, function_def const& rhs) 449 friend inline bool operator!=(function_def const& lhs, function_def const& rhs)
448 { 450 {
449 return !(lhs == rhs); 451 return !(lhs == rhs);
450 } 452 }
451 453 function_def() = default;
452 function_def(type_def return_type, std::string name, std::vector<parameter_def> parameters 454 function_def(type_def return_type, std::string name, std::vector<parameter_def> parameters
453 , std::string c_name, std::string filename, bool is_beta) 455 , std::string c_name, std::string filename, bool is_beta)
454 : return_type(return_type), name(name), parameters(parameters), c_name(c_name), filename(filename), is_beta(is_beta) {} 456 : return_type(return_type), name(name), parameters(parameters), c_name(c_name), filename(filename), is_beta(is_beta) {}
455 function_def() = default; 457 function_def(type_def _return_type, std::string const& _name,
458 std::vector<parameter_def> const& _parameters,
459 std::string const& _c_name,
460 bool _is_beta = false,
461 bool _is_protected = false,
462 bool _is_function_pointer = false)
463 : return_type(_return_type), name(_name), parameters(_parameters),
464 c_name(_c_name), is_beta(_is_beta), is_protected(_is_protected),
465 is_function_pointer(_is_function_pointer) {}
466
456 function_def( ::Eolian_Function const* function, Eolian_Function_Type type, Eolian_Unit const* unit) 467 function_def( ::Eolian_Function const* function, Eolian_Function_Type type, Eolian_Unit const* unit)
457 : return_type(void_) 468 : return_type(void_)
458 { 469 {
@@ -517,6 +528,49 @@ struct function_def
517 is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED; 528 is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED;
518 is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED; 529 is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED;
519 } 530 }
531
532 std::string template_statement() const
533 {
534 std::string statement;
535 char template_typename = 'F';
536 for (auto const& param : this->parameters)
537 {
538 attributes::regular_type_def const* typ =
539 efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
540 if (typ && typ->is_function_ptr)
541 {
542 char typenam[2] = { 0, };
543 typenam[0] = template_typename++;
544 if (statement.empty())
545 statement = std::string("template <typename ") + typenam;
546 else
547 statement += std::string(", typename ") + typenam;
548 }
549 }
550 if (statement.empty()) return statement;
551 else return statement + ">";
552 }
553
554 std::vector<std::string> opening_statements() const
555 {
556 // FIXME: Supports only one function pointer
557 std::vector<std::string> statements;
558 char template_typename = 'F';
559 for (auto const& param : this->parameters)
560 {
561 attributes::regular_type_def const* typ =
562 efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
563 if (typ && typ->is_function_ptr)
564 {
565 char typenam[2] = { 0, };
566 typenam[0] = template_typename++;
567 std::string statement = "auto fw = new ::efl::eolian::function_wrapper<";
568 statement += param.c_type + ", " + typenam + ">(" + param.param_name + ");";
569 statements.push_back(statement);
570 }
571 }
572 return statements;
573 }
520}; 574};
521 575
522template <> 576template <>
diff --git a/src/lib/eolian_cxx/grammar/parameter.hpp b/src/lib/eolian_cxx/grammar/parameter.hpp
index f9e625a514..5d8d3aef5c 100644
--- a/src/lib/eolian_cxx/grammar/parameter.hpp
+++ b/src/lib/eolian_cxx/grammar/parameter.hpp
@@ -25,6 +25,12 @@ struct parameter_type_generator
25 dir = "in"; 25 dir = "in";
26 break; 26 break;
27 } 27 }
28
29 attributes::regular_type_def const* typ =
30 efl::eina::get<attributes::regular_type_def>(&param.type.original_type);
31 if (typ && typ->is_function_ptr)
32 return as_generator("F").generate(sink, attributes::unused, context);
33
28 return as_generator 34 return as_generator
29 ( 35 (
30 " ::efl::eolian::" << string << "_traits<" 36 " ::efl::eolian::" << string << "_traits<"
@@ -44,6 +50,8 @@ struct attributes_needed<parameter_type_generator> : std::integral_constant<int,
44 50
45parameter_type_generator const parameter_type = {}; 51parameter_type_generator const parameter_type = {};
46 52
53
54/* */
47struct parameter_generator 55struct parameter_generator
48{ 56{
49 template <typename OutputIterator, typename Context> 57 template <typename OutputIterator, typename Context>
@@ -59,9 +67,28 @@ template <>
59struct is_generator<parameter_generator> : std::true_type {}; 67struct is_generator<parameter_generator> : std::true_type {};
60namespace type_traits { 68namespace type_traits {
61template <> 69template <>
62struct attributes_needed<parameter_generator> : std::integral_constant<int, 1> {}; 70struct attributes_needed<parameter_generator> : std::integral_constant<int, 1> {};
63} 71}
64parameter_generator const parameter = {}; 72parameter_generator const parameter = {};
73
74
75/* */
76struct parameter_as_argument_generator
77{
78 template <typename OutputIterator, typename Context>
79 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
80 {
81 return as_generator(parameter_type << "(" << string << ")").generate(sink, std::make_tuple(param, param.param_name), context);
82 }
83};
84
85template <>
86struct is_eager_generator<parameter_as_argument_generator> : std::true_type {};
87namespace type_traits {
88template <>
89struct attributes_needed<parameter_as_argument_generator> : std::integral_constant<int, 1> {};
90}
91parameter_as_argument_generator const parameter_as_argument = {};
65 92
66} } } 93} } }
67 94
diff --git a/src/lib/eolian_cxx/grammar/type_function_declaration.hpp b/src/lib/eolian_cxx/grammar/type_function_declaration.hpp
new file mode 100644
index 0000000000..eccedf8f4a
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/type_function_declaration.hpp
@@ -0,0 +1,121 @@
1#ifndef EOLIAN_CXX_TYPE_FUNCTION_DECLARATION_HH
2#define EOLIAN_CXX_TYPE_FUNCTION_DECLARATION_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/keyword.hpp"
14#include "grammar/converting_argument.hpp"
15#include "grammar/eps.hpp"
16
17namespace efl { namespace eolian { namespace grammar {
18
19/** This generates the caller struct for function pointers. */
20struct type_function_declaration_generator {
21 type_function_declaration_generator() {}
22
23 template <typename OutputIterator, typename Context>
24 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& ctx) const
25 {
26 std::string guard = f.c_name + "_defined";
27
28 if (!as_generator("#ifndef " << string << "\n" <<
29 "#define " << string << "\n")
30 .generate(sink, std::make_tuple(guard, guard), add_upper_case_context(ctx)))
31 return false;
32
33 // efl::eolian::function_wrapper<T, F>
34 if (!as_generator("namespace efl { namespace eolian {\n")
35 .generate(sink, attributes::unused, add_lower_case_context(ctx)))
36 return false;
37
38 if (!as_generator(
39 "template <typename F>\n"
40 "struct function_wrapper<" << string << ", F> {\n"
41 << scope_tab << "function_wrapper(F cxx_func) : _cxx_func(cxx_func) {}\n"
42 ).generate(sink, f.c_name, ctx))
43 return false;
44
45 if (!as_generator(
46 scope_tab << "void *data_to_c() { return static_cast<void *>(this); }\n"
47 << scope_tab << string << " func_to_c() const { return &caller; }\n"
48 << scope_tab << "Eina_Free_Cb free_to_c() const { return &deleter; }\n"
49 << "private:\n"
50 << scope_tab << "F _cxx_func;\n"
51 << scope_tab << "static void deleter(void *data) {\n"
52 << scope_tab << scope_tab << "delete static_cast<function_wrapper<" << string << ", F>*>(data);\n"
53 << scope_tab << "}\n"
54 ).generate(sink, std::make_tuple(f.c_name, f.c_name), ctx))
55 return false;
56
57 std::vector<std::string> c_args;
58 for (auto itr : f.parameters)
59 c_args.push_back(", " + itr.c_type + " " + itr.param_name);
60 if (!as_generator(
61 scope_tab << "static " << string << " caller(void *cxx_call_data"
62 << *(string) << ") {\n"
63 << scope_tab << scope_tab << "auto fw = static_cast<function_wrapper<"
64 << string << ", F>*>(cxx_call_data);\n"
65 ).generate(sink, std::make_tuple(f.return_type.c_type, c_args, f.c_name), ctx))
66 return false;
67
68 if (f.return_type != attributes::void_
69 && !as_generator(scope_tab << scope_tab << "auto __return_value =\n")
70 .generate(sink, attributes::unused, ctx))
71 return false;
72
73 if (!f.parameters.empty())
74 {
75 std::vector<attributes::parameter_def> params;
76 for (auto itr = f.parameters.begin() + 1; itr != f.parameters.end(); itr++)
77 params.push_back(*itr);
78 if (!as_generator(
79 scope_tab << scope_tab << "fw->_cxx_func(" << parameter_as_argument << *(", " << parameter_as_argument) << ");\n"
80 ).generate(sink, std::make_tuple(*f.parameters.begin(), params), ctx))
81 return false;
82 }
83
84 if (f.return_type != attributes::void_
85 && !as_generator(scope_tab << scope_tab << "return ::efl::eolian::convert_to_c<"
86 << type << ">(__return_value);\n")
87 .generate(sink, f.return_type, ctx))
88 return false;
89
90 if (!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, ctx))
91 return false;
92
93 if (!as_generator("};\n"
94 "} }\n"
95 "#endif\n\n")
96 .generate(sink, attributes::unused, ctx))
97 return false;
98
99 return true;
100 }
101};
102
103template <>
104struct is_eager_generator<type_function_declaration_generator> : std::true_type {};
105
106namespace type_traits {
107template <>
108struct attributes_needed<type_function_declaration_generator> : std::integral_constant<int, 1> {};
109}
110
111struct type_function_declaration_terminal
112{
113 type_function_declaration_generator operator()() const
114 {
115 return type_function_declaration_generator{};
116 }
117} const type_function_declaration = {};
118
119} } }
120
121#endif
diff --git a/src/lib/eolian_cxx/grammar/types_definition.hpp b/src/lib/eolian_cxx/grammar/types_definition.hpp
new file mode 100644
index 0000000000..e4c40737d6
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/types_definition.hpp
@@ -0,0 +1,38 @@
1#ifndef EOLIAN_CXX_TYPES_DEFINITION_HH
2#define EOLIAN_CXX_TYPES_DEFINITION_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 "type_function_declaration.hpp"
11
12namespace efl { namespace eolian { namespace grammar {
13
14struct types_definition_generator
15{
16 template <typename OutputIterator, typename Context>
17 bool generate(OutputIterator sink, std::vector<attributes::function_def> const& functions, Context const& ctx) const
18 {
19 if(!as_generator(*(type_function_declaration()))
20 .generate(sink, functions, ctx))
21 return false;
22 return true;
23 }
24};
25
26template <>
27struct is_eager_generator<types_definition_generator> : std::true_type {};
28
29namespace type_traits {
30template <>
31struct attributes_needed<types_definition_generator> : std::integral_constant<int, 1> {};
32}
33
34types_definition_generator const types_definition = {};
35
36} } }
37
38#endif