summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2019-02-01 14:03:02 -0500
committerChristopher Michael <cp.michael@samsung.com>2019-02-01 14:03:02 -0500
commit0223bb29dfc4c1621ace044395196064c82b98de (patch)
treefc42c91c0461472391960afd14f232f941911f02 /src/bin/eolian_mono
parente4144504048ff2c9a3c1787b82c73a54e8d209a7 (diff)
eolian-mono: Provide constructor parameters based on the constructors
section of the Eo files. Reviewers: woohyun, segfaultxavi, bu5hm4n, felipealmeida Reviewed By: segfaultxavi Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D7789
Diffstat (limited to 'src/bin/eolian_mono')
-rw-r--r--src/bin/eolian_mono/eolian/mono/documentation.hh48
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh6
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh63
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh11
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh120
-rw-r--r--src/bin/eolian_mono/eolian/mono/type.hh14
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_impl.hh72
7 files changed, 291 insertions, 43 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh
index 3acec94..d2f4669 100644
--- a/src/bin/eolian_mono/eolian/mono/documentation.hh
+++ b/src/bin/eolian_mono/eolian/mono/documentation.hh
@@ -84,6 +84,29 @@ struct documentation_generator
84 return name; 84 return name;
85 } 85 }
86 86
87 static std::string function_conversion(attributes::function_def const& func)
88 {
89 attributes::klass_def klass(get_klass(func.klass, func.unit), func.unit);
90 std::string name = name_helpers::klass_full_concrete_or_interface_name(klass);
91 switch (func.type)
92 {
93 // managed_method_name takes care of reordering the function name so the get/set goes first
94 // for properties
95 case attributes::function_type::method:
96 case attributes::function_type::prop_set:
97 case attributes::function_type::prop_get:
98 if (blacklist::is_function_blacklisted(func.c_name))return "";
99 name += ".";
100 name += name_helpers::managed_method_name(klass.eolian_name, func.name);
101 break;
102 default:
103 // No need to deal with property as function_defs are converted to get/set when building a given klass_def.
104 break;
105 }
106
107 return name;
108 }
109
87 // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag 110 // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
88 static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail) 111 static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail)
89 { 112 {
@@ -299,6 +322,31 @@ struct documentation_generator
299 { 322 {
300 return generate_tag_summary(sink, doc.full_text, context); 323 return generate_tag_summary(sink, doc.full_text, context);
301 } 324 }
325
326 template<typename OutputIterator, typename Context>
327 bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const
328 {
329 // Not sure if this is the best way to generate a reference outside the full doc generator.
330 auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
331 auto func = ctor.function;
332 auto eolian_klass = get_klass(func.klass, unit);
333 attributes::klass_def klass(eolian_klass, unit);
334 std::string summary;
335
336 if (func.type == attributes::function_type::prop_set)
337 summary = func.property_documentation.summary;
338 else
339 summary = func.documentation.summary;
340
341 for (auto &&param : ctor.function.parameters)
342 {
343 if (!as_generator(
344 scope_tab << "///<param name=\"" << constructor_parameter_name(ctor) << "\">" << summary << " See <see cref=\"" << function_conversion(func) << "\"/></param>\n"
345 ).generate(sink, param, context))
346 return false;
347 }
348 return true;
349 }
302}; 350};
303 351
304struct documentation_terminal 352struct documentation_terminal
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh
index ed72345..87a1e9d 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -221,6 +221,12 @@ inline bool is_unique_event(attributes::event_def const& evt
221 }); 221 });
222} 222}
223 223
224inline std::vector<attributes::constructor_def> reorder_constructors(std::vector<attributes::constructor_def> constructors)
225{
226 auto is_required = [](attributes::constructor_def const& ctr) { return !ctr.is_optional; };
227 std::stable_partition(constructors.begin(), constructors.end(), is_required);
228 return constructors;
229}
224 230
225} // namespace helpers 231} // namespace helpers
226 232
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 6a2c818..d8f2e7e 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -220,15 +220,16 @@ struct klass
220 if (!generate_fields(sink, cls, concrete_cxt)) 220 if (!generate_fields(sink, cls, concrete_cxt))
221 return false; 221 return false;
222 222
223 bool root = !helpers::has_regular_ancestor(cls);
223 if (!as_generator 224 if (!as_generator
224 ( 225 (
225 scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename) 226 scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
226 << ")] internal static extern System.IntPtr\n" 227 << ")] internal static extern System.IntPtr\n"
227 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n" 228 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
228 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n" 229 << scope_tab << "///<summary>Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n"
229 << scope_tab << "public " << concrete_name << "(System.IntPtr raw)\n" 230 << scope_tab << "public " << concrete_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
230 << scope_tab << "{\n" 231 << scope_tab << "{\n"
231 << scope_tab << scope_tab << "handle = raw;\n" 232 << scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
232 << scope_tab << scope_tab << "register_event_proxies();\n" 233 << scope_tab << scope_tab << "register_event_proxies();\n"
233 << scope_tab << "}\n" 234 << scope_tab << "}\n"
234 ) 235 )
@@ -503,48 +504,44 @@ struct klass
503 ).generate(sink, attributes::unused, context)) 504 ).generate(sink, attributes::unused, context))
504 return false; 505 return false;
505 506
507 auto constructors = helpers::reorder_constructors(cls.get_all_constructors());
506 508
507 if (!root) 509 // Public (API) constructors
508 { 510 if (!as_generator(
509 return as_generator(
510 scope_tab << "///<summary>Creates a new instance.</summary>\n" 511 scope_tab << "///<summary>Creates a new instance.</summary>\n"
511 << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n" 512 << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
512 << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n" 513 << *(documentation)
513 << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : " 514 // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters.
514 "base(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n" 515 << scope_tab << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null") << "\n"
516 << scope_tab << scope_tab << scope_tab << *(", " << constructor_param ) << ") :\n"
517 << scope_tab << scope_tab << (root ? "this" : "base") << "(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
515 << scope_tab << "{\n" 518 << scope_tab << "{\n"
516 << scope_tab << scope_tab << "if (init_cb != null) {\n" 519 << *(scope_tab << scope_tab << constructor_invocation << "\n" )
517 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
518 << scope_tab << scope_tab << "}\n"
519 << scope_tab << scope_tab << "FinishInstantiation();\n" 520 << scope_tab << scope_tab << "FinishInstantiation();\n"
520 << scope_tab << "}\n" 521 << scope_tab << "}\n"
521 522 << scope_tab << "///<summary>Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n"
522 << scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</summary>\n"
523 << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(klass_name, base_klass, managed_type, parent) {}\n"
524
525 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
526 << scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n" 523 << scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
527 << scope_tab << "{\n" 524 << scope_tab << "{\n"
528 << scope_tab << scope_tab << (root ? "handle = raw;\n" : "") 525 << scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
529 << scope_tab << scope_tab << "register_event_proxies();\n" 526 << scope_tab << scope_tab << "register_event_proxies();\n"
530 << scope_tab << "}\n" 527 << scope_tab << "}\n"
528 ).generate(sink, std::make_tuple(constructors, constructors, constructors), context))
529 return false;
530
531 // Internal constructors
532 if (!root)
533 {
534 return as_generator(
535 scope_tab << "///<summary>Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.</summary>\n"
536 << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(klass_name, base_klass, managed_type, parent) {}\n"
531 ).generate(sink, attributes::unused, context); 537 ).generate(sink, attributes::unused, context);
532 } 538
539 }
533 540
534 // Detailed constructors go only in root classes. 541 // Detailed constructors go only in root classes.
535 return as_generator( 542 return as_generator(
536 scope_tab << "///<summary>Creates a new instance.</summary>\n" 543 /// Actual root costructor that creates class and instantiates
537 << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n" 544 scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
538 << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
539 << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
540 << scope_tab << "{\n"
541 << scope_tab << scope_tab << "if (init_cb != null) {\n"
542 << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
543 << scope_tab << scope_tab << "}\n"
544 << scope_tab << scope_tab << "FinishInstantiation();\n"
545 << scope_tab << "}\n"
546
547 << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
548 << scope_tab << "{\n" 545 << scope_tab << "{\n"
549 << scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n" 546 << scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n"
550 << scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n" 547 << scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n"
@@ -574,12 +571,6 @@ struct klass
574 << scope_tab << scope_tab << "Eina.Error.RaiseIfUnhandledException();\n" 571 << scope_tab << scope_tab << "Eina.Error.RaiseIfUnhandledException();\n"
575 << scope_tab << "}\n" 572 << scope_tab << "}\n"
576 573
577 << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
578 << scope_tab << "public " << inherit_name << "(System.IntPtr raw)\n"
579 << scope_tab << "{\n"
580 << scope_tab << scope_tab << "handle = raw;\n"
581 << scope_tab << scope_tab << "register_event_proxies();\n"
582 << scope_tab << "}\n"
583 ).generate(sink, attributes::unused, context); 574 ).generate(sink, attributes::unused, context);
584 } 575 }
585 576
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index 8910447..ccbbfce 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -187,6 +187,12 @@ inline std::string managed_method_name(std::string const& klass, std::string con
187 return candidate; 187 return candidate;
188} 188}
189 189
190inline std::string managed_name(std::string const& name, char separator='_')
191{
192 auto tokens = utils::split(name, separator);
193 return utils::to_pascal_case(tokens);
194}
195
190inline std::string managed_method_name(attributes::function_def const& f) 196inline std::string managed_method_name(attributes::function_def const& f)
191{ 197{
192 return managed_method_name(f.klass.eolian_name, f.name); 198 return managed_method_name(f.klass.eolian_name, f.name);
@@ -420,7 +426,12 @@ bool close_namespaces(OutputIterator sink, std::vector<std::string> const& names
420 return as_generator(close_namespace).generate(sink, namespaces, context); 426 return as_generator(close_namespace).generate(sink, namespaces, context);
421} 427}
422 428
429std::string constructor_managed_name(std::string full_name)
430{
431 auto tokens = utils::split(full_name, '.');
423 432
433 return managed_name(tokens.at(tokens.size()-1));
434}
424 435
425} // namespace name_helpers 436} // namespace name_helpers
426 437
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
index 416cacb..efb907f 100644
--- a/src/bin/eolian_mono/eolian/mono/parameter.hh
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -3,6 +3,7 @@
3 3
4#include "grammar/generator.hpp" 4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp" 5#include "grammar/klass_def.hpp"
6#include "grammar/attribute_reorder.hpp"
6#include "grammar/case.hpp" 7#include "grammar/case.hpp"
7#include "helpers.hh" 8#include "helpers.hh"
8#include "marshall_type.hh" 9#include "marshall_type.hh"
@@ -34,6 +35,10 @@ namespace eolian_mono {
34 struct native_convert_return_variable_generator; 35 struct native_convert_return_variable_generator;
35 struct convert_function_pointer_generator; 36 struct convert_function_pointer_generator;
36 struct native_convert_function_pointer_generator; 37 struct native_convert_function_pointer_generator;
38 struct constructor_param_generator;
39 struct constructor_invocation_generator;
40 struct constructor_parameter_name_generator;
41 struct constructor_parameter_name_paremeterized;
37} 42}
38 43
39namespace efl { namespace eolian { namespace grammar { 44namespace efl { namespace eolian { namespace grammar {
@@ -232,6 +237,38 @@ template <>
232struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {}; 237struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {};
233} 238}
234 239
240template <>
241struct is_eager_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
242template <>
243struct is_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
244
245namespace type_traits {
246template <>
247struct attributes_needed< ::eolian_mono::constructor_param_generator> : std::integral_constant<int, 1> {};
248}
249
250template <>
251struct is_eager_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
252template <>
253struct is_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
254
255namespace type_traits {
256template <>
257struct attributes_needed< ::eolian_mono::constructor_invocation_generator> : std::integral_constant<int, 1> {};
258}
259
260template <>
261struct is_eager_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
262template <>
263struct is_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
264template <>
265struct is_generator< ::eolian_mono::constructor_parameter_name_paremeterized> : std::true_type {};
266
267namespace type_traits {
268template <>
269struct attributes_needed< ::eolian_mono::constructor_parameter_name_generator> : std::integral_constant<int, 1> {};
270}
271
235} } } 272} } }
236 273
237namespace eolian_mono { 274namespace eolian_mono {
@@ -1436,6 +1473,89 @@ struct native_convert_function_pointer_generator
1436 1473
1437} const native_convert_function_pointer {}; 1474} const native_convert_function_pointer {};
1438 1475
1476struct constructor_parameter_name_generator
1477{
1478
1479 template <typename OutputIterator, typename Context>
1480 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
1481 {
1482 auto target_name = name_helpers::constructor_managed_name(ctor.name);
1483
1484 // Only multi-valued constructing methods get their actual parameter names
1485 if (ctor.function.parameters.size() > 1)
1486 target_name += '_' + param.param_name;
1487
1488 auto name = name_helpers::managed_name(target_name);
1489 name[0] = std::tolower(name[0]);
1490
1491 return as_generator(string).generate(sink, name, context);
1492 }
1493
1494 attributes::constructor_def const& ctor;
1495};
1496
1497struct constructor_parameter_name_parameterized
1498{
1499 constructor_parameter_name_generator const operator()(attributes::constructor_def const& ctor) const
1500 {
1501 return {ctor};
1502 }
1503} const constructor_parameter_name;
1504
1505// Generates the parameters for the given constructor
1506// If the constructor receives multiple parameters, they get the name
1507// of the constructor plus the name of the parameter (e.g. DefineParentData, DefineIndex)
1508struct constructor_param_generator
1509{
1510 template<typename OutputIterator, typename Context>
1511 bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context context) const
1512 {
1513 auto params = ctor.function.parameters;
1514
1515 if (!as_generator(
1516 efl::eolian::grammar::attribute_reorder<1, -1>
1517 (type(false, ctor.is_optional) << " " << constructor_parameter_name(ctor) << (ctor.is_optional ? " = null" : "")) % ","
1518 ).generate(sink, params, context))
1519 return false;
1520 // }
1521 return true;
1522 }
1523
1524} const constructor_param;
1525
1526// Generates the invocation of the given parameter
1527struct constructor_invocation_generator
1528{
1529 template<typename OutputIterator, typename Context>
1530 bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context context) const
1531 {
1532 auto params = ctor.function.parameters;
1533 if (!as_generator(
1534 "if (" <<
1535 (efl::eolian::grammar::attribute_reorder<-1>
1536 ("Efl.Eo.Globals.ParamHelperCheck(" << constructor_parameter_name(ctor) << ")") % "||") << ")\n"
1537 << scope_tab << scope_tab << scope_tab << name_helpers::managed_method_name(ctor.function) << "("
1538 ).generate(sink, params, context))
1539 return false;
1540
1541 size_t idx = 0;
1542
1543 for (auto&& param : params)
1544 {
1545 idx++;
1546 if (!as_generator(
1547 "Efl.Eo.Globals.GetParamHelper(" << constructor_parameter_name(ctor) << ")" << ((idx < params.size()) ? ", " : "")
1548 ).generate(sink, param, context))
1549 return false;
1550 }
1551
1552 if (!as_generator(");").generate(sink, attributes::unused, context))
1553 return false;
1554 return true;
1555 }
1556
1557} const constructor_invocation;
1558
1439} 1559}
1440 1560
1441#endif 1561#endif
diff --git a/src/bin/eolian_mono/eolian/mono/type.hh b/src/bin/eolian_mono/eolian/mono/type.hh
index b968d9e..f6a5285 100644
--- a/src/bin/eolian_mono/eolian/mono/type.hh
+++ b/src/bin/eolian_mono/eolian/mono/type.hh
@@ -14,29 +14,29 @@ struct visitor_generate;
14 14
15struct type_generator 15struct type_generator
16{ 16{
17 type_generator(bool is_return = false) 17 type_generator(bool is_return = false, bool is_optional = false)
18 : is_return(is_return) {} 18 : is_return(is_return), is_optional(is_optional) {}
19 19
20 template <typename OutputIterator, typename Context> 20 template <typename OutputIterator, typename Context>
21 bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const 21 bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
22 { 22 {
23 return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr}); 23 return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr, is_optional});
24 } 24 }
25 template <typename OutputIterator, typename Context> 25 template <typename OutputIterator, typename Context>
26 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const 26 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
27 { 27 {
28 return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type 28 return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
29 , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr}); 29 , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr, is_optional});
30 } 30 }
31 31
32 bool is_return; 32 bool is_return, is_optional;
33}; 33};
34 34
35struct type_terminal 35struct type_terminal
36{ 36{
37 type_generator const operator()(bool is_return) const 37 type_generator const operator()(bool is_return, bool is_optional = false) const
38 { 38 {
39 return type_generator(is_return); 39 return type_generator(is_return, is_optional);
40 } 40 }
41} const type = {}; 41} const type = {};
42 42
diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh
index 3e4ae8d..c449d21 100644
--- a/src/bin/eolian_mono/eolian/mono/type_impl.hh
+++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh
@@ -34,6 +34,20 @@ attributes::regular_type_def replace_base_integer(attributes::regular_type_def v
34 } 34 }
35} 35}
36 36
37template <typename T>
38attributes::regular_type_def replace_base_opt_integer(attributes::regular_type_def v)
39{
40 bool s = std::is_signed<T>::value;
41 switch (sizeof(T))
42 {
43 case 1: return s ? replace_base_type(v, " sbyte?") : replace_base_type(v, " byte?");
44 case 2: return s ? replace_base_type(v, " short?") : replace_base_type(v, " ushort?");
45 case 4: return s ? replace_base_type(v, " int?") : replace_base_type(v, " uint?");
46 case 8: return s ? replace_base_type(v, " long?") : replace_base_type(v, " ulong?");
47 default: return v;
48 }
49}
50
37inline 51inline
38attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular) 52attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular)
39{ 53{
@@ -63,6 +77,7 @@ struct visitor_generate
63 bool is_out; 77 bool is_out;
64 bool is_return; 78 bool is_return;
65 bool is_ptr; 79 bool is_ptr;
80 mutable bool is_optional;
66 81
67 typedef visitor_generate<OutputIterator, Context> visitor_type; 82 typedef visitor_generate<OutputIterator, Context> visitor_type;
68 typedef bool result_type; 83 typedef bool result_type;
@@ -76,6 +91,40 @@ struct visitor_generate
76 eina::optional<bool> has_own; 91 eina::optional<bool> has_own;
77 std::function<attributes::type_def::variant_type()> function; 92 std::function<attributes::type_def::variant_type()> function;
78 } 93 }
94 const optional_match_table[] =
95 {
96 // signed primitives
97 {"byte", nullptr, [&] { return replace_base_type(regular, " sbyte?"); }}
98 , {"float", nullptr, [&] { return replace_base_type(regular, " float?"); }}
99 , {"double", nullptr, [&] { return replace_base_type(regular, " double?"); }}
100 , {"bool", nullptr, [&] { return replace_base_type(regular, " bool?"); }}
101 , {"short", nullptr, [&] { return replace_base_opt_integer<short>(regular); }}
102 , {"int", nullptr, [&] { return replace_base_opt_integer<int>(regular); }}
103 , {"long", nullptr, [&] { return replace_base_opt_integer<long>(regular); }}
104 , {"llong", nullptr, [&] { return replace_base_opt_integer<long long>(regular); }}
105 , {"int8", nullptr, [&] { return replace_base_type(regular, " sbyte?"); }}
106 , {"int16", nullptr, [&] { return replace_base_type(regular, " short?"); }}
107 , {"int32", nullptr, [&] { return replace_base_type(regular, " int?"); }}
108 , {"int64", nullptr, [&] { return replace_base_type(regular, " long?"); }}
109 , {"ssize", nullptr, [&] { return replace_base_opt_integer<ssize_t>(regular); }}
110 // unsigned primitives
111 , {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte?"); }}
112 , {"ushort", nullptr, [&] { return replace_base_opt_integer<unsigned short>(regular); }}
113 , {"uint", nullptr, [&] { return replace_base_opt_integer<unsigned int>(regular); }}
114 , {"ulong", nullptr, [&] { return replace_base_opt_integer<unsigned long>(regular); }}
115 , {"ullong", nullptr, [&] { return replace_base_opt_integer<unsigned long long>(regular); }}
116 , {"uint8", nullptr, [&] { return replace_base_type(regular, " byte?"); }}
117 , {"uint16", nullptr, [&] { return replace_base_type(regular, " ushort?"); }}
118 , {"uint32", nullptr, [&] { return replace_base_type(regular, " uint?"); }}
119 , {"uint64", nullptr, [&] { return replace_base_type(regular, " ulong?"); }}
120 , {"size", nullptr, [&] { return replace_base_opt_integer<size_t>(regular); }}
121
122 , {"ptrdiff", nullptr, [&] { return replace_base_opt_integer<ptrdiff_t>(regular); }}
123 , {"intptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
124 , {"uintptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
125 , {"void_ptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
126 };
127 struct match
79 const match_table[] = 128 const match_table[] =
80 { 129 {
81 // signed primitives 130 // signed primitives
@@ -153,6 +202,29 @@ struct visitor_generate
153 }; 202 };
154 std::string full_type_name = name_helpers::type_full_eolian_name(regular); 203 std::string full_type_name = name_helpers::type_full_eolian_name(regular);
155 if(eina::optional<bool> b = call_match 204 if(eina::optional<bool> b = call_match
205 (optional_match_table
206 , [&] (match const& m)
207 {
208 return is_optional
209 && (!m.name || *m.name == regular.base_type || *m.name == full_type_name)
210 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
211 ;
212 }
213 , [&] (attributes::type_def::variant_type const& v)
214 {
215 return v.visit(*this); // we want to keep is_out info
216 }))
217 {
218 return *b;
219 }
220 else if (is_optional && (regular.is_struct() || regular.is_enum() || regular.is_struct_opaque()))
221 {
222 attributes::regular_type_def r = regular;
223 r.base_type.push_back('?');
224 is_optional = false;
225 return (*this)(r);
226 }
227 else if(eina::optional<bool> b = call_match
156 (match_table 228 (match_table
157 , [&] (match const& m) 229 , [&] (match const& m)
158 { 230 {