efl_mono: Fix support for event arguments.

Summary:
Using a type visitor scheme similar to type and marshall_type, to ease
increasing coverage for other types if needed.

Also, changed the filter functions for those selections to check for the
full name of the regular_type_def, allowing a better specificity of the
name selections. This fixes things like "Eina.Error", which was
conflicting with Efl.Image.Load.Error when we compared only the last
name. It didn't appear before as Load.Error only appears in a
Efl.Image.Load event.
Depends on D5996

Reviewers: felipealmeida

Reviewed By: felipealmeida

Subscribers: cedric

Differential Revision: https://phab.enlightenment.org/D5997
This commit is contained in:
Lauro Moura 2018-04-18 23:07:22 -03:00
parent ff1fda829d
commit 1837e2de10
2 changed files with 64 additions and 14 deletions

View File

@ -1,32 +1,73 @@
#ifndef EOLIAN_MONO_EVENTS_HH
#define EOLINA_MONO_EVENTS_HH
#include <iterator>
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "type_impl.hh" // For call_match
#include "name_helpers.hh"
#include "using_decl.hh"
namespace eolian_mono {
struct get_event_args_visitor
template<typename OutputIterator, typename Context>
struct unpack_event_args_visitor
{
mutable OutputIterator sink;
Context const* context;
std::string arg_type;
attributes::type_def const& type;
typedef get_event_args_visitor visitor_type;
typedef std::string result_type;
std::string operator()(grammar::attributes::regular_type_def const&) const
typedef unpack_event_args_visitor<OutputIterator, Context> visitor_type;
typedef bool result_type;
bool operator()(grammar::attributes::regular_type_def const& regular) const
{
if (arg_type == "string")
return "eina.StringConversion.NativeUtf8ToManagedString(evt.Info)";
return "(" + arg_type + ")Marshal.PtrToStructure(evt.Info, typeof(" + arg_type + "))";
std::string const& arg = "evt.Info";
// Structs are usually passed by pointer to events, like having a ptr<> modifier
if (type.is_ptr || regular.is_struct())
return as_generator("(" + arg_type + ")Marshal.PtrToStructure(" + arg + ", typeof(" + arg_type + "))")
.generate(sink, attributes::unused, *context);
using attributes::regular_type_def;
struct match
{
eina::optional<std::string> name;
std::function<std::string()> function;
}
const match_table [] =
{
{"bool", [&arg] { return arg + " != IntPtr.Zero"; }}
, {"int", [&arg] { return arg + ".ToInt32()"; }}
, {"uint", [&arg] { return "(uint)" + arg + ".ToInt32()";}}
, {"string", [&arg] { return "eina.StringConversion.NativeUtf8ToManagedString(" + arg + ")"; }}
, {"Eina.Error", [&arg] { return "(eina.Error)Marshal.PtrToStructure(" + arg + ", typeof(eina.Error))"; }}
};
std::string full_type_name = name_helpers::type_full_name(regular);
auto filter_func = [&regular, &full_type_name] (match const& m)
{
return (!m.name || *m.name == regular.base_type || *m.name == full_type_name);
};
auto accept_func = [&](std::string const& conversion)
{
return as_generator(conversion).generate(sink, attributes::unused, *context);
};
if (eina::optional<bool> b = call_match(match_table, filter_func, accept_func))
return *b;
else
return as_generator("default(" + arg_type + ")").generate(sink, attributes::unused, *context);
}
std::string operator()(grammar::attributes::klass_name const&) const
bool operator()(grammar::attributes::klass_name const&) const
{
return "new " + arg_type + "Concrete(evt.Info)";
return as_generator("new " + arg_type + "Concrete(evt.Info)").generate(sink, attributes::unused, *context);
}
std::string operator()(attributes::complex_type_def const&) const
bool operator()(attributes::complex_type_def const&) const
{
return "UNSUPPORTED";
return as_generator("UNSUPPORTED").generate(sink, attributes::unused, *context);
}
};
@ -138,7 +179,15 @@ struct event_definition_generator
wrapper_args_template = "<" + wrapper_args_type + ">";
std::string arg_type = wrapper_args_type + " args = new " + wrapper_args_type + "();\n"; // = (*etype).original_type.visit(get_csharp_type_visitor{});
std::string actual_arg_type = (*etype).original_type.visit(name_helpers::get_csharp_type_visitor{});
arg_type += " args.arg = " + (*etype).original_type.visit(get_event_args_visitor{actual_arg_type}) + ";\n";
arg_type += " args.arg = ";
auto arg_type_sink = std::back_inserter(arg_type);
if (!(*etype).original_type.visit(unpack_event_args_visitor<decltype(arg_type_sink), Context>{arg_type_sink, &context, actual_arg_type, *etype}))
return false;
arg_type += ";\n";
event_args = arg_type;
}

View File

@ -115,7 +115,7 @@ struct visitor_generate
r.base_type = " void";
return r;
}}
, {"Error", nullptr, [&] // Eina.Error
, {"Eina.Error", nullptr, [&] // Eina.Error
{
return regular_type_def{" eina.Error", regular.base_qualifier, {}};
}} // TODO
@ -164,11 +164,12 @@ struct visitor_generate
// .generate(sink, attributes::unused, *context);
// }
// else
std::string full_type_name = name_helpers::type_full_name(regular);
if(eina::optional<bool> b = call_match
(match_table
, [&] (match const& m)
{
return (!m.name || *m.name == regular.base_type)
return (!m.name || *m.name == regular.base_type || *m.name == full_type_name)
&& (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
;
}