(tag<typename callback_args_type<C>::type>());
}
+template <typename F>
+Eina_Bool free_callback_calback(void* data, Eo* obj EINA_UNUSED
+ , Eo_Event_Description const* e EINA_UNUSED
+ , void* event_info EINA_UNUSED)
+{
+ delete (F*) data;
+ return EO_CALLBACK_CONTINUE;
+}
+
} } // namespace efl { namespace eolian {
#endif // EFL_EOLIAN_INTEROP_HH
operator<<(std::ostream& out, constructor_functor_type_decl const& x)
{
out << constructor_functor_type_name(x._ctor);
- auto cb_it = parameters_find_callback(x._ctor.params);
- if(cb_it != x._ctor.params.cend())
+
+ if (parameters_count_callbacks(x._ctor.params) == 0)
+ return out;
+
+ bool comma = false;
+ out << "<";
+ auto first = x._ctor.params.cbegin(), last = x._ctor.params.cend();
+ for(auto it = first; it != last; ++it)
{
- out << "<F>";
+ if (type_is_callback((*it).type) && it+1 != last)
+ {
+ if (comma)
+ out << ", ";
+ else
+ comma = true;
+ out << template_parameter_type((*it).type, (*it).name);
+ }
}
- return out;
+ return out << ">";
}
struct functors_constructor_methods
for (it = first; it != last; ++it)
{
eo_constructor const& c = *it;
- auto cb_it = parameters_find_callback(c.params);
- bool has_callback = (cb_it != c.params.cend());
// Struct declaration
- if(has_callback)
- {
- out << tab(1) << "template <typename F>" << endl;
- }
- out << tab(1) << "struct " << constructor_functor_type_name(c) << endl
+ out << template_parameters_declaration(c.params, 1)
+ << tab(1) << "struct " << constructor_functor_type_name(c) << endl
<< tab(1) << "{" << endl;
+ // Callbacks typedefs
+ out << parameters_cxx_generic(c.params,
+ [](param_data d)
+ {
+ if (d.is_cb)
+ d.out << tab(2)
+ << parameter_remove_reference_typedef(d.type, d.name)
+ << endl;
+ }
+ )
+ << endl;
+
// Struct constructor
out << tab(2) << constructor_functor_type_name(c) << "("
<< parameters_declaration(c.params) << ")"
d.out << endl << tab(3) << ": ";
else
d.out << ", ";
- d.out << d.name << "(" << parameter_forward(d.type, d.name) << ")";
+
+ if (d.is_cb)
+ d.out << callback_tmp(d.name) << "(new "
+ << template_parameter_type(d.type, d.name)
+ << "(" << parameter_forward(d.type, d.name) << "))";
+ else
+ d.out << d.name << "(" << parameter_forward(d.type, d.name) << ")";
}
)
<< endl
// Struct operator()
out << tab(2) << "void operator()()" << endl
- << tab(2) << "{" << endl;
- if (has_callback)
- {
- out << tab(3) << "typedef typename std::remove_reference<F>::type function_type;" << endl
- << tab(3) << "function_type* _tmp_f = new F(this->" << (*cb_it).name << ");" << endl;
- }
- out << tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl
+ << tab(2) << "{" << endl
+ << tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl
<< tab(2) << "}" << endl;
// Struct member variables
- out << tab(1) << "private:" << endl
+ out << endl
<< parameters_cxx_generic(c.params,
[](param_data d)
{
- d.out << tab(2) << parameter_type(d.type) << " " << d.name << ";" << endl;
+ d.out << tab(2);
+ if (d.is_cb)
+ d.out << parameter_no_ref_type(d.type, d.name) << "* "
+ << callback_tmp(d.name);
+ else
+ d.out << parameter_type(d.type, d.name) << " " << d.name;
+ d.out << ";" << endl;
}
);
{
eo_constructor const& c = *it;
- out << comment(c.comment, 1);
-
- unsigned cb_count = parameters_count_callbacks(c.params);
- if(cb_count)
- out << tab(1) << "template <typename F>" << endl;
- out << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "("
+ out << comment(c.comment, 1)
+ << template_parameters_declaration(c.params, 1)
+ << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "("
<< parameters_declaration(c.params) << ")" << endl
<< tab(1) << "{" << endl
<< tab(2) << "return " << constructor_functor_type_decl(c) << "("
// TODO Require constructor methods of all base classes ?
//
+ unsigned cb_count = 0;
+
constructors_container_type::const_iterator it,
first = x._cls.constructors.cbegin(),
last = x._cls.constructors.cend();
-
for (it = first; it != last; ++it)
{
- unsigned cb_count = parameters_count_callbacks((*it).params);
- if(cb_count)
+ cb_count += parameters_count_callbacks((*it).params);
+ }
+
+ if (cb_count != 0)
+ {
+ out << tab(1) << "template <";
+ for (unsigned i = 0; i != cb_count; ++i)
{
- out << tab(1) << "template <typename F>" << endl;
- break;
+ if (i != 0)
+ out << ", ";
+ out << "typename F" << i;
}
+ out << ">" << endl;
}
out << tab(1) << x._cls.name << "(";
- for (it = first; it != last; ++it)
- {
- out << constructor_functor_type_decl(*it)
- << " _c" << (it-first) << ", ";
- }
+ {
+ unsigned cb_idx = 0;
+ for (it = first; it != last; ++it)
+ {
+ out << constructor_functor_type_name(*it);
+
+ if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
+ {
+ out << "<"
+ << parameters_cxx_generic((*it).params,
+ [&cb_idx](param_data d)
+ {
+ if (d.is_cb)
+ d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
+ })
+ << ">";
+ }
+ out << " _c" << (it-first) << ", ";
+ }
+ assert(cb_idx == cb_count);
+ }
out << "efl::eo::parent_type _p = (efl::eo::parent = nullptr))" << endl
<< tab(2) << ": " << x._cls.name << "(_ctors_call(";
for (it = first; it != last; ++it)
return out;
}
-struct constructors
-{
- eo_class const& _cls;
- constructors(eo_class const& cls)
- : _cls(cls)
- {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, constructors const& x)
-{
- constructors_container_type::const_iterator it,
- first = x._cls.constructors.cbegin(),
- last = x._cls.constructors.cend();
- for (it = first; it != last; ++it)
- {
- eo_constructor const& ctor = *it;
- out << comment(ctor.comment, 1);
- if (parameters_count_callbacks(ctor.params))
- out << tab(1) << "template <typename F>" << endl;
- out << tab(1)
- << x._cls.name
- << '(' << parameters_declaration(ctor.params)
- << (ctor.params.size() > 0 ? ", " : "")
- << "efl::eo::parent_type _p = (efl::eo::parent = nullptr))" << endl
- << tab(2) << ": " << class_name(x._cls.name)
- << "(_c" << (it - first) << "(" << constructor_parameters_list(ctor.params)
- << (ctor.params.size() > 0 ? ", " : "")
- << "_p))" << endl
- << tab(1) << "{}" << endl << endl;
- }
- return out;
-}
-
struct copy_constructor
{
eo_class const& _cls;
return out;
}
-struct eo_class_constructors
-{
- eo_class const& _cls;
- eo_class_constructors(eo_class const& cls) : _cls(cls) {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, eo_class_constructors const& x)
-{
- constructors_container_type::const_iterator it,
- first = x._cls.constructors.begin(),
- last = x._cls.constructors.end();
- for (it = first; it != last; ++it)
- {
- if (parameters_count_callbacks((*it).params))
- out << tab(1) << "template <typename F>" << endl;
- out << tab(1)
- << "static Eo* _c" << (it - first) << "("
- << parameters_declaration((*it).params)
- << ((*it).params.size() > 0 ? ", " : "")
- << "efl::eo::parent_type _p"
- << ')' << endl
- << tab(1) << "{" << endl;
-
- parameters_container_type::const_iterator callback_iter =
- parameters_find_callback((*it).params);
- if (callback_iter != (*it).params.cend())
- {
- out << tab(2)
- << "typedef typename std::remove_reference<F>::type function_type;" << endl
- << "function_type* _tmp_f = new F(std::forward<F>("
- << (*callback_iter).name << "));"
- << endl;
- }
- out << tab(2) << "return eo_add_ref("
- << x._cls.eo_name << ", _p._eo_raw, " << (*it).name
- << "(" << parameters_list((*it).params) << "));" << endl
- << tab(1) << "}" << endl << endl;
- }
- return out;
-}
-
struct function_call_constructor_methods
{
eo_class const& _cls;
inline std::ostream&
operator<<(std::ostream& out, function_call_constructor_methods const& x)
{
+ unsigned cb_count = 0;
+
constructors_container_type::const_iterator it,
first = x._cls.constructors.cbegin(),
last = x._cls.constructors.cend();
for (it = first; it != last; ++it)
{
- unsigned cb_count = parameters_count_callbacks((*it).params);
- if (cb_count)
+ unsigned param_cb_count = parameters_count_callbacks((*it).params);
+ for (unsigned i = 0; i != param_cb_count; ++i)
{
- out << tab(1) << "template <typename F>" << endl;
- break;
+ if(cb_count == 0)
+ out << tab(1) << "template <";
+ else
+ out << ", ";
+ out << "typename F" << cb_count++;
}
}
+ if (cb_count != 0)
+ out << ">" << endl;
+
+ unsigned cb_idx = 0;
out << tab(1) << "static Eo* _ctors_call(";
for (it = first; it != last; ++it)
{
- out << constructor_functor_type_decl(*it) << " _c" << (it-first) << ", ";
+ out << constructor_functor_type_name(*it);
+
+ if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
+ {
+ out << "<"
+ << parameters_cxx_generic((*it).params,
+ [&cb_idx](param_data d)
+ {
+ if (d.is_cb)
+ d.out << (d.cb_idx ? ", " : "") << "F" << cb_idx++;
+ })
+ << ">";
+ }
+ out << " _c" << (it-first) << ", ";
}
+ assert(cb_idx == cb_count);
+
out << "efl::eo::parent_type _p)" << endl
<< tab(1) << "{" << endl
- << tab(2) << "return eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw, ";
+ << tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw, ";
for (it = first; it != last; ++it)
{
out << "_c" << (it-first) << "(); ";
}
- out << ");" << endl
+ out << ");" << endl << endl;
+
+ cb_idx = 0;
+ for (it = first; it != last; ++it)
+ {
+ if (parameters_count_callbacks((*it).params) == 0)
+ continue;
+
+ out << parameters_cxx_generic((*it).params,
+ [&it, &first, &cb_idx](param_data d)
+ {
+ if (d.is_cb)
+ d.out << tab(2)
+ << "eo_do(_ret_eo," << endl
+ << tab(3) << "eo_event_callback_add(EO_EV_DEL, "
+ << "&efl::eolian::free_callback_calback<F" << cb_idx++
+ << ">, _c" << (it-first) << "." << callback_tmp(d.name)
+ << "));" << endl;
+ })
+ << endl;
+ }
+ assert(cb_idx == cb_count);
+
+ out << tab(2) << "return _ret_eo;" << endl
<< tab(1) << "}" << endl << endl;
return out;
bool is_void = function_is_void(x._func);
return out << (!is_void ? "_tmp_ret = " : "")
<< "::" << x._func.impl
- << "(" << parameters_list(x._func.params) << ")";
+ << "(" << parameters_forward_to_c(x._func.params) << ")";
}
struct function
eo_function const& func = x._func;
out << comment(x._func.comment, 1);
- if (parameters_count_callbacks(x._func.params) == 1)
- out << tab(1) << "template <typename F>" << endl;
+ out << template_parameters_declaration(func.params, 1);
if (function_is_static(func))
out << tab(1) << "static ";
out << tab(2)
<< func.ret.front().native << " _tmp_ret;" << endl;
- parameters_container_type::const_iterator callback_iter =
- parameters_find_callback(func.params);
- if (callback_iter != func.params.cend())
- {
- out << tab(2)
- << "typedef typename std::remove_reference<F>::type function_type;" << endl
- << tab(2) << "function_type* _tmp_f = new function_type(std::forward<F>("
- << (*callback_iter).name << "));"
- << endl;
- }
+ out << callbacks_heap_alloc("_eo_ptr()", func.params, 2);
out << tab(2)
<< "eo_do(_eo_ptr(), " << function_call(x._func) << ");" << endl;
eo_function const& func = x._func;
bool is_void = function_is_void(func);
- if (parameters_count_callbacks(func.params) == 1)
- out << tab(2) << "template <typename F>" << tab(2) << endl;
+ if (parameters_count_callbacks(func.params))
+ out << template_parameters_declaration(func.params, 2) << tab(2);
else
out << tab(2) << "virtual ";
if (!is_void)
out << tab(3) << func.ret.front().native << " _tmp_ret = {};" << endl;
- parameters_container_type::const_iterator
- callback_iter = parameters_find_callback(func.params);
- if (callback_iter != func.params.cend())
- out << tab(3) << "typedef typename std::remove_reference<F>::type function_type;" << endl
- << tab(3) << "function_type* _tmp_f = new function_type(std::forward<F>("
- << (*callback_iter).name << "));" << endl;
+ out << callbacks_heap_alloc("static_cast<T*>(this)->_eo_ptr()", func.params, 3)
+ << endl;
out << tab(3)
<< "eo_do_super(static_cast<T*>(this)->_eo_ptr()," << endl
inline std::ostream&
operator<<(std::ostream& out, inheritance_extension_function const& x)
{
- if (parameters_count_callbacks(x._func.params) == 1)
- out << tab(1) << "template <typename F>" << endl;
+ out << template_parameters_declaration(x._func.params, 1);
bool is_void = function_is_void(x._func);
out << tab(2)
out << tab(3) << x._func.ret.front().native << " _tmp_ret = {};" << endl;
}
- parameters_container_type::const_iterator callback_iter =
- parameters_find_callback(x._func.params);
- if (callback_iter != x._func.params.cend())
- {
- out << tab(2)
- << "typedef typename std::remove_reference<F>::type function_type;" << endl
- << "function_type* _tmp_f = new function_type(std::forward<F>("
- << (*callback_iter).name << "));"
- << endl;
- }
+ out << callbacks_heap_alloc("static_cast<U*>(this)->_eo_ptr()", x._func.params, 2)
+ << endl;
out << tab(3) << "eo_do(static_cast<U*>(this)->_eo_ptr(), "
<< function_call(x._func) << ");" << endl;
namespace efl { namespace eolian { namespace grammar {
struct
-parameter_type
-{
- eolian_type_instance const& _type;
- parameter_type(eolian_type_instance const& t)
- : _type(t)
- {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, parameter_type const& x)
-{
- if(type_is_callback(x._type))
- out << "F";
- else
- out << reinterpret_type(x._type);
- return out;
-}
-
-struct
parameter_forward
{
eolian_type_instance const& _type;
{
if (type_is_callback(x._type))
{
- out << "std::forward<F>(" << x._name << ")";
+ out << "std::forward<" << template_parameter_type(x._type, x._name) << ">(" << x._name << ")";
}
else
out << x._name;
}
struct
+callback_tmp
+{
+ std::string const& _name;
+ callback_tmp(std::string const& name)
+ : _name(name)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callback_tmp const& x)
+{
+ return out << "_tmp_" << x._name;
+}
+
+struct
+callback_parameter_heap_alloc
+{
+ eolian_type_instance const& _type;
+ std::string const& _name;
+ int _tab;
+ callback_parameter_heap_alloc(eolian_type_instance const& type, std::string const& name, int tab)
+ : _type(type)
+ , _name(name)
+ , _tab(tab)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callback_parameter_heap_alloc const& x)
+{
+ out << tab(x._tab) << parameter_remove_reference_typedef(x._type, x._name) << endl
+ << tab(x._tab) << parameter_no_ref_type(x._type, x._name) << "* "
+ << callback_tmp(x._name) << " = new "
+ << parameter_no_ref_type(x._type, x._name) << "(std::forward<"
+ << template_parameter_type(x._type, x._name) << ">(" << x._name << "));" << endl;
+ return out;
+}
+
+struct
+callback_parameter_free_ev_add
+{
+ std::string const& _eo_raw_expr;
+ eolian_type_instance const& _type;
+ std::string const& _name;
+ callback_parameter_free_ev_add(std::string const& eo_raw_expr, eolian_type_instance const& type, std::string const& name)
+ : _eo_raw_expr(eo_raw_expr)
+ , _type(type)
+ , _name(name)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callback_parameter_free_ev_add const& x)
+{
+ out << "eo_do(" << x._eo_raw_expr
+ << ", eo_event_callback_add(EO_EV_DEL, &efl::eolian::free_callback_calback<"
+ << parameter_no_ref_type(x._type, x._name) << ">, "
+ << callback_tmp(x._name) << "));";
+ return out;
+}
+
+struct
+callbacks_heap_alloc
+{
+ std::string const& _eo_raw_expr;
+ parameters_container_type const& _params;
+ int _tab;
+ callbacks_heap_alloc(std::string const& eo_raw_expr, parameters_container_type const& params, int tab)
+ : _eo_raw_expr(eo_raw_expr)
+ , _params(params)
+ , _tab(tab)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, callbacks_heap_alloc const& x)
+{
+ auto first = x._params.cbegin(), last = x._params.cend();
+ for (auto it = first; it != last; ++it)
+ {
+ if (type_is_callback((*it).type) && it+1 != last)
+ {
+ out << callback_parameter_heap_alloc((*it).type, (*it).name, x._tab)
+ << tab(x._tab)
+ << callback_parameter_free_ev_add(x._eo_raw_expr, (*it).type, (*it).name)
+ << endl << endl;
+ ++it; // skip next.
+ }
+ }
+ return out;
+}
+
+struct
+template_parameters_declaration
+{
+ parameters_container_type const& _params;
+ int _tab;
+ template_parameters_declaration(parameters_container_type const& params, int tab)
+ : _params(params)
+ , _tab(tab)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, template_parameters_declaration const& x)
+{
+ if (parameters_count_callbacks(x._params) == 0)
+ return out;
+
+ bool comma = false;
+ out << tab(x._tab) << "template <";
+ auto first = x._params.cbegin(), last = x._params.cend();
+ for (auto it = first; it != last; ++it)
+ {
+ if (type_is_callback((*it).type) && it+1 != last)
+ {
+ if (comma)
+ out << ", ";
+ else
+ comma = true;
+ out << "typename " << template_parameter_type((*it).type, (*it).name);
+ ++it; // skip next.
+ }
+ }
+ return out << ">" << endl;
+}
+
+struct
parameters_declaration
{
parameters_container_type const& _params;
// and does not have a following userdata pointer ?
if (type_is_callback((*it).type) && it+1 != last)
{
- out << "F && " << (*it).name;
- assert(it+1 != last);
+ out << template_parameter_type((*it).type, (*it).name) << " && " << (*it).name;
++it; // skip next.
}
else
}
struct
-parameters_list
-{
- parameters_container_type const& _params;
- parameters_list(parameters_container_type const& params)
- : _params(params)
- {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, parameters_list const& x)
-{
- auto first = x._params.cbegin(), last = x._params.cend();
- for (auto it = first; it != last; ++it)
- {
- if (it != first)
- out << ", ";
- if (type_is_callback((*it).type))
- {
- if(it + 1 != last)
- {
- out << to_c((*it).type, (*it).name)
- << ", _tmp_f";
- ++it; // skip next
- }
- else
- out << it->name;
- }
- else
- out << to_c((*it).type, (*it).name);
- }
- return out;
-}
-
-struct
parameters_c_list
{
parameters_container_type const& _params;
}
struct
-constructor_parameters_list
-{
- parameters_container_type const& _params;
- constructor_parameters_list(parameters_container_type const& params)
- : _params(params)
- {}
-};
-
-inline std::ostream&
-operator<<(std::ostream& out, constructor_parameters_list const& x)
-{
- auto first = x._params.cbegin(),
- last = x._params.cend();
- for (auto it = first; it != last; ++it)
- {
- if (it != first)
- out << ", ";
- if (type_is_callback((*it).type) && it + 1 != last)
- {
- out << "std::forward<F>(" << (*it).name << ")";
- ++it; // skip next.
- }
- else
- out << (*it).name;
- }
- return out;
-}
-
-struct
parameters_forward
{
parameters_container_type const& _params;
{
if (it != first)
out << ", ";
- if (type_is_callback((*it).type) && it + 1 != last)
+ if (type_is_callback((*it).type))
{
- out << to_c((*it).type, (*it).name) << ", _tmp_f";
- ++it; // skip next
+ // TODO: Is it correct to simple not translate the callback type
+ // when it is the last paramenter?
+ if(it + 1 != last)
+ {
+ out << to_c((*it).type, (*it).name) << ", " << callback_tmp((*it).name);
+ ++it; // skip next
+ }
+ else
+ out << (*it).name;
}
else
out << to_c((*it).type, (*it).name);
return out << ">()";
}
+struct
+template_parameter_type
+{
+ eolian_type_instance const& _type;
+ std::string const& _name;
+ template_parameter_type(eolian_type_instance const& type, std::string const& name)
+ : _type(type)
+ , _name(name)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, template_parameter_type const& x)
+{
+ return out << "F_" << x._name;
+}
+
+struct
+parameter_type
+{
+ eolian_type_instance const& _type;
+ std::string const& _name;
+ parameter_type(eolian_type_instance const& t, std::string const& name)
+ : _type(t)
+ , _name(name)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, parameter_type const& x)
+{
+ if(type_is_callback(x._type))
+ out << template_parameter_type(x._type, x._name);
+ else
+ out << reinterpret_type(x._type);
+ return out;
+}
+
+struct
+parameter_no_ref_type
+{
+ eolian_type_instance const& _type;
+ std::string const& _name;
+ parameter_no_ref_type(eolian_type_instance const& type, std::string const& name)
+ : _type(type)
+ , _name(name)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, parameter_no_ref_type const& x)
+{
+ return out << "_no_ref_" << parameter_type(x._type, x._name);
+}
+
+struct
+parameter_remove_reference_typedef
+{
+ eolian_type_instance const& _type;
+ std::string const& _name;
+ parameter_remove_reference_typedef(eolian_type_instance const& type, std::string const& name)
+ : _type(type)
+ , _name(name)
+ {}
+};
+
+inline std::ostream&
+operator<<(std::ostream& out, parameter_remove_reference_typedef const& x)
+{
+ out << "typedef typename std::remove_reference<"
+ << parameter_type(x._type, x._name)
+ << ">::type " << parameter_no_ref_type(x._type, x._name) << ";";
+ return out;
+}
+
struct to_cxx
{
eolian_type_instance const& _type;
operator<<(std::ostream& out, to_c const& x)
{
if (type_is_callback(x._type))
- out << "efl::eolian::get_callback<" << type_to_native_str(x._type) << ", function_type>()";
+ out << "efl::eolian::get_callback<" << type_to_native_str(x._type)
+ << ", " << parameter_no_ref_type(x._type, x._varname) << " >()";
else if (type_is_binding(x._type))
out << "efl::eolian::to_c(" << x._varname << ")";
else