efl_mono: Fix support for event arguments.
authorLauro Moura <lauromoura@expertisesolutions.com.br>
Thu, 19 Apr 2018 02:07:22 +0000 (23:07 -0300)
committerWonki Kim <wonki_.kim@samsung.com>
Thu, 31 May 2018 05:41:05 +0000 (14:41 +0900)
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

src/bin/eolian_mono/eolian/mono/events.hh
src/bin/eolian_mono/eolian/mono/type_impl.hh

index 34aeab5..b73e7d5 100644 (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;
         }
index 169ae18..edd6cc8 100644 (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))
             ;
           }