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 <cedric@osg.samsung.com>
This commit is contained in:
Lauro Moura 2018-03-08 15:43:14 -08:00 committed by Cedric BAIL
parent 34673ab983
commit 067a8baffa
5 changed files with 102 additions and 7 deletions

View File

@ -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 \

View File

@ -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;
}
}

View File

@ -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 <typename OutputIterator, typename Context>
@ -70,6 +64,21 @@ struct struct_definition_generator
if (!as_generator("///<summary>Placeholder field</summary>\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 << "///<summary>Constructor for " << string << ".</summary>\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;

View File

@ -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<typename OutputIterator, typename Context>
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<typename OutputIterator, typename Context>
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<int, 1> {};
template <>
struct attributes_needed< ::eolian_mono::field_argument_assignment_generator> : std::integral_constant<int, 1> {};
}
} } }
#endif

View File

@ -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()