#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HH #define EOLIAN_MONO_FUNCTION_DEFINITION_HH #include #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 "logging.hh" #include "type.hh" #include "name_helpers.hh" #include "helpers.hh" #include "function_helpers.hh" #include "marshall_type.hh" #include "parameter.hh" #include "documentation.hh" #include "using_decl.hh" #include "generation_contexts.hh" #include "blacklist.hh" namespace eolian_mono { struct native_function_definition_generator { attributes::klass_def const* klass; template bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_function_definition_generator: " << f.c_name << std::endl; if(blacklist::is_function_blacklisted(f, context)) return true; else { if(!as_generator ("\n\n" << scope_tab << eolian_mono::marshall_annotation(true) << " private delegate " << eolian_mono::marshall_type(true) << " " << string << "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd") << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (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; if(!as_generator ("\n\n" << scope_tab << eolian_mono::marshall_annotation(true) << " public delegate " << eolian_mono::marshall_type(true) << " " << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj") << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (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; if(!as_generator (scope_tab << " public static Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<" << string << "_api_delegate>(_Module, \"" << string << "\");\n") .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), 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; std::string klass_cast_name; if (klass->type != attributes::class_type::interface_) klass_cast_name = name_helpers::klass_inherit_name(*klass); else klass_cast_name = name_helpers::klass_interface_name(*klass); std::string self = "Efl.Eo.Globals.efl_super(obj, Efl.Eo.Globals.efl_class_get(obj))"; if (f.is_static) self = ""; if(!as_generator (scope_tab << " private 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.PrivateDataGet(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 = " : "") << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")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.UNHANDLED_EXCEPTION);\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 << "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (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 , name_helpers::managed_method_name(f) , f.parameters , f , f.c_name , f.parameters ) , context)) return false; // Static functions do not need to be called from C if (f.is_static) return true; // This is the delegate that will be passed to Eo to be called from C. if(!as_generator( scope_tab << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n" ).generate(sink, attributes::unused, context)) return false; return true; } } }; struct function_definition_generator { function_definition_generator(bool do_super = false) : do_super(do_super) {} template bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl; if(blacklist::is_function_blacklisted(f, context)) return true; 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 (documentation(1)).generate(sink, f, context)) return false; std::string self = "this.NativeHandle"; // inherited is set in the constructor, true if this instance is from a pure C# class (not generated). if (do_super && !f.is_static) self = "(inherited ? Efl.Eo.Globals.efl_super(" + self + ", this.NativeClass) : " + self + ")"; else if (f.is_static) self = ""; if(!as_generator (scope_tab << ((do_super && !f.is_static) ? "virtual " : "") << "public " << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ") << ") {\n " << eolian_mono::function_definition_preamble() << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate(" << self << ((!f.is_static && (f.parameters.size() > 0)) ? "," : "") << (argument_invocation % ", ") << ");\n" << eolian_mono::function_definition_epilogue() << " }\n") .generate(sink, std::make_tuple(name_helpers::managed_method_name(f), 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; struct property_wrapper_definition_generator { template bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const { if (blacklist::is_property_blacklisted(property, *implementing_klass, context)) return true; bool interface = context_find_tag(context).current_wrapper_kind == class_context::interface; bool is_static = (property.getter.is_engaged() && property.getter->is_static) || (property.setter.is_engaged() && property.setter->is_static); if (interface && is_static) return true; auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0; auto set_params = property.setter.is_engaged() ? property.setter->parameters.size() : 0; // C# properties must have a single value. // // Single values in getters are automatically converted to return_type, // meaning they should have 0 parameters. // // For setters, we ignore the return type - usually boolean. if (get_params > 0 || set_params > 1) return true; attributes::type_def prop_type; if (property.getter.is_engaged()) prop_type = property.getter->return_type; else if (property.setter.is_engaged()) prop_type = property.setter->parameters[0].type; else { EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Property must have either a getter or a setter." << std::endl; return false; } std::string dir_mod; if (property.setter.is_engaged()) dir_mod = direction_modifier(property.setter->parameters[0]); std::string managed_name = name_helpers::property_managed_name(property); if (!as_generator( scope_tab << documentation << scope_tab << (interface ? "" : "public ") << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n" ).generate(sink, std::make_tuple(property, prop_type), context)) return false; if (property.getter.is_engaged()) if (!as_generator(scope_tab << scope_tab << "get " << (interface ? ";" : "{ return Get" + managed_name + "(); }") << "\n" ).generate(sink, attributes::unused, context)) return false; if (property.setter.is_engaged()) if (!as_generator(scope_tab << scope_tab << "set " << (interface ? ";" : "{ Set" + managed_name + "(" + dir_mod + "value); }") << "\n" ).generate(sink, attributes::unused, context)) return false; if (!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, context)) return false; return true; } attributes::klass_def const* implementing_klass; }; struct property_wrapper_definition_parameterized { property_wrapper_definition_generator operator()(attributes::klass_def const& klass) const { return {&klass}; } } const property_wrapper_definition; property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized) { return {}; } } 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_eager_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : 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 {}; template <> struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {}; template <> struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::function_definition_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::function_definition_parameterized> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> : std::integral_constant {}; template <> struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant {}; } } } } #endif