efl_mono: Move event generators to its own header.

Summary:
Making it easier to share code between self and inherited events.

During this move, the namespace and keyword headers were merged into the
name_helpers header.

Also added the first seed of a generic namespace reducer function,
to be used by other functions in later commits.
Depends on D5994

Reviewers: felipealmeida

Reviewed By: felipealmeida

Subscribers: segfaultxavi, cedric

Differential Revision: https://phab.enlightenment.org/D5995
This commit is contained in:
Lauro Moura 2018-04-16 21:44:27 -03:00
parent 8e151023b9
commit a413914c18
20 changed files with 444 additions and 403 deletions

View File

@ -88,6 +88,7 @@ bin_eolian_mono_eolian_mono_SOURCES = \
bin/eolian_mono/eolian/mono/marshall_type.hh \
bin/eolian_mono/eolian/mono/klass.hh \
bin/eolian_mono/eolian/mono/type_impl.hh \
bin/eolian_mono/eolian/mono/events.hh \
bin/eolian_mono/eolian/mono/generation_contexts.hh
bin_eolian_mono_eolian_mono_CXXFLAGS = -I$(top_builddir)/src/lib/efl \

View File

@ -5,7 +5,7 @@
#include "grammar/klass_def.hpp"
#include "grammar/html_escaped_string.hpp"
#include "using_decl.hh"
#include "keyword.hh"
#include "name_helpers.hh"
#include <Eina.h>
@ -116,7 +116,7 @@ struct documentation_generator
template<typename OutputIterator, typename Context>
bool generate_parameter(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return generate_tag_param(sink, escape_keyword(param.param_name), param.documentation.summary, context);
return generate_tag_param(sink, name_helpers::escape_keyword(param.param_name), param.documentation.summary, context);
}
template<typename OutputIterator, typename Context>

View File

@ -7,7 +7,7 @@
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "type.hh"
#include "keyword.hh"
#include "name_helpers.hh"
#include "using_decl.hh"
namespace eolian_mono {
@ -17,7 +17,7 @@ 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));
std::vector<std::string> cpp_namespaces = name_helpers::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;

View File

@ -0,0 +1,255 @@
#ifndef EOLIAN_MONO_EVENTS_HH
#define EOLINA_MONO_EVENTS_HH
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "name_helpers.hh"
#include "using_decl.hh"
namespace eolian_mono {
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
{
if (arg_type == "string")
return "eina.StringConversion.NativeUtf8ToManagedString(evt.Info)";
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 event_argument_wrapper_generator
{
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::event_def const& evt, Context const& context) const
{
efl::eina::optional<grammar::attributes::type_def> etype = evt.type;
if (!etype.is_engaged())
return true;
std::string evt_name = name_helpers::managed_event_name(evt.name);
std::string arg_type = (*etype).original_type.visit(name_helpers::get_csharp_type_visitor{});
return as_generator("///<summary>Event argument wrapper for event " << evt_name << ".</summary>\n"
<< "public class " << name_helpers::managed_event_args_short_name(evt) << " : EventArgs {\n"
<< scope_tab << "///<summary>Actual event payload.</summary>\n"
<< scope_tab << "public " << arg_type << " arg { get; set; }\n"
<< "}\n"
).generate(sink, attributes::unused, context);
}
} const event_argument_wrapper {};
struct event_declaration_generator
{
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::event_def const& evt, Context const& context) const
{
std::string wrapper_args_type;
std::string evt_name = name_helpers::managed_event_name(evt.name);
std::string evt_args_name = name_helpers::managed_event_args_name(evt);
efl::eina::optional<grammar::attributes::type_def> etype = evt.type;
if (etype.is_engaged())
wrapper_args_type = "<" + evt_args_name + ">";
if (!as_generator(
documentation(1)
<< scope_tab << "event EventHandler" << wrapper_args_type << " " << evt_name << ";\n"
).generate(sink, evt, context))
return false;
return true;
}
} const event_declaration {};
struct event_registration_generator
{
attributes::klass_def const* klass;
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::event_def const& evt, Context const& context) const
{
std::string wrapper_event_name;
if (klass)
wrapper_event_name = name_helpers::translate_inherited_event_name(evt, *klass);
else
wrapper_event_name = name_helpers::managed_event_name(evt.name);
return as_generator(scope_tab << scope_tab << "evt_" << wrapper_event_name << "_delegate = "
<< "new efl.Event_Cb(on_" << wrapper_event_name << "_NativeCallback);\n"
).generate(sink, attributes::unused, context);
}
};
struct event_registration_parameterized
{
event_registration_generator operator()(attributes::klass_def const* klass=NULL) const
{
return {klass};
}
} const event_registration;
struct event_definition_generator
{
attributes::klass_def const& klass;
bool is_inherited_event;
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::event_def const& evt, Context context) const
{
std::string managed_evt_name = name_helpers::managed_event_name(evt.name);
std::string wrapper_evt_name;
if (is_inherited_event)
wrapper_evt_name = name_helpers::translate_inherited_event_name(evt, klass);
else
wrapper_evt_name = managed_evt_name;
std::string klass_name;
if (is_inherited_event)
klass_name = name_helpers::klass_get_full_name(klass);
else
klass_name = klass.eolian_name;
std::string upper_c_name = utils::to_uppercase(evt.c_name);
std::string wrapper_args_type = "EventArgs";
std::string wrapper_args_template = "";
std::string event_args = "EventArgs args = EventArgs.Empty;\n";
std::string visibility = is_inherit_context(context) ? "protected" : "private";
efl::eina::optional<grammar::attributes::type_def> etype = evt.type;
if (etype.is_engaged())
{
wrapper_args_type = name_helpers::managed_event_args_name(evt);
wrapper_args_template = "<" + wrapper_args_type + ">";
std::string arg_type = wrapper_args_type + " args = new " + wrapper_args_type + "();\n"; // = (*etype).original_type.visit(get_csharp_type_visitor{});
std::string actual_arg_type = (*etype).original_type.visit(name_helpers::get_csharp_type_visitor{});
arg_type += " args.arg = " + (*etype).original_type.visit(get_event_args_visitor{actual_arg_type}) + ";\n";
event_args = arg_type;
}
// Wrapper event declaration
if(!as_generator(documentation(1)).generate(sink, evt, context))
return false;
if(!as_generator(
scope_tab << visibility << " event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << ";\n"
<< scope_tab << "///<summary>Method to raise event "<< wrapper_evt_name << ".</summary>\n"
<< scope_tab << visibility << " void On_" << wrapper_evt_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 = " << 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 << "private void on_" << wrapper_evt_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)\n"
<< scope_tab << "{\n"
<< scope_tab << 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.Error(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_" << wrapper_evt_name << "_delegate;\n"
<< scope_tab << "event EventHandler" << wrapper_args_template << " " << klass_name << "." << managed_evt_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_" << 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 event_definition_parameterized
{
event_definition_generator operator()(attributes::klass_def const& klass, bool is_inherited_event=false) const
{
return {klass, is_inherited_event};
}
} const event_definition;
}
namespace efl { namespace eolian { namespace grammar {
template <>
struct is_eager_generator<struct ::eolian_mono::event_argument_wrapper_generator> : std::true_type {};
template <>
struct is_generator<struct ::eolian_mono::event_argument_wrapper_generator> : std::true_type {};
template <>
struct is_eager_generator<struct ::eolian_mono::event_declaration_generator> : std::true_type {};
template <>
struct is_generator<struct ::eolian_mono::event_declaration_generator> : std::true_type {};
template <>
struct is_eager_generator<struct ::eolian_mono::event_registration_generator> : std::true_type {};
template <>
struct is_generator<struct ::eolian_mono::event_registration_generator> : std::true_type {};
template <>
struct is_generator<struct ::eolian_mono::event_registration_parameterized> : std::true_type {};
template <>
struct is_eager_generator<struct ::eolian_mono::event_definition_generator> : std::true_type {};
template <>
struct is_generator<struct ::eolian_mono::event_definition_generator> : std::true_type {};
template <>
struct is_generator<struct ::eolian_mono::event_definition_parameterized> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed<struct ::eolian_mono::event_argument_wrapper_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<struct ::eolian_mono::event_declaration_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<struct ::eolian_mono::event_registration_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<struct ::eolian_mono::event_registration_parameterized> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<struct ::eolian_mono::event_definition_generator> : std::integral_constant<int, 1> {};
template <>
struct attributes_needed<struct ::eolian_mono::event_definition_parameterized> : std::integral_constant<int, 1> {};
}
} } }
#endif

View File

@ -9,7 +9,7 @@
#include "grammar/alternative.hpp"
#include "type.hh"
#include "parameter.hh"
#include "keyword.hh"
#include "name_helpers.hh"
#include "using_decl.hh"
#include "blacklist.hh"
@ -28,7 +28,7 @@ struct function_declaration_generator
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);
.generate(sink, std::make_tuple(f.return_type, name_helpers::managed_method_name(f.name), f.parameters), context);
}
};

View File

@ -16,7 +16,6 @@
#include "function_helpers.hh"
#include "marshall_type.hh"
#include "parameter.hh"
#include "keyword.hh"
#include "documentation.hh"
#include "using_decl.hh"
#include "generation_contexts.hh"

View File

@ -31,7 +31,7 @@ struct function_pointer {
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);
std::vector<std::string> namespaces = name_helpers::escape_namespace(namesp);
auto funcptr_ctx = context_add_tag(class_context{class_context::function_ptr}, context);
std::string return_type;
@ -48,16 +48,16 @@ struct function_pointer {
if (!as_generator(documentation
<< "public delegate " << type << " " << string
<< "(" << (parameter % ", ") << ");\n")
.generate(sink, std::make_tuple(f, f.return_type, escape_keyword(f.name), f.parameters), funcptr_ctx))
.generate(sink, std::make_tuple(f, f.return_type, name_helpers::escape_keyword(f.name), f.parameters), funcptr_ctx))
return false;
// "Internal" delegate, 1-to-1 with the Unamaged function type
if (!as_generator(marshall_native_annotation(true)
<< "internal delegate " << marshall_type(true) << " " << string // public?
<< "Internal(IntPtr data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_native_annotation << " " << marshall_parameter)) << ");\n")
.generate(sink, std::make_tuple(f.return_type, f.return_type, escape_keyword(f.name), f.parameters), funcptr_ctx))
.generate(sink, std::make_tuple(f.return_type, f.return_type, name_helpers::escape_keyword(f.name), f.parameters), funcptr_ctx))
return false;
std::string f_name = escape_keyword(f.name);
std::string f_name = name_helpers::escape_keyword(f.name);
// Wrapper type, with callback matching the Unamanaged one
if (!as_generator("internal class " << f_name << "Wrapper\n"
<< "{\n\n"

View File

@ -13,7 +13,6 @@
#include "type.hh"
#include "marshall_type.hh"
#include "parameter.hh"
#include "keyword.hh"
#include "using_decl.hh"
#include "generation_contexts.hh"
#include "blacklist.hh"

View File

@ -1,51 +0,0 @@
#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, "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 = utils::split(underscore_name, '_');
name_helpers::reorder_verb(names);
return escape_keyword(utils::to_pascal_case(names));
}
}
#endif

View File

@ -10,12 +10,13 @@
#include "grammar/list.hpp"
#include "grammar/alternative.hpp"
#include "type.hh"
#include "namespace.hh"
#include "name_helpers.hh"
#include "function_definition.hh"
#include "function_registration.hh"
#include "function_declaration.hh"
#include "documentation.hh"
#include "part_definition.hh"
#include "events.hh"
#include "grammar/string.hpp"
#include "grammar/attribute_replace.hpp"
#include "grammar/integral.hpp"
@ -85,59 +86,6 @@ is_inherit_context(Context const& context)
return context_find_tag<class_context>(context).current_wrapper_kind == class_context::inherit;
}
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
{
if (arg_type == "string")
{
return "eina.StringConversion.NativeUtf8ToManagedString(evt.Info)";
}
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>
@ -161,32 +109,11 @@ struct klass
break;
}
std::vector<std::string> namespaces = escape_namespace(cls.namespaces);
std::vector<std::string> namespaces = name_helpers::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 = name_helpers::managed_event_name(e.name);
std::string arg_type = (*etype).original_type.visit(get_csharp_type_visitor{});
if (!as_generator("///<summary>Event argument wrapper for event " << string << ".</summary>\n"
).generate(sink, evt_name, context))
return false;
if (!as_generator("public class " << evt_name << "_Args : EventArgs {\n"
<< scope_tab << "///<summary>Actual event payload.</summary>\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);
@ -204,7 +131,7 @@ struct klass
, 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))
.generate(sink, std::make_tuple(name_helpers::escape_namespace(first->namespaces), first->eolian_name), iface_cxt))
return false;
// if(std::next(first) != last)
// *sink++ = ',';
@ -216,28 +143,8 @@ struct klass
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 = name_helpers::managed_event_name(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>";
if (!as_generator(documentation(1)).generate(sink, e, iface_cxt))
return false;
//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;
}
if (!as_generator(*(event_declaration)).generate(sink, cls.events, iface_cxt))
return false;
for (auto &&p : cls.parts)
if (!as_generator(
@ -346,6 +253,9 @@ struct klass
if(!as_generator(*(function_definition))
.generate(sink, methods, concrete_cxt)) return false;
if(!as_generator(*(event_argument_wrapper)).generate(sink, cls.events, context))
return false;
if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
}
@ -527,29 +437,16 @@ struct klass
// 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;
}
if (!as_generator(*(event_registration())).generate(sink, cls.events, context))
return false;
for (auto&& c : cls.inherits)
{
attributes::klass_def klass(get_klass(c, cls.unit), cls.unit);
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(*(event_registration(&klass))).generate(sink, klass.events, context))
return false;
}
if (!as_generator(
scope_tab << "}\n"
@ -559,19 +456,6 @@ struct klass
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 << '_';
}
s << klass.cxx_name << '_' << name_helpers::managed_event_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
{
@ -628,171 +512,15 @@ struct klass
return false;
// Self events
for (auto&& e : cls.events)
{
std::string upper_name = name_helpers::managed_event_name(e.name);
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(documentation(1)).generate(sink, e, context))
return false;
if(!as_generator(
scope_tab << visibility << " event EventHandler" << wrapper_args_template << " " << upper_name << ";\n"
<< scope_tab << "///<summary>Method to raise event "<< event_name << ".</summary>\n"
<< scope_tab << visibility << " 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 << "private void on_" << event_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)\n"
<< scope_tab << "{\n"
<< scope_tab << 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.Error(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;
}
if (!as_generator(*(event_definition(cls))).generate(sink, cls.events, context))
return false;
// Inherited events
for (auto&& c : cls.inherits)
{
attributes::klass_def klass(get_klass(c, cls.unit), cls.unit);
// 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 = name_helpers::managed_event_name(e.name);
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(documentation(1)).generate(sink, e, context))
return false;
if (!as_generator(
scope_tab << visibility << " event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << ";\n"
<< scope_tab << "///<summary>Method to raise event "<< wrapper_evt_name << ".</summary>\n"
<< scope_tab << visibility << " 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 << "private void on_" << wrapper_evt_name << "_NativeCallback(System.IntPtr data, ref efl.Event evt)"
<< scope_tab << "{\n"
<< scope_tab << 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.Error(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;
}
if (!as_generator(*(event_definition(klass, true))).generate(sink, klass.events, context))
return false;
}
return true;
}

View File

@ -4,7 +4,7 @@
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/case.hpp"
#include "namespace.hh"
#include "name_helpers.hh"
#include "type_impl.hh"
namespace eolian_mono {
@ -144,7 +144,7 @@ struct marshall_annotation_visitor_generate
{
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);
std::vector<std::string> namespaces = name_helpers::escape_namespace(klass_name.namespaces);
return as_generator
((is_return ? return_prefix : no_return_prefix)
<< *(lower_case[string] << ".") << string
@ -251,7 +251,7 @@ struct marshall_native_annotation_visitor_generate
{
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);
std::vector<std::string> namespaces = name_helpers::escape_namespace(klass_name.namespaces);
return as_generator
((is_return ? return_prefix : no_return_prefix)
<< *(lower_case[string] << ".") << string

View File

@ -5,7 +5,7 @@
#include "grammar/klass_def.hpp"
#include "grammar/case.hpp"
#include "helpers.hh"
#include "namespace.hh"
#include "name_helpers.hh"
#include "type_impl.hh"
#include "generation_contexts.hh"
#include "blacklist.hh"
@ -161,7 +161,7 @@ struct marshall_type_visitor_generate
if ((is_out || is_return) && is_ptr)
return as_generator(" System.IntPtr").generate(sink, attributes::unused, *context);
return as_generator(*(lower_case[string] << ".") << string << "_StructInternal")
.generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context);
.generate(sink, std::make_tuple(name_helpers::escape_namespace(regular.namespaces), regular.base_type), *context);
}
else if (eina::optional<bool> b = call_match
(match_table

View File

@ -9,6 +9,8 @@
#include <vector>
#include "utils.hh"
#include "grammar/integral.hpp"
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
namespace eolian_mono {
@ -21,6 +23,62 @@ namespace name_helpers {
namespace attributes = efl::eolian::grammar::attributes;
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, "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;
}
inline 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;
}
inline std::string get_namespaces(std::vector<std::string> const& namespaces, char separator,
std::function<std::string(std::string const&)> func=[] (std::string const& c) { return c; })
{
std::stringstream s;
for (auto&& n : namespaces)
s << func(n) << separator;
return s.str();
}
inline std::string get_namespaces(attributes::klass_def const& klass, char separator,
std::function<std::string(std::string const&)> func=[] (std::string const& c) { return c; })
{
return get_namespaces(klass.namespaces, separator, func);
}
static const std::vector<std::string> verbs =
{
"add",
@ -112,11 +170,56 @@ void reorder_verb(std::vector<std::string> &names)
}
}
inline std::string klass_name_to_csharp(attributes::klass_name const& clsname)
{
std::ostringstream output;
for (auto namesp : clsname.namespaces)
output << utils::to_lowercase(namesp) << ".";
output << clsname.eolian_name;
return output.str();
}
inline std::string managed_method_name(std::string const& underscore_name)
{
std::vector<std::string> names = utils::split(underscore_name, '_');
name_helpers::reorder_verb(names);
return escape_keyword(utils::to_pascal_case(names));
}
inline std::string managed_event_name(std::string const& name)
{
return utils::to_pascal_case(utils::split(name, ','), "") + "Evt";
}
inline std::string managed_event_args_short_name(attributes::event_def evt)
{
return name_helpers::managed_event_name(evt.name) + "_Args";
}
inline std::string managed_event_args_name(attributes::event_def evt)
{
std::string prefix = name_helpers::klass_name_to_csharp(evt.klass);
return prefix + "Concrete." + managed_event_args_short_name(evt);
}
inline 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 << '_';
}
s << klass.cxx_name << '_' << managed_event_name(evt.name);
return s.str();
}
inline std::string type_full_name(attributes::regular_type_def const& type)
{
std::string full_name;
@ -144,14 +247,14 @@ inline std::string to_field_name(std::string const& in)
return utils::capitalize(in);
}
inline std::string klass_name_to_csharp(attributes::klass_name const& clsname)
inline std::string klass_get_full_name(attributes::klass_def const& klass)
{
std::ostringstream output;
for (auto namesp : clsname.namespaces)
output << utils::to_lowercase(namesp) << ".";
for(auto namesp : klass.namespaces)
output << utils::to_lowercase(escape_keyword(namesp)) << ".";
output << clsname.eolian_name;
output << klass.eolian_name;
return output.str();
}
@ -171,6 +274,36 @@ inline std::string klass_get_name(attributes::klass_name const &clsname)
return output.str();
}
struct get_csharp_type_visitor
{
typedef get_csharp_type_visitor visitor_type;
typedef std::string result_type;
std::string operator()(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()(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";
}
};
} // namespace name_helpers
} // namespace eolian_mono

View File

@ -1,27 +0,0 @@
#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

View File

@ -8,8 +8,9 @@
#include "marshall_type.hh"
#include "type.hh"
#include "using_decl.hh"
#include "keyword.hh"
#include "name_helpers.hh"
using namespace eolian_mono::name_helpers;
namespace eolian_mono {
struct parameter_generator;

View File

@ -9,7 +9,6 @@
#include "name_helpers.hh"
#include "helpers.hh"
#include "type.hh"
#include "keyword.hh"
#include "using_decl.hh"
#include "documentation.hh"
#include "struct_fields.hh"
@ -444,7 +443,7 @@ struct struct_entities_generator
if (blacklist::is_struct_blacklisted(struct_))
return true;
std::vector<std::string> cpp_namespaces = escape_namespace(attributes::cpp_namespaces(struct_.namespaces));
std::vector<std::string> cpp_namespaces = name_helpers::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)))

View File

@ -8,7 +8,6 @@
#include "grammar/alternative.hpp"
#include "name_helpers.hh"
#include "type.hh"
#include "keyword.hh"
#include "using_decl.hh"
#include "documentation.hh"

View File

@ -4,7 +4,7 @@
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/case.hpp"
#include "namespace.hh"
#include "name_helpers.hh"
namespace eolian_mono {
@ -256,7 +256,7 @@ struct visitor_generate
// ? /*" const"*/ "" : "")
/*<< (regular.base_qualifier & qualifier_info::is_ref? "&" : "")*/
)
.generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context))
.generate(sink, std::make_tuple(name_helpers::escape_namespace(regular.namespaces), regular.base_type), *context))
return true;
else
return false;
@ -274,7 +274,7 @@ struct visitor_generate
// .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)
.generate(sink, std::make_tuple(name_helpers::escape_namespace(klass.namespaces), klass.eolian_name), *context)
// && (!(klass.base_qualifier & qualifier_info::is_ref)
// || as_generator("&").generate(sink, attributes::unused, *context))
;

View File

@ -23,6 +23,7 @@
#include <Eina.hh>
#include <Eolian_Cxx.hh>
#include <eolian/mono/name_helpers.hh>
#include <eolian/mono/klass.hh>
#include <eolian/mono/enum_definition.hh>
#include <eolian/mono/struct_definition.hh>
@ -150,7 +151,7 @@ run(options_type const& opts)
}
if (!eolian_mono::function_pointer
.generate(iterator, function_def, escape_namespace(namespaces), context))
.generate(iterator, function_def, eolian_mono::name_helpers::escape_namespace(namespaces), context))
{
throw std::runtime_error("Failed to generate function pointer wrapper");
}

View File

@ -787,6 +787,7 @@ struct compare_klass_name_by_name
struct event_def
{
klass_name klass;
eina::optional<type_def> type;
std::string name, c_name;
bool beta, protect;
@ -794,7 +795,8 @@ struct event_def
friend inline bool operator==(event_def const& lhs, event_def const& rhs)
{
return lhs.type == rhs.type
return lhs.klass == rhs.klass
&& lhs.type == rhs.type
&& lhs.name == rhs.name
&& lhs.c_name == rhs.c_name
&& lhs.beta == rhs.beta
@ -806,12 +808,14 @@ struct event_def
return !(lhs == rhs);
}
event_def(type_def type, std::string name, std::string c_name, bool beta, bool protect,
documentation_def documentation)
: type(type), name(name), c_name(c_name), beta(beta), protect(protect)
event_def(klass_name _klass, type_def type, std::string name, std::string c_name,
bool beta, bool protect, documentation_def documentation)
: klass(_klass), type(type), name(name), c_name(c_name), beta(beta), protect(protect)
, documentation(documentation) {}
event_def(Eolian_Event const* event, Eolian_Unit const* unit)
: type( ::eolian_event_type_get(event) ? eina::optional<type_def>{{::eolian_event_type_get(event), unit, EOLIAN_C_TYPE_DEFAULT}} : eina::optional<type_def>{})
event_def(Eolian_Event const* event, Eolian_Class const* cls, Eolian_Unit const* unit)
: klass(cls, {attributes::qualifier_info::is_none, std::string()})
, type( ::eolian_event_type_get(event) ? eina::optional<type_def>{{::eolian_event_type_get(event), unit, EOLIAN_C_TYPE_DEFAULT}} : eina::optional<type_def>{})
, name( ::eolian_event_name_get(event))
, c_name( ::eolian_event_c_name_get(event))
, beta( ::eolian_event_is_beta(event))
@ -1035,7 +1039,7 @@ struct klass_def
, event_last; event_iterator != event_last; ++event_iterator)
{
try {
events.push_back({&*event_iterator, unit});
events.push_back({&*event_iterator, klass, unit});
} catch(std::exception const&) {}
}