summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono/eolian/mono/klass.hh
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/eolian_mono/eolian/mono/klass.hh
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/eolian_mono/eolian/mono/klass.hh')
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh745
1 files changed, 745 insertions, 0 deletions
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