summaryrefslogtreecommitdiff
path: root/src/lib
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/lib
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/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
8 files changed, 275 insertions, 25 deletions
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