summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2017-11-23 21:50:16 -0300
committerLauro Moura <lauromoura@expertisesolutions.com.br>2017-12-04 15:47:50 -0300
commitd93e9ff286ce1961f530d56b5536881f47104ebd (patch)
treed9fd8cd25a64b9ab6b23ae34b92c342dc8e6b543 /src/bin
parent9391407319424c503a78479b407737ccead945b7 (diff)
eolian_mono: Added code for eolian_mono generator
Based on the eolian_cxx library generators. Buildsystem files will come in a future commmit.
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/eolian_mono/.gitignore1
-rw-r--r--src/bin/eolian_mono/eolian/mono/enum_definition.hh74
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_blacklist.hh48
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_declaration.hh49
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh223
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_helpers.hh243
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_pointer.hh95
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_registration.hh78
-rw-r--r--src/bin/eolian_mono/eolian/mono/generation_contexts.hh42
-rw-r--r--src/bin/eolian_mono/eolian/mono/keyword.hh52
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh745
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_annotation.hh246
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type.hh165
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh263
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh139
-rw-r--r--src/bin/eolian_mono/eolian/mono/namespace.hh27
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh1171
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh95
-rw-r--r--src/bin/eolian_mono/eolian/mono/type.hh68
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_impl.hh373
-rw-r--r--src/bin/eolian_mono/eolian/mono/using_decl.hh21
-rw-r--r--src/bin/eolian_mono/eolian/mono/utils.hh22
-rw-r--r--src/bin/eolian_mono/eolian_mono.cc367
23 files changed, 4607 insertions, 0 deletions
diff --git a/src/bin/eolian_mono/.gitignore b/src/bin/eolian_mono/.gitignore
new file mode 100644
index 0000000000..1562e43a4d
--- /dev/null
+++ b/src/bin/eolian_mono/.gitignore
@@ -0,0 +1 @@
/eolian_mono
diff --git a/src/bin/eolian_mono/eolian/mono/enum_definition.hh b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
new file mode 100644
index 0000000000..ae9775e71f
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
@@ -0,0 +1,74 @@
1#ifndef EOLIAN_MONO_ENUM_DEFINITION_HH
2#define EOLIAN_MONO_ENUM_DEFINITION_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/indentation.hpp"
7#include "grammar/list.hpp"
8#include "grammar/alternative.hpp"
9#include "type.hh"
10#include "keyword.hh"
11#include "using_decl.hh"
12
13namespace eolian_mono {
14
15struct enum_definition_generator
16{
17 template <typename OutputIterator, typename Context>
18 bool generate(OutputIterator sink, attributes::enum_def const& enum_, Context const& context) const
19 {
20 std::vector<std::string> cpp_namespaces = escape_namespace(attributes::cpp_namespaces(enum_.namespaces));
21
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 "public enum " << string << "\n{\n"
28 )
29 .generate(sink, enum_.cxx_name, context))
30 return false;
31
32 // iterate enum fiels
33 for(auto first = std::begin(enum_.fields)
34 , last = std::end(enum_.fields); first != last; ++first)
35 {
36 auto name = (*first).name;
37 auto literal = (*first).value.literal;
38 name[0] = std::toupper(name[0]); // Hack to allow 'static' as a field name
39 if (!as_generator
40 (
41 string << " = " << string << ",\n"
42 )
43 .generate(sink, std::make_tuple(name, literal), context))
44 return false;
45 }
46
47 if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
48
49 auto close_namespace = *(lit("} ")) << "\n";
50 if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
51
52 return true;
53 }
54};
55
56enum_definition_generator const enum_definition = {};
57
58}
59
60namespace efl { namespace eolian { namespace grammar {
61
62template <>
63struct is_eager_generator< ::eolian_mono::enum_definition_generator> : std::true_type {};
64template <>
65struct is_generator< ::eolian_mono::enum_definition_generator> : std::true_type {};
66
67namespace type_traits {
68template <>
69struct attributes_needed< ::eolian_mono::enum_definition_generator> : std::integral_constant<int, 1> {};
70}
71
72} } }
73
74#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_blacklist.hh b/src/bin/eolian_mono/eolian/mono/function_blacklist.hh
new file mode 100644
index 0000000000..9b08295ca4
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/function_blacklist.hh
@@ -0,0 +1,48 @@
1#ifndef EOLIAN_MONO_FUNCTION_BLACKLIST_HH
2#define EOLIAN_MONO_FUNCTION_BLACKLIST_HH
3
4namespace eolian_mono {
5
6inline bool is_function_blacklisted(std::string const& c_name)
7{
8 return
9 c_name == "efl_event_callback_array_priority_add"
10 || c_name == "efl_player_position_get"
11 || c_name == "efl_image_load_error_get"
12 || c_name == "efl_text_font_source_get"
13 || c_name == "efl_text_font_source_set"
14 || c_name == "efl_ui_focus_manager_focus_get"
15 || c_name == "efl_ui_widget_focus_set"
16 || c_name == "efl_ui_widget_focus_get"
17 || c_name == "efl_ui_text_password_get"
18 || c_name == "efl_ui_text_password_set"
19 || c_name == "elm_interface_scrollable_repeat_events_get"
20 || c_name == "elm_interface_scrollable_repeat_events_set"
21 || c_name == "elm_wdg_item_del"
22 || c_name == "elm_wdg_item_focus_get"
23 || c_name == "elm_wdg_item_focus_set"
24 || c_name == "elm_interface_scrollable_mirrored_set"
25 || c_name == "edje_obj_load_error_get"
26 || c_name == "efl_ui_focus_user_parent_get"
27 || c_name == "efl_canvas_object_scale_get" // duplicated signature
28 || c_name == "efl_canvas_object_scale_set" // duplicated signature
29 || c_name == "efl_ui_format_cb_set"
30 || c_name == "efl_access_parent_get"
31 || c_name == "efl_access_name_get"
32 || c_name == "efl_access_name_set"
33 || c_name == "efl_access_root_get"
34 || c_name == "efl_access_type_get"
35 || c_name == "efl_access_role_get"
36 || c_name == "efl_access_action_description_get"
37 || c_name == "efl_access_action_description_set"
38 || c_name == "efl_access_image_description_get"
39 || c_name == "efl_access_image_description_set"
40 || c_name == "efl_access_component_layer_get" // duplicated signature
41 || c_name == "efl_access_component_alpha_get"
42 || c_name == "efl_ui_spin_button_loop_get"
43 ;
44}
45
46}
47
48#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_declaration.hh b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
new file mode 100644
index 0000000000..561c975118
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
@@ -0,0 +1,49 @@
1#ifndef EOLIAN_MONO_FUNCTION_DECLARATION_HH
2#define EOLIAN_MONO_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 "type.hh"
11#include "parameter.hh"
12#include "keyword.hh"
13#include "using_decl.hh"
14
15namespace eolian_mono {
16
17struct function_declaration_generator
18{
19 template <typename OutputIterator, typename Context>
20 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
21 {
22 if(is_function_blacklisted(f.c_name))
23 return true;
24 else
25 return as_generator
26 (eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n")
27 .generate(sink, std::make_tuple(f.return_type, managed_method_name(f.name), f.parameters), context);
28 }
29};
30
31function_declaration_generator const function_declaration = {};
32
33}
34
35namespace efl { namespace eolian { namespace grammar {
36
37template <>
38struct is_eager_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
39template <>
40struct is_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
41
42namespace type_traits {
43template <>
44struct attributes_needed< ::eolian_mono::function_declaration_generator> : std::integral_constant<int, 1> {};
45}
46
47} } }
48
49#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
new file mode 100644
index 0000000000..2a4c027896
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -0,0 +1,223 @@
1#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HH
2#define EOLIAN_MONO_FUNCTION_DEFINITION_HH
3
4#include <Eina.hh>
5
6#include "grammar/generator.hpp"
7#include "grammar/klass_def.hpp"
8
9#include "grammar/indentation.hpp"
10#include "grammar/list.hpp"
11#include "grammar/alternative.hpp"
12#include "grammar/attribute_reorder.hpp"
13#include "type.hh"
14#include "function_helpers.hh"
15#include "marshall_type.hh"
16#include "parameter.hh"
17#include "keyword.hh"
18#include "using_decl.hh"
19#include "generation_contexts.hh"
20
21namespace eolian_mono {
22
23struct native_function_definition_generator
24{
25 attributes::klass_def const* klass;
26
27 template <typename OutputIterator, typename Context>
28 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
29 {
30 if(is_function_blacklisted(f.c_name))
31 return true;
32 else
33 {
34 if(!as_generator
35 ("\n\n" << scope_tab
36 << eolian_mono::marshall_native_annotation(true)
37 << " public delegate "
38 << eolian_mono::marshall_type(true)
39 << " "
40 << string
41 << "_delegate(System.IntPtr obj, System.IntPtr pd"
42 << *grammar::attribute_reorder<-1, -1>
43 (
44 (", " << marshall_native_annotation << " " << marshall_parameter)
45 )
46 << ");\n")
47 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
48 return false;
49
50 if(!as_generator
51 (scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")] "
52 << eolian_mono::marshall_native_annotation(true)
53 << " public static extern "
54 << eolian_mono::marshall_type(true)
55 << " " << string
56 << "(System.IntPtr obj"
57 << *grammar::attribute_reorder<-1, -1>
58 (
59 (", " << marshall_native_annotation << " " << marshall_parameter)
60 )
61 << ");\n")
62 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
63 return false;
64
65 std::string return_type;
66 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
67 return false;
68
69 if(!as_generator
70 (scope_tab
71 << " public static "
72 << eolian_mono::marshall_type(true) << " "
73 << string
74 << "(System.IntPtr obj, System.IntPtr pd"
75 << *(", " << marshall_parameter)
76 << ")\n"
77 << scope_tab << "{\n"
78 /****/
79 << scope_tab << scope_tab << "eina.Log.Debug(\"function " << string << " was called\");\n"
80 /****/
81 << scope_tab << scope_tab << "efl.eo.IWrapper wrapper = efl.eo.Globals.data_get(pd);\n"
82 << scope_tab << scope_tab << "if(wrapper != null) {\n"
83 << scope_tab << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble()
84 << scope_tab << scope_tab << scope_tab << "try {\n"
85 << scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << string << "Inherit)wrapper)." << string
86 << "(" << (native_argument_invocation % ", ") << ");\n"
87 << scope_tab << scope_tab << scope_tab << "} catch (Exception e) {\n"
88 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
89 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Error.Set(eina.Error.EFL_ERROR);\n"
90 << scope_tab << scope_tab << scope_tab << "}\n"
91 << eolian_mono::native_function_definition_epilogue(*klass)
92 << scope_tab << scope_tab << "} else {\n"
93 << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "return " : "") << string
94 << "(efl.eo.Globals.efl_super(obj, " << string << "Inherit.klass)" << *(", " << argument) << ");\n"
95 << scope_tab << scope_tab << "}\n"
96 << scope_tab << "}\n"
97 )
98 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters
99 , /***/f.c_name/***/
100 , f
101 , klass->cxx_name, managed_method_name(f.name)
102 , f.parameters
103 , f
104 , f.c_name
105 , klass->cxx_name, f.parameters
106 )
107 , context))
108 return false;
109
110 if(!as_generator
111 (scope_tab << "public static "
112 << string
113 << "_delegate "
114 << string << "_static_delegate = new " << string << "_delegate(" << string << "NativeInherit." << string << ");\n"
115 )
116 .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, klass->cxx_name
117 , escape_keyword(f.name)), context))
118 return false;
119 return true;
120 }
121 }
122};
123
124struct function_definition_generator
125{
126 function_definition_generator(bool do_super = false)
127 : do_super(do_super)
128 {}
129
130 template <typename OutputIterator, typename Context>
131 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
132 {
133 if(is_function_blacklisted(f.c_name))
134 return true;
135 else
136 {
137 if(!as_generator
138 ("\n\n" << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")]\n"
139 << scope_tab << eolian_mono::marshall_annotation(true)
140 << " public static extern "
141 << eolian_mono::marshall_type(true)
142 << " " << string
143 << "(System.IntPtr obj"
144 << *grammar::attribute_reorder<-1, -1>
145 (
146 (", " << marshall_annotation << " " << marshall_parameter)
147 )
148 << ");\n")
149 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
150 return false;
151
152 std::string return_type;
153 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
154 return false;
155
156 if(!as_generator
157 (scope_tab << (do_super ? "virtual " : "") << "public " << return_type << " " << string << "(" << (parameter % ", ")
158 << ") {\n "
159 << eolian_mono::function_definition_preamble() << string << "("
160 << (do_super ? "efl.eo.Globals.efl_super(" : "")
161 << "this.raw_handle"
162 << (do_super ? ", this.raw_klass)" : "")
163 << *(", " << argument_invocation ) << ");\n"
164 << eolian_mono::function_definition_epilogue()
165 << " }\n")
166 .generate(sink, std::make_tuple(managed_method_name(f.name), f.parameters, f, f.c_name, f.parameters, f), context))
167 return false;
168
169 return true;
170 }
171 }
172
173 bool do_super;
174};
175
176struct function_definition_parameterized
177{
178 function_definition_generator operator()(bool do_super) const
179 {
180 return {do_super};
181 }
182} const function_definition;
183function_definition_generator as_generator(function_definition_parameterized)
184{
185 return {};
186}
187struct native_function_definition_parameterized
188{
189 native_function_definition_generator operator()(attributes::klass_def const& klass) const
190 {
191 return {&klass};
192 }
193} const native_function_definition;
194
195}
196
197namespace efl { namespace eolian { namespace grammar {
198
199template <>
200struct is_eager_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
201template <>
202struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
203template <>
204struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
205template <>
206struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
207template <>
208struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {};
209
210namespace type_traits {
211template <>
212struct attributes_needed< ::eolian_mono::function_definition_generator> : std::integral_constant<int, 1> {};
213
214template <>
215struct attributes_needed< ::eolian_mono::function_definition_parameterized> : std::integral_constant<int, 1> {};
216
217template <>
218struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {};
219}
220
221} } }
222
223#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_helpers.hh b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
new file mode 100644
index 0000000000..e7af6f9dc0
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
@@ -0,0 +1,243 @@
1#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH
2#define EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH
3
4#include <Eina.hh>
5
6#include "grammar/generator.hpp"
7#include "grammar/klass_def.hpp"
8
9#include "grammar/indentation.hpp"
10#include "grammar/list.hpp"
11#include "grammar/alternative.hpp"
12#include "grammar/attribute_reorder.hpp"
13/* #include "type.hh" */
14/* #include "marshall_type.hh" */
15#include "parameter.hh"
16#include "function_pointer.hh"
17/* #include "keyword.hh" */
18/* #include "using_decl.hh" */
19/* #include "generation_contexts.hh" */
20
21namespace eolian_mono {
22
23/*
24 * Generators for things that must happen inside the function definition *before* and
25 * *after* the actual invocation of the underlying C function.
26 *
27 * For example, declaration and assignment of intermediate variables for out/ return types
28 * that require some kind of manual work (e.g. string and Stringshare).
29 */
30
31struct native_function_definition_preamble_generator
32{
33 // FIXME Suport scoping tabs
34 template <typename OutputIterator, typename Context>
35 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
36 {
37 std::string return_type;
38
39 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
40 return false;
41
42 if (!as_generator(
43 scope_tab << scope_tab << "//Placeholder in variables\n"
44 << *(scope_tab << scope_tab << native_convert_in_variable << "\n")
45 << scope_tab << scope_tab << "//Placeholder out variables\n"
46 << *(scope_tab << scope_tab << native_convert_out_variable << "\n")
47 << scope_tab << scope_tab << "//Function pointer wrappers\n"
48 << *(scope_tab << scope_tab << native_convert_function_pointer << "\n")
49 << scope_tab << scope_tab << "//Return variable and function call\n"
50 << scope_tab << scope_tab << scope_tab << native_convert_return_variable << "\n"
51 ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.parameters, f.return_type), context))
52 return false;
53
54 return true;
55 }
56};
57
58struct function_definition_preamble_generator
59{
60 // FIXME Suport scoping tabs
61 template <typename OutputIterator, typename Context>
62 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
63 {
64 std::string return_type;
65
66 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
67 return false;
68
69 if (!as_generator(
70 scope_tab << scope_tab << "//Placeholder in variables\n"
71 << *(scope_tab << scope_tab << convert_in_variable << "\n")
72 << scope_tab << scope_tab << "//Placeholder out variables\n"
73 << *(scope_tab << scope_tab << convert_out_variable << "\n")
74 << scope_tab << scope_tab << "//Function pointers handling\n"
75 << *(scope_tab << scope_tab << convert_function_pointer << "\n")
76 << scope_tab << scope_tab << "//Return variable and function call\n"
77 << scope_tab << scope_tab << convert_return_variable
78 ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.parameters, f.return_type), context))
79 return false;
80
81 return true;
82 }
83};
84
85struct native_function_definition_epilogue_generator
86{
87 attributes::klass_def const* klass;
88
89 // FIXME Suport scoping tabs
90 template <typename OutputIterator, typename Context>
91 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
92 {
93 std::string return_type;
94
95 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
96 return false;
97
98 if (!as_generator(
99 scope_tab << scope_tab << "//Assigning out variables\n"
100 << *(scope_tab << scope_tab << native_convert_out_assign(*klass) << "\n")
101 << scope_tab << scope_tab << "//Converting return variable\n"
102 << scope_tab << scope_tab << native_convert_return(*klass)
103 ).generate(sink, std::make_tuple(f.parameters, f.return_type), context))
104 return false;
105
106 return true;
107 }
108};
109
110struct function_definition_epilogue_generator
111{
112 // FIXME Suport scoping tabs
113 template <typename OutputIterator, typename Context>
114 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
115 {
116 if (!as_generator(
117 scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
118 << scope_tab << scope_tab << "//Assigning out variables\n"
119 << *(scope_tab << scope_tab << convert_out_assign << "\n")
120 << scope_tab << scope_tab << "//Converting return variable\n"
121 << scope_tab << scope_tab << convert_return
122 ).generate(sink, std::make_tuple(f.parameters, f.return_type), context))
123 return false;
124
125 return true;
126 }
127};
128
129// Preamble tokens
130struct native_function_definition_preamble_terminal
131{
132 native_function_definition_preamble_generator const operator()() const
133 {
134 return native_function_definition_preamble_generator();
135 }
136} const native_function_definition_preamble = {};
137
138native_function_definition_preamble_generator const as_generator(native_function_definition_preamble_terminal)
139{
140 return native_function_definition_preamble_generator{};
141}
142
143struct function_definition_preamble_terminal
144{
145 function_definition_preamble_generator const operator()() const
146 {
147 return function_definition_preamble_generator();
148 }
149} const function_definition_preamble = {};
150
151function_definition_preamble_generator const as_generator(function_definition_preamble_terminal)
152{
153 return function_definition_preamble_generator{};
154}
155
156// Epilogue tokens
157struct native_function_definition_epilogue_parameterized
158{
159 native_function_definition_epilogue_generator const operator()(attributes::klass_def const& klass) const
160 {
161 return {&klass};
162 }
163} const native_function_definition_epilogue;
164
165struct function_definition_epilogue_terminal
166{
167 function_definition_epilogue_generator const operator()() const
168 {
169 return function_definition_epilogue_generator();
170 }
171} const function_definition_epilogue = {};
172
173function_definition_epilogue_generator const as_generator(function_definition_epilogue_terminal)
174{
175 return function_definition_epilogue_generator{};
176}
177
178} // namespace eolian_mono
179
180namespace efl { namespace eolian { namespace grammar {
181
182// Preamble
183template <>
184struct is_eager_generator< ::eolian_mono::native_function_definition_preamble_generator> : std::true_type {};
185
186template <>
187struct is_generator< ::eolian_mono::native_function_definition_preamble_generator> : std::true_type {};
188template <>
189struct is_generator< ::eolian_mono::native_function_definition_preamble_terminal> : std::true_type {};
190
191template <>
192struct is_eager_generator< ::eolian_mono::function_definition_preamble_generator> : std::true_type {};
193
194template <>
195struct is_generator< ::eolian_mono::function_definition_preamble_generator> : std::true_type {};
196template <>
197struct is_generator< ::eolian_mono::function_definition_preamble_terminal> : std::true_type {};
198
199// Epilogue
200template <>
201struct is_eager_generator< ::eolian_mono::native_function_definition_epilogue_generator> : std::true_type {};
202
203template <>
204struct is_generator< ::eolian_mono::native_function_definition_epilogue_generator> : std::true_type {};
205template <>
206struct is_generator< ::eolian_mono::native_function_definition_epilogue_parameterized> : std::true_type {};
207
208template <>
209struct is_eager_generator< ::eolian_mono::function_definition_epilogue_generator> : std::true_type {};
210
211template <>
212struct is_generator< ::eolian_mono::function_definition_epilogue_generator> : std::true_type {};
213template <>
214struct is_generator< ::eolian_mono::function_definition_epilogue_terminal> : std::true_type {};
215
216namespace type_traits {
217// Preamble
218template <>
219struct attributes_needed< ::eolian_mono::native_function_definition_preamble_generator> : std::integral_constant<int, 1> {};
220template <>
221struct attributes_needed< ::eolian_mono::native_function_definition_preamble_terminal> : std::integral_constant<int, 1> {};
222
223template <>
224struct attributes_needed< ::eolian_mono::function_definition_preamble_generator> : std::integral_constant<int, 1> {};
225template <>
226struct attributes_needed< ::eolian_mono::function_definition_preamble_terminal> : std::integral_constant<int, 1> {};
227
228// Epilogue
229template <>
230struct attributes_needed< ::eolian_mono::native_function_definition_epilogue_generator> : std::integral_constant<int, 1> {};
231template <>
232struct attributes_needed< ::eolian_mono::native_function_definition_epilogue_parameterized> : std::integral_constant<int, 1> {};
233
234template <>
235struct attributes_needed< ::eolian_mono::function_definition_epilogue_generator> : std::integral_constant<int, 1> {};
236template <>
237struct attributes_needed< ::eolian_mono::function_definition_epilogue_terminal> : std::integral_constant<int, 1> {};
238
239}
240
241} } }
242
243#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
new file mode 100644
index 0000000000..84fdb79881
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
@@ -0,0 +1,95 @@
1#ifndef EOLIAN_MONO_FUNCTION_POINTER_HPP
2#define EOLIAN_MONO_FUNCTION_POINTER_HPP
3
4#include <Eolian.h>
5
6#include <vector>
7#include <string>
8
9namespace eolian_mono {
10
11// Blacklist structs that require some kind of manual binding.
12static bool is_function_ptr_blacklisted(attributes::function_def const& func, std::vector<std::string> const &namesp)
13{
14 std::stringstream full_name;
15
16 for (auto&& i : namesp)
17 full_name << i << ".";
18 full_name << func.name;
19
20 std::string name = full_name.str();
21
22 return name == "Efl.Ui.Format_Func_Cb";
23}
24
25struct function_pointer {
26 template <typename OutputIterator, typename Context>
27 bool generate(OutputIterator sink, attributes::function_def const& f, std::vector<std::string> const &namesp, Context const& context) const
28 {
29 // FIXME export Typedecl in eolian_cxx API
30 std::vector<std::string> namespaces = escape_namespace(namesp);
31
32 if (is_function_ptr_blacklisted(f, namesp))
33 return true;
34
35 auto open_namespace = *("namespace " << string << " {") << "\n";
36 if(!as_generator(open_namespace).generate(sink, namespaces, add_lower_case_context(context))) return false;
37
38 // C# visible delegate
39 if (!as_generator("public delegate " << type << " " << string
40 << "(" << (parameter % ", ") << ");\n")
41 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context))
42 return false;
43 // "Internal" delegate, 1-to-1 with the Unamaged function type
44 if (!as_generator("public delegate " << type << " " << string // public?
45 << "Internal(IntPtr data, " << (parameter % ", ") << ");\n")
46 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context))
47 return false;
48
49 std::string f_name = escape_keyword(f.name);
50 // Wrapper type, with callback matching the Unamanaged one
51 if (!as_generator("public class " << f_name << "Wrapper\n"
52 << "{\n\n"
53 << scope_tab << "private " << f_name << "Internal _cb;\n"
54 << scope_tab << "private IntPtr _cb_data;\n"
55 << scope_tab << "private Eina_Free_Cb _cb_free_cb;\n\n"
56
57 << scope_tab << "public " << f_name << "Wrapper (" << f_name << "Internal _cb, IntPtr _cb_data, Eina_Free_Cb _cb_free_cb)\n"
58 << scope_tab << "{\n"
59 << scope_tab << scope_tab << "this._cb = _cb;\n"
60 << scope_tab << scope_tab << "this._cb_data = _cb_data;\n"
61 << scope_tab << scope_tab << "this._cb_free_cb = _cb_free_cb;\n"
62 << scope_tab << "}\n\n"
63
64 << scope_tab << "~" << f_name << "Wrapper()\n"
65 << scope_tab << "{\n"
66 << scope_tab << scope_tab << "if (this._cb_free_cb != null)\n"
67 << scope_tab << scope_tab << scope_tab << "this._cb_free_cb(this._cb_data);\n"
68 << scope_tab << "}\n\n"
69
70 << scope_tab << "public " << type << " ManagedCb(" << (parameter % ",") << ")\n"
71 << scope_tab << "{\n"
72 << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return ": "") << "_cb(_cb_data, " << (argument_invocation % ", ") << ");\n"
73 << scope_tab << "}\n\n"
74
75 << scope_tab << "public static " << type << " Cb(IntPtr cb_data, " << (parameter % ", ") << ")\n"
76 << scope_tab << "{\n"
77 << scope_tab << scope_tab << "GCHandle handle = GCHandle.FromIntPtr(cb_data);\n"
78 << scope_tab << scope_tab << string << " cb = (" << string << ")handle.Target;\n"
79 << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return " : "") << "cb(" << (argument_invocation % ", ") << ");\n"
80 << scope_tab << "}\n"
81 << "}\n"
82 ).generate(sink, std::make_tuple(f.return_type, f.parameters, f.parameters, f.return_type, f.parameters, f_name, f_name, f.parameters), context))
83 return false;
84
85 auto close_namespace = *(lit("} ")) << "\n";
86 if(!as_generator(close_namespace).generate(sink, namespaces, context)) return false;
87
88 return true;
89 }
90};
91
92struct function_pointer const function_pointer = {};
93}
94
95#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh
new file mode 100644
index 0000000000..a88c938924
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh
@@ -0,0 +1,78 @@
1#ifndef EOLIAN_MONO_FUNCTION_REGISTRATION_HH
2#define EOLIAN_MONO_FUNCTION_REGISTRATION_HH
3
4#include <Eina.hh>
5
6#include "grammar/generator.hpp"
7#include "grammar/klass_def.hpp"
8
9#include "grammar/indentation.hpp"
10#include "grammar/list.hpp"
11#include "grammar/alternative.hpp"
12#include "grammar/attribute_reorder.hpp"
13#include "type.hh"
14#include "marshall_type.hh"
15#include "parameter.hh"
16#include "keyword.hh"
17#include "using_decl.hh"
18#include "generation_contexts.hh"
19
20namespace eolian_mono {
21
22template <typename I>
23struct function_registration_generator
24{
25 I index_generator;
26 attributes::klass_def const* klass;
27
28 template <typename OutputIterator, typename Context>
29 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
30 {
31 if(is_function_blacklisted(f.c_name))
32 return true;
33 else
34 {
35 auto index = index_generator();
36
37 if(!as_generator
38#ifdef _WIN32
39 (scope_tab << scope_tab << "descs[" << index << "].api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\");\n"
40#else
41 (scope_tab << scope_tab << "descs[" << index << "].api_func = efl.eo.Globals.dlsym(efl.eo.Globals.RTLD_DEFAULT, \"" << string << "\");\n"
42#endif
43 << scope_tab << scope_tab << "descs[" << index << "].func = Marshal.GetFunctionPointerForDelegate(" << string << "NativeInherit." << string << "_static_delegate);\n"
44 )
45 .generate(sink, std::make_tuple(f.c_name, klass->cxx_name, f.c_name), context))
46 return false;
47 return true;
48 }
49 }
50};
51
52struct function_registration_parameterized
53{
54 template <typename I>
55 function_registration_generator<I> operator()(I i, attributes::klass_def const& klass) const
56 {
57 return {i, &klass};
58 }
59} const function_registration;
60
61}
62
63namespace efl { namespace eolian { namespace grammar {
64
65template <typename I>
66struct is_eager_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {};
67template <typename I>
68struct is_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {};
69
70namespace type_traits {
71
72template <typename I>
73struct attributes_needed< ::eolian_mono::function_registration_generator<I>> : std::integral_constant<int, 1> {};
74}
75
76} } }
77
78#endif
diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
new file mode 100644
index 0000000000..f220c94cb6
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
@@ -0,0 +1,42 @@
1#ifndef EOLIAN_MONO_GENERATION_CONTEXTS_HH
2#define EOLIAN_MONO_GENERATION_CONTEXTS_HH
3
4namespace eolian_mono {
5
6struct class_context
7{
8 enum wrapper_kind {
9 interface,
10 concrete,
11 inherit,
12 inherit_native,
13 };
14 wrapper_kind current_wrapper_kind;
15};
16
17struct library_context
18{
19 std::string library_name;
20 int v_major;
21 int v_minor;
22 std::map<const std::string, std::string> references;
23
24 const std::string actual_library_name(const std::string& filename) const;
25};
26
27const std::string
28library_context::actual_library_name(const std::string& filename) const
29{
30 // Libraries mapped follow the efl.Libs.NAME scheme.
31 // TODO What about references from outside efl (not present in the efl.Libs class?)
32 auto ref = references.find(filename);
33 if (ref != references.end())
34 return "efl.Libs." + ref->second;
35
36 // Fallback to original behaviour with explicit library name
37 return '"' + library_name + '"';
38}
39
40}
41
42#endif
diff --git a/src/bin/eolian_mono/eolian/mono/keyword.hh b/src/bin/eolian_mono/eolian/mono/keyword.hh
new file mode 100644
index 0000000000..fbe853af5b
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/keyword.hh
@@ -0,0 +1,52 @@
1#ifndef EOLIAN_CXX_KEYWORD_HH
2#define EOLIAN_CXX_KEYWORD_HH
3
4#include <string>
5#include <strings.h>
6#include <vector>
7
8#include "name_helpers.hh"
9
10namespace eolian_mono {
11namespace detail {
12inline bool is_iequal(std::string const& lhs, std::string const& rhs)
13{
14 return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
15}
16}
17
18inline std::string escape_keyword(std::string const& name)
19{
20 using detail::is_iequal;
21 if(is_iequal(name, "delete")
22 || is_iequal(name, "register")
23 || is_iequal(name, "do")
24 || is_iequal(name, "lock")
25 || is_iequal(name, "event")
26 || is_iequal(name, "in")
27 || is_iequal(name, "object")
28 || is_iequal(name, "interface")
29 || is_iequal(name, "string")
30 || is_iequal(name, "internal")
31 || is_iequal(name, "fixed")
32 || is_iequal(name, "base"))
33 return "kw_" + name;
34
35 if (is_iequal(name, "Finalize"))
36 return name + "Add"; // Eo's Finalize is actually the end of efl_add.
37 return name;
38}
39
40
41std::string managed_method_name(std::string const& underscore_name)
42{
43 std::vector<std::string> names = name_helpers::split(underscore_name, '_');
44
45 name_helpers::reorder_verb(names);
46
47 return escape_keyword(name_helpers::pascal_case(names));
48}
49
50}
51
52#endif
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
new file mode 100644
index 0000000000..fe2d35dfa6
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -0,0 +1,745 @@
1#ifndef EOLIAN_MONO_CLASS_DEFINITION_HPP
2#define EOLIAN_MONO_CLASS_DEFINITION_HPP
3
4#include "grammar/integral.hpp"
5#include "grammar/generator.hpp"
6#include "grammar/klass_def.hpp"
7#include "function_blacklist.hh"
8
9#include "grammar/indentation.hpp"
10#include "grammar/list.hpp"
11#include "grammar/alternative.hpp"
12#include "type.hh"
13#include "namespace.hh"
14#include "function_definition.hh"
15#include "function_registration.hh"
16#include "function_declaration.hh"
17#include "grammar/string.hpp"
18#include "grammar/attribute_replace.hpp"
19#include "grammar/integral.hpp"
20#include "grammar/case.hpp"
21#include "using_decl.hh"
22#include "utils.hh"
23
24#include <string>
25#include <algorithm>
26
27namespace eolian_mono {
28
29template <typename OutputIterator, typename Context>
30static bool generate_static_cast_method(OutputIterator sink, const std::string &class_name, Context const &context)
31{
32 return as_generator(
33 scope_tab << "public static " << class_name << " static_cast(efl.Object obj)\n"
34 << scope_tab << "{\n"
35 << scope_tab << scope_tab << "if (obj == null)\n"
36 << scope_tab << scope_tab << scope_tab << "throw new System.ArgumentNullException(\"obj\");\n"
37 << scope_tab << scope_tab << "return new " << class_name << "Concrete(obj.raw_handle);\n"
38 << scope_tab << "}\n"
39 ).generate(sink, nullptr, context);
40}
41
42template <typename OutputIterator, typename Context>
43static bool generate_equals_method(OutputIterator sink, Context const &context)
44{
45 return as_generator(
46 scope_tab << "public override bool Equals(object obj)\n"
47 << scope_tab << "{\n"
48 << scope_tab << scope_tab << "var other = obj as efl.Object;\n"
49 << scope_tab << scope_tab << "if (other == null)\n"
50 << scope_tab << scope_tab << scope_tab << "return false;\n"
51 << scope_tab << scope_tab << "return this.raw_handle == other.raw_handle;\n"
52 << scope_tab << "}\n"
53 << scope_tab << "public override int GetHashCode()\n"
54 << scope_tab << "{\n"
55 << scope_tab << scope_tab << "return this.raw_handle.ToInt32();\n"
56 << scope_tab << "}\n"
57 ).generate(sink, nullptr, context);
58}
59
60/* Get the actual number of functions of a class, checking for blacklisted ones */
61static std::size_t
62get_function_count(grammar::attributes::klass_def const& cls)
63{
64 auto methods = cls.get_all_methods();
65 return std::count_if(methods.cbegin(), methods.cend(), [](grammar::attributes::function_def const& func)
66 {
67 return !is_function_blacklisted(func.c_name);
68 });
69}
70
71struct get_csharp_type_visitor
72{
73 typedef get_csharp_type_visitor visitor_type;
74 typedef std::string result_type;
75 std::string operator()(grammar::attributes::regular_type_def const& type) const
76 {
77 std::stringstream csharp_name;
78 for (auto&& i : escape_namespace(type.namespaces))
79 csharp_name << utils::to_lowercase(i) << ".";
80 csharp_name << type.base_type;
81
82 return csharp_name.str();
83 }
84 std::string operator()(grammar::attributes::klass_name const& name) const
85 {
86 std::stringstream csharp_name;
87 for (auto&& i : escape_namespace(name.namespaces))
88 csharp_name << utils::to_lowercase(i) << ".";
89 csharp_name << name.eolian_name;
90
91 return csharp_name.str();
92 }
93 std::string operator()(attributes::complex_type_def const&) const
94 {
95 return "UNSUPPORTED";
96 }
97};
98
99struct get_event_args_visitor
100{
101
102 std::string arg_type;
103
104 typedef get_event_args_visitor visitor_type;
105 typedef std::string result_type;
106 std::string operator()(grammar::attributes::regular_type_def const&) const
107 {
108 return "(" + arg_type + ")Marshal.PtrToStructure(evt.Info, typeof(" + arg_type + "))";
109 }
110 std::string operator()(grammar::attributes::klass_name const&) const
111 {
112 return "new " + arg_type + "Concrete(evt.Info)";
113 }
114 std::string operator()(attributes::complex_type_def const&) const
115 {
116 return "UNSUPPORTED";
117 }
118};
119
120struct klass
121{
122 template <typename OutputIterator, typename Context>
123 bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
124 {
125 std::string suffix, class_type;
126 switch(cls.type)
127 {
128 case attributes::class_type::regular:
129 case attributes::class_type::abstract_:
130 class_type = "class";
131 suffix = "CLASS";
132 break;
133 case attributes::class_type::mixin:
134 class_type = "interface";
135 suffix = "MIXIN";
136 break;
137 case attributes::class_type::interface_:
138 class_type = "interface";
139 suffix = "INTERFACE";
140 break;
141 }
142
143 std::vector<std::string> namespaces = escape_namespace(cls.namespaces);
144 auto open_namespace = *("namespace " << string << " { ") << "\n";
145 if(!as_generator(open_namespace).generate(sink, namespaces, add_lower_case_context(context))) return false;
146 auto methods = cls.get_all_methods();
147
148 // FIXME Generate local event argument wrappers
149 for (auto&& e : cls.events)
150 {
151 efl::eina::optional<grammar::attributes::type_def> etype = e.type;
152 if (!etype.is_engaged())
153 continue;
154
155 std::string evt_name = utils::to_uppercase(e.name);
156 std::replace(evt_name.begin(), evt_name.end(), ',', '_');
157 std::string arg_type = (*etype).original_type.visit(get_csharp_type_visitor{});
158
159
160 if (!as_generator("public class " << evt_name << "_Args : EventArgs {\n"
161 << scope_tab << "public " << arg_type << " arg { get; set; }\n"
162 << "}\n").generate(sink, NULL, context))
163 return false;
164 }
165
166 // Interface class
167 {
168 auto iface_cxt = context_add_tag(class_context{class_context::interface}, context);
169 if(!as_generator
170 (
171 "public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : "
172 )
173 .generate(sink, cls.cxx_name, iface_cxt))
174 return false;
175 for(auto first = std::begin(cls.immediate_inherits)
176 , last = std::end(cls.immediate_inherits); first != last; ++first)
177 {
178 if(!as_generator("\n" << scope_tab << *(lower_case[string] << ".") << string << " ,")
179 .generate(sink, std::make_tuple(escape_namespace(first->namespaces), first->eolian_name), iface_cxt))
180 return false;
181 // if(std::next(first) != last)
182 // *sink++ = ',';
183 }
184 // if(cls.immediate_inherits.empty())
185 if(!as_generator("\n" << scope_tab << "efl.eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt)) return false;
186 if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) return false;
187
188 if(!as_generator(*(scope_tab << function_declaration))
189 .generate(sink, cls.functions, iface_cxt)) return false;
190
191 // FIXME Move the event generator into another generator like function?
192 for (auto &&e : cls.events)
193 {
194 std::string wrapper_args_type;
195 std::string evt_name = utils::to_uppercase(e.name);
196 std::replace(evt_name.begin(), evt_name.end(), ',', '_');
197
198 efl::eina::optional<grammar::attributes::type_def> etype = e.type;
199 if (etype.is_engaged())
200 wrapper_args_type = "<" + evt_name + "_Args>";
201
202 //FIXME Add a way to generate camelcase names
203 if (!as_generator(
204 scope_tab << "event EventHandler" << wrapper_args_type << " "
205 << evt_name << ";\n"
206 ).generate(sink, NULL, iface_cxt))
207 return false;
208 }
209
210 // End of interface declaration
211 if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false;
212 }
213
214 auto class_get_name = *(lower_case[string] << "_") << lower_case[string] << "_class_get";
215 // Concrete class
216 // if(class_type == "class")
217 {
218 auto concrete_cxt = context_add_tag(class_context{class_context::concrete}, context);
219 if(!as_generator
220 (
221 "public class " << string << "Concrete : " << string << "\n{\n"
222 << scope_tab << "System.IntPtr handle;\n"
223 << scope_tab << "public System.IntPtr raw_handle {\n"
224 << scope_tab << scope_tab << "get { return handle; }\n"
225 << scope_tab << "}\n"
226 << scope_tab << "public System.IntPtr raw_klass {\n"
227 << scope_tab << scope_tab << "get { return efl.eo.Globals.efl_class_get(handle); }\n"
228 << scope_tab << "}\n"
229 << scope_tab << "public delegate void ConstructingMethod(" << string << " obj);\n"
230 << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
231 << ")] static extern System.IntPtr\n"
232 << scope_tab << scope_tab << class_get_name << "();\n"
233 << (class_type == "class" ? "" : "/*")
234 << scope_tab << "public " << string << "Concrete(efl.Object parent = null, ConstructingMethod init_cb=null)\n"
235 << scope_tab << "{\n"
236 << scope_tab << scope_tab << "System.IntPtr klass = " << class_get_name << "();\n"
237 << scope_tab << scope_tab << "System.IntPtr parent_ptr = System.IntPtr.Zero;\n"
238 << scope_tab << scope_tab << "if(parent != null)\n"
239 << scope_tab << scope_tab << scope_tab << "parent_ptr = parent.raw_handle;\n"
240 << scope_tab << scope_tab << "handle = efl.eo.Globals._efl_add_internal_start(\"file\", 0, klass, parent_ptr, 0, 0);\n"
241 << scope_tab << scope_tab << "if (init_cb != null) {\n"
242 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
243 << scope_tab << scope_tab << "}\n"
244 << scope_tab << scope_tab << "handle = efl.eo.Globals._efl_add_end(handle, 0, 0);\n" // replace handle with the actual final handle
245 << scope_tab << scope_tab << "register_event_proxies();\n"
246 << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
247 << scope_tab << "}\n"
248 << (class_type == "class" ? "" : "*/")
249 << scope_tab << "public " << string << "Concrete(System.IntPtr raw)\n"
250 << scope_tab << "{\n"
251 << scope_tab << scope_tab << "handle = raw;\n"
252 << scope_tab << scope_tab << "register_event_proxies();\n"
253 << scope_tab << "}\n"
254 << scope_tab << "~" << string << "Concrete()\n"
255 << scope_tab << "{\n"
256 << scope_tab << scope_tab << "Dispose(false);\n"
257 << scope_tab << "}\n"
258 << scope_tab << "protected virtual void Dispose(bool disposing)\n"
259 << scope_tab << "{\n"
260 << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
261 << scope_tab << scope_tab << scope_tab << "efl.eo.Globals.efl_unref(handle);\n"
262 << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
263 << scope_tab << scope_tab << "}\n"
264 << scope_tab << "}\n"
265 << scope_tab << "public void Dispose()\n"
266 << scope_tab << "{\n"
267 << scope_tab << scope_tab << "Dispose(true);\n"
268 << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
269 << scope_tab << "}\n"
270 )
271 .generate(sink
272 , std::make_tuple(
273 cls.cxx_name, cls.cxx_name, cls.cxx_name, cls.namespaces, cls.eolian_name
274 , cls.cxx_name, cls.namespaces, cls.eolian_name, cls.cxx_name
275 , cls.cxx_name)
276 , concrete_cxt))
277 return false;
278
279 if (!generate_static_cast_method(sink, cls.cxx_name, concrete_cxt))
280 return false;
281
282 if (!generate_equals_method(sink, concrete_cxt))
283 return false;
284
285 if (!generate_events(sink, cls, concrete_cxt))
286 return false;
287
288 if (!generate_events_registration(sink, cls, concrete_cxt))
289 return false;
290
291 // Concrete function definitions
292 if(!as_generator(*(function_definition))
293 .generate(sink, methods, concrete_cxt)) return false;
294
295 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
296 }
297
298 // Inherit class
299 if(class_type == "class")
300 {
301 auto inherit_cxt = context_add_tag(class_context{class_context::inherit}, context);
302 bool cls_has_string_return = has_string_return(cls);
303 bool cls_has_stringshare_return = has_stringshare_return(cls);
304
305 if(!as_generator
306 (
307 "public " << class_type << " " << string << "Inherit : " << string << "\n{\n"
308 << scope_tab << "System.IntPtr handle;\n"
309 << scope_tab << "public static System.IntPtr klass = System.IntPtr.Zero;\n"
310 << scope_tab << "private static readonly object klassAllocLock = new object();\n"
311 << scope_tab << (cls_has_string_return ? ("public Dictionary<String, IntPtr> cached_strings = new Dictionary<String, IntPtr>();") : "") << "\n"
312 << scope_tab << (cls_has_stringshare_return ? ("public Dictionary<String, IntPtr> cached_stringshares = new Dictionary<String, IntPtr>();") : "") << "\n"
313 << scope_tab << "public System.IntPtr raw_handle {\n"
314 << scope_tab << scope_tab << "get { return handle; }\n"
315 << scope_tab << "}\n"
316 << scope_tab << "public System.IntPtr raw_klass {\n"
317 << scope_tab << scope_tab << "get { return klass; }\n"
318 << scope_tab << "}\n"
319 << scope_tab << "public delegate void ConstructingMethod(" << string << " obj);\n"
320 << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(inherit_cxt).actual_library_name(cls.filename)
321 << ")] static extern System.IntPtr\n"
322 << scope_tab << scope_tab << class_get_name << "();\n"
323 << scope_tab << "public " << string << "Inherit(efl.Object parent = null, ConstructingMethod init_cb=null)\n"
324 << scope_tab << "{\n"
325 << scope_tab << scope_tab << "if (klass == System.IntPtr.Zero) {\n"
326 << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
327 << scope_tab << scope_tab << scope_tab << scope_tab << "if (klass == System.IntPtr.Zero) {\n"
328 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "klass = efl.eo.Globals.register_class(new efl.eo.Globals.class_initializer(" << string << "NativeInherit.class_initializer), " << class_get_name << "());\n"
329 //<< scope_tab << scope_tab << "klass = efl.eo.Globals.register_class(null/*new efl.eo.Globals.class_initializer(" << string << "NativeInherit.class_initializer)*/, " << class_get_name << "());\n"
330 << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
331 << scope_tab << scope_tab << scope_tab << "}\n"
332 << scope_tab << scope_tab << "}\n"
333 << scope_tab << scope_tab << "handle = efl.eo.Globals.instantiate_start(klass, parent);\n"
334 << scope_tab << scope_tab << "if (init_cb != null) {\n"
335 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
336 << scope_tab << scope_tab << "}\n"
337 << scope_tab << scope_tab << "handle = efl.eo.Globals.instantiate_end(handle);\n"
338 << scope_tab << scope_tab << "efl.eo.Globals.data_set(this);\n"
339 << scope_tab << scope_tab << "register_event_proxies();\n"
340 << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
341 << scope_tab << "}\n"
342 << scope_tab << "~" << string << "Inherit()\n"
343 << scope_tab << "{\n"
344 << scope_tab << scope_tab << "Dispose(false);\n"
345 << scope_tab << "}\n"
346 << scope_tab << "protected virtual void Dispose(bool disposing)\n"
347 << scope_tab << "{\n"
348 << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
349 << scope_tab << scope_tab << scope_tab << "efl.eo.Globals.efl_unref(handle);\n"
350 << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
351 << scope_tab << scope_tab << "}\n"
352 << scope_tab << "}\n"
353 << scope_tab << "public void Dispose()\n"
354 << scope_tab << "{\n"
355 << scope_tab << (cls_has_string_return ? "efl.eo.Globals.free_dict_values(cached_strings);" : "") << "\n"
356 << scope_tab << (cls_has_stringshare_return ? "efl.eo.Globals.free_stringshare_values(cached_stringshares);" : "") << "\n"
357 << scope_tab << scope_tab << "Dispose(true);\n"
358 << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
359 << scope_tab << "}\n"
360 )
361 .generate(sink
362 , std::make_tuple(
363 cls.cxx_name, cls.cxx_name, cls.cxx_name, cls.namespaces, cls.eolian_name
364 , cls.cxx_name, cls.cxx_name, cls.namespaces, cls.eolian_name, cls.cxx_name
365 , cls.cxx_name)
366 , inherit_cxt))
367 return false;
368
369 if (!generate_static_cast_method(sink, cls.cxx_name, inherit_cxt))
370 return false;
371
372 if (!generate_equals_method(sink, inherit_cxt))
373 return false;
374
375 if (!generate_events(sink, cls, inherit_cxt))
376 return false;
377
378 if (!generate_events_registration(sink, cls, inherit_cxt))
379 return false;
380
381 // Inherit function definitions
382 if(!as_generator(*(function_definition(true)))
383 .generate(sink, methods, inherit_cxt)) return false;
384
385 if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
386 }
387
388 std::size_t function_count = get_function_count(cls);
389
390 int function_registration_index = 0;
391 auto index_generator = [&function_registration_index]
392 {
393 return function_registration_index++;
394 };
395
396 // Native Inherit class
397 if(class_type == "class")
398 {
399 auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context);
400 if(!as_generator
401 (
402 "public " << class_type << " " << string << "NativeInherit {\n"
403 << scope_tab << "public static byte class_initializer(IntPtr klass)\n"
404 << scope_tab << "{\n"
405 << scope_tab << scope_tab << "Efl_Op_Description[] descs = new Efl_Op_Description[" << grammar::int_ << "];\n"
406 )
407 .generate(sink, std::make_tuple(cls.cxx_name, function_count), inative_cxt))
408 return false;
409
410 // Native wrapper registration
411 if(!as_generator(*(function_registration(index_generator, cls)))
412 .generate(sink, methods, inative_cxt)) return false;
413
414 if(!as_generator
415 ( scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*" << function_count << ");\n"
416 << scope_tab << scope_tab << "IntPtr ptr = descs_ptr;\n"
417 << scope_tab << scope_tab << "for(int i = 0; i != " << function_count << "; ++i)\n"
418 << scope_tab << scope_tab << "{\n"
419 << scope_tab << scope_tab << scope_tab << "Marshal.StructureToPtr(descs[i], ptr, false);\n"
420 << scope_tab << scope_tab << scope_tab << "ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0]));\n"
421 << scope_tab << scope_tab << "}\n"
422 << scope_tab << scope_tab << "Efl_Object_Ops ops;\n"
423 << scope_tab << scope_tab << "ops.descs = descs_ptr;\n"
424 << scope_tab << scope_tab << "ops.count = (UIntPtr)" << function_count << ";\n"
425 << scope_tab << scope_tab << "IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));\n"
426 << scope_tab << scope_tab << "Marshal.StructureToPtr(ops, ops_ptr, false);\n"
427 << scope_tab << scope_tab << "efl.eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);\n"
428 ).generate(sink, attributes::unused, inative_cxt)) return false;
429
430
431 if(!as_generator(scope_tab << scope_tab << "return 1;\n"
432 << scope_tab << "}\n")
433 .generate(sink, attributes::unused, inative_cxt)) return false;
434
435 // Native method definitions
436 if(!as_generator(*(native_function_definition(cls)))
437 .generate(sink, methods, inative_cxt)) return false;
438
439 if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false;
440 }
441
442 auto close_namespace = *(lit("} ")) << "\n";
443 if(!as_generator(close_namespace).generate(sink, namespaces, context)) return false;
444
445 return true;
446 }
447
448 template <typename OutputIterator, typename Context>
449 bool generate_events_registration(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
450 {
451 // Event proxy registration
452 if (!as_generator(
453 scope_tab << "private void register_event_proxies()\n"
454 << scope_tab << "{\n"
455 )
456 .generate(sink, NULL, context))
457 return false;
458
459 // Generate event registrations here
460
461 // Assigning the delegates
462 for (auto&& e : cls.events)
463 {
464 if (!as_generator(scope_tab << scope_tab << "evt_" << grammar::string_replace(',', '_') << "_delegate = "
465 << "new efl.Event_Cb(on_" << grammar::string_replace(',', '_') << "_NativeCallback);\n")
466 .generate(sink, std::make_tuple(e.name, e.name), context))
467 return false;
468 }
469
470 for (auto&& c : cls.inherits)
471 {
472 attributes::klass_def klass(get_klass(c, NULL), NULL);
473
474 for (auto&& e : klass.events)
475 {
476 std::string wrapper_event_name = translate_inherited_event_name(e, klass);
477
478 if (!as_generator(scope_tab << scope_tab << "evt_" << wrapper_event_name << "_delegate = "
479 << "new efl.Event_Cb(on_" << wrapper_event_name << "_NativeCallback);\n")
480 .generate(sink, NULL, context))
481 return false;
482 }
483 }
484
485
486 if (!as_generator(
487 scope_tab << "}\n"
488 ).generate(sink, NULL, context))
489 return false;
490
491 return true;
492 }
493
494 static std::string translate_inherited_event_name(const attributes::event_def &evt, const attributes::klass_def &klass)
495 {
496 std::stringstream s;
497
498 for (auto&& n : klass.namespaces)
499 {
500 s << n;
501 s << '_';
502 }
503 std::string evt_name = utils::to_uppercase(evt.name);
504 std::replace(evt_name.begin(), evt_name.end(), ',', '_');
505 s << klass.cxx_name << '_' << evt_name;
506 return s.str();
507 }
508
509 template <typename OutputIterator, typename Context>
510 bool generate_events(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
511 {
512
513 if (!has_events(cls))
514 return true;
515
516 if (!as_generator(scope_tab << "private readonly object eventLock = new object();\n"
517 << scope_tab << "private Dictionary<string, int> event_cb_count = new Dictionary<string, int>();\n")
518 .generate(sink, NULL, context))
519 return false;
520
521 // Callback registration functions
522 if (!as_generator(
523 scope_tab << "private bool add_cpp_event_handler(string key, efl.Event_Cb evt_delegate) {\n"
524 << scope_tab << scope_tab << "int event_count = 0;\n"
525 << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
526 << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
527 << scope_tab << scope_tab << "if (event_count == 0) {\n"
528 << scope_tab << scope_tab << scope_tab << "efl.kw_event.Description desc = new efl.kw_event.Description(key);\n"
529 << scope_tab << scope_tab << scope_tab << "bool result = efl.eo.Globals.efl_event_callback_priority_add(handle, desc, 0, evt_delegate, System.IntPtr.Zero);\n"
530 << scope_tab << scope_tab << scope_tab << "if (!result) {\n"
531 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Failed to add event proxy for event ${key}\");\n"
532 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
533 << scope_tab << scope_tab << scope_tab << "}\n"
534 << scope_tab << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
535 << scope_tab << scope_tab << "} \n"
536 << scope_tab << scope_tab << "event_cb_count[key]++;\n"
537 << scope_tab << scope_tab << "return true;\n"
538 << scope_tab << "}\n"
539 << scope_tab << "private bool remove_cpp_event_handler(string key, efl.Event_Cb evt_delegate) {\n"
540 << scope_tab << scope_tab << "int event_count = 0;\n"
541 << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
542 << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
543 << scope_tab << scope_tab << "if (event_count == 1) {\n"
544 << scope_tab << scope_tab << scope_tab << "efl.kw_event.Description desc = new efl.kw_event.Description(key);\n"
545 << scope_tab << scope_tab << scope_tab << "bool result = efl.eo.Globals.efl_event_callback_del(handle, desc, evt_delegate, System.IntPtr.Zero);\n"
546 << scope_tab << scope_tab << scope_tab << "if (!result) {\n"
547 << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Failed to remove event proxy for event ${key}\");\n"
548 << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
549 << scope_tab << scope_tab << scope_tab << "}\n"
550 << scope_tab << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
551 << scope_tab << scope_tab << "} else if (event_count == 0) {\n"
552 << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Trying to remove proxy for event ${key} when there is nothing registered.\");\n"
553 << scope_tab << scope_tab << scope_tab << "return false;\n"
554 << scope_tab << scope_tab << "} \n"
555 << scope_tab << scope_tab << "event_cb_count[key]--;\n"
556 << scope_tab << scope_tab << "return true;\n"
557 << scope_tab << "}\n"
558 )
559 .generate(sink, NULL, context))
560 return false;
561
562 // Self events
563 for (auto&& e : cls.events)
564 {
565 std::string upper_name = utils::to_uppercase(e.name);
566 std::replace(upper_name.begin(), upper_name.end(), ',', '_');
567 std::string upper_c_name = utils::to_uppercase(e.c_name);
568 std::string event_name = e.name;
569 std::replace(event_name.begin(), event_name.end(), ',', '_');
570
571 std::string wrapper_args_type = "EventArgs";
572 std::string wrapper_args_template = "";
573 std::string event_args = "EventArgs args = EventArgs.Empty;\n";
574
575 efl::eina::optional<grammar::attributes::type_def> etype = e.type;
576 if (etype.is_engaged())
577 {
578 wrapper_args_type = upper_name + "_Args";
579 wrapper_args_template = "<" + wrapper_args_type + ">";
580 std::string arg_type = wrapper_args_type + " args = new " + wrapper_args_type + "();\n"; // = (*etype).original_type.visit(get_csharp_type_visitor{});
581 std::string actual_arg_type = (*etype).original_type.visit(get_csharp_type_visitor{});
582 arg_type += "args.arg = " + (*etype).original_type.visit(get_event_args_visitor{actual_arg_type}) + ";\n";
583
584 event_args = arg_type;
585 }
586 // Marshal.PtrToStructure for value types
587
588 // Wrapper event declaration
589 if(!as_generator(
590 scope_tab << "protected event EventHandler" << wrapper_args_template << " " << upper_name << ";\n"
591 << scope_tab << "protected void On_" << event_name << "(" << wrapper_args_type << " e)\n"
592 << scope_tab << "{\n"
593 << scope_tab << scope_tab << "EventHandler" << wrapper_args_template << " evt;\n"
594 << scope_tab << scope_tab << "lock (eventLock) {\n"
595 << scope_tab << scope_tab << scope_tab << "evt = " << upper_name << ";\n"
596 << scope_tab << scope_tab << "}\n"
597 << scope_tab << scope_tab << "if (evt != null) { evt(this, e); }\n"
598 << scope_tab << "}\n"
599 << scope_tab << "public void on_" << event_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)\n"
600 << scope_tab << "{\n"
601 << scope_tab << event_args
602 << scope_tab << scope_tab << "try {\n"
603 << scope_tab << scope_tab << scope_tab << "On_" << event_name << "(args);\n"
604 << scope_tab << scope_tab << "} catch (Exception e) {\n"
605 << scope_tab << scope_tab << scope_tab << "eina.Log.Warning(e.ToString());\n"
606 << scope_tab << scope_tab << scope_tab << "eina.Error.Set(eina.Error.EFL_ERROR);\n"
607 << scope_tab << scope_tab << "}\n"
608 << scope_tab << "}\n"
609 << scope_tab << "efl.Event_Cb evt_" << event_name << "_delegate;\n"
610 << scope_tab << "event EventHandler" << wrapper_args_template << " " << cls.cxx_name << "." << upper_name << "{\n")
611 .generate(sink, NULL, context))
612 return false;
613
614 if (!as_generator(
615 scope_tab << scope_tab << "add {\n"
616 << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
617 << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
618 << scope_tab << scope_tab << scope_tab << scope_tab << "if (add_cpp_event_handler(key, this.evt_" << event_name << "_delegate))\n"
619 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << upper_name << " += value;\n"
620 << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
621 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error adding proxy for event ${key}\");\n"
622 << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
623 << scope_tab << scope_tab << "}\n"
624 << scope_tab << scope_tab << "remove {\n"
625 << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
626 << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
627 << scope_tab << scope_tab << scope_tab << scope_tab << "if (remove_cpp_event_handler(key, this.evt_" << event_name << "_delegate))\n"
628 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << upper_name << " -= value;\n"
629 << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
630 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error removing proxy for event ${key}\");\n"
631 << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
632 << scope_tab << scope_tab << "}\n"
633 << scope_tab << "}\n")
634 .generate(sink, NULL, context))
635 return false;
636 }
637
638 // Inherited events
639 for (auto&& c : cls.inherits)
640 {
641 attributes::klass_def klass(get_klass(c, NULL), NULL);
642
643 // FIXME Enable inherited events registration. Beware of conflicting events
644 for (auto&& e : klass.events)
645 {
646
647 std::string wrapper_evt_name = translate_inherited_event_name(e, klass);
648 std::string upper_name = utils::to_uppercase(e.name);
649 std::replace(upper_name.begin(), upper_name.end(), ',', '_');
650 std::string upper_c_name = utils::to_uppercase(e.c_name);
651
652 std::stringstream wrapper_args_type;
653 std::string wrapper_args_template;
654 std::string event_args = "EventArgs args = EventArgs.Empty;\n";
655
656 efl::eina::optional<grammar::attributes::type_def> etype = e.type;
657 if (etype.is_engaged())
658 {
659 for (auto&& i : klass.namespaces)
660 {
661 wrapper_args_type << escape_keyword(utils::to_lowercase(i)) << ".";
662 }
663 wrapper_args_type << upper_name << "_Args";
664 wrapper_args_template = "<" + wrapper_args_type.str() + ">";
665 std::string arg_type = wrapper_args_type.str() + " args = new " + wrapper_args_type.str() + "();\n"; // = (*etype).original_type.visit(get_csharp_type_visitor{});
666 std::string actual_arg_type = (*etype).original_type.visit(get_csharp_type_visitor{});
667 arg_type += "args.arg = " + (*etype).original_type.visit(get_event_args_visitor{actual_arg_type}) + ";\n";
668 event_args = arg_type;
669 }
670 else
671 {
672 wrapper_args_type << "EventArgs";
673 }
674
675 if (!as_generator(
676 scope_tab << "protected event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << ";\n"
677 << scope_tab << "protected void On_" << wrapper_evt_name << "(" << wrapper_args_type.str() << " e)\n"
678 << scope_tab << "{\n"
679 << scope_tab << scope_tab << "EventHandler" << wrapper_args_template << " evt;\n"
680 << scope_tab << scope_tab << "lock (eventLock) {\n"
681 << scope_tab << scope_tab << scope_tab << "evt = " << wrapper_evt_name << ";\n"
682 << scope_tab << scope_tab << "}\n"
683 << scope_tab << scope_tab << "if (evt != null) { evt(this, e); }\n"
684 << scope_tab << "}\n"
685 << scope_tab << "efl.Event_Cb evt_" << wrapper_evt_name << "_delegate;\n"
686 << scope_tab << "protected void on_" << wrapper_evt_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)"
687 << scope_tab << "{\n"
688 << scope_tab << event_args
689 << scope_tab << scope_tab << "try {\n"
690 << scope_tab << scope_tab << scope_tab << "On_" << wrapper_evt_name << "(args);\n"
691 << scope_tab << scope_tab << "} catch (Exception e) {\n"
692 << scope_tab << scope_tab << scope_tab << "eina.Log.Warning(e.ToString());\n"
693 << scope_tab << scope_tab << scope_tab << "eina.Error.Set(eina.Error.EFL_ERROR);\n"
694 << scope_tab << scope_tab << "}\n"
695 << scope_tab << "}\n"
696 << scope_tab << "event EventHandler" << wrapper_args_template << " " << *(lower_case[string] << ".") << klass.cxx_name << ".")
697 .generate(sink, escape_namespace(klass.namespaces), context))
698 return false;
699 if (!as_generator(upper_name << " {\n"
700 << scope_tab << scope_tab << "add {\n"
701 << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
702 << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
703 << scope_tab << scope_tab << scope_tab << scope_tab << "if (add_cpp_event_handler(key, this.evt_" << wrapper_evt_name << "_delegate))\n"
704 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << wrapper_evt_name << " += value;\n"
705 << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
706 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error adding proxy for event ${key}\");\n"
707 << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
708 << scope_tab << scope_tab << "}\n"
709 << scope_tab << scope_tab << "remove {\n"
710 << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
711 << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
712 << scope_tab << scope_tab << scope_tab << scope_tab << "if (remove_cpp_event_handler(key, this.evt_" << wrapper_evt_name << "_delegate))\n"
713 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << wrapper_evt_name << " -= value;\n"
714 << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
715 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error removing proxy for event ${key}\");\n"
716 << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
717 << scope_tab << scope_tab << "}\n"
718 << scope_tab << "}\n")
719 .generate(sink, NULL, context))
720 return false;
721 }
722 }
723 return true;
724 }
725};
726
727struct klass const klass = {};
728
729}
730
731namespace efl { namespace eolian { namespace grammar {
732
733template <>
734struct is_eager_generator<struct ::eolian_mono::klass> : std::true_type {};
735template <>
736struct is_generator<struct ::eolian_mono::klass> : std::true_type {};
737
738namespace type_traits {
739template <>
740struct attributes_needed<struct ::eolian_mono::klass> : std::integral_constant<int, 1> {};
741}
742
743} } }
744
745#endif
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
new file mode 100644
index 0000000000..2765dcdc25
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
@@ -0,0 +1,246 @@
1#ifndef EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH
2#define EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7#include "namespace.hh"
8#include "type_impl.hh"
9
10namespace eolian_mono {
11
12namespace eina = efl::eina;
13
14namespace detail {
15
16template <typename Array, typename F, int N, typename A>
17eina::optional<bool> call_annotation_match(Array const (&array)[N], F f, A a)
18{
19 typedef Array const* iterator_type;
20 iterator_type match_iterator = &array[0], match_last = match_iterator + N;
21 match_iterator = std::find_if(match_iterator, match_last, f);
22 if(match_iterator != match_last)
23 {
24 return a(match_iterator->function());
25 }
26 return {nullptr};
27}
28
29template <typename OutputIterator, typename Context>
30struct marshall_annotation_visitor_generate
31{
32 mutable OutputIterator sink;
33 Context const* context;
34 std::string c_type;
35 bool is_out;
36 bool is_return;
37 bool is_ptr;
38
39 typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
40 typedef bool result_type;
41
42 bool operator()(attributes::regular_type_def const& regular) const
43 {
44 using attributes::regular_type_def;
45 struct match
46 {
47 eina::optional<std::string> name;
48 eina::optional<bool> has_own;
49 std::function<std::string()> function;
50 };
51 match const parameter_match_table[] =
52 {
53 // signed primitives
54 {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.I1)]"; }},
55 {"string", true, [&] {
56 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
57 }},
58 {"string", false, [&] {
59 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
60 }},
61 {"mstring", true, [&] {
62 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
63 }},
64 {"mstring", false, [&] {
65 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
66 }},
67 {"stringshare", true, [&] {
68 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
69 }},
70 {"stringshare", false, [&] {
71 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
72 }},
73 {"any_value_ptr", true, [&] {
74 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshalerOwn))]";
75 }},
76 {"any_value_ptr", false, [&] {
77 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshaler))]";
78 }},
79 };
80 match const return_match_table[] =
81 {
82 // signed primitives
83 {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.I1)]"; }},
84 {"string", true, [&] {
85 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
86 }},
87 {"string", false, [&] {
88 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
89 }},
90 {"mstring", true, [&] {
91 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
92 }},
93 {"mstring", false, [&] {
94 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
95 }},
96 {"stringshare", true, [&] {
97 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
98 }},
99 {"stringshare", false, [&] {
100 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
101 }},
102 {"any_value_ptr", true, [&] {
103 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshalerOwn))]";
104 }},
105 {"any_value_ptr", false, [&] {
106 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshaler))]";
107 }},
108 };
109
110 if(eina::optional<bool> b = call_annotation_match
111 ((is_return ? return_match_table : parameter_match_table)
112 , [&] (match const& m)
113 {
114 return (!m.name || *m.name == regular.base_type)
115 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
116 ;
117 }
118 , [&] (std::string const& string)
119 {
120 std::copy(string.begin(), string.end(), sink);
121 return true;
122 }))
123 {
124 return *b;
125 }
126 else
127 {
128 return true;
129 }
130 }
131 bool operator()(attributes::klass_name const& klass_name) const
132 {
133 const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
134 const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
135 std::vector<std::string> namespaces = escape_namespace(klass_name.namespaces);
136 return as_generator
137 ((is_return ? return_prefix : no_return_prefix)
138 << *(lower_case[string] << ".") << string
139 << "Concrete, efl.eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
140 ).generate(sink, std::make_tuple(namespaces, klass_name.eolian_name), *context);
141 }
142 bool operator()(attributes::complex_type_def const&) const
143 {
144 return true;
145 }
146};
147
148template <typename OutputIterator, typename Context>
149struct marshall_native_annotation_visitor_generate
150{
151 mutable OutputIterator sink;
152 Context const* context;
153 std::string c_type;
154 bool is_out;
155 bool is_return;
156 bool is_ptr;
157
158 typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
159 typedef bool result_type;
160
161 bool operator()(attributes::regular_type_def const& regular) const
162 {
163 using attributes::regular_type_def;
164 struct match
165 {
166 eina::optional<std::string> name;
167 eina::optional<bool> has_own;
168 std::function<std::string()> function;
169 };
170 match const parameter_match_table[] =
171 {
172 // signed primitives
173 {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.I1)]"; }},
174 {"string", true, [&] {
175 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
176 }},
177 {"string", false, [&] {
178 if (is_out)
179 return "";
180 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
181 }},
182 {"stringshare", true, [&] {
183 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
184 }},
185 {"stringshare", false, [&] {
186 if (is_out)
187 return "";
188 return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
189 }},
190 };
191 match const return_match_table[] =
192 {
193 // signed primitives
194 {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.I1)]"; }},
195 {"string", true, [&] {
196 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
197 }},
198 {"string", false, [&] { return ""; }},
199 {"stringshare", true, [&] {
200 return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
201 }},
202 {"stringshare", false, [&] { return ""; }},
203 };
204
205 if(eina::optional<bool> b = call_annotation_match
206 ((is_return ? return_match_table : parameter_match_table)
207 , [&] (match const& m)
208 {
209 return (!m.name || *m.name == regular.base_type)
210 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
211 ;
212 }
213 , [&] (std::string const& string)
214 {
215 std::copy(string.begin(), string.end(), sink);
216 return true;
217 }))
218 {
219 return *b;
220 }
221 else
222 {
223 return true;
224 }
225 }
226 bool operator()(attributes::klass_name const& klass_name) const
227 {
228 const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
229 const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
230 std::vector<std::string> namespaces = escape_namespace(klass_name.namespaces);
231 return as_generator
232 ((is_return ? return_prefix : no_return_prefix)
233 << *(lower_case[string] << ".") << string
234 << "Concrete, efl.eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
235 ).generate(sink, std::make_tuple(namespaces, klass_name.eolian_name), *context);
236 }
237 bool operator()(attributes::complex_type_def const&) const
238 {
239 return true;
240 }
241};
242
243
244} }
245
246#endif
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type.hh b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
new file mode 100644
index 0000000000..a946e15ea8
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
@@ -0,0 +1,165 @@
1#ifndef EOLIAN_MONO_MARSHALL_TYPE_HH
2#define EOLIAN_MONO_MARSHALL_TYPE_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7
8namespace eolian_mono {
9
10namespace attributes = efl::eolian::grammar::attributes;
11namespace detail {
12template <typename OutputIterator, typename Context>
13struct marshall_type_visitor_generate;
14template <typename OutputIterator, typename Context>
15struct marshall_annotation_visitor_generate;
16template <typename OutputIterator, typename Context>
17struct marshall_native_annotation_visitor_generate;
18}
19struct marshall_type_generator
20{
21 marshall_type_generator(bool is_return = false)
22 : is_return(is_return) {}
23
24 template <typename OutputIterator, typename Context>
25 bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
26 {
27 return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr });
28 }
29 template <typename OutputIterator, typename Context>
30 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
31 {
32 return param.type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
33 , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
34 }
35
36 bool is_return;
37};
38
39struct marshall_annotation_generator
40{
41 marshall_annotation_generator(bool is_return = false)
42 : is_return(is_return) {}
43
44 template <typename OutputIterator, typename Context>
45 bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
46 {
47 return type.original_type.visit(detail::marshall_annotation_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
48 }
49 template <typename OutputIterator, typename Context>
50 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
51 {
52 return param.type.original_type.visit(detail::marshall_annotation_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
53 , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
54 }
55
56 bool is_return;
57};
58
59struct marshall_native_annotation_generator
60{
61 marshall_native_annotation_generator(bool is_return = false)
62 : is_return(is_return) {}
63
64 template <typename OutputIterator, typename Context>
65 bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
66 {
67 return type.original_type.visit(detail::marshall_native_annotation_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
68 }
69 template <typename OutputIterator, typename Context>
70 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
71 {
72 return param.type.original_type.visit(detail::marshall_native_annotation_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
73 , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
74 }
75
76 bool is_return;
77};
78
79struct marshall_type_terminal
80{
81 marshall_type_generator const operator()(bool is_return) const
82 {
83 return marshall_type_generator(is_return);
84 }
85} const marshall_type = {};
86
87marshall_type_generator const as_generator(marshall_type_terminal)
88{
89 return marshall_type_generator{};
90}
91
92struct marshall_annotation_terminal
93{
94 marshall_annotation_generator const operator()(bool is_return) const
95 {
96 return marshall_annotation_generator(is_return);
97 }
98} const marshall_annotation = {};
99
100marshall_annotation_generator const as_generator(marshall_annotation_terminal)
101{
102 return marshall_annotation_generator{};
103}
104
105
106struct marshall_native_annotation_terminal
107{
108 marshall_native_annotation_generator const operator()(bool is_return) const
109 {
110 return marshall_native_annotation_generator(is_return);
111 }
112} const marshall_native_annotation = {};
113
114marshall_native_annotation_generator const as_generator(marshall_native_annotation_terminal)
115{
116 return marshall_native_annotation_generator{};
117}
118
119}
120
121namespace efl { namespace eolian { namespace grammar {
122
123template <>
124struct is_eager_generator< ::eolian_mono::marshall_type_generator> : std::true_type {};
125template <>
126struct is_generator< ::eolian_mono::marshall_type_generator> : std::true_type {};
127template <>
128struct is_generator< ::eolian_mono::marshall_type_terminal> : std::true_type {};
129
130namespace type_traits {
131template <>
132struct attributes_needed< ::eolian_mono::marshall_type_generator> : std::integral_constant<int, 1> {};
133template <>
134struct attributes_needed< ::eolian_mono::marshall_type_terminal> : std::integral_constant<int, 1> {};
135}
136
137template <>
138struct is_eager_generator< ::eolian_mono::marshall_annotation_generator> : std::true_type {};
139template <>
140struct is_generator< ::eolian_mono::marshall_annotation_generator> : std::true_type {};
141template <>
142struct is_generator< ::eolian_mono::marshall_annotation_terminal> : std::true_type {};
143
144template <>
145struct is_eager_generator< ::eolian_mono::marshall_native_annotation_generator> : std::true_type {};
146template <>
147struct is_generator< ::eolian_mono::marshall_native_annotation_generator> : std::true_type {};
148template <>
149struct is_generator< ::eolian_mono::marshall_native_annotation_terminal> : std::true_type {};
150
151namespace type_traits {
152template <>
153struct attributes_needed< ::eolian_mono::marshall_annotation_generator> : std::integral_constant<int, 1> {};
154template <>
155struct attributes_needed< ::eolian_mono::marshall_annotation_terminal> : std::integral_constant<int, 1> {};
156
157template <>
158struct attributes_needed< ::eolian_mono::marshall_native_annotation_generator> : std::integral_constant<int, 1> {};
159template <>
160struct attributes_needed< ::eolian_mono::marshall_native_annotation_terminal> : std::integral_constant<int, 1> {};
161}
162
163} } }
164
165#endif
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
new file mode 100644
index 0000000000..caeb17f83f
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
@@ -0,0 +1,263 @@
1#ifndef EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH
2#define EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7#include "namespace.hh"
8#include "type_impl.hh"
9#include "generation_contexts.hh"
10
11namespace eolian_mono {
12
13namespace eina = efl::eina;
14
15namespace detail {
16
17template <typename OutputIterator, typename Context>
18struct marshall_type_visitor_generate
19{
20 mutable OutputIterator sink;
21 Context const* context;
22 std::string c_type;
23 bool is_out;
24 bool is_return;
25 bool is_ptr;
26
27 typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
28 typedef bool result_type;
29
30 bool operator()(attributes::regular_type_def const& regular) const
31 {
32 using attributes::regular_type_def;
33 bool is_inherit_native = context_find_tag<class_context>(*context).current_wrapper_kind == class_context::inherit_native;
34
35 struct match
36 {
37 eina::optional<std::string> name;
38 eina::optional<bool> has_own;
39 std::function<attributes::type_def::variant_type()> function;
40 }
41 const match_table[] =
42 {
43 // signed primitives
44 {"string", true, [&]
45 {
46 regular_type_def r = regular;
47 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
48 // if(is_out || is_return)
49 return replace_base_type(r, " System.String");
50 // else return replace_base_type(r, " ::efl::eina::string_view");
51 }}
52 , {"string", false, [&]
53 {
54 regular_type_def r = regular;
55 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
56 if (is_inherit_native && (is_return || is_out))
57 return replace_base_type(r, " System.IntPtr");
58 return replace_base_type(r, " System.String");
59 }}
60 , {"mstring", true, [&]
61 {
62 regular_type_def r = regular;
63 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
64 // if(is_out || is_return)
65 return replace_base_type(r, " System.String");
66 // else return replace_base_type(r, " ::efl::eina::string_view");
67 }}
68 , {"mstring", false, [&]
69 {
70 regular_type_def r = regular;
71 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
72 if (is_inherit_native && (is_return || is_out))
73 return replace_base_type(r, " System.IntPtr");
74 return replace_base_type(r, " System.String");
75 }}
76 , {"stringshare", true, [&]
77 {
78 regular_type_def r = regular;
79 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
80 return replace_base_type(r, " System.String");
81 }}
82 , {"stringshare", false, [&]
83 {
84 regular_type_def r = regular;
85 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
86 if (is_inherit_native && (is_return || is_out))
87 return replace_base_type(r, " System.IntPtr");
88 else
89 return replace_base_type(r, " System.String");
90 }}
91 , {"Binbuf", true, [&]
92 {
93 regular_type_def r = regular;
94 r.base_type = " System.IntPtr";
95 r.namespaces.clear();
96 return r;
97 }}
98 , {"Binbuf", false, [&]
99 {
100 regular_type_def r = regular;
101 r.base_type = " System.IntPtr";
102 r.namespaces.clear();
103 return r;
104 }}
105 , {"any_value", true, [&]
106 {
107 regular_type_def r = regular;
108 r.namespaces.clear();
109 if (is_ptr)
110 r.base_type = " eina.Value";
111 else
112 r.base_type = " eina.Value_Native";
113 return r;
114 }}
115 , {"any_value", false, [&]
116 {
117 regular_type_def r = regular;
118 r.namespaces.clear();
119 if (is_ptr)
120 r.base_type = " eina.Value";
121 else
122 r.base_type = " eina.Value_Native";
123 return r;
124 }}
125 , {"any_value_ptr", true, [&]
126 {
127 regular_type_def r = regular;
128 r.namespaces.clear();
129 r.base_type = " eina.Value";
130 return r;
131 }}
132 , {"any_value_ptr", false, [&]
133 {
134 regular_type_def r = regular;
135 r.namespaces.clear();
136 r.base_type = " eina.Value";
137 return r;
138 }}
139 , {"void", nullptr, [&]
140 {
141 regular_type_def r = regular;
142 r.namespaces.clear();
143 if (is_out) // @inout too
144 r.base_type = " System.IntPtr";
145 else
146 r.base_type = " void";
147 return r;
148 }}
149 };
150
151 if(eina::optional<bool> b = call_match
152 (match_table
153 , [&] (match const& m)
154 {
155 return (!m.name || *m.name == regular.base_type)
156 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
157 ;
158 }
159 , [&] (attributes::type_def::variant_type const& v)
160 {
161 return v.visit(*this); // we want to keep is_out info
162 }))
163 {
164 return *b;
165 }
166 else
167 {
168 return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return}(regular);
169 }
170 }
171 bool operator()(attributes::klass_name klass_name) const
172 {
173 return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return}(klass_name);
174 // return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
175 }
176 bool operator()(attributes::complex_type_def const& complex) const
177 {
178 using attributes::regular_type_def;
179 using attributes::qualifier_info;
180 struct match
181 {
182 eina::optional<std::string> name;
183 eina::optional<bool> has_own;
184 eina::optional<bool> is_const;
185 std::function<attributes::type_def::variant_type()> function;
186 } const matches[] =
187 {
188 {"array", nullptr, nullptr, [&]
189 {
190 return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
191 }
192 }
193 ,{"inarray", nullptr, nullptr, [&]
194 {
195 return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
196 }
197 }
198 ,{"list", nullptr, nullptr, [&]
199 {
200 return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
201 }
202 }
203 ,{"inlist", nullptr, nullptr, [&]
204 {
205 return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
206 }
207 }
208 ,{"hash", nullptr, nullptr, [&]
209 {
210 return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
211 }
212 }
213 ,{"iterator", nullptr, nullptr, [&]
214 {
215 return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
216 }
217 }
218 };
219
220 auto default_match = [&] (attributes::complex_type_def const& complex)
221 {
222 regular_type_def no_pointer_regular = complex.outer;
223 // std::vector<attributes::pointer_indirection> pointers;
224 // pointers.swap(no_pointer_regular.pointers);
225 // if(is_out)
226 // pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
227 return visitor_type{sink, context, c_type, false}(no_pointer_regular)
228 && as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
229 ;
230 // && detail::generate_pointers(sink, pointers, *context, false);
231 };
232
233 if(eina::optional<bool> b = call_match
234 (matches
235 , [&] (match const& m)
236 {
237 return (!m.name || *m.name == complex.outer.base_type)
238 && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own))
239 && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const));
240 }
241 , [&] (attributes::type_def::variant_type const& v)
242 {
243 if(v.empty())
244 return true;
245 else if(attributes::complex_type_def const* complex
246 = eina::get<attributes::complex_type_def>(&v))
247 return default_match(*complex);
248 else
249 return v.visit(*this);
250 }))
251 {
252 return *b;
253 }
254
255 //return default_match(complex);
256 return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return}(complex);
257 // return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
258 }
259};
260
261} }
262
263#endif
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
new file mode 100644
index 0000000000..6b40829b20
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -0,0 +1,139 @@
1#ifndef EOLIAN_MONO_NAME_HELPERS_HH
2#define EOLIAN_MONO_NAME_HELPERS_HH
3
4#include <algorithm>
5#include <cctype>
6#include <iterator>
7#include <sstream>
8#include <string>
9#include <vector>
10
11namespace eolian_mono {
12
13namespace name_helpers {
14
15static const std::vector<std::string> verbs =
16 {
17 "add",
18 "get",
19 "is",
20 "del",
21 "thaw",
22 "freeze",
23 "save",
24 "wait",
25 "eject",
26 "raise",
27 "lower",
28 "load",
29 "dup",
30 "reset",
31 "unload",
32 "close",
33 "set",
34 "interpolate",
35 "has",
36 "grab",
37 "check",
38 "find",
39 "ungrab",
40 "unset",
41 "clear",
42 "pop",
43 "new",
44 "peek",
45 "push",
46 "update",
47 "show",
48 "move",
49 "hide",
50 "calculate",
51 "resize",
52 "attach",
53 "pack",
54 "unpack",
55 "emit",
56 "call",
57 "append"
58 };
59
60const std::vector<std::string> not_verbs =
61 {
62 "below",
63 "above",
64 "name",
65 "unfreezable",
66 "value",
67 "r",
68 "g",
69 "b",
70 "a",
71 "finalize",
72 "destructor",
73 "to",
74 "circle",
75 "rect",
76 "path",
77 "commands",
78 "type",
79 "colorspace"
80 "op",
81 "type",
82 "properties",
83 "status",
84 "status",
85 "relative",
86 "ptr",
87 "pair",
88 "pos",
89 "end"
90 };
91
92void reorder_verb(std::vector<std::string> &names)
93{
94 if (names.size() <= 1)
95 return;
96
97 std::string verb = names.back();
98
99 if (std::find(verbs.begin(), verbs.end(), verb) != verbs.end())
100 {
101 names.pop_back();
102 names.insert(names.begin(), verb);
103 }
104}
105
106std::vector<std::string> split(std::string const &input, char delim)
107{
108 std::stringstream ss(input);
109 std::string name;
110 std::vector<std::string> names;
111
112 while (std::getline(ss, name, delim)) {
113 if (!name.empty())
114 names.push_back(name);
115 }
116 return names;
117}
118
119std::string pascal_case(const std::vector<std::string> &names)
120{
121 std::vector<std::string> outv(names.size());
122 std::stringstream osstream;
123
124 std::transform(names.begin(), names.end(), outv.begin(),
125 [](std::string name) {
126 name[0] = std::toupper(name[0]);
127 return name;
128 });
129
130 std::copy(outv.begin(), outv.end(), std::ostream_iterator<std::string>(osstream, ""));
131
132 return osstream.str();
133}
134
135} // namespace name_helpers
136
137} // namespace eolian_mono
138
139#endif
diff --git a/src/bin/eolian_mono/eolian/mono/namespace.hh b/src/bin/eolian_mono/eolian/mono/namespace.hh
new file mode 100644
index 0000000000..b0f1ddb0b3
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/namespace.hh
@@ -0,0 +1,27 @@
1#ifndef EOLIAN_MONO_NAMESPACE_HH
2#define EOLIAN_MONO_NAMESPACE_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7#include "grammar/type.hpp"
8#include "using_decl.hh"
9#include "keyword.hh"
10
11namespace eolian_mono {
12
13std::vector<std::string> escape_namespace(std::vector<std::string> namespaces)
14{
15 // if(namespaces.empty())
16 // namespaces.push_back("nonamespace");
17 // else
18 {
19 for(auto&& i : namespaces)
20 i = escape_keyword(i);
21 }
22 return namespaces;
23}
24
25}
26
27#endif
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
new file mode 100644
index 0000000000..dcbb0a44d5
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -0,0 +1,1171 @@
1#ifndef EOLIAN_MONO_PARAMETER_HH
2#define EOLIAN_MONO_PARAMETER_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7#include "marshall_type.hh"
8#include "type.hh"
9#include "using_decl.hh"
10#include "keyword.hh"
11
12
13namespace eolian_mono {
14 struct parameter_generator;
15 struct marshall_parameter_generator;
16 struct argument_generator;
17 struct argument_invocation_generator;
18 struct native_argument_invocation_generator;
19 struct native_convert_in_variable_generator;
20 struct convert_in_variable_generator;
21 struct native_convert_out_variable_generator;
22 struct convert_out_variable_generator;
23 struct convert_out_assign_generator;
24 struct native_convert_out_assign_parameterized;
25 struct native_convert_out_assign_generator;
26 struct convert_return_generator;
27 struct convert_return_variable_generator;
28 struct native_convert_return_generator;
29 struct native_convert_return_parameterized;
30 struct native_convert_return_variable_generator;
31 struct convert_function_pointer_generator;
32 struct native_convert_function_pointer_generator;
33}
34
35namespace efl { namespace eolian { namespace grammar {
36
37template <>
38struct is_eager_generator< ::eolian_mono::parameter_generator> : std::true_type {};
39template <>
40struct is_generator< ::eolian_mono::parameter_generator> : std::true_type {};
41
42namespace type_traits {
43template <>
44struct attributes_needed< ::eolian_mono::parameter_generator> : std::integral_constant<int, 1> {};
45}
46
47template <>
48struct is_eager_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {};
49template <>
50struct is_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {};
51
52namespace type_traits {
53template <>
54struct attributes_needed< ::eolian_mono::marshall_parameter_generator> : std::integral_constant<int, 1> {};
55}
56
57template <>
58struct is_eager_generator< ::eolian_mono::argument_generator> : std::true_type {};
59template <>
60struct is_generator< ::eolian_mono::argument_generator> : std::true_type {};
61
62namespace type_traits {
63template <>
64struct attributes_needed< ::eolian_mono::argument_generator> : std::integral_constant<int, 1> {};
65}
66
67template <>
68struct is_eager_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
69template <>
70struct is_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
71
72namespace type_traits {
73template <>
74struct attributes_needed< ::eolian_mono::argument_invocation_generator> : std::integral_constant<int, 1> {};
75}
76
77template <>
78struct is_eager_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {};
79template <>
80struct is_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {};
81
82namespace type_traits {
83template <>
84struct attributes_needed< ::eolian_mono::native_argument_invocation_generator> : std::integral_constant<int, 1> {};
85}
86
87template <>
88struct is_eager_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
89template <>
90struct is_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
91
92namespace type_traits {
93template <>
94struct attributes_needed< ::eolian_mono::native_convert_in_variable_generator> : std::integral_constant<int, 1> {};
95}
96
97template <>
98struct is_eager_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {};
99template <>
100struct is_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {};
101
102namespace type_traits {
103template <>
104struct attributes_needed< ::eolian_mono::convert_in_variable_generator> : std::integral_constant<int, 1> {};
105}
106
107template <>
108struct is_eager_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {};
109template <>
110struct is_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {};
111
112namespace type_traits {
113template <>
114struct attributes_needed< ::eolian_mono::convert_out_variable_generator> : std::integral_constant<int, 1> {};
115}
116
117template <>
118struct is_eager_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {};
119template <>
120struct is_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {};
121
122namespace type_traits {
123template <>
124struct attributes_needed< ::eolian_mono::native_convert_out_variable_generator> : std::integral_constant<int, 1> {};
125}
126
127template <>
128struct is_eager_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {};
129template <>
130struct is_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {};
131
132namespace type_traits {
133template <>
134struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::integral_constant<int, 1> {};
135}
136
137template <>
138struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
139template <>
140struct is_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
141
142namespace type_traits {
143template <>
144struct attributes_needed< ::eolian_mono::convert_return_variable_generator> : std::integral_constant<int, 1> {};
145}
146
147template <>
148struct is_eager_generator< ::eolian_mono::convert_return_generator> : std::true_type {};
149template <>
150struct is_generator< ::eolian_mono::convert_return_generator> : std::true_type {};
151
152namespace type_traits {
153template <>
154struct attributes_needed< ::eolian_mono::convert_return_generator> : std::integral_constant<int, 1> {};
155}
156
157template <>
158struct is_eager_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {};
159template <>
160struct is_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {};
161template <>
162struct is_generator< ::eolian_mono::native_convert_out_assign_parameterized> : std::true_type {};
163
164namespace type_traits {
165template <>
166struct attributes_needed< ::eolian_mono::native_convert_out_assign_generator> : std::integral_constant<int, 1> {};
167}
168
169template <>
170struct is_eager_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {};
171template <>
172struct is_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {};
173
174namespace type_traits {
175template <>
176struct attributes_needed< ::eolian_mono::native_convert_return_variable_generator> : std::integral_constant<int, 1> {};
177}
178
179template <>
180struct is_eager_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {};
181template <>
182struct is_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {};
183template <>
184struct is_generator< ::eolian_mono::native_convert_return_parameterized> : std::true_type {};
185
186namespace type_traits {
187template <>
188struct attributes_needed< ::eolian_mono::native_convert_return_generator> : std::integral_constant<int, 1> {};
189}
190
191template <>
192struct is_eager_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {};
193template <>
194struct is_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {};
195
196namespace type_traits {
197template <>
198struct attributes_needed< ::eolian_mono::convert_function_pointer_generator> : std::integral_constant<int, 1> {};
199}
200
201template <>
202struct is_eager_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {};
203template <>
204struct is_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {};
205
206namespace type_traits {
207template <>
208struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {};
209}
210
211} } }
212
213namespace eolian_mono {
214
215namespace attributes = efl::eolian::grammar::attributes;
216
217// Helper function to query parameter attributes
218const static bool WANT_OWN = true;
219const static bool WANT_OUT = true;
220inline bool param_is_acceptable(attributes::parameter_def const &param, std::string c_type, bool want_own, bool want_out)
221{
222 return (param.type.c_type == c_type)
223 && ((param.direction != attributes::parameter_direction::in) == want_out)
224 && (param.type.has_own == want_own);
225}
226
227inline bool param_should_use_out_var(attributes::parameter_def const& param, bool native)
228{
229 if ((native && param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT))
230 || (native && param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
231 || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
232 || param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
233 || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
234 || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
235 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
236 || param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
237 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
238 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
239 || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
240 || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
241 || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
242 || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
243 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
244 || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
245 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
246 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
247 || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
248 || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
249 || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
250 || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
251 || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
252 || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
253 || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
254 || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
255 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
256 || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
257 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
258 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
259 || param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
260 || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT)
261 )
262 return true;
263
264 return false;
265}
266
267inline bool param_should_use_in_var(attributes::parameter_def const& param, bool /*native*/)
268{
269 if (param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, !WANT_OUT)
270 || param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, !WANT_OUT)
271 || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, !WANT_OUT)
272 || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, !WANT_OUT)
273 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, !WANT_OUT)
274 || param_is_acceptable(param, "Eina_Array *", WANT_OWN, !WANT_OUT)
275 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, !WANT_OUT)
276 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, !WANT_OUT)
277 || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, !WANT_OUT)
278 || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, !WANT_OUT)
279 || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, !WANT_OUT)
280 || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, !WANT_OUT)
281 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, !WANT_OUT)
282 || param_is_acceptable(param, "Eina_List *", WANT_OWN, !WANT_OUT)
283 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, !WANT_OUT)
284 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, !WANT_OUT)
285 || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, !WANT_OUT)
286 || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, !WANT_OUT)
287 || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, !WANT_OUT)
288 || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, !WANT_OUT)
289 || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, !WANT_OUT)
290 || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, !WANT_OUT)
291 || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, !WANT_OUT)
292 || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, !WANT_OUT)
293 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, !WANT_OUT)
294 || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, !WANT_OUT)
295 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, !WANT_OUT)
296 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, !WANT_OUT)
297 || param_is_acceptable(param, "Eina_Value", WANT_OWN, !WANT_OUT)
298 || param_is_acceptable(param, "Eina_Value", !WANT_OWN, !WANT_OUT)
299 )
300 return true;
301
302 return false;
303}
304
305inline std::string out_variable_name(std::string const& param_name)
306{
307 return "_out_" + escape_keyword(param_name);
308}
309
310inline std::string in_variable_name(std::string const& param_name)
311{
312 return "_in_" + escape_keyword(param_name);
313}
314
315inline std::string direction_modifier(attributes::parameter_def const& param)
316{
317 if (param.direction == attributes::parameter_direction::inout)
318 {
319 return " ref ";
320 }
321 else if (param.direction != attributes::parameter_direction::in)
322 {
323 if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice")
324 return " ref ";
325 else
326 return " out ";
327 }
328 return " ";
329}
330
331struct is_fp_visitor
332{
333 typedef is_fp_visitor visitor_type;
334 typedef bool result_type;
335
336 bool operator()(grammar::attributes::regular_type_def const &type) const
337 {
338 return type.is_function_ptr;
339 }
340
341 template<typename T>
342 bool operator()(T const &) const
343 {
344 return false;
345 }
346};
347
348struct type_name_visitor
349{
350 typedef type_name_visitor visitor_type;
351 typedef std::string result_type;
352
353 std::string operator()(grammar::attributes::regular_type_def const &type) const
354 {
355 std::stringstream type_name;
356 for (auto&& i : escape_namespace(type.namespaces))
357 type_name << i << ".";
358 type_name << type.base_type;
359 return type_name.str();
360 }
361
362 template<typename T>
363 std::string operator()(T const &) const
364 {
365 return "";
366 }
367};
368
369struct parameter_generator
370{
371 template <typename OutputIterator, typename Context>
372 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
373 {
374 std::string param_name = escape_keyword(param.param_name);
375
376 return as_generator(
377 direction_modifier(param) << type << " " << string
378 ).generate(sink, std::make_tuple(param, param_name), context);
379
380 }
381} const parameter {};
382
383struct marshall_parameter_generator
384{
385 template <typename OutputIterator, typename Context>
386 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
387 {
388 std::string param_name = escape_keyword(param.param_name);
389
390 if (!param.type.original_type.visit(is_fp_visitor{}))
391 return as_generator(
392 direction_modifier(param) << marshall_type << " " << string
393 ).generate(sink, std::make_tuple(param, param_name), context);
394
395 return as_generator(
396 "IntPtr " << param_name << "_data, " << type << "Internal " << param_name << ", Eina_Free_Cb "
397 << param_name << "_free_cb"
398 ).generate(sink, param, context);
399 }
400} const marshall_parameter {};
401
402struct argument_generator
403{
404 template <typename OutputIterator, typename Context>
405 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
406 {
407 std::string param_name = escape_keyword(param.param_name);
408 std::string direction = direction_modifier(param);
409
410 if (!param.type.original_type.visit(is_fp_visitor{}))
411 return as_generator(
412 direction << param_name
413 ).generate(sink, attributes::unused, context);
414
415 return as_generator(
416 param_name << "_data, " << param_name << ", " << param_name << "_free_cb"
417 ).generate(sink, attributes::unused, context);
418
419 }
420
421} const argument {};
422
423struct native_argument_invocation_generator
424{
425 template <typename OutputIterator, typename Context>
426 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
427 {
428 std::string arg = direction_modifier(param);
429
430 if (param_should_use_out_var(param, true))
431 arg += out_variable_name(param.param_name);
432 else if (param_should_use_in_var(param, true))
433 arg += in_variable_name(param.param_name);
434 else if (param.type.original_type.visit(is_fp_visitor{}))
435 {
436 arg += escape_keyword(param.param_name) + "_wrapper.ManagedCb";
437 }
438 else // FIXME Wrap data and C function pointers into some kind of structure.
439 arg += escape_keyword(param.param_name);
440
441 return as_generator(arg).generate(sink, attributes::unused, context);
442 }
443} const native_argument_invocation {};
444
445// Generates the correct parameter name when invoking a function
446struct argument_invocation_generator
447{
448 template <typename OutputIterator, typename Context>
449 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
450 {
451 std::string arg = direction_modifier(param);
452
453 if (param_should_use_out_var(param, false))
454 arg += out_variable_name(param.param_name);
455 else if (param_should_use_in_var(param, false))
456 arg += in_variable_name(param.param_name);
457 else if (param.type.original_type.visit(is_fp_visitor{}))
458 {
459 std::string param_name = escape_keyword(param.param_name);
460 return as_generator("GCHandle.ToIntPtr(" << param_name << "_handle), " << type << "Wrapper.Cb, efl.eo.Globals.free_gchandle")
461 .generate(sink, param.type, context);
462 }
463 else
464 arg += escape_keyword(param.param_name);
465
466 return as_generator(arg).generate(sink, attributes::unused, context);
467 }
468} const argument_invocation {};
469
470struct native_convert_in_variable_generator
471{
472 template <typename OutputIterator, typename Context>
473 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
474 {
475 if (param.direction != attributes::parameter_direction::in)
476 return true;
477
478 if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
479 {
480 return as_generator(
481 "var " << string << " = new eina.Binbuf(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
482 ).generate(sink, in_variable_name(param.param_name), context);
483 }
484 else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *")
485 {
486 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
487 if (!complex || complex->subtypes.size() != 2)
488 return false;
489 return as_generator(
490 "var " << string << " = new " << type << "(" << escape_keyword(param.param_name)
491 << ", " << (param.type.has_own ? "true" : "false")
492 << ", " << (complex->subtypes.front().has_own ? "true" : "false")
493 << ", " << (complex->subtypes.back().has_own ? "true" : "false")
494 << ");\n"
495 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
496 }
497 else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *"
498 || param.type.c_type == "Eina_Inarray *" || param.type.c_type == "const Eina_Inarray *"
499 || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
500 || param.type.c_type == "Eina_Inlist *" || param.type.c_type == "const Eina_Inlist *"
501 || param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *"
502 )
503 {
504 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
505 if (!complex)
506 return false;
507 return as_generator(
508 "var " << string << " = new " << type << "(" << escape_keyword(param.param_name)
509 << ", " << (param.type.has_own ? "true" : "false")
510 << ", " << (complex->subtypes.front().has_own ? "true" : "false")
511 << ");\n"
512 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
513 }
514 else if (param.type.c_type == "Eina_Value")
515 {
516 return as_generator(
517 "var " << string << " = new " << type << "(" << string << ");\n"
518 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type, param.param_name), context);
519 }
520 return true;
521 }
522
523} const native_convert_in_variable {};
524
525struct convert_in_variable_generator
526{
527 template <typename OutputIterator, typename Context>
528 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
529 {
530 if (param.direction != attributes::parameter_direction::in)
531 return true;
532
533 if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
534 {
535 auto var_name = in_variable_name(param.param_name);
536 if (!as_generator(
537 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
538 ).generate(sink, var_name, context))
539 return false;
540 if (param.type.has_own)
541 {
542 return as_generator(
543 escape_keyword(param.param_name) << ".Own = false;\n"
544 ).generate(sink, attributes::unused, context);
545 }
546 }
547 else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *")
548 {
549 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
550 if (!complex || complex->subtypes.size() != 2)
551 return false;
552 auto var_name = in_variable_name(param.param_name);
553 if (!as_generator(
554 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
555 ).generate(sink, var_name, context))
556 return false;
557 if (param.type.has_own && !as_generator(
558 escape_keyword(param.param_name) << ".SetOwn(false);\n"
559 ).generate(sink, attributes::unused, context))
560 return false;
561 if (complex->subtypes.front().has_own && !as_generator(
562 escape_keyword(param.param_name) << ".SetOwnKey(false);\n"
563 ).generate(sink, attributes::unused, context))
564 return false;
565 if (complex->subtypes.back().has_own && !as_generator(
566 escape_keyword(param.param_name) << ".SetOwnValue(false);\n"
567 << escape_keyword(param.param_name) << ".UnSetFreeCb();\n"
568 ).generate(sink, attributes::unused, context))
569 return false;
570 }
571 else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *"
572 || param.type.c_type == "Eina_Inarray *" || param.type.c_type == "const Eina_Inarray *"
573 || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
574 || param.type.c_type == "Eina_Inlist *" || param.type.c_type == "const Eina_Inlist *"
575 || param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *"
576 )
577 {
578 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
579 if (!complex)
580 return false;
581 auto var_name = in_variable_name(param.param_name);
582 if (!as_generator(
583 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
584 ).generate(sink, var_name, context))
585 return false;
586 if (param.type.has_own && !as_generator(
587 escape_keyword(param.param_name) << ".Own = false;\n"
588 ).generate(sink, attributes::unused, context))
589 return false;
590 if (complex->subtypes.front().has_own && !as_generator(
591 escape_keyword(param.param_name) << ".OwnContent = false;\n"
592 ).generate(sink, attributes::unused, context))
593 return false;
594 }
595 else if (param.type.c_type == "Eina_Value")
596 {
597 return as_generator(
598 "var " << string << " = " << string << ".GetNative();\n"
599 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.param_name), context);
600 }
601 return true;
602 }
603
604} const convert_in_variable {};
605
606struct convert_out_variable_generator
607{
608 template <typename OutputIterator, typename Context>
609 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
610 {
611 if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
612 || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
613 || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
614 || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
615 )
616 {
617 return as_generator(
618 "System.IntPtr " << string << " = System.IntPtr.Zero;\n"
619 ).generate(sink, out_variable_name(param.param_name), context);
620 }
621 else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
622 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
623 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
624 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
625 || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
626 || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
627 || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
628 || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
629 || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
630 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
631 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
632 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
633 || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
634 || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
635 || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
636 || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
637 || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
638 || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
639 || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
640 || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
641 || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
642 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
643 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
644 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
645 )
646 {
647 return as_generator(
648 "System.IntPtr " << string << " = System.IntPtr.Zero;\n"
649 ).generate(sink, out_variable_name(param.param_name), context);
650 }
651 else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
652 || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
653 {
654 return as_generator(
655 marshall_type << " " << string << ";\n"
656 ).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name)), context);
657 }
658 return true;
659 }
660
661} const convert_out_variable {};
662
663struct native_convert_out_variable_generator
664{
665 template <typename OutputIterator, typename Context>
666 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
667 {
668 if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT)
669 || param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
670 {
671 return as_generator(
672 type << " " << string << " = default(" << type << ");\n"
673 ).generate(sink, std::make_tuple(param, out_variable_name(param.param_name), param), context);
674 }
675 else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
676 || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
677 || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
678 || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
679 )
680 {
681 return as_generator(
682 "eina.Binbuf " << string << " = default(eina.Binbuf);\n"
683 ).generate(sink, out_variable_name(param.param_name), context);
684 }
685 else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
686 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
687 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
688 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
689 || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
690 || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
691 || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
692 || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
693 || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
694 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
695 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
696 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
697 || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
698 || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
699 || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
700 || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
701 || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
702 || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
703 || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
704 || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
705 || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
706 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
707 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
708 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
709 )
710 {
711 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
712 if (!complex)
713 return false;
714 return as_generator(
715 type << " " << string << " = default(" << type << ");\n"
716 ).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name), param.type), context);
717 }
718 else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
719 || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
720 {
721 return as_generator(
722 string << " = default(" << marshall_type << ");\n"
723 << type << " " << string << " = null;\n"
724 ).generate(sink, std::make_tuple(param.param_name, param, param, out_variable_name(param.param_name)), context);
725 }
726 else if (param.direction == attributes::parameter_direction::out)
727 {
728 // Assign a default value to the out variable in case we end up in the catch clause.
729 return as_generator(
730 string << " = default(" << type << ");"
731 ).generate(sink, std::make_tuple(param.param_name, param), context);
732 }
733 return true;
734 }
735
736} const native_convert_out_variable {};
737
738struct convert_out_assign_generator
739{
740 template <typename OutputIterator, typename Context>
741 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
742 {
743 if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
744 || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
745 || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
746 || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
747 )
748 {
749 return as_generator(
750 string << " = new eina.Binbuf(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n"
751 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
752 }
753 else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
754 || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
755 || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
756 || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
757 )
758 {
759 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
760 if (!complex || complex->subtypes.size() != 2)
761 return false;
762 return as_generator(
763 string << " = new " << type << "(" << string
764 << ", " << (param.type.has_own ? "true" : "false")
765 << ", " << (complex->subtypes.front().has_own ? "true" : "false")
766 << ", " << (complex->subtypes.back().has_own ? "true" : "false")
767 << ");\n"
768 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
769 }
770 else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
771 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
772 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
773 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
774 || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
775 || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
776 || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
777 || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
778 || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
779 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
780 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
781 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
782 || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
783 || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
784 || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
785 || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
786 || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
787 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
788 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
789 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
790 )
791 {
792 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
793 if (!complex)
794 return false;
795 return as_generator(
796 string << " = new " << type << "(" << string
797 << ", " << (param.type.has_own ? "true" : "false")
798 << ", " << (complex->subtypes.front().has_own ? "true" : "false")
799 << ");\n"
800 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
801 }
802 else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
803 || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
804 {
805 return as_generator(
806 string << " = new " << type << "(" << string << ");\n"
807 ).generate(sink, std::make_tuple(param.param_name, param.type, out_variable_name(param.param_name)), context);
808 }
809 return true;
810 }
811
812} const convert_out_assign {};
813
814struct convert_return_variable_generator
815{
816 template <typename OutputIterator, typename Context>
817 bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
818 {
819 if (ret_type.c_type != "void")
820 return as_generator("var _ret_var = ").generate(sink, attributes::unused, context);
821 return true;
822 }
823
824} const convert_return_variable {};
825
826
827struct convert_return_generator
828{
829 template <typename OutputIterator, typename Context>
830 bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
831 {
832 if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *")
833 {
834 if (!as_generator("var _binbuf_ret = new eina.Binbuf(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ");\n"
835 << scope_tab << scope_tab << "return _binbuf_ret;\n")
836 .generate(sink, attributes::unused, context))
837 return false;
838 }
839 else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *")
840 {
841 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
842 if (!complex || complex->subtypes.size() != 2)
843 return false;
844 if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"}
845 << ", " << (complex->subtypes.front().has_own ? "true" : "false")
846 << ", " << (complex->subtypes.back().has_own ? "true" : "false")
847 << ");\n")
848 .generate(sink, ret_type, context))
849 return false;
850 }
851 else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *"
852 || ret_type.c_type == "Eina_Inarray *" || ret_type.c_type == "const Eina_Inarray *"
853 || ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *"
854 || ret_type.c_type == "Eina_Inlist *" || ret_type.c_type == "const Eina_Inlist *"
855 || ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *"
856 )
857 {
858 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
859 if (!complex)
860 return false;
861 if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"}
862 << ", " << (complex->subtypes.front().has_own ? "true" : "false")
863 << ");\n")
864 .generate(sink, ret_type, context))
865 return false;
866 }
867 else if (ret_type.c_type != "void")
868 {
869 return as_generator("return _ret_var;\n").generate(sink, ret_type, context);
870 }
871 return true;
872 }
873
874} const convert_return {};
875
876// Native (virtual wrappers) generators
877struct native_convert_out_assign_generator
878{
879 attributes::klass_def const* klass;
880
881 template <typename OutputIterator, typename Context>
882 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
883 {
884 if (param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
885 {
886 return as_generator(
887 string << "= efl.eo.Globals.cached_stringshare_to_intptr(((" << string << "Inherit)wrapper).cached_stringshares, " << string << ");\n"
888 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), klass->cxx_name, out_variable_name(param.param_name)), context);