--- /dev/null
+/eolian_mono
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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 ¶m, 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>(¶m.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>(¶m.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>(¶m.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>(¶m.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>(¶m.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>(¶m.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>(¶m.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>(¶m.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>(¶m.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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+
+#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;
+}
+
+