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