From 067a8baffa692668acc0f19c91e2198195f480e2 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Thu, 8 Mar 2018 15:43:14 -0800 Subject: [PATCH] csharp: generate helper constructors for structs. Summary: C# does not have a literal form for structs (like C++'s {} aggregate initialization). Before this commit the user would need to explicitly instantiate a struct and assign the required values to it, like: eina.Size2D size; size.W = width; size.H = height; widget.SetSize(size); As a workaround, this commit generates helper constructor with parameters corresponding to the struct fields in the order they are declared. These parameters have default values if one does not want to explicitly initialize all fields directly. With these constructs, the above code could be translated to: widget.SetSize(new eina.Size2D(width, height)); It should be noted that the constructed struct will live on the managed memory (GC) instead of the stack. Test Plan: run "make check" Reviewers: felipealmeida Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D5838 Signed-off-by: Cedric BAIL --- src/Makefile_Efl_Mono.am | 1 + src/bin/eolian_mono/eolian/mono/helpers.hh | 6 ++ .../eolian/mono/struct_definition.hh | 23 +++++-- .../eolian_mono/eolian/mono/struct_fields.hh | 68 +++++++++++++++++++ src/tests/efl_mono/Structs.cs | 11 +++ 5 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 src/bin/eolian_mono/eolian/mono/struct_fields.hh diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am index 9344fbda2f..e442d09fb5 100644 --- a/src/Makefile_Efl_Mono.am +++ b/src/Makefile_Efl_Mono.am @@ -78,6 +78,7 @@ bin_eolian_mono_eolian_mono_SOURCES = \ bin/eolian_mono/eolian/mono/function_registration.hh \ bin/eolian_mono/eolian/mono/enum_definition.hh \ bin/eolian_mono/eolian/mono/struct_definition.hh \ + bin/eolian_mono/eolian/mono/struct_fields.hh \ bin/eolian_mono/eolian/mono/parameter.hh \ bin/eolian_mono/eolian/mono/utils.hh \ bin/eolian_mono/eolian/mono/using_decl.hh \ diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh index 7d013bd6f5..e02fd05b70 100644 --- a/src/bin/eolian_mono/eolian/mono/helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/helpers.hh @@ -76,6 +76,12 @@ inline bool need_pointer_conversion(attributes::regular_type_def const* regular) return false; } +inline std::string to_field_name(std::string const& in) +{ + std::string field_name = in; + field_name[0] = std::toupper(field_name[0]); // Hack to allow 'static' as a field name + return field_name; +} } diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh index 324e787748..a0ff03315e 100644 --- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh @@ -11,6 +11,7 @@ #include "keyword.hh" #include "using_decl.hh" #include "documentation.hh" +#include "struct_fields.hh" namespace eolian_mono { @@ -24,13 +25,6 @@ inline std::string binding_struct_internal_name(attributes::struct_def const& st return struct_.cxx_name + "_StructInternal"; } -inline std::string to_field_name(std::string const& in) -{ - std::string field_name = in; - field_name[0] = std::toupper(field_name[0]); // Hack to allow 'static' as a field name - return field_name; -} - struct struct_definition_generator { template @@ -70,6 +64,21 @@ struct struct_definition_generator if (!as_generator("///Placeholder field\npublic IntPtr field;\n").generate(sink, nullptr, context)) return false; } + else + { + // Constructor with default parameters for easy struct initialization + auto struct_name = binding_struct_name(struct_); + if(!as_generator( + scope_tab << "///Constructor for " << string << ".\n" + << scope_tab << "public " << string << "(\n" + << ((scope_tab << scope_tab << field_argument_default) % ",\n") + << scope_tab << ")\n" + << scope_tab << "{\n" + << *(scope_tab << scope_tab << field_argument_assignment << ";\n") + << scope_tab << "}\n") + .generate(sink, std::make_tuple(struct_name, struct_name, struct_.fields, struct_.fields), context)) + return false; + } if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false; diff --git a/src/bin/eolian_mono/eolian/mono/struct_fields.hh b/src/bin/eolian_mono/eolian/mono/struct_fields.hh new file mode 100644 index 0000000000..0cd018b06f --- /dev/null +++ b/src/bin/eolian_mono/eolian/mono/struct_fields.hh @@ -0,0 +1,68 @@ +#ifndef EOLIAN_MONO_STRUCT_FIELDS_HH +#define EOLIAN_MONO_STRUCT_FIELDS_HH + +#include "grammar/generator.hpp" +#include "grammar/klass_def.hpp" +#include "grammar/indentation.hpp" +#include "grammar/list.hpp" +#include "grammar/alternative.hpp" +#include "helpers.hh" +#include "type.hh" +#include "keyword.hh" +#include "using_decl.hh" +#include "documentation.hh" + +namespace eolian_mono { + +struct field_argument_default_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const + { + if (!as_generator(type << " " << string << "=default(" << type << ")") + .generate(sink, std::make_tuple(field.type, to_field_name(field.name), field.type), context)) + return false; + return true; + } +} const field_argument_default {}; + +struct field_argument_assignment_generator +{ + template + bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const + { + if (!as_generator("this." << string << " = " << string) + .generate(sink, std::make_tuple(to_field_name(field.name), to_field_name(field.name)), context)) + return false; + return true; + } +} const field_argument_assignment {}; + +} + +namespace efl { namespace eolian { namespace grammar { + +template<> +struct is_eager_generator< ::eolian_mono::field_argument_default_generator> : std::true_type {}; +template<> +struct is_generator< ::eolian_mono::field_argument_default_generator> : std::true_type {}; + +template<> +struct is_eager_generator< ::eolian_mono::field_argument_assignment_generator> : std::true_type {}; +template<> +struct is_generator< ::eolian_mono::field_argument_assignment_generator> : std::true_type {}; + +namespace type_traits { + +template <> +struct attributes_needed< ::eolian_mono::field_argument_default_generator> : std::integral_constant {}; + +template <> +struct attributes_needed< ::eolian_mono::field_argument_assignment_generator> : std::integral_constant {}; + +} + +} } } + +#endif + diff --git a/src/tests/efl_mono/Structs.cs b/src/tests/efl_mono/Structs.cs index dcdea0d757..07917d0c56 100644 --- a/src/tests/efl_mono/Structs.cs +++ b/src/tests/efl_mono/Structs.cs @@ -245,6 +245,17 @@ class TestStructs checkZeroedStructComplex(complex); } + public static void parameter_initialization() + { + var simple = new test.StructSimple(0x1, 0x2, (char)0x3, 0x4, 0x5); + Test.AssertEquals(0x1, simple.Fbyte); + Test.AssertEquals(0x2, simple.Fubyte); + Test.AssertEquals(0x3, simple.Fchar); + Test.AssertEquals(0x4, simple.Fshort); + Test.AssertEquals(0x5, simple.Fushort); + Test.AssertEquals(0, simple.Fint); + } + // As parameters public static void simple_in()