eolian_mono: Added code for eolian_mono generator
authorLauro Moura <lauromoura@expertisesolutions.com.br>
Fri, 24 Nov 2017 00:50:16 +0000 (21:50 -0300)
committerLauro Moura <lauromoura@expertisesolutions.com.br>
Mon, 4 Dec 2017 18:47:50 +0000 (15:47 -0300)
Based on the eolian_cxx library generators. Buildsystem files will come
in a future commmit.

23 files changed:
src/bin/eolian_mono/.gitignore [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/enum_definition.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/function_blacklist.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/function_declaration.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/function_definition.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/function_helpers.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/function_pointer.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/function_registration.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/generation_contexts.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/keyword.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/klass.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/marshall_annotation.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/marshall_type.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/name_helpers.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/namespace.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/parameter.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/struct_definition.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/type.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/type_impl.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/using_decl.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian/mono/utils.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian_mono.cc [new file with mode: 0644]

diff --git a/src/bin/eolian_mono/.gitignore b/src/bin/eolian_mono/.gitignore
new file mode 100644 (file)
index 0000000..1562e43
--- /dev/null
@@ -0,0 +1 @@
+/eolian_mono
diff --git a/src/bin/eolian_mono/eolian/mono/enum_definition.hh b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
new file mode 100644 (file)
index 0000000..ae9775e
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef EOLIAN_MONO_ENUM_DEFINITION_HH
+#define EOLIAN_MONO_ENUM_DEFINITION_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "type.hh"
+#include "keyword.hh"
+#include "using_decl.hh"
+
+namespace eolian_mono {
+
+struct enum_definition_generator
+{
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::enum_def const& enum_, Context const& context) const
+  {
+     std::vector<std::string> cpp_namespaces = escape_namespace(attributes::cpp_namespaces(enum_.namespaces));
+
+     auto open_namespace = *("namespace " << string << " { ") << "\n";
+     if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false;
+
+     if(!as_generator
+        (
+         "public enum " << string << "\n{\n"
+         )
+        .generate(sink, enum_.cxx_name, context))
+       return false;
+
+     // iterate enum fiels
+     for(auto first = std::begin(enum_.fields)
+             , last = std::end(enum_.fields); first != last; ++first)
+       {
+          auto name = (*first).name;
+          auto literal = (*first).value.literal;
+          name[0] = std::toupper(name[0]); // Hack to allow 'static' as a field name
+          if (!as_generator
+              (
+               string << " = " << string << ",\n"
+              )
+              .generate(sink, std::make_tuple(name, literal), context))
+            return false;
+       }
+
+     if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
+
+     auto close_namespace = *(lit("} ")) << "\n";
+     if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
+     
+     return true;
+  }
+};
+
+enum_definition_generator const enum_definition = {};
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::enum_definition_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::enum_definition_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::enum_definition_generator> : std::integral_constant<int, 1> {};
+}
+      
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_blacklist.hh b/src/bin/eolian_mono/eolian/mono/function_blacklist.hh
new file mode 100644 (file)
index 0000000..9b08295
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef EOLIAN_MONO_FUNCTION_BLACKLIST_HH
+#define EOLIAN_MONO_FUNCTION_BLACKLIST_HH
+
+namespace eolian_mono {
+
+inline bool is_function_blacklisted(std::string const& c_name)
+{
+  return
+    c_name == "efl_event_callback_array_priority_add"
+    || c_name == "efl_player_position_get"
+    || c_name == "efl_image_load_error_get"
+    || c_name == "efl_text_font_source_get"
+    || c_name == "efl_text_font_source_set"
+    || c_name == "efl_ui_focus_manager_focus_get"
+    || c_name == "efl_ui_widget_focus_set"
+    || c_name == "efl_ui_widget_focus_get"
+    || c_name == "efl_ui_text_password_get"
+    || c_name == "efl_ui_text_password_set"
+    || c_name == "elm_interface_scrollable_repeat_events_get"
+    || c_name == "elm_interface_scrollable_repeat_events_set"
+    || c_name == "elm_wdg_item_del"
+    || c_name == "elm_wdg_item_focus_get"
+    || c_name == "elm_wdg_item_focus_set"
+    || c_name == "elm_interface_scrollable_mirrored_set"
+    || c_name == "edje_obj_load_error_get"
+    || c_name == "efl_ui_focus_user_parent_get"
+    || c_name == "efl_canvas_object_scale_get" // duplicated signature
+    || c_name == "efl_canvas_object_scale_set" // duplicated signature
+    || c_name == "efl_ui_format_cb_set"
+    || c_name == "efl_access_parent_get"
+    || c_name == "efl_access_name_get"
+    || c_name == "efl_access_name_set"
+    || c_name == "efl_access_root_get"
+    || c_name == "efl_access_type_get"
+    || c_name == "efl_access_role_get"
+    || c_name == "efl_access_action_description_get"
+    || c_name == "efl_access_action_description_set"
+    || c_name == "efl_access_image_description_get"
+    || c_name == "efl_access_image_description_set"
+    || c_name == "efl_access_component_layer_get" // duplicated signature
+    || c_name == "efl_access_component_alpha_get"
+    || c_name == "efl_ui_spin_button_loop_get"
+    ;
+}
+
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_declaration.hh b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
new file mode 100644 (file)
index 0000000..561c975
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef EOLIAN_MONO_FUNCTION_DECLARATION_HH
+#define EOLIAN_MONO_FUNCTION_DECLARATION_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "type.hh"
+#include "parameter.hh"
+#include "keyword.hh"
+#include "using_decl.hh"
+
+namespace eolian_mono {
+
+struct function_declaration_generator
+{
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  {
+    if(is_function_blacklisted(f.c_name))
+      return true;
+    else
+      return as_generator
+        (eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n")
+        .generate(sink, std::make_tuple(f.return_type, managed_method_name(f.name), f.parameters), context);
+  }
+};
+
+function_declaration_generator const function_declaration = {};
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::function_declaration_generator> : std::integral_constant<int, 1> {};
+}
+      
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
new file mode 100644 (file)
index 0000000..2a4c027
--- /dev/null
@@ -0,0 +1,223 @@
+#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HH
+#define EOLIAN_MONO_FUNCTION_DEFINITION_HH
+
+#include <Eina.hh>
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "grammar/attribute_reorder.hpp"
+#include "type.hh"
+#include "function_helpers.hh"
+#include "marshall_type.hh"
+#include "parameter.hh"
+#include "keyword.hh"
+#include "using_decl.hh"
+#include "generation_contexts.hh"
+
+namespace eolian_mono {
+
+struct native_function_definition_generator
+{
+  attributes::klass_def const* klass;
+  
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  {
+    if(is_function_blacklisted(f.c_name))
+      return true;
+    else
+      {
+    if(!as_generator
+       ("\n\n" << scope_tab
+        << eolian_mono::marshall_native_annotation(true)
+        << " public delegate "
+        << eolian_mono::marshall_type(true)
+        << " "
+        << string
+        << "_delegate(System.IntPtr obj, System.IntPtr pd"
+        << *grammar::attribute_reorder<-1, -1>
+        (
+         (", " << marshall_native_annotation << " " << marshall_parameter)
+        )
+        << ");\n")
+       .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
+      return false;
+
+    if(!as_generator
+       (scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")] "
+        << eolian_mono::marshall_native_annotation(true)
+        << " public static extern "
+        << eolian_mono::marshall_type(true)
+        << " " << string
+        << "(System.IntPtr obj"
+        << *grammar::attribute_reorder<-1, -1>
+        (
+         (", " << marshall_native_annotation << " " << marshall_parameter)
+        )
+        << ");\n")
+       .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
+      return false;
+
+    std::string return_type;
+    if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
+      return false;
+
+    if(!as_generator
+       (scope_tab
+        << " public static "
+        << eolian_mono::marshall_type(true) << " "
+        << string
+        << "(System.IntPtr obj, System.IntPtr pd"
+        << *(", " << marshall_parameter)
+        << ")\n"
+        << scope_tab << "{\n"
+        /****/
+        << scope_tab << scope_tab << "eina.Log.Debug(\"function " << string << " was called\");\n"
+        /****/
+        << scope_tab << scope_tab << "efl.eo.IWrapper wrapper = efl.eo.Globals.data_get(pd);\n"
+        << scope_tab << scope_tab << "if(wrapper != null) {\n"
+        << scope_tab << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble()
+        << scope_tab << scope_tab << scope_tab << "try {\n"
+        << scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << string << "Inherit)wrapper)." << string
+        << "(" << (native_argument_invocation % ", ") << ");\n"
+        << scope_tab << scope_tab << scope_tab << "} catch (Exception e) {\n"
+        << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
+        << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Error.Set(eina.Error.EFL_ERROR);\n"
+        << scope_tab << scope_tab << scope_tab << "}\n"
+        << eolian_mono::native_function_definition_epilogue(*klass)
+        << scope_tab << scope_tab << "} else {\n"
+        << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "return " : "") << string
+        << "(efl.eo.Globals.efl_super(obj, " << string << "Inherit.klass)" << *(", " << argument) << ");\n"
+        << scope_tab << scope_tab << "}\n"
+        << scope_tab << "}\n"
+       )
+       .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters
+                                       , /***/f.c_name/***/
+                                       , f
+                                       , klass->cxx_name, managed_method_name(f.name)
+                                       , f.parameters
+                                       , f
+                                       , f.c_name
+                                       , klass->cxx_name, f.parameters
+                                      )
+                 , context))
+      return false;
+
+    if(!as_generator
+       (scope_tab << "public static  "
+        << string
+        << "_delegate "
+        << string << "_static_delegate = new " << string << "_delegate(" << string << "NativeInherit." << string << ");\n"
+       )
+       .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, klass->cxx_name
+                                       , escape_keyword(f.name)), context))
+      return false;
+    return true;
+      }
+  }
+};
+  
+struct function_definition_generator
+{
+  function_definition_generator(bool do_super = false)
+    : do_super(do_super)
+  {}
+  
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  {
+    if(is_function_blacklisted(f.c_name))
+      return true;
+    else
+      {
+    if(!as_generator
+       ("\n\n" << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(f.filename) << ")]\n"
+        << scope_tab << eolian_mono::marshall_annotation(true)
+        << " public static extern "
+        << eolian_mono::marshall_type(true)
+        << " " << string
+        << "(System.IntPtr obj"
+        << *grammar::attribute_reorder<-1, -1>
+        (
+         (", " << marshall_annotation << " " << marshall_parameter)
+        )
+        << ");\n")
+       .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
+      return false;
+
+    std::string return_type;
+    if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
+      return false;
+
+    if(!as_generator
+       (scope_tab << (do_super ? "virtual " : "") << "public " << return_type << " " << string << "(" << (parameter % ", ")
+        << ") {\n "
+        << eolian_mono::function_definition_preamble() << string << "("
+        << (do_super ? "efl.eo.Globals.efl_super(" : "")
+        << "this.raw_handle"
+        << (do_super ? ", this.raw_klass)" : "")
+        << *(", " << argument_invocation ) << ");\n"
+        << eolian_mono::function_definition_epilogue()
+        << " }\n")
+       .generate(sink, std::make_tuple(managed_method_name(f.name), f.parameters, f, f.c_name, f.parameters, f), context))
+      return false;
+
+    return true;
+      }
+  }
+
+  bool do_super;
+};
+
+struct function_definition_parameterized
+{
+  function_definition_generator operator()(bool do_super) const
+  {
+    return {do_super};
+  }
+} const function_definition;
+function_definition_generator as_generator(function_definition_parameterized)
+{
+  return {};
+}
+struct native_function_definition_parameterized
+{
+  native_function_definition_generator operator()(attributes::klass_def const& klass) const
+  {
+    return {&klass};
+  }
+} const native_function_definition;
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
+template <>
+struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::function_definition_generator> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::function_definition_parameterized> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {};
+}
+      
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_helpers.hh b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
new file mode 100644 (file)
index 0000000..e7af6f9
--- /dev/null
@@ -0,0 +1,243 @@
+#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH
+#define EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH
+
+#include <Eina.hh>
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "grammar/attribute_reorder.hpp"
+/* #include "type.hh" */
+/* #include "marshall_type.hh" */
+#include "parameter.hh"
+#include "function_pointer.hh"
+/* #include "keyword.hh" */
+/* #include "using_decl.hh" */
+/* #include "generation_contexts.hh" */
+
+namespace eolian_mono {
+
+/*
+ * Generators for things that must happen inside the function definition *before* and
+ * *after* the actual invocation of the underlying C function.
+ *
+ * For example, declaration and assignment of intermediate variables for out/ return types
+ * that require some kind of manual work (e.g. string and Stringshare).
+ */
+
+struct native_function_definition_preamble_generator
+{
+    // FIXME Suport scoping tabs
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  { 
+      std::string return_type;
+
+      if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
+          return false;
+
+      if (!as_generator(
+                scope_tab << scope_tab << "//Placeholder in variables\n"
+                << *(scope_tab << scope_tab << native_convert_in_variable << "\n")
+                << scope_tab << scope_tab << "//Placeholder out variables\n"
+                << *(scope_tab << scope_tab << native_convert_out_variable << "\n")
+                << scope_tab << scope_tab << "//Function pointer wrappers\n"
+                << *(scope_tab << scope_tab << native_convert_function_pointer << "\n")
+                << scope_tab << scope_tab << "//Return variable and function call\n"
+                << scope_tab << scope_tab << scope_tab << native_convert_return_variable << "\n"
+                ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.parameters, f.return_type), context))
+          return false;
+
+      return true;
+  }
+};
+
+struct function_definition_preamble_generator
+{
+    // FIXME Suport scoping tabs
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  { 
+      std::string return_type;
+
+      if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
+          return false;
+
+      if (!as_generator(
+                  scope_tab << scope_tab << "//Placeholder in variables\n"
+                  << *(scope_tab << scope_tab << convert_in_variable << "\n")
+                  << scope_tab << scope_tab << "//Placeholder out variables\n"
+                  << *(scope_tab << scope_tab << convert_out_variable << "\n")
+                  << scope_tab << scope_tab << "//Function pointers handling\n"
+                  << *(scope_tab << scope_tab << convert_function_pointer << "\n")
+                  << scope_tab << scope_tab << "//Return variable and function call\n"
+                  << scope_tab << scope_tab << convert_return_variable
+                  ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.parameters, f.return_type), context))
+          return false;
+
+      return true;
+  }
+};
+
+struct native_function_definition_epilogue_generator
+{
+    attributes::klass_def const* klass;
+
+    // FIXME Suport scoping tabs
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  { 
+      std::string return_type;
+
+      if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
+          return false;
+
+      if (!as_generator(
+                  scope_tab << scope_tab << "//Assigning out variables\n"
+                  << *(scope_tab << scope_tab << native_convert_out_assign(*klass) << "\n")
+                  << scope_tab << scope_tab << "//Converting return variable\n"
+                  << scope_tab << scope_tab << native_convert_return(*klass)
+                  ).generate(sink, std::make_tuple(f.parameters, f.return_type), context))
+          return false;
+
+      return true;
+  }
+};
+
+struct function_definition_epilogue_generator
+{
+    // FIXME Suport scoping tabs
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  { 
+      if (!as_generator(
+                  scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
+                  << scope_tab << scope_tab << "//Assigning out variables\n"
+                  << *(scope_tab << scope_tab << convert_out_assign << "\n")
+                  << scope_tab << scope_tab << "//Converting return variable\n"
+                  << scope_tab << scope_tab << convert_return
+                  ).generate(sink, std::make_tuple(f.parameters, f.return_type), context))
+          return false;
+
+      return true;
+  }
+};
+
+// Preamble tokens
+struct native_function_definition_preamble_terminal
+{
+  native_function_definition_preamble_generator const operator()() const
+  {
+      return native_function_definition_preamble_generator();
+  }
+} const native_function_definition_preamble = {};
+
+native_function_definition_preamble_generator const as_generator(native_function_definition_preamble_terminal)
+{
+    return native_function_definition_preamble_generator{};
+}
+
+struct function_definition_preamble_terminal
+{
+  function_definition_preamble_generator const operator()() const
+  {
+      return function_definition_preamble_generator();
+  }
+} const function_definition_preamble = {};
+
+function_definition_preamble_generator const as_generator(function_definition_preamble_terminal)
+{
+    return function_definition_preamble_generator{};
+}
+
+// Epilogue tokens
+struct native_function_definition_epilogue_parameterized
+{
+  native_function_definition_epilogue_generator const operator()(attributes::klass_def const& klass) const
+  {
+    return {&klass};
+  }
+} const native_function_definition_epilogue;
+
+struct function_definition_epilogue_terminal
+{
+  function_definition_epilogue_generator const operator()() const
+  {
+      return function_definition_epilogue_generator();
+  }
+} const function_definition_epilogue = {};
+
+function_definition_epilogue_generator const as_generator(function_definition_epilogue_terminal)
+{
+    return function_definition_epilogue_generator{};
+}
+
+} // namespace eolian_mono
+
+namespace efl { namespace eolian { namespace grammar {
+
+// Preamble
+template <>
+struct is_eager_generator< ::eolian_mono::native_function_definition_preamble_generator> : std::true_type {};
+
+template <>
+struct is_generator< ::eolian_mono::native_function_definition_preamble_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_function_definition_preamble_terminal> : std::true_type {};
+
+template <>
+struct is_eager_generator< ::eolian_mono::function_definition_preamble_generator> : std::true_type {};
+
+template <>
+struct is_generator< ::eolian_mono::function_definition_preamble_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::function_definition_preamble_terminal> : std::true_type {};
+
+// Epilogue
+template <>
+struct is_eager_generator< ::eolian_mono::native_function_definition_epilogue_generator> : std::true_type {};
+
+template <>
+struct is_generator< ::eolian_mono::native_function_definition_epilogue_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_function_definition_epilogue_parameterized> : std::true_type {};
+
+template <>
+struct is_eager_generator< ::eolian_mono::function_definition_epilogue_generator> : std::true_type {};
+
+template <>
+struct is_generator< ::eolian_mono::function_definition_epilogue_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::function_definition_epilogue_terminal> : std::true_type {};
+
+namespace type_traits {
+// Preamble
+template <>
+struct attributes_needed< ::eolian_mono::native_function_definition_preamble_generator> : std::integral_constant<int, 1> {};
+template <>
+struct attributes_needed< ::eolian_mono::native_function_definition_preamble_terminal> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::function_definition_preamble_generator> : std::integral_constant<int, 1> {};
+template <>
+struct attributes_needed< ::eolian_mono::function_definition_preamble_terminal> : std::integral_constant<int, 1> {};
+
+// Epilogue
+template <>
+struct attributes_needed< ::eolian_mono::native_function_definition_epilogue_generator> : std::integral_constant<int, 1> {};
+template <>
+struct attributes_needed< ::eolian_mono::native_function_definition_epilogue_parameterized> : std::integral_constant<int, 1> {};
+
+template <>
+struct attributes_needed< ::eolian_mono::function_definition_epilogue_generator> : std::integral_constant<int, 1> {};
+template <>
+struct attributes_needed< ::eolian_mono::function_definition_epilogue_terminal> : std::integral_constant<int, 1> {};
+
+}
+
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
new file mode 100644 (file)
index 0000000..84fdb79
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef EOLIAN_MONO_FUNCTION_POINTER_HPP
+#define EOLIAN_MONO_FUNCTION_POINTER_HPP
+
+#include <Eolian.h>
+
+#include <vector>
+#include <string>
+
+namespace eolian_mono {
+
+// Blacklist structs that require some kind of manual binding.
+static bool is_function_ptr_blacklisted(attributes::function_def const& func, std::vector<std::string> const &namesp)
+{
+  std::stringstream full_name;
+
+  for (auto&& i : namesp)
+    full_name << i << ".";
+  full_name << func.name;
+
+  std::string name = full_name.str();
+
+  return name == "Efl.Ui.Format_Func_Cb";
+}
+
+struct function_pointer {
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::function_def const& f, std::vector<std::string> const &namesp, Context const& context) const
+   {
+      // FIXME export Typedecl in eolian_cxx API
+      std::vector<std::string> namespaces =  escape_namespace(namesp);
+
+      if (is_function_ptr_blacklisted(f, namesp))
+        return true;
+
+      auto open_namespace = *("namespace " << string << " {") << "\n";
+      if(!as_generator(open_namespace).generate(sink, namespaces, add_lower_case_context(context))) return false;
+
+      // C# visible delegate
+      if (!as_generator("public delegate " << type << " " << string
+                  << "(" << (parameter % ", ") << ");\n")
+              .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context))
+          return false;
+      // "Internal" delegate, 1-to-1 with the Unamaged function type
+      if (!as_generator("public delegate " << type << " " << string // public?
+                  << "Internal(IntPtr data, " << (parameter % ", ") << ");\n")
+              .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context))
+          return false;
+
+      std::string f_name = escape_keyword(f.name);
+      // Wrapper type, with callback matching the Unamanaged one
+      if (!as_generator("public class " << f_name << "Wrapper\n"
+                  << "{\n\n"
+                  << scope_tab << "private " << f_name  << "Internal _cb;\n"
+                  << scope_tab << "private IntPtr _cb_data;\n"
+                  << scope_tab << "private Eina_Free_Cb _cb_free_cb;\n\n"
+
+                  << scope_tab << "public " << f_name << "Wrapper (" << f_name << "Internal _cb, IntPtr _cb_data, Eina_Free_Cb _cb_free_cb)\n"
+                  << scope_tab << "{\n"
+                  << scope_tab << scope_tab << "this._cb = _cb;\n"
+                  << scope_tab << scope_tab << "this._cb_data = _cb_data;\n"
+                  << scope_tab << scope_tab << "this._cb_free_cb = _cb_free_cb;\n"
+                  << scope_tab << "}\n\n"
+
+                  << scope_tab << "~" << f_name << "Wrapper()\n"
+                  << scope_tab << "{\n"
+                  << scope_tab << scope_tab << "if (this._cb_free_cb != null)\n"
+                  << scope_tab << scope_tab << scope_tab << "this._cb_free_cb(this._cb_data);\n"
+                  << scope_tab << "}\n\n"
+
+                  << scope_tab << "public " << type << " ManagedCb(" << (parameter % ",") << ")\n"
+                  << scope_tab << "{\n"
+                  << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return ": "") << "_cb(_cb_data, " << (argument_invocation % ", ") << ");\n"
+                  << scope_tab << "}\n\n"
+
+                  << scope_tab << "public static " << type << " Cb(IntPtr cb_data, " << (parameter % ", ") << ")\n"
+                  << scope_tab << "{\n"
+                  << scope_tab << scope_tab << "GCHandle handle = GCHandle.FromIntPtr(cb_data);\n"
+                  << scope_tab << scope_tab << string << " cb = (" << string << ")handle.Target;\n"
+                  << scope_tab << scope_tab << (f.return_type.c_type != "void" ? "return " : "") << "cb(" << (argument_invocation % ", ") << ");\n"
+                  << scope_tab << "}\n"
+                  << "}\n"
+                  ).generate(sink, std::make_tuple(f.return_type, f.parameters, f.parameters, f.return_type, f.parameters, f_name, f_name, f.parameters), context))
+          return false;
+
+      auto close_namespace = *(lit("} ")) << "\n";
+      if(!as_generator(close_namespace).generate(sink, namespaces, context)) return false;
+
+      return true;
+   }
+};
+
+struct function_pointer const function_pointer = {};
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh
new file mode 100644 (file)
index 0000000..a88c938
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef EOLIAN_MONO_FUNCTION_REGISTRATION_HH
+#define EOLIAN_MONO_FUNCTION_REGISTRATION_HH
+
+#include <Eina.hh>
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "grammar/attribute_reorder.hpp"
+#include "type.hh"
+#include "marshall_type.hh"
+#include "parameter.hh"
+#include "keyword.hh"
+#include "using_decl.hh"
+#include "generation_contexts.hh"
+
+namespace eolian_mono {
+
+template <typename I>
+struct function_registration_generator
+{
+  I index_generator;
+  attributes::klass_def const* klass;
+  
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
+  {
+    if(is_function_blacklisted(f.c_name))
+      return true;
+    else
+      {
+    auto index = index_generator();
+    
+    if(!as_generator
+#ifdef _WIN32
+       (scope_tab << scope_tab << "descs[" << index << "].api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\");\n"
+#else
+       (scope_tab << scope_tab << "descs[" << index << "].api_func = efl.eo.Globals.dlsym(efl.eo.Globals.RTLD_DEFAULT, \"" << string << "\");\n"
+#endif
+        << scope_tab << scope_tab << "descs[" << index << "].func = Marshal.GetFunctionPointerForDelegate(" << string << "NativeInherit." << string << "_static_delegate);\n"
+       )
+       .generate(sink, std::make_tuple(f.c_name, klass->cxx_name, f.c_name), context))
+      return false;
+    return true;
+      }
+  }
+};
+  
+struct function_registration_parameterized
+{
+  template <typename I>
+  function_registration_generator<I> operator()(I i, attributes::klass_def const& klass) const
+  {
+    return {i, &klass};
+  }
+} const function_registration;
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <typename I>
+struct is_eager_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {};
+template <typename I>
+struct is_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {};
+
+namespace type_traits {
+
+template <typename I>
+struct attributes_needed< ::eolian_mono::function_registration_generator<I>> : std::integral_constant<int, 1> {};
+}
+      
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
new file mode 100644 (file)
index 0000000..f220c94
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef EOLIAN_MONO_GENERATION_CONTEXTS_HH
+#define EOLIAN_MONO_GENERATION_CONTEXTS_HH
+
+namespace eolian_mono {
+
+struct class_context
+{
+    enum wrapper_kind {
+        interface,
+        concrete,
+        inherit,
+        inherit_native,
+    };
+    wrapper_kind current_wrapper_kind;
+};
+
+struct library_context
+{
+  std::string library_name;
+  int v_major;
+  int v_minor;
+  std::map<const std::string, std::string> references;
+
+  const std::string actual_library_name(const std::string& filename) const;
+};
+
+const std::string
+library_context::actual_library_name(const std::string& filename) const
+{
+    // Libraries mapped follow the efl.Libs.NAME scheme.
+    // TODO What about references from outside efl (not present in the efl.Libs class?)
+    auto ref = references.find(filename);
+    if (ref != references.end())
+      return "efl.Libs." + ref->second;
+
+    // Fallback to original behaviour with explicit library name
+    return '"' + library_name + '"';
+}
+
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/keyword.hh b/src/bin/eolian_mono/eolian/mono/keyword.hh
new file mode 100644 (file)
index 0000000..fbe853a
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef EOLIAN_CXX_KEYWORD_HH
+#define EOLIAN_CXX_KEYWORD_HH
+
+#include <string>
+#include <strings.h>
+#include <vector>
+
+#include "name_helpers.hh"
+
+namespace eolian_mono {
+namespace detail {
+inline bool is_iequal(std::string const& lhs, std::string const& rhs)
+{
+  return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
+}
+}
+
+inline std::string escape_keyword(std::string const& name)
+{
+  using detail::is_iequal;
+  if(is_iequal(name, "delete")
+     || is_iequal(name,  "register")
+     || is_iequal(name, "do")
+     || is_iequal(name,  "lock")
+     || is_iequal(name, "event")
+     || is_iequal(name, "in")
+     || is_iequal(name, "object")
+     || is_iequal(name, "interface")
+     || is_iequal(name, "string")
+     || is_iequal(name, "internal")
+     || is_iequal(name, "fixed")
+     || is_iequal(name, "base"))
+    return "kw_" + name;
+
+  if (is_iequal(name, "Finalize"))
+    return name + "Add"; // Eo's Finalize is actually the end of efl_add.
+  return name;
+}
+
+
+std::string managed_method_name(std::string const& underscore_name)
+{
+  std::vector<std::string> names = name_helpers::split(underscore_name, '_');
+
+  name_helpers::reorder_verb(names);
+
+  return escape_keyword(name_helpers::pascal_case(names));
+}
+
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
new file mode 100644 (file)
index 0000000..fe2d35d
--- /dev/null
@@ -0,0 +1,745 @@
+#ifndef EOLIAN_MONO_CLASS_DEFINITION_HPP
+#define EOLIAN_MONO_CLASS_DEFINITION_HPP
+
+#include "grammar/integral.hpp"
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "function_blacklist.hh"
+
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "type.hh"
+#include "namespace.hh"
+#include "function_definition.hh"
+#include "function_registration.hh"
+#include "function_declaration.hh"
+#include "grammar/string.hpp"
+#include "grammar/attribute_replace.hpp"
+#include "grammar/integral.hpp"
+#include "grammar/case.hpp"
+#include "using_decl.hh"
+#include "utils.hh"
+
+#include <string>
+#include <algorithm>
+
+namespace eolian_mono {
+
+template <typename OutputIterator, typename Context>
+static bool generate_static_cast_method(OutputIterator sink, const std::string &class_name, Context const &context)
+{
+   return as_generator(
+       scope_tab << "public static " << class_name << " static_cast(efl.Object obj)\n"
+       << scope_tab << "{\n"
+       << scope_tab << scope_tab << "if (obj == null)\n"
+       << scope_tab << scope_tab << scope_tab << "throw new System.ArgumentNullException(\"obj\");\n"
+       << scope_tab << scope_tab << "return new " << class_name << "Concrete(obj.raw_handle);\n"
+       << scope_tab << "}\n"
+       ).generate(sink, nullptr, context);
+}
+
+template <typename OutputIterator, typename Context>
+static bool generate_equals_method(OutputIterator sink, Context const &context)
+{
+   return as_generator(
+       scope_tab << "public override bool Equals(object obj)\n"
+       << scope_tab << "{\n"
+       << scope_tab << scope_tab << "var other = obj as efl.Object;\n"
+       << scope_tab << scope_tab << "if (other == null)\n"
+       << scope_tab << scope_tab << scope_tab << "return false;\n"
+       << scope_tab << scope_tab << "return this.raw_handle == other.raw_handle;\n"
+       << scope_tab << "}\n"
+       << scope_tab << "public override int GetHashCode()\n"
+       << scope_tab << "{\n"
+       << scope_tab << scope_tab << "return this.raw_handle.ToInt32();\n"
+       << scope_tab << "}\n"
+      ).generate(sink, nullptr, context);
+}
+
+/* Get the actual number of functions of a class, checking for blacklisted ones */
+static std::size_t
+get_function_count(grammar::attributes::klass_def const& cls)
+{
+   auto methods = cls.get_all_methods();
+   return std::count_if(methods.cbegin(), methods.cend(), [](grammar::attributes::function_def const& func)
+     {
+        return !is_function_blacklisted(func.c_name);
+     });
+}
+
+struct get_csharp_type_visitor
+{
+    typedef get_csharp_type_visitor visitor_type;
+    typedef std::string result_type;
+    std::string operator()(grammar::attributes::regular_type_def const& type) const
+    {
+        std::stringstream csharp_name;
+        for (auto&& i  : escape_namespace(type.namespaces))
+           csharp_name << utils::to_lowercase(i) << ".";
+        csharp_name << type.base_type;
+
+        return csharp_name.str();
+    }
+    std::string operator()(grammar::attributes::klass_name const& name) const
+    {
+        std::stringstream csharp_name;
+        for (auto&& i  : escape_namespace(name.namespaces))
+           csharp_name << utils::to_lowercase(i) << ".";
+        csharp_name << name.eolian_name;
+
+        return csharp_name.str();
+    }
+    std::string operator()(attributes::complex_type_def const&) const
+    {
+        return "UNSUPPORTED";
+    }
+};
+
+struct get_event_args_visitor
+{
+
+    std::string arg_type;
+
+    typedef get_event_args_visitor visitor_type;
+    typedef std::string result_type;
+    std::string operator()(grammar::attributes::regular_type_def const&) const
+    {
+        return "(" + arg_type + ")Marshal.PtrToStructure(evt.Info, typeof(" + arg_type + "))";
+    }
+    std::string operator()(grammar::attributes::klass_name const&) const
+    {
+        return "new " + arg_type + "Concrete(evt.Info)";
+    }
+    std::string operator()(attributes::complex_type_def const&) const
+    {
+        return "UNSUPPORTED";
+    }
+};
+
+struct klass
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
+   {
+     std::string suffix, class_type;
+     switch(cls.type)
+       {
+       case attributes::class_type::regular:
+       case attributes::class_type::abstract_:
+         class_type = "class";
+         suffix = "CLASS";
+         break;
+       case attributes::class_type::mixin:
+         class_type = "interface";
+         suffix = "MIXIN";
+         break;
+       case attributes::class_type::interface_:
+         class_type = "interface";
+         suffix = "INTERFACE";
+         break;
+       }
+
+     std::vector<std::string> namespaces = escape_namespace(cls.namespaces);
+     auto open_namespace = *("namespace " << string << " { ") << "\n";
+     if(!as_generator(open_namespace).generate(sink, namespaces, add_lower_case_context(context))) return false;
+     auto methods = cls.get_all_methods();
+
+     // FIXME Generate local event argument wrappers
+     for (auto&& e : cls.events)
+       {
+          efl::eina::optional<grammar::attributes::type_def> etype = e.type;
+          if (!etype.is_engaged())
+            continue;
+
+          std::string evt_name = utils::to_uppercase(e.name);
+          std::replace(evt_name.begin(), evt_name.end(), ',', '_');
+          std::string arg_type = (*etype).original_type.visit(get_csharp_type_visitor{});
+
+
+          if (!as_generator("public class " << evt_name << "_Args : EventArgs {\n"
+                      << scope_tab << "public " << arg_type << " arg { get; set; }\n"
+                      << "}\n").generate(sink, NULL, context))
+              return false;
+       }
+
+     // Interface class
+     {
+     auto iface_cxt = context_add_tag(class_context{class_context::interface}, context);
+     if(!as_generator
+        (
+         "public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : "
+         )
+        .generate(sink, cls.cxx_name, iface_cxt))
+       return false;
+     for(auto first = std::begin(cls.immediate_inherits)
+           , last = std::end(cls.immediate_inherits); first != last; ++first)
+       {
+         if(!as_generator("\n" << scope_tab << *(lower_case[string] << ".") << string << " ,")
+            .generate(sink, std::make_tuple(escape_namespace(first->namespaces), first->eolian_name), iface_cxt))
+           return false;
+         // if(std::next(first) != last)
+         //   *sink++ = ',';
+       }
+     // if(cls.immediate_inherits.empty())
+       if(!as_generator("\n" << scope_tab << "efl.eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt)) return false;
+     if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) return false;
+     
+     if(!as_generator(*(scope_tab << function_declaration))
+        .generate(sink, cls.functions, iface_cxt)) return false;
+
+     // FIXME Move the event generator into another generator like function?
+     for (auto &&e : cls.events)
+       {
+          std::string wrapper_args_type;
+          std::string evt_name = utils::to_uppercase(e.name);
+          std::replace(evt_name.begin(), evt_name.end(), ',', '_');
+
+          efl::eina::optional<grammar::attributes::type_def> etype = e.type;
+          if (etype.is_engaged())
+              wrapper_args_type = "<" + evt_name + "_Args>";
+
+         //FIXME Add a way to generate camelcase names
+         if (!as_generator(
+                     scope_tab << "event EventHandler" << wrapper_args_type << " " 
+                     << evt_name << ";\n"
+                     ).generate(sink, NULL, iface_cxt))
+             return false;
+       }
+
+     // End of interface declaration
+     if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false;
+     }
+
+     auto class_get_name = *(lower_case[string] << "_") << lower_case[string] << "_class_get";
+     // Concrete class
+     // if(class_type == "class")
+       {
+         auto concrete_cxt = context_add_tag(class_context{class_context::concrete}, context);
+         if(!as_generator
+            (
+             "public class " << string << "Concrete : " << string << "\n{\n"
+             << scope_tab << "System.IntPtr handle;\n"
+             << scope_tab << "public System.IntPtr raw_handle {\n"
+             << scope_tab << scope_tab << "get { return handle; }\n"
+             << scope_tab << "}\n"
+             << scope_tab << "public System.IntPtr raw_klass {\n"
+             << scope_tab << scope_tab << "get { return efl.eo.Globals.efl_class_get(handle); }\n"
+             << scope_tab << "}\n"
+             << scope_tab << "public delegate void ConstructingMethod(" << string << " obj);\n"
+             << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
+             << ")] static extern System.IntPtr\n"
+             << scope_tab << scope_tab << class_get_name << "();\n"
+             << (class_type == "class" ? "" : "/*")
+             << scope_tab << "public " << string << "Concrete(efl.Object parent = null, ConstructingMethod init_cb=null)\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "System.IntPtr klass = " << class_get_name << "();\n"
+             << scope_tab << scope_tab << "System.IntPtr parent_ptr = System.IntPtr.Zero;\n"
+             << scope_tab << scope_tab << "if(parent != null)\n"
+             << scope_tab << scope_tab << scope_tab << "parent_ptr = parent.raw_handle;\n"
+             << scope_tab << scope_tab << "handle = efl.eo.Globals._efl_add_internal_start(\"file\", 0, klass, parent_ptr, 0, 0);\n"
+             << scope_tab << scope_tab << "if (init_cb != null) {\n"
+             << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
+             << scope_tab << scope_tab << "}\n"
+             << scope_tab << scope_tab << "handle = efl.eo.Globals._efl_add_end(handle, 0, 0);\n" // replace handle with the actual final handle
+             << scope_tab << scope_tab << "register_event_proxies();\n"
+             << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
+             << scope_tab << "}\n"
+             << (class_type == "class" ? "" : "*/")
+             << scope_tab << "public " << string << "Concrete(System.IntPtr raw)\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "handle = raw;\n"
+             << scope_tab << scope_tab << "register_event_proxies();\n"
+             << scope_tab << "}\n"
+             << scope_tab << "~" << string << "Concrete()\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "Dispose(false);\n"
+             << scope_tab << "}\n"
+             << scope_tab << "protected virtual void Dispose(bool disposing)\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
+             << scope_tab << scope_tab << scope_tab << "efl.eo.Globals.efl_unref(handle);\n"
+             << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
+             << scope_tab << scope_tab << "}\n"
+             << scope_tab << "}\n"
+             << scope_tab << "public void Dispose()\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "Dispose(true);\n"
+             << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
+             << scope_tab << "}\n"
+            )
+            .generate(sink
+              , std::make_tuple(
+                cls.cxx_name, cls.cxx_name, cls.cxx_name, cls.namespaces, cls.eolian_name
+                , cls.cxx_name, cls.namespaces, cls.eolian_name, cls.cxx_name
+                , cls.cxx_name)
+              , concrete_cxt))
+           return false;
+
+         if (!generate_static_cast_method(sink, cls.cxx_name, concrete_cxt))
+           return false;
+
+         if (!generate_equals_method(sink, concrete_cxt))
+           return false;
+
+         if (!generate_events(sink, cls, concrete_cxt))
+             return false;
+
+         if (!generate_events_registration(sink, cls, concrete_cxt))
+             return false;
+
+         // Concrete function definitions
+         if(!as_generator(*(function_definition))
+            .generate(sink, methods, concrete_cxt)) return false;
+
+         if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
+       }
+
+     // Inherit class
+     if(class_type == "class")
+       {
+        auto inherit_cxt = context_add_tag(class_context{class_context::inherit}, context);
+        bool cls_has_string_return = has_string_return(cls);
+        bool cls_has_stringshare_return = has_stringshare_return(cls);
+
+         if(!as_generator
+            (
+             "public " << class_type << " " << string << "Inherit : " << string << "\n{\n"
+             << scope_tab << "System.IntPtr handle;\n"
+             << scope_tab << "public static System.IntPtr klass = System.IntPtr.Zero;\n"
+             << scope_tab << "private static readonly object klassAllocLock = new object();\n"
+             << scope_tab << (cls_has_string_return ? ("public Dictionary<String, IntPtr> cached_strings = new Dictionary<String, IntPtr>();") : "") << "\n"
+             << scope_tab << (cls_has_stringshare_return ? ("public Dictionary<String, IntPtr> cached_stringshares = new Dictionary<String, IntPtr>();") : "") << "\n"
+             << scope_tab << "public System.IntPtr raw_handle {\n"
+             << scope_tab << scope_tab << "get { return handle; }\n"
+             << scope_tab << "}\n"
+             << scope_tab << "public System.IntPtr raw_klass {\n"
+             << scope_tab << scope_tab << "get { return klass; }\n"
+             << scope_tab << "}\n"
+             << scope_tab << "public delegate void ConstructingMethod(" << string << " obj);\n"
+             << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(inherit_cxt).actual_library_name(cls.filename)
+             << ")] static extern System.IntPtr\n"
+             << scope_tab << scope_tab << class_get_name << "();\n"
+             << scope_tab << "public " << string << "Inherit(efl.Object parent = null, ConstructingMethod init_cb=null)\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "if (klass == System.IntPtr.Zero) {\n"
+             << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
+             << scope_tab << scope_tab << scope_tab << scope_tab << "if (klass == System.IntPtr.Zero) {\n"
+             << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "klass = efl.eo.Globals.register_class(new efl.eo.Globals.class_initializer(" << string << "NativeInherit.class_initializer), " << class_get_name << "());\n"
+             //<< scope_tab << scope_tab << "klass = efl.eo.Globals.register_class(null/*new efl.eo.Globals.class_initializer(" << string << "NativeInherit.class_initializer)*/, " << class_get_name << "());\n"
+             << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
+             << scope_tab << scope_tab << scope_tab << "}\n"
+             << scope_tab << scope_tab << "}\n"
+             << scope_tab << scope_tab << "handle = efl.eo.Globals.instantiate_start(klass, parent);\n"
+             << scope_tab << scope_tab << "if (init_cb != null) {\n"
+             << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
+             << scope_tab << scope_tab << "}\n"
+             << scope_tab << scope_tab << "handle = efl.eo.Globals.instantiate_end(handle);\n"
+             << scope_tab << scope_tab << "efl.eo.Globals.data_set(this);\n"
+             << scope_tab << scope_tab << "register_event_proxies();\n"
+             << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
+             << scope_tab << "}\n"
+             << scope_tab << "~" << string << "Inherit()\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "Dispose(false);\n"
+             << scope_tab << "}\n"
+             << scope_tab << "protected virtual void Dispose(bool disposing)\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "if (handle != System.IntPtr.Zero) {\n"
+             << scope_tab << scope_tab << scope_tab << "efl.eo.Globals.efl_unref(handle);\n"
+             << scope_tab << scope_tab << scope_tab << "handle = System.IntPtr.Zero;\n"
+             << scope_tab << scope_tab << "}\n"
+             << scope_tab << "}\n"
+             << scope_tab << "public void Dispose()\n"
+             << scope_tab << "{\n"
+             << scope_tab << (cls_has_string_return ? "efl.eo.Globals.free_dict_values(cached_strings);" : "") << "\n"
+             << scope_tab << (cls_has_stringshare_return ? "efl.eo.Globals.free_stringshare_values(cached_stringshares);" : "") << "\n"
+             << scope_tab << scope_tab << "Dispose(true);\n"
+             << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
+             << scope_tab << "}\n"
+            )
+            .generate(sink
+              , std::make_tuple(
+                cls.cxx_name, cls.cxx_name, cls.cxx_name, cls.namespaces, cls.eolian_name
+                , cls.cxx_name, cls.cxx_name, cls.namespaces, cls.eolian_name, cls.cxx_name
+                , cls.cxx_name)
+              , inherit_cxt))
+           return false;
+
+         if (!generate_static_cast_method(sink, cls.cxx_name, inherit_cxt))
+           return false;
+
+         if (!generate_equals_method(sink, inherit_cxt))
+           return false;
+
+         if (!generate_events(sink, cls, inherit_cxt))
+             return false;
+
+         if (!generate_events_registration(sink, cls, inherit_cxt))
+             return false;
+
+         // Inherit function definitions
+         if(!as_generator(*(function_definition(true)))
+            .generate(sink, methods, inherit_cxt)) return false;
+
+         if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
+       }
+
+     std::size_t function_count = get_function_count(cls);
+
+     int function_registration_index = 0;
+     auto index_generator = [&function_registration_index]
+       {
+         return function_registration_index++;
+       };
+     
+     // Native Inherit class
+     if(class_type == "class")
+       {
+         auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context);
+         if(!as_generator
+            (
+             "public " << class_type << " " << string << "NativeInherit {\n"
+             << scope_tab << "public static byte class_initializer(IntPtr klass)\n"
+             << scope_tab << "{\n"
+             << scope_tab << scope_tab << "Efl_Op_Description[] descs = new Efl_Op_Description[" << grammar::int_ << "];\n"
+            )
+            .generate(sink, std::make_tuple(cls.cxx_name, function_count), inative_cxt))
+           return false;
+
+         // Native wrapper registration
+         if(!as_generator(*(function_registration(index_generator, cls)))
+            .generate(sink, methods, inative_cxt)) return false;
+
+         if(!as_generator
+            (   scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*" << function_count << ");\n"
+             << scope_tab << scope_tab << "IntPtr ptr = descs_ptr;\n"
+             << scope_tab << scope_tab << "for(int i = 0; i != " << function_count << "; ++i)\n"
+             << scope_tab << scope_tab << "{\n"
+             << scope_tab << scope_tab << scope_tab << "Marshal.StructureToPtr(descs[i], ptr, false);\n"
+             << scope_tab << scope_tab << scope_tab << "ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0]));\n"
+             << scope_tab << scope_tab << "}\n"
+             << scope_tab << scope_tab << "Efl_Object_Ops ops;\n"
+             << scope_tab << scope_tab << "ops.descs = descs_ptr;\n"
+             << scope_tab << scope_tab << "ops.count = (UIntPtr)" << function_count << ";\n"
+             << scope_tab << scope_tab << "IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));\n"
+             << scope_tab << scope_tab << "Marshal.StructureToPtr(ops, ops_ptr, false);\n"
+             << scope_tab << scope_tab << "efl.eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);\n"
+            ).generate(sink, attributes::unused, inative_cxt)) return false;
+         
+         
+         if(!as_generator(scope_tab << scope_tab << "return 1;\n"
+                          << scope_tab << "}\n")
+            .generate(sink, attributes::unused, inative_cxt)) return false;
+     
+         // Native method definitions
+         if(!as_generator(*(native_function_definition(cls)))
+            .generate(sink, methods, inative_cxt)) return false;
+
+         if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false;
+       }
+     
+     auto close_namespace = *(lit("} ")) << "\n";
+     if(!as_generator(close_namespace).generate(sink, namespaces, context)) return false;
+     
+     return true;
+   }
+
+   template <typename OutputIterator, typename Context>
+   bool generate_events_registration(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
+   {
+     // Event proxy registration
+     if (!as_generator(
+            scope_tab << "private void register_event_proxies()\n"
+            << scope_tab << "{\n"
+         )
+         .generate(sink, NULL, context))
+         return false;
+
+     // Generate event registrations here
+
+     // Assigning the delegates
+     for (auto&& e : cls.events)
+       {
+           if (!as_generator(scope_tab << scope_tab << "evt_" << grammar::string_replace(',', '_') << "_delegate = "
+                       << "new efl.Event_Cb(on_" << grammar::string_replace(',', '_') << "_NativeCallback);\n")
+                   .generate(sink, std::make_tuple(e.name, e.name), context))
+                return false;
+       }
+
+     for (auto&& c : cls.inherits)
+       {
+          attributes::klass_def klass(get_klass(c, NULL), NULL);
+
+          for (auto&& e : klass.events)
+            {
+               std::string wrapper_event_name = translate_inherited_event_name(e, klass);
+
+               if (!as_generator(scope_tab << scope_tab << "evt_" << wrapper_event_name << "_delegate = "
+                           << "new efl.Event_Cb(on_" << wrapper_event_name << "_NativeCallback);\n")
+                       .generate(sink, NULL, context))
+                   return false;
+            }
+       }
+     
+
+     if (!as_generator(
+            scope_tab << "}\n"
+                 ).generate(sink, NULL, context))
+         return false;
+
+     return true;
+   }
+
+   static std::string translate_inherited_event_name(const attributes::event_def &evt, const attributes::klass_def &klass)
+   {
+       std::stringstream s;
+
+       for (auto&& n : klass.namespaces)
+         {
+            s << n;
+            s << '_';
+         }
+       std::string evt_name = utils::to_uppercase(evt.name);
+       std::replace(evt_name.begin(), evt_name.end(), ',', '_');
+       s << klass.cxx_name << '_' << evt_name;
+       return s.str();
+   }
+
+   template <typename OutputIterator, typename Context>
+   bool generate_events(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
+   {
+
+     if (!has_events(cls))
+         return true;
+
+     if (!as_generator(scope_tab << "private readonly object eventLock = new object();\n"
+             << scope_tab << "private Dictionary<string, int> event_cb_count = new Dictionary<string, int>();\n")
+             .generate(sink, NULL, context))
+         return false;
+
+     // Callback registration functions
+     if (!as_generator(
+            scope_tab << "private bool add_cpp_event_handler(string key, efl.Event_Cb evt_delegate) {\n"
+            << scope_tab << scope_tab << "int event_count = 0;\n"
+            << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
+            << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
+            << scope_tab << scope_tab << "if (event_count == 0) {\n"
+            << scope_tab << scope_tab << scope_tab << "efl.kw_event.Description desc = new efl.kw_event.Description(key);\n"
+            << scope_tab << scope_tab << scope_tab << "bool result = efl.eo.Globals.efl_event_callback_priority_add(handle, desc, 0, evt_delegate, System.IntPtr.Zero);\n"
+            << scope_tab << scope_tab << scope_tab << "if (!result) {\n"
+            << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Failed to add event proxy for event ${key}\");\n"
+            << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
+            << scope_tab << scope_tab << scope_tab << "}\n"
+            << scope_tab << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
+            << scope_tab << scope_tab << "} \n"
+            << scope_tab << scope_tab << "event_cb_count[key]++;\n"
+            << scope_tab << scope_tab << "return true;\n"
+            << scope_tab << "}\n"
+            << scope_tab << "private bool remove_cpp_event_handler(string key, efl.Event_Cb evt_delegate) {\n"
+            << scope_tab << scope_tab << "int event_count = 0;\n"
+            << scope_tab << scope_tab << "if (!event_cb_count.TryGetValue(key, out event_count))\n"
+            << scope_tab << scope_tab << scope_tab << "event_cb_count[key] = event_count;\n"
+            << scope_tab << scope_tab << "if (event_count == 1) {\n"
+            << scope_tab << scope_tab << scope_tab << "efl.kw_event.Description desc = new efl.kw_event.Description(key);\n"
+            << scope_tab << scope_tab << scope_tab << "bool result = efl.eo.Globals.efl_event_callback_del(handle, desc, evt_delegate, System.IntPtr.Zero);\n"
+            << scope_tab << scope_tab << scope_tab << "if (!result) {\n"
+            << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Failed to remove event proxy for event ${key}\");\n"
+            << scope_tab << scope_tab << scope_tab << scope_tab << "return false;\n"
+            << scope_tab << scope_tab << scope_tab << "}\n"
+            << scope_tab << scope_tab << scope_tab << "eina.Error.RaiseIfOccurred();\n"
+            << scope_tab << scope_tab << "} else if (event_count == 0) {\n"
+            << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Trying to remove proxy for event ${key} when there is nothing registered.\");\n"
+            << scope_tab << scope_tab << scope_tab << "return false;\n"
+            << scope_tab << scope_tab << "} \n"
+            << scope_tab << scope_tab << "event_cb_count[key]--;\n"
+            << scope_tab << scope_tab << "return true;\n"
+            << scope_tab << "}\n"
+            )
+             .generate(sink, NULL, context))
+         return false;
+
+     // Self events
+     for (auto&& e : cls.events)
+       {
+           std::string upper_name = utils::to_uppercase(e.name);
+           std::replace(upper_name.begin(), upper_name.end(), ',', '_');
+           std::string upper_c_name = utils::to_uppercase(e.c_name);
+           std::string event_name = e.name;
+           std::replace(event_name.begin(), event_name.end(), ',', '_');
+
+           std::string wrapper_args_type = "EventArgs";
+           std::string wrapper_args_template = "";
+           std::string event_args = "EventArgs args = EventArgs.Empty;\n";
+
+           efl::eina::optional<grammar::attributes::type_def> etype = e.type;
+           if (etype.is_engaged())
+             {
+                wrapper_args_type = upper_name + "_Args";
+                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(get_csharp_type_visitor{});
+                arg_type += "args.arg = " + (*etype).original_type.visit(get_event_args_visitor{actual_arg_type}) + ";\n";
+
+                event_args = arg_type;
+             }
+           // Marshal.PtrToStructure for value types
+
+           // Wrapper event declaration
+          if(!as_generator(
+                scope_tab << "protected event EventHandler" << wrapper_args_template << " " << upper_name << ";\n"
+                << scope_tab << "protected void On_" << event_name << "(" << wrapper_args_type << " e)\n"
+                << scope_tab << "{\n"
+                << scope_tab << scope_tab << "EventHandler" << wrapper_args_template << " evt;\n"
+                << scope_tab << scope_tab << "lock (eventLock) {\n"
+                << scope_tab << scope_tab << scope_tab << "evt = " << upper_name << ";\n"
+                << scope_tab << scope_tab << "}\n"
+                << scope_tab << scope_tab << "if (evt != null) { evt(this, e); }\n"
+                << scope_tab << "}\n"
+                << scope_tab << "public void on_" << event_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)\n"
+                << scope_tab << "{\n"
+                << scope_tab << event_args
+                << scope_tab << scope_tab << "try {\n"
+                << scope_tab << scope_tab << scope_tab << "On_" << event_name << "(args);\n"
+                << scope_tab << scope_tab <<  "} catch (Exception e) {\n"
+                << scope_tab << scope_tab << scope_tab << "eina.Log.Warning(e.ToString());\n"
+                << scope_tab << scope_tab << scope_tab << "eina.Error.Set(eina.Error.EFL_ERROR);\n"
+                << scope_tab << scope_tab << "}\n"
+                << scope_tab << "}\n"
+                << scope_tab << "efl.Event_Cb evt_" << event_name << "_delegate;\n"
+                << scope_tab << "event EventHandler" << wrapper_args_template << " " << cls.cxx_name << "." << upper_name << "{\n")
+                  .generate(sink, NULL, context))
+              return false;
+
+          if (!as_generator(
+                      scope_tab << scope_tab << "add {\n"
+                      << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << "if (add_cpp_event_handler(key, this.evt_" << event_name << "_delegate))\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << upper_name << " += value;\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error adding proxy for event ${key}\");\n"
+                      << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
+                      << scope_tab << scope_tab << "}\n"
+                      << scope_tab << scope_tab << "remove {\n"
+                      << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << "if (remove_cpp_event_handler(key, this.evt_" << event_name << "_delegate))\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << upper_name << " -= value;\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
+                      << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error removing proxy for event ${key}\");\n"
+                      << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
+                      << scope_tab << scope_tab << "}\n"
+                      << scope_tab << "}\n")
+                  .generate(sink, NULL, context))
+              return false;
+       }
+
+     // Inherited events
+     for (auto&& c : cls.inherits)
+       {
+          attributes::klass_def klass(get_klass(c, NULL), NULL);
+
+          // FIXME Enable inherited events registration. Beware of conflicting events
+          for (auto&& e : klass.events)
+            {
+
+               std::string wrapper_evt_name = translate_inherited_event_name(e, klass);
+               std::string upper_name = utils::to_uppercase(e.name);
+               std::replace(upper_name.begin(), upper_name.end(), ',', '_');
+               std::string upper_c_name = utils::to_uppercase(e.c_name);
+
+               std::stringstream wrapper_args_type;
+               std::string wrapper_args_template;
+               std::string event_args = "EventArgs args = EventArgs.Empty;\n";
+
+               efl::eina::optional<grammar::attributes::type_def> etype = e.type;
+               if (etype.is_engaged())
+                 {
+                   for (auto&& i : klass.namespaces) 
+                     {
+                         wrapper_args_type << escape_keyword(utils::to_lowercase(i)) << ".";
+                     }
+                   wrapper_args_type << upper_name << "_Args";
+                   wrapper_args_template = "<" + wrapper_args_type.str() + ">";
+                   std::string arg_type = wrapper_args_type.str() + " args = new " + wrapper_args_type.str() + "();\n"; // = (*etype).original_type.visit(get_csharp_type_visitor{});
+                   std::string actual_arg_type = (*etype).original_type.visit(get_csharp_type_visitor{});
+                arg_type += "args.arg = " + (*etype).original_type.visit(get_event_args_visitor{actual_arg_type}) + ";\n";
+                   event_args = arg_type;
+                 }
+               else
+                 {
+                   wrapper_args_type << "EventArgs";
+                 }
+
+               if (!as_generator(
+                     scope_tab << "protected event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << ";\n"
+                     << scope_tab << "protected void On_" << wrapper_evt_name << "(" << wrapper_args_type.str() << " e)\n"
+                     << scope_tab << "{\n"
+                     << scope_tab << scope_tab << "EventHandler" << wrapper_args_template << " evt;\n"
+                     << scope_tab << scope_tab << "lock (eventLock) {\n"
+                     << scope_tab << scope_tab << scope_tab << "evt = " << wrapper_evt_name << ";\n"
+                     << scope_tab << scope_tab << "}\n"
+                     << scope_tab << scope_tab << "if (evt != null) { evt(this, e); }\n"
+                     << scope_tab << "}\n"
+                     << scope_tab << "efl.Event_Cb evt_" << wrapper_evt_name << "_delegate;\n"
+                     << scope_tab << "protected void on_" << wrapper_evt_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)"
+                     << scope_tab << "{\n"
+                     << scope_tab << event_args
+                    << scope_tab << scope_tab << "try {\n"
+                    << scope_tab << scope_tab << scope_tab << "On_" << wrapper_evt_name << "(args);\n"
+                    << scope_tab << scope_tab <<  "} catch (Exception e) {\n"
+                    << scope_tab << scope_tab << scope_tab << "eina.Log.Warning(e.ToString());\n"
+                    << scope_tab << scope_tab << scope_tab << "eina.Error.Set(eina.Error.EFL_ERROR);\n"
+                    << scope_tab << scope_tab << "}\n"
+                     << scope_tab << "}\n"
+                     << scope_tab << "event EventHandler" << wrapper_args_template << " " << *(lower_case[string] << ".") << klass.cxx_name << ".")
+                       .generate(sink, escape_namespace(klass.namespaces), context))
+                   return false;
+               if (!as_generator(upper_name << " {\n"
+                          << scope_tab << scope_tab << "add {\n"
+                          << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << "if (add_cpp_event_handler(key, this.evt_" << wrapper_evt_name << "_delegate))\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << wrapper_evt_name << " += value;\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error adding proxy for event ${key}\");\n"
+                          << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
+                          << scope_tab << scope_tab << "}\n"
+                          << scope_tab << scope_tab << "remove {\n"
+                          << scope_tab << scope_tab << scope_tab << "lock (eventLock) {\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << "if (remove_cpp_event_handler(key, this.evt_" << wrapper_evt_name << "_delegate))\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << wrapper_evt_name << " -= value;\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << "else\n"
+                          << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "eina.Log.Error(\"Error removing proxy for event ${key}\");\n"
+                          << scope_tab << scope_tab << scope_tab << "}\n" // End of lock block
+                          << scope_tab << scope_tab << "}\n"
+                     << scope_tab << "}\n")
+                 .generate(sink, NULL, context))
+                   return false;
+            }
+       }
+     return true;
+   }
+};
+
+struct klass const klass = {};
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+  
+template <>
+struct is_eager_generator<struct ::eolian_mono::klass> : std::true_type {};
+template <>
+struct is_generator<struct ::eolian_mono::klass> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed<struct ::eolian_mono::klass> : std::integral_constant<int, 1> {};
+}
+      
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
new file mode 100644 (file)
index 0000000..2765dcd
--- /dev/null
@@ -0,0 +1,246 @@
+#ifndef EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH
+#define EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+#include "namespace.hh"
+#include "type_impl.hh"
+
+namespace eolian_mono {
+
+namespace eina = efl::eina;
+
+namespace detail {
+
+template <typename Array, typename F, int N, typename A>
+eina::optional<bool> call_annotation_match(Array const (&array)[N], F f, A a)
+{
+   typedef Array const* iterator_type;
+   iterator_type match_iterator = &array[0], match_last = match_iterator + N;
+   match_iterator = std::find_if(match_iterator, match_last, f);
+   if(match_iterator != match_last)
+     {
+        return a(match_iterator->function());
+     }
+   return {nullptr};
+}
+  
+template <typename OutputIterator, typename Context>
+struct marshall_annotation_visitor_generate
+{
+   mutable OutputIterator sink;
+   Context const* context;
+   std::string c_type;
+   bool is_out;
+   bool is_return;
+   bool is_ptr;
+
+   typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
+   typedef bool result_type;
+  
+   bool operator()(attributes::regular_type_def const& regular) const
+   {
+      using attributes::regular_type_def;
+      struct match
+      {
+        eina::optional<std::string> name;
+        eina::optional<bool> has_own;
+        std::function<std::string()> function;
+      };
+      match const parameter_match_table[] =
+        {
+           // signed primitives
+          {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.I1)]"; }},
+          {"string", true, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
+          }},
+          {"string", false, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
+          }},
+          {"mstring", true, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
+          }},
+          {"mstring", false, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
+          }},
+          {"stringshare", true, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
+          }},
+          {"stringshare", false, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
+          }},
+          {"any_value_ptr", true, [&] {
+                    return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshalerOwn))]";
+          }},
+          {"any_value_ptr", false, [&] {
+                    return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshaler))]";
+          }},
+        };
+      match const return_match_table[] =
+        {
+           // signed primitives
+          {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.I1)]"; }},
+          {"string", true, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
+          }},
+          {"string", false, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
+          }},
+          {"mstring", true, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
+          }},
+          {"mstring", false, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
+          }},
+          {"stringshare", true, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
+          }},
+          {"stringshare", false, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
+          }},
+          {"any_value_ptr", true, [&] {
+                    return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshalerOwn))]";
+          }},
+          {"any_value_ptr", false, [&] {
+                    return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(eina.ValueMarshaler))]";
+          }},
+        };
+
+        if(eina::optional<bool> b = call_annotation_match
+           ((is_return ? return_match_table : parameter_match_table)
+          , [&] (match const& m)
+          {
+            return (!m.name || *m.name == regular.base_type)
+            && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
+            ;
+          }
+          , [&] (std::string const& string)
+          {
+            std::copy(string.begin(), string.end(), sink);
+            return true;
+          }))
+        {
+           return *b;
+        }
+      else
+        {
+          return true;
+        }
+   }
+   bool operator()(attributes::klass_name const& klass_name) const
+   {
+     const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
+     const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
+     std::vector<std::string> namespaces = escape_namespace(klass_name.namespaces);
+     return as_generator
+       ((is_return ? return_prefix : no_return_prefix)
+        << *(lower_case[string] << ".") << string
+        << "Concrete, efl.eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
+        ).generate(sink, std::make_tuple(namespaces, klass_name.eolian_name), *context);
+   }
+   bool operator()(attributes::complex_type_def const&) const
+   {
+     return true;
+   }
+};
+
+template <typename OutputIterator, typename Context>
+struct marshall_native_annotation_visitor_generate
+{
+   mutable OutputIterator sink;
+   Context const* context;
+   std::string c_type;
+   bool is_out;
+   bool is_return;
+   bool is_ptr;
+
+   typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
+   typedef bool result_type;
+
+   bool operator()(attributes::regular_type_def const& regular) const
+   {
+      using attributes::regular_type_def;
+      struct match
+      {
+        eina::optional<std::string> name;
+        eina::optional<bool> has_own;
+        std::function<std::string()> function;
+      };
+      match const parameter_match_table[] =
+        {
+           // signed primitives
+          {"bool", nullptr, [&] { return " [MarshalAs(UnmanagedType.I1)]"; }},
+          {"string", true, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
+          }},
+          {"string", false, [&] {
+                if (is_out)
+                   return "";
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringKeepOwnershipMarshaler))]";
+          }},
+          {"stringshare", true, [&] {
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
+          }},
+          {"stringshare", false, [&] {
+                if (is_out)
+                    return "";
+                return " [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringshareKeepOwnershipMarshaler))]";
+          }},
+        };
+      match const return_match_table[] =
+        {
+           // signed primitives
+          {"bool", nullptr, [&] { return " [return: MarshalAs(UnmanagedType.I1)]"; }},
+          {"string", true, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringPassOwnershipMarshaler))]";
+          }},
+          {"string", false, [&] { return ""; }},
+          {"stringshare", true, [&] {
+                return " [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(efl.eo.StringsharePassOwnershipMarshaler))]";
+          }},
+          {"stringshare", false, [&] { return ""; }},
+        };
+
+        if(eina::optional<bool> b = call_annotation_match
+           ((is_return ? return_match_table : parameter_match_table)
+          , [&] (match const& m)
+          {
+            return (!m.name || *m.name == regular.base_type)
+            && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
+            ;
+          }
+          , [&] (std::string const& string)
+          {
+            std::copy(string.begin(), string.end(), sink);
+            return true;
+          }))
+        {
+           return *b;
+        }
+      else
+        {
+          return true;
+        }
+   }
+   bool operator()(attributes::klass_name const& klass_name) const
+   {
+     const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
+     const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(efl.eo.MarshalTest<";
+     std::vector<std::string> namespaces = escape_namespace(klass_name.namespaces);
+     return as_generator
+       ((is_return ? return_prefix : no_return_prefix)
+        << *(lower_case[string] << ".") << string
+        << "Concrete, efl.eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
+        ).generate(sink, std::make_tuple(namespaces, klass_name.eolian_name), *context);
+   }
+   bool operator()(attributes::complex_type_def const&) const
+   {
+     return true;
+   }
+};
+
+      
+} }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type.hh b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
new file mode 100644 (file)
index 0000000..a946e15
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef EOLIAN_MONO_MARSHALL_TYPE_HH
+#define EOLIAN_MONO_MARSHALL_TYPE_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+
+namespace eolian_mono {
+
+namespace attributes = efl::eolian::grammar::attributes;
+namespace detail {
+template <typename OutputIterator, typename Context>
+struct marshall_type_visitor_generate;
+template <typename OutputIterator, typename Context>
+struct marshall_annotation_visitor_generate;
+template <typename OutputIterator, typename Context>
+struct marshall_native_annotation_visitor_generate;
+}
+struct marshall_type_generator
+{
+   marshall_type_generator(bool is_return = false)
+     : is_return(is_return) {}
+  
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
+   {
+      return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr });
+   }
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      return param.type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
+            , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
+   }
+
+   bool is_return;
+};
+
+struct marshall_annotation_generator
+{
+   marshall_annotation_generator(bool is_return = false)
+     : is_return(is_return) {}
+  
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
+   {
+      return type.original_type.visit(detail::marshall_annotation_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
+   }
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      return param.type.original_type.visit(detail::marshall_annotation_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
+            , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
+   }
+
+   bool is_return;
+};
+
+struct marshall_native_annotation_generator
+{
+   marshall_native_annotation_generator(bool is_return = false)
+     : is_return(is_return) {}
+
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
+   {
+      return type.original_type.visit(detail::marshall_native_annotation_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
+   }
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      return param.type.original_type.visit(detail::marshall_native_annotation_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
+            , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
+   }
+
+   bool is_return;
+};
+  
+struct marshall_type_terminal
+{
+  marshall_type_generator const operator()(bool is_return) const
+  {
+    return marshall_type_generator(is_return);
+  }
+} const marshall_type = {};
+
+marshall_type_generator const as_generator(marshall_type_terminal)
+{
+  return marshall_type_generator{};
+}
+
+struct marshall_annotation_terminal
+{
+  marshall_annotation_generator const operator()(bool is_return) const
+  {
+    return marshall_annotation_generator(is_return);
+  }
+} const marshall_annotation = {};
+
+marshall_annotation_generator const as_generator(marshall_annotation_terminal)
+{
+  return marshall_annotation_generator{};
+}
+
+
+struct marshall_native_annotation_terminal
+{
+  marshall_native_annotation_generator const operator()(bool is_return) const
+  {
+    return marshall_native_annotation_generator(is_return);
+  }
+} const marshall_native_annotation = {};
+
+marshall_native_annotation_generator const as_generator(marshall_native_annotation_terminal)
+{
+  return marshall_native_annotation_generator{};
+}
+  
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::marshall_type_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_type_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_type_terminal> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::marshall_type_generator> : std::integral_constant<int, 1> {};  
+template <>
+struct attributes_needed< ::eolian_mono::marshall_type_terminal> : std::integral_constant<int, 1> {};  
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::marshall_annotation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_annotation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_annotation_terminal> : std::true_type {};
+
+template <>
+struct is_eager_generator< ::eolian_mono::marshall_native_annotation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_native_annotation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_native_annotation_terminal> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::marshall_annotation_generator> : std::integral_constant<int, 1> {};  
+template <>
+struct attributes_needed< ::eolian_mono::marshall_annotation_terminal> : std::integral_constant<int, 1> {};  
+
+template <>
+struct attributes_needed< ::eolian_mono::marshall_native_annotation_generator> : std::integral_constant<int, 1> {};
+template <>
+struct attributes_needed< ::eolian_mono::marshall_native_annotation_terminal> : std::integral_constant<int, 1> {};
+}
+      
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
new file mode 100644 (file)
index 0000000..caeb17f
--- /dev/null
@@ -0,0 +1,263 @@
+#ifndef EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH
+#define EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+#include "namespace.hh"
+#include "type_impl.hh"
+#include "generation_contexts.hh"
+
+namespace eolian_mono {
+
+namespace eina = efl::eina;
+
+namespace detail {
+  
+template <typename OutputIterator, typename Context>
+struct marshall_type_visitor_generate
+{
+   mutable OutputIterator sink;
+   Context const* context;
+   std::string c_type;
+   bool is_out;
+   bool is_return;
+   bool is_ptr;
+
+   typedef marshall_type_visitor_generate<OutputIterator, Context> visitor_type;
+   typedef bool result_type;
+  
+   bool operator()(attributes::regular_type_def const& regular) const
+   {
+      using attributes::regular_type_def;
+      bool is_inherit_native = context_find_tag<class_context>(*context).current_wrapper_kind == class_context::inherit_native;
+
+      struct match
+      {
+        eina::optional<std::string> name;
+        eina::optional<bool> has_own;
+        std::function<attributes::type_def::variant_type()> function;
+      }
+      const match_table[] =
+        {
+           // signed primitives
+           {"string", true, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                // if(is_out || is_return)
+                return replace_base_type(r, " System.String");
+                // else return replace_base_type(r, " ::efl::eina::string_view");
+              }}
+           , {"string", false, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                if (is_inherit_native && (is_return || is_out))
+                    return replace_base_type(r, " System.IntPtr");
+                return replace_base_type(r, " System.String");
+              }}
+           , {"mstring", true, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                // if(is_out || is_return)
+                return replace_base_type(r, " System.String");
+                // else return replace_base_type(r, " ::efl::eina::string_view");
+              }}
+           , {"mstring", false, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                if (is_inherit_native && (is_return || is_out))
+                    return replace_base_type(r, " System.IntPtr");
+                return replace_base_type(r, " System.String");
+              }}
+           , {"stringshare", true, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                return replace_base_type(r, " System.String");
+              }}
+           , {"stringshare", false, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                if (is_inherit_native && (is_return || is_out))
+                   return replace_base_type(r, " System.IntPtr");
+                else
+                   return replace_base_type(r, " System.String");
+              }}
+           , {"Binbuf", true, [&]
+              {
+                regular_type_def r = regular;
+                r.base_type = " System.IntPtr";
+                r.namespaces.clear();
+                return r;
+              }}
+           , {"Binbuf", false, [&]
+              {
+                regular_type_def r = regular;
+                r.base_type = " System.IntPtr";
+                r.namespaces.clear();
+                return r;
+              }}
+           , {"any_value", true, [&]
+               {
+                regular_type_def r = regular;
+                r.namespaces.clear();
+                if (is_ptr)
+                    r.base_type = " eina.Value";
+                else
+                    r.base_type = " eina.Value_Native";
+                return r;
+               }}
+           , {"any_value", false, [&]
+               {
+                regular_type_def r = regular;
+                r.namespaces.clear();
+                if (is_ptr)
+                    r.base_type = " eina.Value";
+                else
+                    r.base_type = " eina.Value_Native";
+                return r;
+               }}
+           , {"any_value_ptr", true, [&]
+               {
+                regular_type_def r = regular;
+                r.namespaces.clear();
+                r.base_type = " eina.Value";
+                return r;
+               }}
+           , {"any_value_ptr", false, [&]
+               {
+                regular_type_def r = regular;
+                r.namespaces.clear();
+                r.base_type = " eina.Value";
+                return r;
+               }}
+           , {"void", nullptr, [&]
+               {
+                regular_type_def r = regular;
+                r.namespaces.clear();
+                if (is_out) // @inout too
+                    r.base_type = " System.IntPtr";
+                else
+                    r.base_type = " void";
+                return r;
+               }}
+        };
+
+        if(eina::optional<bool> b = call_match
+         (match_table
+          , [&] (match const& m)
+          {
+            return (!m.name || *m.name == regular.base_type)
+            && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
+            ;
+          }
+          , [&] (attributes::type_def::variant_type const& v)
+          {
+            return v.visit(*this); // we want to keep is_out info
+          }))
+        {
+           return *b;
+        }
+      else
+        {
+          return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return}(regular);
+        }
+   }
+   bool operator()(attributes::klass_name klass_name) const
+   {
+     return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return}(klass_name);
+     // return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
+   }
+   bool operator()(attributes::complex_type_def const& complex) const
+   {
+      using attributes::regular_type_def;
+      using attributes::qualifier_info;
+      struct match
+      {
+        eina::optional<std::string> name;
+        eina::optional<bool> has_own;
+        eina::optional<bool> is_const;
+        std::function<attributes::type_def::variant_type()> function;
+      } const matches[] =
+      {
+        {"array", nullptr, nullptr, [&]
+           {
+              return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
+           }
+        }
+        ,{"inarray", nullptr, nullptr, [&]
+           {
+              return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
+           }
+        }
+        ,{"list", nullptr, nullptr, [&]
+           {
+              return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
+           }
+        }
+        ,{"inlist", nullptr, nullptr, [&]
+           {
+              return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
+           }
+        }
+        ,{"hash", nullptr, nullptr, [&]
+           {
+              return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
+           }
+        }
+        ,{"iterator", nullptr, nullptr, [&]
+           {
+              return regular_type_def{" System.IntPtr", complex.outer.base_qualifier, {}};
+           }
+        }
+      };
+
+      auto default_match = [&] (attributes::complex_type_def const& complex)
+        {
+          regular_type_def no_pointer_regular = complex.outer;
+          // std::vector<attributes::pointer_indirection> pointers;
+          // pointers.swap(no_pointer_regular.pointers);
+          // if(is_out)
+          //   pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
+          return visitor_type{sink, context, c_type, false}(no_pointer_regular)
+            && as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
+          ;
+            // && detail::generate_pointers(sink, pointers, *context, false);
+        };
+
+      if(eina::optional<bool> b = call_match
+         (matches
+          , [&] (match const& m)
+          {
+            return (!m.name || *m.name == complex.outer.base_type)
+            && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own))
+            && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const));
+          }
+          , [&] (attributes::type_def::variant_type const& v)
+          {
+            if(v.empty())
+              return true;
+            else if(attributes::complex_type_def const* complex
+               = eina::get<attributes::complex_type_def>(&v))
+              return default_match(*complex);
+            else
+              return v.visit(*this);
+          }))
+        {
+           return *b;
+        }
+
+      //return default_match(complex);
+     return visitor_generate<OutputIterator, Context>{sink, context, c_type, is_out, is_return}(complex);
+     // return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
+   }
+};
+      
+} }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
new file mode 100644 (file)
index 0000000..6b40829
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef EOLIAN_MONO_NAME_HELPERS_HH
+#define EOLIAN_MONO_NAME_HELPERS_HH
+
+#include <algorithm>
+#include <cctype>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace eolian_mono {
+
+namespace name_helpers {
+
+static const std::vector<std::string> verbs =
+  {
+    "add",
+    "get",
+    "is",
+    "del",
+    "thaw",
+    "freeze",
+    "save",
+    "wait",
+    "eject",
+    "raise",
+    "lower",
+    "load",
+    "dup",
+    "reset",
+    "unload",
+    "close",
+    "set",
+    "interpolate",
+    "has",
+    "grab",
+    "check",
+    "find",
+    "ungrab",
+    "unset",
+    "clear",
+    "pop",
+    "new",
+    "peek",
+    "push",
+    "update",
+    "show",
+    "move",
+    "hide",
+    "calculate",
+    "resize",
+    "attach",
+    "pack",
+    "unpack",
+    "emit",
+    "call",
+    "append"
+  };
+
+const std::vector<std::string> not_verbs =
+  {
+    "below",
+    "above",
+    "name",
+    "unfreezable",
+    "value",
+    "r",
+    "g",
+    "b",
+    "a",
+    "finalize",
+    "destructor",
+    "to",
+    "circle",
+    "rect",
+    "path",
+    "commands",
+    "type",
+    "colorspace"
+    "op",
+    "type",
+    "properties",
+    "status",
+    "status",
+    "relative",
+    "ptr",
+    "pair",
+    "pos",
+    "end"
+  };
+
+void reorder_verb(std::vector<std::string> &names)
+{
+  if (names.size() <= 1)
+    return;
+
+  std::string verb = names.back();
+
+  if (std::find(verbs.begin(), verbs.end(), verb) != verbs.end())
+    {
+       names.pop_back();
+       names.insert(names.begin(), verb);
+    }
+}
+
+std::vector<std::string> split(std::string const &input, char delim)
+{
+  std::stringstream ss(input);
+  std::string name;
+  std::vector<std::string> names;
+
+  while (std::getline(ss, name, delim)) {
+    if (!name.empty())
+      names.push_back(name);
+  }
+  return names;
+}
+
+std::string pascal_case(const std::vector<std::string> &names)
+{
+    std::vector<std::string> outv(names.size());
+    std::stringstream osstream;
+
+    std::transform(names.begin(), names.end(), outv.begin(),
+          [](std::string name) { 
+            name[0] = std::toupper(name[0]);
+            return name;
+          });
+
+    std::copy(outv.begin(), outv.end(), std::ostream_iterator<std::string>(osstream, ""));
+
+    return osstream.str();
+}
+
+} // namespace name_helpers
+
+} // namespace eolian_mono
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/namespace.hh b/src/bin/eolian_mono/eolian/mono/namespace.hh
new file mode 100644 (file)
index 0000000..b0f1ddb
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef EOLIAN_MONO_NAMESPACE_HH
+#define EOLIAN_MONO_NAMESPACE_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+#include "grammar/type.hpp"
+#include "using_decl.hh"
+#include "keyword.hh"
+
+namespace eolian_mono {
+
+std::vector<std::string> escape_namespace(std::vector<std::string> namespaces)
+{
+  // if(namespaces.empty())
+  //   namespaces.push_back("nonamespace");
+  // else
+    {
+      for(auto&& i : namespaces)
+        i = escape_keyword(i);
+    }
+  return namespaces;
+}
+  
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
new file mode 100644 (file)
index 0000000..dcbb0a4
--- /dev/null
@@ -0,0 +1,1171 @@
+#ifndef EOLIAN_MONO_PARAMETER_HH
+#define EOLIAN_MONO_PARAMETER_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+#include "marshall_type.hh"
+#include "type.hh"
+#include "using_decl.hh"
+#include "keyword.hh"
+
+
+namespace eolian_mono {
+    struct parameter_generator;
+    struct marshall_parameter_generator;
+    struct argument_generator;
+    struct argument_invocation_generator;
+    struct native_argument_invocation_generator;
+    struct native_convert_in_variable_generator;
+    struct convert_in_variable_generator;
+    struct native_convert_out_variable_generator;
+    struct convert_out_variable_generator;
+    struct convert_out_assign_generator;
+    struct native_convert_out_assign_parameterized;
+    struct native_convert_out_assign_generator;
+    struct convert_return_generator;
+    struct convert_return_variable_generator;
+    struct native_convert_return_generator;
+    struct native_convert_return_parameterized;
+    struct native_convert_return_variable_generator;
+    struct convert_function_pointer_generator;
+    struct native_convert_function_pointer_generator;
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::parameter_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::parameter_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::parameter_generator> : std::integral_constant<int, 1> {};  
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::marshall_parameter_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::marshall_parameter_generator> : std::integral_constant<int, 1> {};  
+}
+      
+template <>
+struct is_eager_generator< ::eolian_mono::argument_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::argument_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::argument_generator> : std::integral_constant<int, 1> {};  
+}
+      
+template <>
+struct is_eager_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::argument_invocation_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_argument_invocation_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_argument_invocation_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_convert_in_variable_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::convert_in_variable_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::convert_in_variable_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::convert_out_variable_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::convert_out_variable_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_out_variable_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_convert_out_variable_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::convert_out_assign_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::convert_out_assign_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::convert_return_variable_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::convert_return_variable_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::convert_return_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::convert_return_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::convert_return_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_out_assign_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_out_assign_parameterized> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_convert_out_assign_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_return_variable_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_convert_return_variable_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_return_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_return_parameterized> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_convert_return_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::convert_function_pointer_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::convert_function_pointer_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::native_convert_function_pointer_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {};
+}
+
+} } }
+
+namespace eolian_mono {
+
+namespace attributes = efl::eolian::grammar::attributes;
+
+// Helper function to query parameter attributes
+const static bool WANT_OWN = true;
+const static bool WANT_OUT = true;
+inline bool param_is_acceptable(attributes::parameter_def const &param, std::string c_type, bool want_own, bool want_out)
+{
+   return (param.type.c_type == c_type)
+          && ((param.direction != attributes::parameter_direction::in) == want_out)
+          && (param.type.has_own == want_own);
+}
+
+inline bool param_should_use_out_var(attributes::parameter_def const& param, bool native)
+{
+   if ((native && param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT))
+           || (native && param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
+           || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
+           || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT)
+      )
+     return true;
+
+   return false;
+}
+
+inline bool param_should_use_in_var(attributes::parameter_def const& param, bool /*native*/)
+{
+    if (param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Array *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_List *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_List *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_List *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Value", WANT_OWN, !WANT_OUT)
+        || param_is_acceptable(param, "Eina_Value", !WANT_OWN, !WANT_OUT)
+       )
+        return true;
+
+    return false;
+}
+
+inline std::string out_variable_name(std::string const& param_name)
+{
+   return "_out_" + escape_keyword(param_name);
+}
+
+inline std::string in_variable_name(std::string const& param_name)
+{
+   return "_in_" + escape_keyword(param_name);
+}
+
+inline std::string direction_modifier(attributes::parameter_def const& param)
+{
+   if (param.direction == attributes::parameter_direction::inout)
+     {
+        return " ref ";
+     }
+   else if (param.direction != attributes::parameter_direction::in)
+     {
+        if (param.type.c_type == "Eina_Slice" || param.type.c_type == "Eina_Rw_Slice")
+           return " ref ";
+        else
+           return " out ";
+     }
+   return " ";
+}
+
+struct is_fp_visitor
+{
+   typedef is_fp_visitor visitor_type;
+   typedef bool result_type;
+
+   bool operator()(grammar::attributes::regular_type_def const &type) const
+   {
+      return type.is_function_ptr;
+   }
+
+   template<typename T>
+   bool operator()(T const &) const
+   {
+      return false;
+   }
+};
+
+struct type_name_visitor
+{
+   typedef type_name_visitor visitor_type;
+   typedef std::string result_type;
+
+   std::string operator()(grammar::attributes::regular_type_def const &type) const
+   {
+      std::stringstream type_name;
+      for (auto&& i : escape_namespace(type.namespaces))
+        type_name << i << ".";
+      type_name << type.base_type;
+      return type_name.str();
+   }
+
+   template<typename T>
+   std::string operator()(T const &) const
+   {
+       return "";
+   }
+};
+
+struct parameter_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+     std::string param_name = escape_keyword(param.param_name);
+
+     return as_generator(
+               direction_modifier(param) << type << " " << string
+          ).generate(sink, std::make_tuple(param, param_name), context);
+
+   }
+} const parameter {};
+
+struct marshall_parameter_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      std::string param_name = escape_keyword(param.param_name);
+
+      if (!param.type.original_type.visit(is_fp_visitor{}))
+         return as_generator(
+                 direction_modifier(param) << marshall_type << " " << string
+            ).generate(sink, std::make_tuple(param, param_name), context);
+
+      return as_generator(
+               "IntPtr " << param_name << "_data, " << type << "Internal " << param_name << ", Eina_Free_Cb "
+               << param_name << "_free_cb"
+           ).generate(sink, param, context);
+   }
+} const marshall_parameter {};
+  
+struct argument_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+     std::string param_name = escape_keyword(param.param_name);
+     std::string direction = direction_modifier(param);
+
+     if (!param.type.original_type.visit(is_fp_visitor{}))
+       return as_generator(
+                direction << param_name
+           ).generate(sink, attributes::unused, context);
+
+    return as_generator(
+            param_name << "_data, " << param_name << ", " << param_name << "_free_cb"
+          ).generate(sink, attributes::unused, context);
+
+   }
+
+} const argument {};
+
+struct native_argument_invocation_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+     std::string arg = direction_modifier(param);
+
+     if (param_should_use_out_var(param, true))
+       arg += out_variable_name(param.param_name);
+     else if (param_should_use_in_var(param, true))
+       arg += in_variable_name(param.param_name);
+     else if (param.type.original_type.visit(is_fp_visitor{}))
+       {
+          arg += escape_keyword(param.param_name) + "_wrapper.ManagedCb";
+       }
+     else // FIXME Wrap data and C function pointers into some kind of structure.
+       arg += escape_keyword(param.param_name);
+
+     return as_generator(arg).generate(sink, attributes::unused, context);
+   }
+} const native_argument_invocation {};
+
+// Generates the correct parameter name when invoking a function
+struct argument_invocation_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+     std::string arg = direction_modifier(param);
+
+     if (param_should_use_out_var(param, false))
+       arg += out_variable_name(param.param_name);
+     else if (param_should_use_in_var(param, false))
+       arg += in_variable_name(param.param_name);
+     else if (param.type.original_type.visit(is_fp_visitor{}))
+       {
+          std::string param_name = escape_keyword(param.param_name);
+          return as_generator("GCHandle.ToIntPtr(" << param_name << "_handle), " << type << "Wrapper.Cb, efl.eo.Globals.free_gchandle")
+             .generate(sink, param.type, context);
+       }
+     else
+       arg += escape_keyword(param.param_name);
+
+     return as_generator(arg).generate(sink, attributes::unused, context);
+   }
+} const argument_invocation {};
+
+struct native_convert_in_variable_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param.direction != attributes::parameter_direction::in)
+        return true;
+
+      if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
+        {
+           return as_generator(
+                "var " << string << " = new eina.Binbuf(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
+             ).generate(sink, in_variable_name(param.param_name), context);
+        }
+     else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *")
+       {
+          attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+          if (!complex || complex->subtypes.size() != 2)
+            return false;
+          return as_generator(
+               "var " << string << " = new " << type << "(" << escape_keyword(param.param_name)
+               << ", " << (param.type.has_own ? "true" : "false")
+               << ", " << (complex->subtypes.front().has_own ? "true" : "false")
+               << ", " << (complex->subtypes.back().has_own ? "true" : "false")
+               << ");\n"
+            ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
+       }
+     else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *"
+              || param.type.c_type == "Eina_Inarray *" || param.type.c_type == "const Eina_Inarray *"
+              || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
+              || param.type.c_type == "Eina_Inlist *" || param.type.c_type == "const Eina_Inlist *"
+              || param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *"
+     )
+       {
+          attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+          if (!complex)
+            return false;
+          return as_generator(
+               "var " << string << " = new " << type << "(" << escape_keyword(param.param_name)
+               << ", " << (param.type.has_own ? "true" : "false")
+               << ", " << (complex->subtypes.front().has_own ? "true" : "false")
+               << ");\n"
+            ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
+       }
+     else if (param.type.c_type == "Eina_Value")
+       {
+          return as_generator(
+                "var " << string << " = new " << type << "(" << string << ");\n"
+                  ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type, param.param_name), context);
+       }
+      return true;
+   }
+
+} const native_convert_in_variable {};
+
+struct convert_in_variable_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param.direction != attributes::parameter_direction::in)
+        return true;
+
+      if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
+        {
+           auto var_name = in_variable_name(param.param_name);
+           if (!as_generator(
+                 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
+              ).generate(sink, var_name, context))
+             return false;
+           if (param.type.has_own)
+             {
+                return as_generator(
+                     escape_keyword(param.param_name) << ".Own = false;\n"
+                  ).generate(sink, attributes::unused, context);
+             }
+        }
+      else if (param.type.c_type == "Eina_Hash *" || param.type.c_type == "const Eina_Hash *")
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex || complex->subtypes.size() != 2)
+             return false;
+           auto var_name = in_variable_name(param.param_name);
+           if (!as_generator(
+                 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
+              ).generate(sink, var_name, context))
+             return false;
+           if (param.type.has_own && !as_generator(
+                     escape_keyword(param.param_name) << ".SetOwn(false);\n"
+                  ).generate(sink, attributes::unused, context))
+             return false;
+           if (complex->subtypes.front().has_own && !as_generator(
+                     escape_keyword(param.param_name) << ".SetOwnKey(false);\n"
+                  ).generate(sink, attributes::unused, context))
+             return false;
+           if (complex->subtypes.back().has_own && !as_generator(
+                     escape_keyword(param.param_name) << ".SetOwnValue(false);\n"
+                     << escape_keyword(param.param_name) << ".UnSetFreeCb();\n"
+                  ).generate(sink, attributes::unused, context))
+             return false;
+        }
+      else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *"
+               || param.type.c_type == "Eina_Inarray *" || param.type.c_type == "const Eina_Inarray *"
+               || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
+               || param.type.c_type == "Eina_Inlist *" || param.type.c_type == "const Eina_Inlist *"
+               || param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *"
+      )
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex)
+             return false;
+           auto var_name = in_variable_name(param.param_name);
+           if (!as_generator(
+                 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n"
+              ).generate(sink, var_name, context))
+             return false;
+           if (param.type.has_own && !as_generator(
+                     escape_keyword(param.param_name) << ".Own = false;\n"
+                  ).generate(sink, attributes::unused, context))
+             return false;
+           if (complex->subtypes.front().has_own && !as_generator(
+                     escape_keyword(param.param_name) << ".OwnContent = false;\n"
+                  ).generate(sink, attributes::unused, context))
+             return false;
+        }
+     else if (param.type.c_type == "Eina_Value")
+       {
+          return as_generator(
+                "var " << string << " = " << string << ".GetNative();\n"
+                  ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.param_name), context);
+       }
+      return true;
+   }
+
+} const convert_in_variable {};
+  
+struct convert_out_variable_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           return as_generator(
+               "System.IntPtr " << string << " = System.IntPtr.Zero;\n"
+             ).generate(sink, out_variable_name(param.param_name), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           return as_generator(
+               "System.IntPtr " << string << " = System.IntPtr.Zero;\n"
+             ).generate(sink, out_variable_name(param.param_name), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
+        {
+           return as_generator(
+                 marshall_type << " " << string << ";\n"
+                   ).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name)), context);
+        }
+      return true;
+   }
+
+} const convert_out_variable {};
+
+struct native_convert_out_variable_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT)
+          || param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
+        {
+           return as_generator(
+                  type << " " << string << " = default(" << type << ");\n"
+             ).generate(sink, std::make_tuple(param, out_variable_name(param.param_name), param), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           return as_generator(
+               "eina.Binbuf " << string << " = default(eina.Binbuf);\n"
+             ).generate(sink, out_variable_name(param.param_name), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex)
+             return false;
+           return as_generator(
+               type << " " << string << " = default(" << type << ");\n"
+             ).generate(sink, std::make_tuple(param.type, out_variable_name(param.param_name), param.type), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
+        {
+           return as_generator(
+                 string << " = default(" << marshall_type << ");\n"
+                 << type << " " << string << " =  null;\n"
+                   ).generate(sink, std::make_tuple(param.param_name, param, param, out_variable_name(param.param_name)), context);
+        }
+      else if (param.direction == attributes::parameter_direction::out)
+        {
+           // Assign a default value to the out variable in case we end up in the catch clause.
+           return as_generator(
+                   string << " = default(" << type << ");"
+                   ).generate(sink, std::make_tuple(param.param_name, param), context);
+        }
+      return true;
+   }
+
+} const native_convert_out_variable {};
+
+struct convert_out_assign_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           return as_generator(
+               string << " = new eina.Binbuf(" << string << ", " << (param.type.has_own ? "true" : "false") << ");\n"
+             ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex || complex->subtypes.size() != 2)
+             return false;
+           return as_generator(
+               string << " = new " << type << "(" << string
+               << ", " << (param.type.has_own ? "true" : "false")
+               << ", " << (complex->subtypes.front().has_own ? "true" : "false")
+               << ", " << (complex->subtypes.back().has_own ? "true" : "false")
+               << ");\n"
+             ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex)
+             return false;
+           return as_generator(
+               string << " = new " << type << "(" << string
+               << ", " << (param.type.has_own ? "true" : "false")
+               << ", " << (complex->subtypes.front().has_own ? "true" : "false")
+               << ");\n"
+             ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Value", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Value", !WANT_OWN, WANT_OUT))
+        {
+           return as_generator(
+                 string << " = new " << type << "(" << string << ");\n"
+                   ).generate(sink, std::make_tuple(param.param_name, param.type, out_variable_name(param.param_name)), context);
+        }
+      return true;
+   }
+
+} const convert_out_assign {};
+
+struct convert_return_variable_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
+   {
+     if (ret_type.c_type != "void")
+       return as_generator("var _ret_var = ").generate(sink, attributes::unused, context);
+     return true;
+   }
+
+} const convert_return_variable {};
+
+
+struct convert_return_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
+   {
+     if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *")
+       {
+           if (!as_generator("var _binbuf_ret = new eina.Binbuf(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ");\n"
+                             << scope_tab << scope_tab << "return _binbuf_ret;\n")
+             .generate(sink, attributes::unused, context))
+             return false;
+       }
+     else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *")
+       {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
+           if (!complex || complex->subtypes.size() != 2)
+             return false;
+           if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"}
+                   << ", " << (complex->subtypes.front().has_own ? "true" : "false")
+                   << ", " << (complex->subtypes.back().has_own ? "true" : "false")
+                   << ");\n")
+             .generate(sink, ret_type, context))
+             return false;
+       }
+     else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *"
+              || ret_type.c_type == "Eina_Inarray *" || ret_type.c_type == "const Eina_Inarray *"
+              || ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *"
+              || ret_type.c_type == "Eina_Inlist *" || ret_type.c_type == "const Eina_Inlist *"
+              || ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *"
+     )
+       {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
+           if (!complex)
+             return false;
+           if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"}
+                   << ", " << (complex->subtypes.front().has_own ? "true" : "false")
+                   << ");\n")
+             .generate(sink, ret_type, context))
+             return false;
+       }
+     else if (ret_type.c_type != "void")
+       {
+         return as_generator("return _ret_var;\n").generate(sink, ret_type, context);
+       }
+     return true;
+   }
+
+} const convert_return {};
+
+// Native (virtual wrappers) generators
+struct native_convert_out_assign_generator
+{
+   attributes::klass_def const* klass;
+
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param_is_acceptable(param, "Eina_Stringshare *", !WANT_OWN, WANT_OUT))
+        {
+           return as_generator(
+                string << "= efl.eo.Globals.cached_stringshare_to_intptr(((" << string << "Inherit)wrapper).cached_stringshares, " << string << ");\n"
+              ).generate(sink, std::make_tuple(escape_keyword(param.param_name), klass->cxx_name, out_variable_name(param.param_name)), context);
+        }
+      else if (param_is_acceptable(param, "const char *", !WANT_OWN, WANT_OUT))
+        {
+           return as_generator(
+                string << "= efl.eo.Globals.cached_string_to_intptr(((" << string << "Inherit)wrapper).cached_strings, " << string << ");\n"
+              ).generate(sink, std::make_tuple(escape_keyword(param.param_name), klass->cxx_name, out_variable_name(param.param_name)), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Binbuf *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           if (!as_generator(
+                string << " = " << string << ".Handle;\n"
+              ).generate(sink, std::make_tuple(escape_keyword(param.param_name), out_variable_name(param.param_name)), context))
+             return false;
+           if (param.type.has_own)
+             return as_generator(
+                 string << ".Own = false;\n"
+               ).generate(sink, out_variable_name(param.param_name), context);
+        }
+      else if (param_is_acceptable(param, "Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Hash *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Hash *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex || complex->subtypes.size() != 2)
+             return false;
+           auto outvar = out_variable_name(param.param_name);
+           if (!as_generator(
+                string << " = " << string << ".Handle;\n"
+              ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
+             return false;
+           if (param.type.has_own && !as_generator(
+                 string << ".SetOwn(false);\n"
+               ).generate(sink, outvar, context))
+             return false;
+           if (complex->subtypes.front().has_own && !as_generator(
+                 string << ".SetOwnKey(false);\n"
+               ).generate(sink, outvar, context))
+             return false;
+           if (complex->subtypes.back().has_own && !as_generator(
+                 string << ".SetOwnValue(false);\n"
+                 << string << ".UnSetFreeCb();\n"
+               ).generate(sink, std::make_tuple(outvar, outvar), context))
+             return false;
+        }
+      else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inarray *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Inlist *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
+               || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
+              )
+        {
+           attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
+           if (!complex)
+             return false;
+           auto outvar = out_variable_name(param.param_name);
+           if (!as_generator(
+                string << " = " << string << ".Handle;\n"
+              ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
+             return false;
+           if (param.type.has_own && !as_generator(
+                 string << ".Own = false;\n"
+               ).generate(sink, outvar, context))
+             return false;
+           if (complex->subtypes.front().has_own && !as_generator(
+                 string << ".OwnContent = false;\n"
+               ).generate(sink, outvar, context))
+             return false;
+        }
+      return true;
+   }
+
+};
+
+struct native_convert_return_variable_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
+   {
+     if (ret_type.c_type != "void")
+       return as_generator(
+                    type << " _ret_var = default(" << type << ");"
+               ).generate(sink, std::make_tuple(ret_type, ret_type), context);
+     return true;
+   }
+
+} const native_convert_return_variable {};
+
+struct native_convert_return_generator
+{
+   attributes::klass_def const* klass;
+
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& ret_type, Context const& context) const
+   {
+     if (ret_type.c_type == "const char *")
+       {
+          if(!ret_type.has_own)
+            {
+               return as_generator(
+                    "return efl.eo.Globals.cached_string_to_intptr(((" << string << "Inherit)wrapper).cached_strings, _ret_var);\n"
+                 ).generate(sink, klass->cxx_name, context);
+            }
+          else
+            {
+                return as_generator("return _ret_var;\n"
+                    ).generate(sink, attributes::unused, context);
+            }
+       }
+     else if (ret_type.c_type == "Eina_Stringshare *") { // Correct check for string?
+         if (!ret_type.has_own)
+           {
+              return as_generator(
+                   "return efl.eo.Globals.cached_stringshare_to_intptr(((" << string << "Inherit)wrapper).cached_stringshares, _ret_var);\n"
+                ).generate(sink, klass->cxx_name, context);
+           }
+         else
+           {
+              return as_generator("return _ret_var;\n")
+                 .generate(sink, attributes::unused, context);
+           }
+     }
+     else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *")
+       {
+          if (ret_type.has_own && !as_generator("_ret_var.Own = false; ")
+              .generate(sink, attributes::unused, context))
+            return false;
+
+          return as_generator("return _ret_var.Handle;\n")
+            .generate(sink, attributes::unused, context);
+       }
+     else if (ret_type.c_type == "Eina_Hash *" || ret_type.c_type == "const Eina_Hash *")
+       {
+          attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
+          if (!complex || complex->subtypes.size() != 2)
+            return false;
+          if (ret_type.has_own && !as_generator("_ret_var.SetOwn(false); ")
+              .generate(sink, attributes::unused, context))
+            return false;
+          if (complex->subtypes.front().has_own && !as_generator("_ret_var.SetOwnKey(false); ")
+              .generate(sink, attributes::unused, context))
+            return false;
+          if (complex->subtypes.back().has_own && !as_generator("_ret_var.SetOwnValue(false); _ret_var.UnSetFreeCb(); ")
+              .generate(sink, attributes::unused, context))
+            return false;
+
+          return as_generator("return _ret_var.Handle;\n")
+            .generate(sink, attributes::unused, context);
+       }
+     else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *"
+              || ret_type.c_type == "Eina_Inarray *" || ret_type.c_type == "const Eina_Inarray *"
+              || ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *"
+              || ret_type.c_type == "Eina_Inlist *" || ret_type.c_type == "const Eina_Inlist *"
+              || ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *"
+     )
+       {
+          attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
+          if (!complex)
+            return false;
+          if (ret_type.has_own && !as_generator("_ret_var.Own = false; ")
+              .generate(sink, attributes::unused, context))
+            return false;
+          if (complex->subtypes.front().has_own && !as_generator("_ret_var.OwnContent = false; ")
+              .generate(sink, attributes::unused, context))
+            return false;
+
+          return as_generator("return _ret_var.Handle;\n")
+            .generate(sink, attributes::unused, context);
+       }
+     else if (ret_type.c_type != "void")
+       return as_generator("return _ret_var;\n").generate(sink, ret_type, context);
+     return true;
+   }
+
+};
+
+struct native_convert_out_assign_parameterized
+{
+    native_convert_out_assign_generator const operator()(attributes::klass_def const &klass) const
+    {
+        return {&klass};
+    }
+} const native_convert_out_assign;
+
+struct native_convert_return_parameterized
+{
+    native_convert_return_generator const operator()(attributes::klass_def const &klass) const
+    {
+        return {&klass};
+    }
+} const native_convert_return;
+
+struct convert_function_pointer_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param.direction != attributes::parameter_direction::in)
+        return true;
+
+      if (!param.type.original_type.visit(is_fp_visitor{}))
+          return true;
+
+      std::string param_name = escape_keyword(param.param_name);
+      // Allocate GCHandle in "param_name"_handle for param;
+      if (!as_generator(
+                  "GCHandle " << param_name << "_handle = GCHandle.Alloc(" << param_name << ");\n"
+                  ).generate(sink, attributes::unused, context))
+      return false;
+
+      return true;
+   }
+
+} const convert_function_pointer {};
+
+struct native_convert_function_pointer_generator
+{
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      if (param.direction != attributes::parameter_direction::in)
+        return true;
+
+      if (!param.type.original_type.visit(is_fp_visitor{}))
+        return true;
+
+      // Getting the type through C api
+      std::string type_name = param.type.original_type.visit(type_name_visitor{});
+
+      const Eolian_Typedecl *tpd = ::eolian_typedecl_alias_get_by_name(NULL, type_name.c_str());
+      if (!tpd)
+        {
+           EINA_LOG_ERR("Failed to get typedecl for c type [%s]", param.type.c_type.c_str());
+           return false;
+        }
+      if (eolian_typedecl_type_get(tpd) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
+        return true;
+
+      const Eolian_Function *fd = eolian_typedecl_function_pointer_get(tpd);
+      if (!fd)
+        {
+           EINA_LOG_ERR("Failed to get function pointer info for c type [%s]", param.type.c_type.c_str());
+           return false;
+        }
+      attributes::function_def f(fd, EOLIAN_FUNCTION_POINTER, NULL);
+
+      std::string param_name = escape_keyword(param.param_name);
+      // Allocate GCHandle in "param_name"_handle for param;
+      if (!as_generator(
+                  scope_tab << type << "Wrapper " << param_name << "_wrapper = new " << type << "Wrapper("
+                      << param_name << ", " << param_name << "_data, " << param_name << "_free_cb);\n"
+                  ).generate(sink, std::make_tuple(param.type, param.type), context))
+      return false;
+      // FIXME What about calling the free function?
+
+      return true;
+   }
+
+} const native_convert_function_pointer {};
+
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
new file mode 100644 (file)
index 0000000..1b5e27c
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef EOLIAN_MONO_STRUCT_DEFINITION_HH
+#define EOLIAN_MONO_STRUCT_DEFINITION_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/indentation.hpp"
+#include "grammar/list.hpp"
+#include "grammar/alternative.hpp"
+#include "type.hh"
+#include "keyword.hh"
+#include "using_decl.hh"
+
+namespace eolian_mono {
+
+// Blacklist structs that require some kind of manual binding.
+static bool is_struct_blacklisted(attributes::struct_def const& struct_)
+{
+  std::string full_name;
+
+  for (auto it=struct_.namespaces.begin(); it != struct_.namespaces.end(); it++)
+    {
+       full_name += *it + ".";
+    }
+
+  full_name += struct_.cxx_name;
+  return full_name == "Efl.Event.Description"
+      || full_name == "Eina.File"
+      || full_name == "Eina.Binbuf"
+      || full_name == "Eina.Slice"
+      || full_name == "Eina.Rw_Slice";
+}
+
+struct struct_definition_generator
+{
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
+  {
+     if (is_struct_blacklisted(struct_))
+         return true;
+
+     std::vector<std::string> cpp_namespaces = escape_namespace(attributes::cpp_namespaces(struct_.namespaces));
+
+     auto open_namespace = *("namespace " << string << " { ") << "\n";
+     if(!as_generator(open_namespace).generate(sink, cpp_namespaces, add_lower_case_context(context))) return false;
+
+     if(!as_generator
+        (
+         "public struct " << string << "\n{\n"
+         )
+        .generate(sink, struct_.cxx_name, context))
+       return false;
+
+     // iterate enum fiels
+     for(auto first = std::begin(struct_.fields)
+             , last = std::end(struct_.fields); first != last; ++first)
+       {
+          auto field_name = (*first).name;
+          auto field_type = (*first).type;
+          field_name[0] = std::toupper(field_name[0]); // Hack to allow 'static' as a field name
+          if (!as_generator
+              (
+               "public " << type << " " << string << ";\n"
+              )
+              .generate(sink, std::make_tuple(field_type, field_name), context))
+            return false;
+       }
+
+     if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
+
+     auto close_namespace = *(lit("} ")) << "\n";
+     if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
+
+     return true;
+  }
+};
+
+struct_definition_generator const struct_definition = {};
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::struct_definition_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {};
+}
+
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/type.hh b/src/bin/eolian_mono/eolian/mono/type.hh
new file mode 100644 (file)
index 0000000..b0e1451
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef EOLIAN_MONO_TYPE_HH
+#define EOLIAN_MONO_TYPE_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+
+namespace eolian_mono {
+
+namespace attributes = efl::eolian::grammar::attributes;
+
+template <typename OutputIterator, typename Context>
+struct visitor_generate;
+      
+struct type_generator
+{
+   type_generator(bool is_return = false)
+     : is_return(is_return) {}
+  
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
+   {
+      return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return});
+   }
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+      return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
+            , param.direction != attributes::parameter_direction::in, false});
+   }
+
+   bool is_return;
+};
+
+struct type_terminal
+{
+  type_generator const operator()(bool is_return) const
+  {
+    return type_generator(is_return);
+  }
+} const type = {};
+
+type_generator const as_generator(type_terminal)
+{
+  return type_generator{};
+}
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::type_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::type_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::type_terminal> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::type_generator> : std::integral_constant<int, 1> {};  
+template <>
+struct attributes_needed< ::eolian_mono::type_terminal> : std::integral_constant<int, 1> {};  
+}
+
+} } }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh
new file mode 100644 (file)
index 0000000..d6d753b
--- /dev/null
@@ -0,0 +1,373 @@
+#ifndef EOLIAN_MONO_TYPE_IMPL_HH
+#define EOLIAN_MONO_TYPE_IMPL_HH
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/case.hpp"
+#include "namespace.hh"
+
+namespace eolian_mono {
+
+namespace eina = efl::eina;
+
+template <typename T>
+T const* as_const_pointer(T* p) { return p; }
+
+attributes::regular_type_def replace_base_type(attributes::regular_type_def v, std::string name)
+{
+  v.base_type = name;
+  return v;
+}
+
+attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular)
+{
+  v.outer = regular;
+  return v;
+}
+      
+template <typename Array, typename F, int N, typename A>
+eina::optional<bool> call_match(Array const (&array)[N], F f, A a)
+{
+   typedef Array const* iterator_type;
+   iterator_type match_iterator = &array[0], match_last = match_iterator + N;
+   match_iterator = std::find_if(match_iterator, match_last, f);
+   if(match_iterator != match_last)
+     {
+        return a(match_iterator->function());
+     }
+   return {nullptr};
+}
+      
+template <typename OutputIterator, typename Context>
+struct visitor_generate
+{
+   mutable OutputIterator sink;
+   Context const* context;
+   std::string c_type;
+   bool is_out;
+   bool is_return;
+
+   typedef visitor_generate<OutputIterator, Context> visitor_type;
+   typedef bool result_type;
+  
+   bool operator()(attributes::regular_type_def const& regular) const
+   {
+      using attributes::regular_type_def;
+      struct match
+      {
+        eina::optional<std::string> name;
+        eina::optional<bool> has_own;
+        std::function<attributes::type_def::variant_type()> function;
+      }
+      const match_table[] =
+        {
+           // signed primitives
+             {"byte", nullptr, [&] { return replace_base_type(regular, " byte"); }}
+           , {"llong", nullptr, [&] { return replace_base_type(regular, " long"); }}
+           , {"int8", nullptr, [&] { return replace_base_type(regular, " byte"); }}
+           , {"int16", nullptr, [&] { return replace_base_type(regular, " short"); }}
+           , {"int32", nullptr, [&] { return replace_base_type(regular, " int"); }}
+           , {"int64", nullptr, [&] { return replace_base_type(regular, " long"); }}
+           , {"ssize", nullptr, [&] { return replace_base_type(regular, " long"); }}
+           // unsigned primitives
+           , {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte"); }}
+           , {"ushort", nullptr, [&] { return replace_base_type(regular, " ushort"); }}
+           , {"uint", nullptr, [&] { return replace_base_type(regular, " uint"); }}
+           , {"ulong", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
+           , {"ullong", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
+           , {"uint8", nullptr, [&] { return replace_base_type(regular, " byte"); }}
+           , {"uint16", nullptr, [&] { return replace_base_type(regular, " ushort"); }}
+           , {"uint32", nullptr, [&] { return replace_base_type(regular, " uint"); }}
+           , {"uint64", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
+           , {"size", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
+           
+           , {"ptrdiff", nullptr, [&] { return replace_base_type(regular, " long"); }}
+           , {"intptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr"); }}
+           , {"void_ptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr"); }}
+           , {"void", nullptr, [&]
+               {
+                  regular_type_def r = regular;
+                  r.namespaces.clear();
+                  if (is_out) // @inout too
+                      r.base_type = " System.IntPtr";
+                  else
+                      r.base_type = " void";
+                  return r;
+              }}
+           , {"Error", nullptr, [&] // Eina.Error
+              {
+                return regular_type_def{" eina.Error", regular.base_qualifier, {}};
+              }} // TODO
+           , {"string", nullptr, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                return replace_base_type(r, " System.String");
+              }}
+           , {"mstring", nullptr, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                return replace_base_type(r, " System.String");
+              }}
+           , {"stringshare", nullptr, [&]
+              {
+                regular_type_def r = regular;
+                r.base_qualifier.qualifier ^= qualifier_info::is_ref;
+                return replace_base_type(r, " System.String");
+              }}
+           , {"any_value", true, [&]
+              { return regular_type_def{" eina.Value", regular.base_qualifier, {}};
+              }}
+           , {"any_value", false, [&]
+              { return regular_type_def{" eina.Value", regular.base_qualifier, {}};
+              }}
+           , {"any_value_ptr", nullptr, [&] 
+              { return regular_type_def{" eina.Value", regular.base_qualifier, {}};
+              }} // FIXME add proper support for any_value_ptr
+        };
+      // if(regular.base_type == "void_ptr")
+      //   {
+      //     if(regular.base_qualifier & qualifier_info::is_ref)
+      //       throw std::runtime_error("ref of void_ptr is invalid");
+      //     return as_generator
+      //        (
+      //         lit("void") << (regular.base_qualifier & qualifier_info::is_const ? " const" : "")
+      //         << "*"
+      //         << (is_out ? "&" : "")
+      //        )
+      //        .generate(sink, attributes::unused, *context);
+      //   }
+      // else
+        if(eina::optional<bool> b = call_match
+         (match_table
+          , [&] (match const& m)
+          {
+            return (!m.name || *m.name == regular.base_type)
+            && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
+            ;
+          }
+          , [&] (attributes::type_def::variant_type const& v)
+          {
+            return v.visit(*this); // we want to keep is_out info
+          }))
+        {
+           return *b;
+        }
+      // in A @optional -> optional<A>
+      // in A& @optional -> optional<A&>
+      // in A& @optional -> optional<A&>
+      // in own(A&) @optional -> A*
+      //
+      // out A @optional -> optional<A&>
+      // out A& @optional -> optional<A&>
+      // out own(A&) @optional -> optional<A*&>
+      // else if(regular.base_qualifier & qualifier_info::is_optional)
+      //  {
+      //    attributes::regular_type_def no_optional_regular = regular;
+      //    no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_optional;
+      //    if(is_out)
+      //      {
+      //        if(no_optional_regular.base_qualifier & qualifier_info::is_own)
+      //          {
+      //            return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context)
+      //              && (*this)(no_optional_regular)
+      //              && as_generator("&>").generate(sink, attributes::unused, *context);
+      //         }
+      //        else if(no_optional_regular.base_qualifier & qualifier_info::is_ref)
+      //          {
+      //             no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_ref;
+      //             return (*this)(no_optional_regular)
+      //               && as_generator("**").generate(sink, attributes::unused, *context);
+      //          }
+      //        else
+      //          return (*this)(no_optional_regular)
+      //            && as_generator("*").generate(sink, attributes::unused, *context);
+      //      }
+      //    else
+      //      {
+      //        // regular.base_qualifier & qualifier_info::is_ref
+      //        return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context)
+      //          && (*this)(no_optional_regular)
+      //          && as_generator(">").generate(sink, attributes::unused, *context);
+      //      }
+      //  }
+      // else if((is_return || is_out) && regular.base_qualifier & qualifier_info::is_ref
+      //         && regular.base_qualifier & qualifier_info::is_own)
+      //   {
+      //     if(as_generator
+      //        (
+      //         " ::std::unique_ptr<"
+      //         << *(string << "_")
+      //         << string
+      //         << (regular.base_qualifier & qualifier_info::is_const ? " const" : "")
+      //         << ", ::efl::eina::malloc_deleter>"
+      //        )
+      //        .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context))
+      //       return true;
+      //     else
+      //       return false;
+      //   }
+      // else if(Eolian_Typedecl const* typedecl = eolian_typedecl_struct_get_by_name(c_type.c_str()))
+      //   {
+      //   return as_generator
+      //        (
+      //         *(string << ".")
+      //         << string
+      //        )
+      //     .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context);
+      //   }
+      else
+        {
+          // as_generator(" Generating: " << *(lower_case[string] << ".") << string << "\n")
+          //   .generate(std::ostream_iterator<char>(std::cerr), std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context);
+          if(as_generator
+             (
+              *(lower_case[string] << ".")
+              << string
+              // << (regular.base_qualifier & qualifier_info::is_const
+              //     || (regular.base_qualifier & qualifier_info::is_ref
+              //         && !is_return && !is_out)
+              //     ? /*" const"*/ "" : "")
+              /*<< (regular.base_qualifier & qualifier_info::is_ref? "&" : "")*/
+             )
+             .generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context))
+            return true;
+          else
+            return false;
+        }
+   }
+   bool operator()(attributes::klass_name klass) const
+   {
+     // as_generator(" Generating: " << *(lower_case[string] << ".") << string << "\n")
+     //   .generate(std::ostream_iterator<char>(std::cerr), std::make_tuple(attributes::cpp_namespaces(klass.namespaces), klass.eolian_name), *context);
+     // if(klass.namespaces.size() == 1
+     //    && klass.namespaces[0] == "Eina"
+     //    && klass.eolian_name == "Error")
+     // return
+     //   as_generator(" System.IntPtr")
+     //   .generate(sink, attributes::unused, *context);
+     return
+       as_generator(*(lower_case[string] << ".") << string)
+       .generate(sink, std::make_tuple(eolian_mono::escape_namespace(klass.namespaces), klass.eolian_name), *context)
+       // && (!(klass.base_qualifier & qualifier_info::is_ref)
+       //     || as_generator("&").generate(sink, attributes::unused, *context))
+       ;
+   }
+   bool operator()(attributes::complex_type_def const& complex) const
+   {
+      using attributes::regular_type_def;
+      using attributes::complex_type_def;
+      using attributes::qualifier_info;
+       struct match
+      {
+        eina::optional<std::string> name;
+        eina::optional<bool> has_own;
+        eina::optional<bool> is_const;
+        std::function<attributes::type_def::variant_type()> function;
+      } const matches[] =
+      {
+        {"list", nullptr, nullptr, [&]
+         {
+           complex_type_def c = complex;
+           c.outer.base_type = "eina.List";
+           return c;
+         }}
+        , {"inlist", nullptr, nullptr, [&]
+           {
+           complex_type_def c = complex;
+           c.outer.base_type = "eina.Inlist";
+           return c;
+         }}
+        , {"array", nullptr, nullptr, [&]
+           {
+           complex_type_def c = complex;
+           c.outer.base_type = "eina.Array";
+           return c;
+         }}
+        , {"inarray", nullptr, nullptr, [&]
+           {
+           complex_type_def c = complex;
+           c.outer.base_type = "eina.Inarray";
+           return c;
+         }}
+        , {"hash", nullptr, nullptr
+           , [&]
+           {
+             complex_type_def c = complex;
+             c.outer.base_type = "eina.Hash";
+             return c;
+           }}
+        , {"promise", nullptr, nullptr, [&]
+           {
+             return replace_outer
+             (complex, regular_type_def{" ::efl::promise", complex.outer.base_qualifier, {}});
+           }           
+          }
+        , {"future", nullptr, nullptr, [&]
+           {
+             (*this)(regular_type_def{" int", complex.outer.base_qualifier, {}});
+             return attributes::type_def::variant_type();
+             // return replace_outer
+             // (complex, regular_type_def{" ::efl::shared_future", complex.outer.base_qualifier, {}});
+           }           
+          }
+        , {"iterator", nullptr, nullptr, [&]
+           {
+             complex_type_def c = complex;
+             c.outer.base_type = "eina.Iterator";
+             return c;
+           }           
+          }
+        , {"accessor", nullptr, nullptr, [&]
+           {
+             (*this)(regular_type_def{" int", complex.outer.base_qualifier, {}});
+             return attributes::type_def::variant_type();
+             // return replace_outer
+             // (complex, regular_type_def{" ::efl::eina::accessor", complex.outer.base_qualifier, {}});
+           }           
+          }
+      };
+
+      auto default_match = [&] (attributes::complex_type_def const& complex)
+        {
+          regular_type_def no_pointer_regular = complex.outer;
+          // std::vector<attributes::pointer_indirection> pointers;
+          // pointers.swap(no_pointer_regular.pointers);
+          // if(is_out)
+          //   pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
+          return visitor_type{sink, context, c_type, false}(no_pointer_regular)
+            && as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
+          ;
+            // && detail::generate_pointers(sink, pointers, *context, false);
+        };
+       
+      if(eina::optional<bool> b = call_match
+         (matches
+          , [&] (match const& m)
+          {
+            return (!m.name || *m.name == complex.outer.base_type)
+            && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own))
+            && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const));
+          }
+          , [&] (attributes::type_def::variant_type const& v)
+          {
+            if(v.empty())
+              return true;
+            else if(attributes::complex_type_def const* complex
+               = eina::get<attributes::complex_type_def>(&v))
+              return default_match(*complex);
+            else
+              return v.visit(*this);
+          }))
+        return *b;
+      else
+        {
+          return default_match(complex);
+        }
+   }
+};
+      
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/using_decl.hh b/src/bin/eolian_mono/eolian/mono/using_decl.hh
new file mode 100644 (file)
index 0000000..97bf62c
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef EOLIAN_MONO_USING_DECL_HH
+#define EOLIAN_MONO_USING_DECL_HH
+
+namespace eolian_mono {
+
+namespace grammar = efl::eolian::grammar;
+using efl::eolian::grammar::as_generator;
+using efl::eolian::grammar::string;
+using efl::eolian::grammar::operator<<;
+using efl::eolian::grammar::operator%;
+using efl::eolian::grammar::operator*;
+using efl::eolian::grammar::scope_tab;
+using efl::eolian::grammar::lower_case;
+using efl::eolian::grammar::upper_case;
+using efl::eolian::grammar::lit;
+using efl::eolian::grammar::qualifier_info;
+using efl::eolian::grammar::context_find_tag;
+
+}
+
+#endif
diff --git a/src/bin/eolian_mono/eolian/mono/utils.hh b/src/bin/eolian_mono/eolian/mono/utils.hh
new file mode 100644 (file)
index 0000000..3e48e51
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef EOLIAN_MONO_UTILS_HPP
+#define EOLIAN_MONO_UTILS_HPP
+
+#include <string>
+#include <algorithm>
+
+namespace eolian_mono { namespace utils {
+
+   // Helper method to avoid multiple as_generator calls when mixing case strings
+   std::string to_uppercase(std::string s)
+   {
+       std::transform(s.begin(), s.end(), s.begin(), ::toupper);
+       return s;
+   }
+   std::string to_lowercase(std::string s)
+   {
+       std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+       return s;
+   }
+} }
+
+#endif
diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc
new file mode 100644 (file)
index 0000000..220f1e4
--- /dev/null
@@ -0,0 +1,367 @@
+
+#include <iostream>
+#include <fstream>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <libgen.h>
+
+#include <string>
+#include <map>
+#include <algorithm>
+#include <stdexcept>
+#include <iosfwd>
+#include <type_traits>
+#include <cassert>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <Eolian.h>
+
+#include <Eina.hh>
+#include <Eolian_Cxx.hh>
+
+#include <eolian/mono/klass.hh>
+#include <eolian/mono/enum_definition.hh>
+#include <eolian/mono/struct_definition.hh>
+#include <eolian/mono/type_impl.hh>
+#include <eolian/mono/marshall_type_impl.hh>
+#include <eolian/mono/marshall_annotation.hh>
+#include <eolian/mono/function_pointer.hh>
+
+namespace eolian_mono {
+
+/// Program options.
+struct options_type
+{
+   std::vector<std::string> include_dirs;
+   std::string in_file;
+   std::string out_file;
+   std::string dllimport;
+   int v_major;
+   int v_minor;
+   std::map<const std::string, std::string> references_map;
+};
+
+efl::eina::log_domain domain("eolian_mono");
+
+// Parses a CSV file in the format 'filename,library' (without trimming spaces around ',')
+static std::vector<std::pair<std::string, std::string> >
+parse_reference(std::string filename)
+{
+    std::vector<std::pair<std::string, std::string> > ret;
+    std::string delimiter = ",";
+    std::ifstream infile(filename);
+    std::string line;
+
+    while (std::getline(infile, line))
+      {
+         size_t pos = line.find(delimiter);
+
+         if (pos == std::string::npos)
+           throw std::invalid_argument("Malformed mapping. Must be 'filename,library'");
+
+         std::string eo_filename = line.substr(0, pos);
+         std::string library = line.substr(pos + 1);
+         library[0] = std::toupper(library[0]);
+         ret.push_back(std::pair<std::string, std::string>(eo_filename, library));
+      }
+    return ret;
+}
+
+static bool
+opts_check(eolian_mono::options_type const& opts)
+{
+   if (opts.in_file.empty())
+     {
+        EINA_CXX_DOM_LOG_ERR(eolian_mono::domain)
+          << "Nothing to generate?" << std::endl;
+     }
+   else if (opts.out_file.empty())
+     {
+        EINA_CXX_DOM_LOG_ERR(eolian_mono::domain)
+          << "Nowhere to generate?" << std::endl;
+     }
+   else
+     return true; // valid.
+   return false;
+}
+
+static void
+run(options_type const& opts)
+{
+   const Eolian_Class *klass = NULL;
+   Eina_Iterator *aliases = NULL;
+   const Eolian_Typedecl *tp = NULL;
+   char* dup = strdup(opts.in_file.c_str());
+   std::string basename_input = basename(dup);
+   klass = ::eolian_class_get_by_file(NULL, basename_input.c_str());
+   aliases= ::eolian_typedecl_aliases_get_by_file(NULL, basename_input.c_str());
+   free(dup);
+
+   std::string class_file_name = opts.out_file;
+
+   std::ofstream output_file;
+   std::ostream_iterator<char> iterator
+     {[&]
+     {
+       if(opts.out_file == "-")
+         return std::ostream_iterator<char>(std::cout);
+       else
+         {
+           output_file.open(class_file_name);
+           if (!output_file.good())
+             {
+               EINA_CXX_DOM_LOG_ERR(eolian_mono::domain)
+                 << "Can't open output file: " << class_file_name << std::endl;
+               throw std::runtime_error("");
+             }
+           return std::ostream_iterator<char>(output_file);
+         }
+     }()};
+
+   if (!as_generator("using System;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\n")
+     .generate(iterator, efl::eolian::grammar::attributes::unused, efl::eolian::grammar::context_null()))
+     {
+        throw std::runtime_error("Failed to generate file preamble");
+     }
+
+   auto context = efl::eolian::grammar::context_add_tag(eolian_mono::library_context{opts.dllimport,
+                                                                                     opts.v_major,
+                                                                                     opts.v_minor,
+                                                                                     opts.references_map},
+                                                        efl::eolian::grammar::context_null());
+   EINA_ITERATOR_FOREACH(aliases, tp)
+     {
+         if (eolian_typedecl_type_get(tp) != EOLIAN_TYPEDECL_FUNCTION_POINTER)
+             continue;
+
+         const Eolian_Function *fp = eolian_typedecl_function_pointer_get(tp);
+         efl::eolian::grammar::attributes::function_def function_def(fp, EOLIAN_FUNCTION_POINTER, NULL);
+         std::vector<std::string> namespaces;
+
+         for (efl::eina::iterator<const char> namespace_iterator(::eolian_typedecl_namespaces_get(tp)), namespace_last; namespace_iterator != namespace_last; ++namespace_iterator)
+           {
+              namespaces.push_back(&*namespace_iterator);
+           }
+
+         if (!eolian_mono::function_pointer
+               .generate(iterator, function_def, escape_namespace(namespaces), context))
+           {
+              throw std::runtime_error("Failed to generate function pointer wrapper");
+           }
+     }
+
+   if (klass)
+     {
+       efl::eolian::grammar::attributes::klass_def klass_def(klass, NULL);
+       std::vector<efl::eolian::grammar::attributes::klass_def> klasses{klass_def};
+
+       if (!eolian_mono::klass
+         .generate(iterator, klass_def, context))
+         {
+            throw std::runtime_error("Failed to generate class");
+         }
+     }
+   //else
+     {
+       for (efl::eina::iterator<const Eolian_Typedecl> enum_iterator( ::eolian_typedecl_enums_get_by_file(NULL, basename_input.c_str()))
+               , enum_last; enum_iterator != enum_last; ++enum_iterator)
+         {
+            efl::eolian::grammar::attributes::enum_def enum_(&*enum_iterator);
+            if (!eolian_mono::enum_definition.generate(iterator, enum_, efl::eolian::grammar::context_null()))
+              {
+                 throw std::runtime_error("Failed to generate enum");
+              }
+         }
+
+       for (efl::eina::iterator<const Eolian_Typedecl> struct_iterator( ::eolian_typedecl_structs_get_by_file(NULL, basename_input.c_str()))
+               , struct_last; struct_iterator != struct_last; ++struct_iterator)
+         {
+            efl::eolian::grammar::attributes::struct_def struct_(&*struct_iterator);
+            if (!eolian_mono::struct_definition.generate(iterator, struct_, efl::eolian::grammar::context_null()))
+              {
+                 throw std::runtime_error("Failed to generate struct");
+              }
+         }
+
+    }
+}
+
+static void
+database_load(options_type const& opts)
+{
+   for (auto src : opts.include_dirs)
+     {
+        if (!::eolian_directory_scan(src.c_str()))
+          {
+             EINA_CXX_DOM_LOG_WARN(eolian_mono::domain)
+               << "Couldn't load eolian from '" << src << "'.";
+          }
+     }
+   if (!::eolian_all_eot_files_parse())
+     {
+        EINA_CXX_DOM_LOG_ERR(eolian_mono::domain)
+          << "Eolian failed parsing eot files";
+        assert(false && "Error parsing eot files");
+     }
+   if (opts.in_file.empty())
+     {
+       EINA_CXX_DOM_LOG_ERR(eolian_mono::domain)
+         << "No input file.";
+       assert(false && "Error parsing input file");
+     }
+   if (!::eolian_file_parse(opts.in_file.c_str()))
+     {
+       EINA_CXX_DOM_LOG_ERR(eolian_mono::domain)
+         << "Failed parsing: " << opts.in_file << ".";
+       assert(false && "Error parsing input file");
+     }
+}
+
+} // namespace eolian_mono {
+
+static void
+_print_version()
+{
+   std::cerr
+     << "Eolian C++ Binding Generator (EFL "
+     << PACKAGE_VERSION << ")" << std::endl;
+}
+
+static void
+_usage(const char *progname)
+{
+   std::cerr
+     << progname
+     << " [options] [file.eo]" << std::endl
+     << " A single input file must be provided (unless -a is specified)." << std::endl
+     << "Options:" << std::endl
+     << "  -a, --all               Generate bindings for all Eo classes." << std::endl
+     << "  -c, --class <name>      The Eo class name to generate code for." << std::endl
+     << "  -D, --out-dir <dir>     Output directory where generated code will be written." << std::endl
+     << "  -I, --in <file/dir>     The source containing the .eo descriptions." << std::endl
+     << "  -o, --out-file <file>   The output file name. [default: <classname>.eo.hh]" << std::endl
+     << "  -n, --namespace <ns>    Wrap generated code in a namespace. [Eg: efl::ecore::file]" << std::endl
+     << "  -r, --recurse           Recurse input directories loading .eo files." << std::endl
+     << "  -v, --version           Print the version." << std::endl
+     << "  -h, --help              Print this help." << std::endl;
+   exit(EXIT_FAILURE);
+}
+
+static void
+_assert_not_dup(std::string option, std::string value)
+{
+   if (value != "")
+     {
+        EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) <<
+          "Option -" + option + " already set (" + value + ")";
+     }
+}
+
+static eolian_mono::options_type
+opts_get(int argc, char **argv)
+{
+   eolian_mono::options_type opts;
+
+   const struct option long_options[] =
+     {
+       { "in",        required_argument, 0,  'I' },
+       { "out-file",  required_argument, 0,  'o' },
+       { "version",   no_argument,       0,  'v' },
+       { "help",      no_argument,       0,  'h' },
+       { "dllimport",      required_argument,       0,  'l' },
+       { "vmaj", required_argument, 0, 'M' },
+       { "vmin", required_argument, 0, 'm' },
+       { "references", required_argument, 0, 'r'},
+       { 0,           0,                 0,   0  }
+     };
+   const char* options = "I:D:o:c:M:m:ar:vh";
+
+   int c, idx;
+   while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
+     {
+        if (c == 'I')
+          {
+             opts.include_dirs.push_back(optarg);
+          }
+        else if (c == 'o')
+          {
+             _assert_not_dup("o", opts.out_file);
+             opts.out_file = optarg;
+          }
+        else if (c == 'h')
+          {
+           _usage(argv[0]);
+          }
+        else if (c == 'l')
+          {
+            opts.dllimport = optarg;
+          }
+        else if (c == 'M')
+          {
+            opts.v_major = std::stoi(optarg);
+          }
+        else if (c == 'm')
+          {
+            opts.v_minor = std::stoi(optarg);
+          }
+        else if (c == 'r')
+          {
+             try
+               {
+                  std::vector<std::pair<std::string, std::string> > names = eolian_mono::parse_reference(optarg);
+                 for (auto&& p : names)
+                   {
+                      opts.references_map[p.first] = p.second;
+                   }
+               }
+             catch (const std::invalid_argument &e)
+               {
+                   std::cerr << "Invalid argument processing argument " << optarg << std::endl;
+                   _usage(argv[0]);
+                   assert(false && e.what());
+               }
+          }
+        else if (c == 'v')
+          {
+             _print_version();
+             if (argc == 2) exit(EXIT_SUCCESS);
+          }
+     }
+   if (optind == argc-1)
+     {
+        opts.in_file = argv[optind];
+     }
+
+   if (!eolian_mono::opts_check(opts))
+     {
+        _usage(argv[0]);
+        assert(false && "Wrong options passed in command-line");
+     }
+
+   return opts;
+}
+
+int main(int argc, char **argv)
+{
+   try
+     {
+        efl::eina::eina_init eina_init;
+        efl::eolian::eolian_init eolian_init;
+        eolian_mono::options_type opts = opts_get(argc, argv);
+        eolian_mono::database_load(opts);
+        eolian_mono::run(opts);
+     }
+   catch(std::exception const& e)
+     {
+       std::cerr << "EOLCXX: Eolian C++ failed generation for the following reason: " << e.what() << std::endl;
+       std::cout << "EOLCXX: Eolian C++ failed generation for the following reason: " << e.what() << std::endl;
+       return -1;
+     }
+   return 0;
+}
+
+