efl/src/lib/eolian_cxx/grammar/parameters_generator.hh

453 lines
11 KiB
C++

#ifndef EOLIAN_CXX_STD_PARAMETERS_GENERATOR_HH
#define EOLIAN_CXX_STD_PARAMETERS_GENERATOR_HH
#include <iosfwd>
#include "tab.hh"
#include "eo_types.hh"
#include "type_generator.hh"
namespace efl { namespace eolian { namespace grammar {
struct
parameter_forward
{
eolian_type_instance const& _type;
std::string const& _name;
parameter_forward(eolian_type_instance const& type, std::string const& name)
: _type(type)
, _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameter_forward const& x)
{
if (type_is_callback(x._type))
{
out << "std::forward<" << template_parameter_type(x._type, x._name) << ">(" << x._name << ")";
}
else
out << x._name;
return out;
}
struct param_data
{
std::ostream& out;
unsigned pos;
eolian_type_instance const& type;
std::string const& name;
int cb_idx;
bool is_cb;
param_data(std::ostream& out_, unsigned pos_, eolian_type_instance const& type_, std::string const& name_, int cb_idx_)
: out(out_)
, pos(pos_)
, type(type_)
, name(name_)
, cb_idx(cb_idx_)
, is_cb(cb_idx_ >= 0)
{}
};
template <typename T>
struct
_parameters_cxx_generic
{
parameters_container_type const& _params;
T _fparam;
_parameters_cxx_generic(parameters_container_type const& params, T fparam)
: _params(params)
, _fparam(fparam)
{}
};
template <typename T>
std::ostream&
operator<<(std::ostream& out, _parameters_cxx_generic<T> const& x)
{
int cb_idx = 0u;
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)
{
x._fparam(param_data(out, it - first, (*it).type, (*it).name, cb_idx++));
++it; // skip next.
}
else
x._fparam(param_data(out, it - first, (*it).type, (*it).name, -1));
}
return out;
}
template <typename T>
_parameters_cxx_generic<T>
parameters_cxx_generic(parameters_container_type const& params, T fparam)
{
return _parameters_cxx_generic<T>(params, fparam);
}
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_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;
bool _is_static_func;
int _tab;
callbacks_heap_alloc(std::string const& eo_raw_expr, parameters_container_type const& params, bool is_static_func, int tab)
: _eo_raw_expr(eo_raw_expr)
, _params(params)
, _is_static_func(is_static_func)
, _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)
{
auto type = (*it).type;
auto name = (*it).name;
if (type_is_callback(type) && it+1 != last)
{
out << tab(x._tab) << parameter_remove_reference_typedef(type, name) << endl
<< tab(x._tab) << parameter_no_ref_type(type, name) << "* "
<< callback_tmp(name) << " = ";
if (!x._is_static_func)
{
out << "new " << parameter_no_ref_type(type, name)
<< "(std::forward< "
<< template_parameter_type(type, name) << " >(" << name << "));" << endl
<< tab(x._tab)
<< callback_parameter_free_ev_add(x._eo_raw_expr, type, name)
<< endl << endl;
}
else
{
out << "::efl::eolian::alloc_static_callback< "
<< parameter_no_ref_type(type, name) << " >(std::forward< "
<< template_parameter_type(type, name) << " >(" << name << "));" << 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;
parameters_declaration(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_declaration const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
// TODO What to do when callback happens in the middle of parameters
// and does not have a following userdata pointer ?
if (type_is_callback((*it).type) && it+1 != last)
{
out << template_parameter_type((*it).type, (*it).name) << " && " << (*it).name;
++it; // skip next.
}
else
out << reinterpret_type((*it).type) << " " << (*it).name;
}
return out;
}
struct
parameters_c_declaration
{
parameters_container_type const& _params;
parameters_c_declaration(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_c_declaration const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << c_type(it->type) << " " << (*it).name;
}
return out;
}
struct
parameters_names
{
parameters_container_type const& _params;
parameters_names(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_names const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << it->name;
if (type_is_callback(it->type) && it+1 != last)
++it; // skip next.
}
return out;
}
struct
parameters_c_names
{
parameters_container_type const& _params;
parameters_c_names(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_c_names const& x)
{
auto first = x._params.cbegin(),
last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << it->name;
}
return out;
}
struct
parameters_types
{
parameters_container_type const& _params;
parameters_types(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_types const& x)
{
parameters_container_type::const_iterator it,
first = x._params.begin(),
last = x._params.end();
for (it = first; it != last; ++it)
{
if(it != first) out << ", ";
out << reinterpret_type((*it).type);
}
return out;
}
struct
parameters_c_list
{
parameters_container_type const& _params;
parameters_c_list(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_c_list const& x)
{
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << it->name;
}
return out;
}
struct
parameters_cxx_list
{
parameters_container_type const& _params;
parameters_cxx_list(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_cxx_list const& x)
{
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << to_cxx(it->type, it->name);
}
return out;
}
struct
parameters_forward
{
parameters_container_type const& _params;
parameters_forward(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_forward const& x)
{
auto first = x._params.cbegin(), last = x._params.cend();
for (auto it = first; it != last; ++it)
{
if (it != first)
out << ", ";
out << parameter_forward((*it).type, (*it).name);
if (type_is_callback((*it).type) && it+1 != last)
{
++it; // skip next.
}
}
return out;
}
struct
parameters_forward_to_c
{
parameters_container_type const& _params;
parameters_forward_to_c(parameters_container_type const& params)
: _params(params)
{}
};
inline std::ostream&
operator<<(std::ostream& out, parameters_forward_to_c 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))
{
// 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;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_PARAMETERS_GENERATOR_HH