efl/src/lib/eolian_cxx/grammar/eo_class_constructors_gener...

482 lines
14 KiB
C++

#ifndef EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
#define EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH
#include <iosfwd>
#include <string>
#include "eo_types.hh"
#include "tab.hh"
#include "comment.hh"
#include "parameters_generator.hh"
#include "namespace_generator.hh"
namespace efl { namespace eolian { namespace grammar {
struct class_name
{
std::string _name;
class_name(std::string name)
: _name(name)
{}
};
inline std::ostream&
operator<<(std::ostream& out, class_name const& x)
{
out << x._name;
return out;
}
struct class_inheritance
{
eo_class const& _cls;
class_inheritance(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, class_inheritance const& x)
{
eo_class const& cls = x._cls;
parents_container_type::const_iterator it,
first = cls.parents.cbegin(),
last = cls.parents.cend();
for (it = first; it != last; ++it)
{
out << tab(2) << (it == first ? ": " : ", ")
<< "::" << abstract_namespace << "::" << *it << endl;
}
return out;
}
struct constructor_functor_type_name
{
eo_constructor const& _ctor;
constructor_functor_type_name(eo_constructor const& ctor)
: _ctor(ctor)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_functor_type_name const& x)
{
out << "_c_" << x._ctor.name;
return out;
}
struct constructor_functor_type_decl
{
eo_constructor const& _ctor;
constructor_functor_type_decl(eo_constructor const& ctor)
: _ctor(ctor)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_functor_type_decl const& x)
{
out << constructor_functor_type_name(x._ctor);
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)
{
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 << ">";
}
struct functors_constructor_methods
{
eo_class const& _cls;
functors_constructor_methods(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, functors_constructor_methods 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& c = *it;
// Struct declaration
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) << ")"
<< parameters_cxx_generic(c.params,
[](param_data d)
{
if(d.pos == 0u)
d.out << endl << tab(3) << ": ";
else
d.out << ", ";
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
<< tab(2) << "{}" << endl;
// Struct operator()
out << tab(2) << "void operator()()" << endl
<< tab(2) << "{" << endl
<< tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl
<< tab(2) << "}" << endl;
// Struct member variables
out << endl
<< parameters_cxx_generic(c.params,
[](param_data d)
{
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;
}
);
// Close struct
out << tab(1) << "};" << endl << endl;
}
return out;
}
struct constructor_method_function_declarations
{
eo_class const& _cls;
constructor_method_function_declarations(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_method_function_declarations 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& c = *it;
// "eo_constructor" is already called in the eo_add_ref macro (used in
// _ctors_call).
// Creating a function with this name yields an error in the eo_add_ref
// macro expansion, because "eo_constructor" will refers to the class
// function instead of the Eo.Base function which is intended.
if (c.name == "eo_constructor")
{
continue;
}
out << comment(c.comment, 0)
<< template_parameters_declaration(c.params, 1)
<< tab(1) << constructor_functor_type_decl(c) << " " << c.name << "("
<< parameters_declaration(c.params) << ") const;" << endl << endl;
}
return out;
}
struct constructor_method_function_definitions
{
eo_class const& _cls;
constructor_method_function_definitions(eo_class const& cls) : _cls(cls) {}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_method_function_definitions 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& c = *it;
// Same explanation as the one in constructor_method_function_declarations
if (c.name == "eo_constructor")
{
continue;
}
out << template_parameters_declaration(c.params, 0)
<< "inline " << abstract_full_name(x._cls)
<< "::" << constructor_functor_type_decl(c) << " "
<< abstract_full_name(x._cls, false) << "::" << c.name << "("
<< parameters_declaration(c.params) << ") const" << endl
<< "{" << endl
<< tab(1) << "return " << constructor_functor_type_decl(c) << "("
<< parameters_forward(c.params) << ");" << endl
<< "}" << endl << endl;
}
return out;
}
struct constructor_with_constructor_methods
{
eo_class const& _cls;
constructor_with_constructor_methods(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_with_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)
{
cb_count += parameters_count_callbacks((*it).params);
}
if (cb_count != 0)
{
out << tab(1) << "template <";
for (unsigned i = 0; i != cb_count; ++i)
{
if (i != 0)
out << ", ";
out << "typename F" << i;
}
out << ">" << endl;
}
out << tab(1) << x._cls.name << "(";
{
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)
{
out << "_c" << (it-first) << ", ";
}
out << "_p))" << endl
<< tab(1) << "{}" << endl << endl;
return out;
}
struct constructor_eo
{
eo_class const& _cls;
constructor_eo(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, constructor_eo const& x)
{
std::string doc = "@brief Eo Constructor.\n\n"
"Constructs the object from an Eo* pointer stealing its ownership.\n\n"
"@param eo The Eo object pointer.\n\n";
out << comment(doc, 1)
<< tab(1)
<< "explicit " << x._cls.name << "(Eo* eo)" << endl
<< tab(2) << ": ::efl::eo::concrete(eo)" << endl
<< tab(1) << "{}" << endl << endl;
out << comment(
"@brief nullptr_t Constructor.\n\n"
"Constructs an empty (null) object.\n\n"
, 1
)
<< tab(1)
<< "explicit " << x._cls.name << "(std::nullptr_t)" << endl
<< tab(2) << ": ::efl::eo::concrete(nullptr)" << endl
<< tab(1) << "{}" << endl << endl;
return out;
}
struct copy_constructor
{
eo_class const& _cls;
copy_constructor(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, copy_constructor const& x)
{
std::string doc = "@brief Copy Constructor.\n\n";
out << comment(doc, 1)
<< tab(1)
<< x._cls.name << "(" << x._cls.name << " const& other)" << endl
<< tab(2) << ": " << x._cls.name
<< "(eo_ref(other._eo_ptr()))" << endl
<< tab(1) << "{}" << endl << endl;
return out;
}
struct destructor
{
eo_class const& _cls;
destructor(eo_class const& cls)
: _cls(cls)
{}
};
inline std::ostream&
operator<<(std::ostream& out, destructor const& x)
{
out << tab(1)
<< '~' << x._cls.name << "() {}" << endl << endl;
return out;
}
struct function_call_constructor_methods
{
eo_class const& _cls;
function_call_constructor_methods(eo_class const& cls) : _cls(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 param_cb_count = parameters_count_callbacks((*it).params);
for (unsigned i = 0; i != param_cb_count; ++i)
{
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_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) << "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 << 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;
}
} } } // namespace efl { namespace eolian { namespace grammar {
#endif // EOLIAN_CXX_STD_EO_CLASS_CONSTRUCTORS_GENERATOR_HH