#ifndef EOLIAN_CXX_KLASS_DEF_HH #define EOLIAN_CXX_KLASS_DEF_HH #include "grammar/type_traits.hpp" #include "grammar/attributes.hpp" #include "grammar/qualifier_def.hpp" #include "grammar/string.hpp" #include "grammar/sequence.hpp" #include "grammar/kleene.hpp" #include "grammar/case.hpp" #include #include #include #include #include namespace efl { namespace eolian { namespace grammar { namespace attributes { struct complex_type_def; } namespace attributes { template bool lexicographical_compare_impl(std::tuple const& , std::tuple const& , std::integral_constant , std::true_type) { return true; } template bool lexicographical_compare_impl(std::tuple const& lhs , std::tuple const& rhs , std::integral_constant , std::false_type) { return std::get(lhs) < std::get(rhs) || (!(std::get(rhs) < std::get(lhs)) && lexicographical_compare_impl(lhs, rhs, std::integral_constant() , std::integral_constant()) ) ; } template bool lexicographical_compare(std::tuple const& lhs , std::tuple const& rhs) { return lexicographical_compare_impl(lhs, rhs, std::integral_constant(), std::false_type()); } template bool lexicographical_compare(std::tuple const& lhs , std::tuple const& rhs) { return std::get<0>(lhs) < std::get<0>(rhs) || (!(std::get<0>(rhs) < std::get<0>(lhs)) && std::get<1>(lhs) < std::get<1>(rhs)); } enum class typedecl_type { unknown, struct_, struct_opaque, enum_, alias, function_ptr, }; inline typedecl_type typedecl_type_get(Eolian_Typedecl const* decl) { if (!decl) return typedecl_type::unknown; Eolian_Typedecl_Type t = eolian_typedecl_type_get(decl); switch (t) { case EOLIAN_TYPEDECL_UNKNOWN: return typedecl_type::unknown; case EOLIAN_TYPEDECL_STRUCT: return typedecl_type::struct_; case EOLIAN_TYPEDECL_STRUCT_OPAQUE: return typedecl_type::struct_opaque; case EOLIAN_TYPEDECL_ENUM: return typedecl_type::enum_; case EOLIAN_TYPEDECL_ALIAS: return typedecl_type::alias; case EOLIAN_TYPEDECL_FUNCTION_POINTER: return typedecl_type::function_ptr; default: return typedecl_type::unknown; } } struct type_def; bool operator==(type_def const& rhs, type_def const& lhs); bool operator!=(type_def const& rhs, type_def const& lhs); enum class class_type { regular, abstract_, mixin, interface_ }; struct klass_name { std::vector namespaces; std::string eolian_name; qualifier_def base_qualifier; class_type type; klass_name() { } klass_name(std::vector namespaces , std::string eolian_name, qualifier_def base_qualifier , class_type type) : namespaces(namespaces), eolian_name(eolian_name), base_qualifier(base_qualifier) , type(type) {} klass_name(Eolian_Class const* klass, qualifier_def base_qualifier) : eolian_name( ::eolian_class_short_name_get(klass)) , base_qualifier(base_qualifier) { for(efl::eina::iterator namespace_iterator ( ::eolian_class_namespaces_get(klass)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) { namespaces.push_back(&*namespace_iterator); } switch(eolian_class_type_get(klass)) { case EOLIAN_CLASS_REGULAR: type = class_type::regular; break; case EOLIAN_CLASS_ABSTRACT: type = class_type::abstract_; break; case EOLIAN_CLASS_MIXIN: type = class_type::mixin; break; case EOLIAN_CLASS_INTERFACE: type = class_type::interface_; break; default: throw std::runtime_error("Class with unknown type"); } } }; inline bool operator==(klass_name const& lhs, klass_name const& rhs) { return lhs.namespaces == rhs.namespaces && lhs.eolian_name == rhs.eolian_name && lhs.base_qualifier == rhs.base_qualifier/* && lhs.pointers == rhs.pointers*/; } inline bool operator!=(klass_name const& lhs, klass_name const& rhs) { return !(lhs == rhs); } inline bool operator<(klass_name const& lhs, klass_name const& rhs) { typedef std::tupleconst& , std::string const& , qualifier_def const& , class_type > tuple_type; return lexicographical_compare(tuple_type(lhs.namespaces, lhs.eolian_name , lhs.base_qualifier , lhs.type) , tuple_type(rhs.namespaces, rhs.eolian_name , rhs.base_qualifier , rhs.type)); } struct documentation_def { std::string summary; std::string description; std::string since; std::vector desc_paragraphs; documentation_def() {} documentation_def(std::string summary, std::string description, std::string since) : summary(summary), description(description), since(since) {} documentation_def(Eolian_Documentation const* eolian_doc) { const char *str; if (!eolian_doc) return; str = eolian_documentation_summary_get(eolian_doc); if (str) summary = str; str = eolian_documentation_description_get(eolian_doc); if (str) description = str; str = eolian_documentation_since_get(eolian_doc); if (str) since = str; efl::eina::ptr_list l(eolian_documentation_string_split(description.c_str())); for (auto&& i : l) desc_paragraphs.push_back({&i}); } friend inline bool operator==(documentation_def const& lhs, documentation_def const& rhs) { return lhs.summary == rhs.summary && lhs.description == rhs.description && lhs.since == rhs.since; } }; template <> struct tuple_element<0ul, klass_name> { typedef std::vector type; static type& get(klass_name& klass) { return klass.namespaces; } static type const& get(klass_name const& klass) { return klass.namespaces; } }; template <> struct tuple_element<1ul, klass_name> { typedef std::string type; static type& get(klass_name& klass) { return klass.eolian_name; } static type const& get(klass_name const& klass) { return klass.eolian_name; } }; template struct tuple_element : tuple_element {}; template typename tuple_element::type& get(klass_name& klass) { return tuple_element::get(klass); } template typename tuple_element::type const& get(klass_name const& klass) { return tuple_element::get(klass); } struct regular_type_def { regular_type_def() : type_type(typedecl_type::unknown), is_undefined(false) {} regular_type_def(std::string base_type, qualifier_def qual, std::vector namespaces , typedecl_type type_type = typedecl_type::unknown, bool is_undefined = false) : base_type(std::move(base_type)), base_qualifier(qual), namespaces(std::move(namespaces)) , type_type(type_type), is_undefined(is_undefined) {} bool is_type(typedecl_type tt) const { return type_type == tt; } bool is_unknown() const { return is_type(typedecl_type::unknown); } bool is_struct() const { return is_type(typedecl_type::struct_); } bool is_struct_opaque() const { return is_type(typedecl_type::struct_opaque); } bool is_enum() const { return is_type(typedecl_type::enum_); } bool is_alias() const { return is_type(typedecl_type::alias); } bool is_function_ptr() const { return is_type(typedecl_type::function_ptr); } std::string base_type; qualifier_def base_qualifier; std::vector namespaces; typedecl_type type_type; bool is_undefined; }; inline bool operator==(regular_type_def const& rhs, regular_type_def const& lhs) { return rhs.base_type == lhs.base_type && rhs.base_qualifier == lhs.base_qualifier; } inline bool operator!=(regular_type_def const& rhs, regular_type_def const& lhs) { return !(rhs == lhs); } struct complex_type_def { regular_type_def outer; std::vector subtypes; }; inline bool operator==(complex_type_def const& lhs, complex_type_def const& rhs) { return lhs.outer == rhs.outer && lhs.subtypes == rhs.subtypes; } inline bool operator!=(complex_type_def const& lhs, complex_type_def const& rhs) { return !(lhs == rhs); } struct type_def { typedef eina::variant variant_type; variant_type original_type; std::string c_type; bool has_own; bool is_ptr; type_def() {} type_def(variant_type original_type, std::string c_type, bool has_own) : original_type(original_type), c_type(c_type), has_own(has_own) {} type_def(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype) { set(eolian_type, unit, ctype); } void set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype); void set(Eolian_Expression_Type eolian_exp_type); friend inline bool operator<(type_def const& lhs, type_def const& rhs) { return lhs.c_type < rhs.c_type; } }; struct get_qualifier_visitor { typedef qualifier_def result_type; template qualifier_def operator()(T const& object) const { return object.base_qualifier; } qualifier_def operator()(complex_type_def const& complex) const { return complex.outer.base_qualifier; } }; inline bool operator==(type_def const& lhs, type_def const& rhs) { return lhs.original_type == rhs.original_type && lhs.c_type == rhs.c_type; } inline bool operator!=(type_def const& lhs, type_def const& rhs) { return !(lhs == rhs); } type_def const void_ {attributes::regular_type_def{"void", {qualifier_info::is_none, {}}, {}}, "void", false}; inline void type_def::set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype) { c_type = ::eolian_type_c_type_get(eolian_type, ctype); // ::eina_stringshare_del(stringshare); // this crashes Eolian_Type const* stp = eolian_type_base_type_get(eolian_type); has_own = !!::eolian_type_is_owned(eolian_type); is_ptr = !!::eolian_type_is_ptr(eolian_type); switch( ::eolian_type_type_get(eolian_type)) { case EOLIAN_TYPE_VOID: original_type = attributes::regular_type_def{"void", {qualifiers(eolian_type), {}}, {}}; break; case EOLIAN_TYPE_REGULAR: if (!stp) { bool is_undefined = false; Eolian_Typedecl const* decl = eolian_type_typedecl_get(eolian_type); typedecl_type type_type = (decl ? typedecl_type_get(decl) : typedecl_type::unknown); if(decl && eolian_typedecl_type_get(decl) == EOLIAN_TYPEDECL_ALIAS) { Eolian_Type const* aliased = eolian_typedecl_base_type_get(decl); if(aliased && eolian_type_type_get(aliased) == EOLIAN_TYPE_UNDEFINED) { is_undefined = true; } } if(c_type == "va_list *") throw std::runtime_error(""); std::vector namespaces; for(efl::eina::iterator namespace_iterator( ::eolian_type_namespaces_get(eolian_type)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) namespaces.push_back(&*namespace_iterator); original_type = {regular_type_def{ ::eolian_type_short_name_get(eolian_type), {qualifiers(eolian_type), {}}, namespaces, type_type, is_undefined}}; } else { complex_type_def complex {{::eolian_type_short_name_get(eolian_type), {qualifiers(eolian_type), {}}, {}}, {}}; while (stp) { complex.subtypes.push_back({stp, unit, EOLIAN_C_TYPE_DEFAULT}); stp = eolian_type_next_type_get(stp); } original_type = complex; } break; case EOLIAN_TYPE_CLASS: { Eolian_Class const* klass = eolian_type_class_get(eolian_type); original_type = klass_name(klass, {qualifiers(eolian_type), {}}); } break; default: throw std::runtime_error("Type not supported"); break; } } inline void type_def::set(Eolian_Expression_Type eolian_exp_type) { switch(eolian_exp_type) { case EOLIAN_EXPR_INT: original_type = attributes::regular_type_def{"int", {{}, {}}, {}}; c_type = "int"; break; default: // FIXME implement the remaining types EINA_LOG_ERR("Unsupported expression type"); std::abort(); break; } } struct alias_def { std::string eolian_name; std::string cxx_name; std::vector namespaces; bool is_undefined; type_def base_type {}; documentation_def documentation; alias_def(Eolian_Typedecl const* alias_obj, Eolian_Unit const* unit) { cxx_name = eolian_name = ::eolian_typedecl_short_name_get(alias_obj); for(efl::eina::iterator namespace_iterator( ::eolian_typedecl_namespaces_get(alias_obj)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) { this->namespaces.push_back((&*namespace_iterator)); } Eolian_Type const* bt = ::eolian_typedecl_base_type_get(alias_obj); if (eolian_type_type_get(bt) == EOLIAN_TYPE_UNDEFINED) is_undefined = true; else { base_type = type_def(::eolian_typedecl_base_type_get(alias_obj), unit, EOLIAN_C_TYPE_DEFAULT); is_undefined = false; } documentation = ::eolian_typedecl_documentation_get(alias_obj); } }; enum class parameter_direction { unknown, in, inout, out }; namespace detail { struct add_optional_qualifier_visitor { typedef void result_type; template void operator()(T& object) const { object.base_qualifier.qualifier |= qualifier_info::is_optional; } void operator()(complex_type_def& complex) const { (*this)(complex.outer); } }; } struct parameter_def { parameter_direction direction; type_def type; std::string param_name; documentation_def documentation; Eolian_Unit const* unit; friend inline bool operator==(parameter_def const& lhs, parameter_def const& rhs) { return lhs.direction == rhs.direction && lhs.type == rhs.type && lhs.param_name == rhs.param_name && lhs.documentation == rhs.documentation; } friend inline bool operator!=(parameter_def const& lhs, parameter_def const& rhs) { return !(lhs == rhs); } parameter_def(parameter_direction direction, type_def type, std::string param_name, documentation_def documentation, Eolian_Unit const* unit) : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)), documentation(documentation), unit(unit) {} parameter_def(Eolian_Function_Parameter const* param, Eolian_Unit const* unit) : type( ::eolian_parameter_type_get(param), unit, EOLIAN_C_TYPE_PARAM) , param_name( ::eolian_parameter_name_get(param)), unit(unit) { Eolian_Parameter_Dir direction = ::eolian_parameter_direction_get(param); switch(direction) { case EOLIAN_UNKNOWN_PARAM: case EOLIAN_IN_PARAM: this->direction = parameter_direction::in; break; case EOLIAN_INOUT_PARAM: this->direction = parameter_direction::inout; break; case EOLIAN_OUT_PARAM: this->direction = parameter_direction::out; break; } if( ::eolian_parameter_is_optional(param)) type.original_type.visit(detail::add_optional_qualifier_visitor{}); documentation = eolian_parameter_documentation_get(param); } }; template <> struct tuple_element<0ul, parameter_def> { typedef parameter_direction type; static type const& get(parameter_def const& p) { return p.direction; } static type& get(parameter_def& p) { return p.direction; } }; template <> struct tuple_element<1ul, parameter_def> { typedef type_def type; static type const& get(parameter_def const& p) { return p.type; } static type& get(parameter_def& p) { return p.type; } }; template <> struct tuple_element<2ul, parameter_def> { typedef std::string type; static type const& get(parameter_def const& p) { return p.param_name; } static type& get(parameter_def& p) { return p.param_name; } }; template <> struct tuple_element<3ul, parameter_def> { typedef std::string type; static type const& get(parameter_def const& p) { return p.type.c_type; } static type& get(parameter_def& p) { return p.type.c_type; } }; template typename tuple_element::type const& get(parameter_def const& p) { return tuple_element::get(p); } template typename tuple_element::type& get(parameter_def& p) { return tuple_element::get(p); } enum class function_type { unresolved, property, prop_set, prop_get, method, function_pointer }; struct function_def { klass_name klass; // Klass information for function_def as method type_def return_type; std::string name; std::vector parameters; std::string c_name; std::string filename; std::vector namespaces; // Namespaces for top-level function pointers documentation_def documentation; documentation_def return_documentation; documentation_def property_documentation; function_type type; bool is_beta; bool is_protected; bool is_static; Eolian_Unit const* unit; friend inline bool operator==(function_def const& lhs, function_def const& rhs) { return lhs.klass == rhs.klass && lhs.return_type == rhs.return_type && lhs.name == rhs.name && lhs.parameters == rhs.parameters && lhs.c_name == rhs.c_name && lhs.filename == rhs.filename && lhs.namespaces == rhs.namespaces && lhs.documentation == rhs.documentation && lhs.return_documentation == rhs.return_documentation && lhs.property_documentation == rhs.property_documentation && lhs.type == rhs.type && lhs.is_beta == rhs.is_beta && lhs.is_protected == rhs.is_protected && lhs.is_static == rhs.is_static; } friend inline bool operator!=(function_def const& lhs, function_def const& rhs) { return !(lhs == rhs); } function_def() = default; function_def(klass_name _klass, type_def _return_type, std::string const& _name, std::vector const& _parameters, std::string const& _c_name, std::string _filename, std::vector const& _namespaces, documentation_def _documentation, documentation_def _return_documentation, documentation_def _property_documentation, function_type _type, bool _is_beta = false, bool _is_protected = false, Eolian_Unit const* unit = nullptr) : klass(_klass), return_type(_return_type), name(_name), parameters(_parameters), c_name(_c_name), filename(_filename), namespaces(_namespaces), documentation(_documentation), return_documentation(_return_documentation), property_documentation(_property_documentation), type(_type), is_beta(_is_beta), is_protected(_is_protected), unit(unit) {} function_def( ::Eolian_Function const* function, Eolian_Function_Type type, Eolian_Typedecl const* tp, Eolian_Unit const* unit) : return_type(void_), unit(unit) { Eolian_Type const* r_type = ::eolian_function_return_type_get(function, type); name = ::eolian_function_name_get(function); if(r_type) return_type.set(r_type, unit, EOLIAN_C_TYPE_RETURN); if(type == EOLIAN_METHOD || type == EOLIAN_FUNCTION_POINTER) { for(efl::eina::iterator param_iterator ( ::eolian_function_parameters_get(function)) , param_last; param_iterator != param_last; ++param_iterator) { parameters.push_back({&*param_iterator, unit}); } } else if(type == EOLIAN_PROP_GET || type == EOLIAN_PROP_SET) { if(type == EOLIAN_PROP_GET) name += "_get"; else name += "_set"; for(efl::eina::iterator param_iterator ( ::eolian_property_keys_get(function, type)) , param_last; param_iterator != param_last; ++param_iterator) { parameters.push_back({&*param_iterator, unit}); } std::vector values; for(efl::eina::iterator param_iterator ( ::eolian_property_values_get(function, type)) , param_last; param_iterator != param_last; ++param_iterator) { values.push_back({&*param_iterator, unit}); } if(!r_type && type == EOLIAN_PROP_GET && values.size() == 1) { return_type = values[0].type; } else if(type == EOLIAN_PROP_GET) { for(auto&& v : values) { v.direction = parameter_direction::out; parameters.push_back(v); } } else parameters.insert(parameters.end(), values.begin(), values.end()); } c_name = eolian_function_full_c_name_get(function, type, EINA_FALSE); if (type != EOLIAN_FUNCTION_POINTER) { const Eolian_Class *eolian_klass = eolian_function_class_get(function); filename = eolian_object_file_get((const Eolian_Object *)eolian_klass); klass = klass_name(eolian_klass, {attributes::qualifier_info::is_none, std::string()}); } else { filename = ""; if (tp) { for (efl::eina::iterator ns_iterator(::eolian_typedecl_namespaces_get(tp)), ns_last; ns_iterator != ns_last; ns_iterator++) namespaces.push_back(&*ns_iterator); } } is_beta = eolian_function_is_beta(function); is_protected = eolian_function_scope_get(function, type) == EOLIAN_SCOPE_PROTECTED; is_static = eolian_function_is_class(function); return_documentation = eolian_function_return_documentation_get(function, type); Eolian_Implement const* implement = eolian_function_implement_get(function); if (!implement) return; documentation = eolian_implement_documentation_get(implement, type); if (type == EOLIAN_PROP_GET || type == EOLIAN_PROP_SET) property_documentation = eolian_implement_documentation_get(implement, EOLIAN_PROPERTY); switch (type) { case EOLIAN_UNRESOLVED: this->type = function_type::unresolved; break; case EOLIAN_PROPERTY: this->type = function_type::property; break; case EOLIAN_PROP_GET: this->type = function_type::prop_get; break; case EOLIAN_PROP_SET: this->type = function_type::prop_set; break; case EOLIAN_METHOD: this->type = function_type::method; break; case EOLIAN_FUNCTION_POINTER: this->type = function_type::function_pointer; break; } } std::string template_statement() const { std::string statement; char template_typename = 'F'; for (auto const& param : this->parameters) { attributes::regular_type_def const* typ = efl::eina::get(¶m.type.original_type); if (typ && typ->is_function_ptr()) { char typenam[2] = { 0, }; typenam[0] = template_typename++; if (statement.empty()) statement = std::string("template "; } std::vector opening_statements() const { std::vector statements; char template_typename = 'F'; for (auto const& param : this->parameters) { attributes::regular_type_def const* typ = efl::eina::get(¶m.type.original_type); if (typ && typ->is_function_ptr()) { char typenam[2] = { 0, }; typenam[0] = template_typename++; std::string statement = "auto fw_" + param.param_name + " = new ::efl::eolian::function_wrapper<"; statement += param.type.c_type + ", " + typenam + ">(" + param.param_name + ");"; statements.push_back(statement); } } return statements; } }; template <> struct tuple_element<0ul, function_def> { typedef type_def type; static type& get(function_def& f) { return f.return_type; } static type const& get(function_def const& f) { return f.return_type; } }; template <> struct tuple_element<1ul, function_def> { typedef std::string type; static type& get(function_def& f) { return f.name; } static type const& get(function_def const& f) { return f.name; } }; template <> struct tuple_element<2ul, function_def> { typedef std::vector type; static type& get(function_def& f) { return f.parameters; } static type const& get(function_def const& f) { return f.parameters; } }; // template // struct tuple_element : tuple_element {}; // template // struct tuple_element : tuple_element {}; // template // struct tuple_element : tuple_element {}; // template // typename tuple_element::type const& // get(function_def const& f) // { // return tuple_element::get(f); // } // template // typename tuple_element::type& // get(function_def& f) // { // return tuple_element::get(f); // } struct compare_klass_name_by_name { bool operator()(klass_name const& lhs, klass_name const& rhs) const { return lhs.namespaces < rhs.namespaces || (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name); } }; struct event_def { klass_name klass; eina::optional type; std::string name, c_name; bool beta, protect; documentation_def documentation; friend inline bool operator==(event_def const& lhs, event_def const& rhs) { return lhs.klass == rhs.klass && lhs.type == rhs.type && lhs.name == rhs.name && lhs.c_name == rhs.c_name && lhs.beta == rhs.beta && lhs.protect == rhs.protect && lhs.documentation == rhs.documentation; } friend inline bool operator!=(event_def const& lhs, event_def const& rhs) { return !(lhs == rhs); } 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_Class const* cls, Eolian_Unit const* unit) : klass(cls, {attributes::qualifier_info::is_none, std::string()}) , type( ::eolian_event_type_get(event) ? eina::optional{{::eolian_event_type_get(event), unit, EOLIAN_C_TYPE_DEFAULT}} : eina::optional{}) , name( ::eolian_event_name_get(event)) , c_name( ::eolian_event_c_name_get(event)) , beta( ::eolian_event_is_beta(event)) , protect( ::eolian_event_scope_get(event) == EOLIAN_SCOPE_PROTECTED) , documentation( ::eolian_event_documentation_get(event)) {} }; template <> struct tuple_element<0, event_def> { typedef eina::optional type; static type& get(event_def& def) { return def.type; } static type const& get(event_def const& def) { return def.type; } }; template <> struct tuple_element<1, event_def> { typedef std::string type; static type& get(event_def& def) { return def.name; } static type const& get(event_def const& def) { return def.name; } }; template <> struct tuple_element<2, event_def> { typedef std::string type; static type& get(event_def& def) { return def.c_name; } static type const& get(event_def const& def) { return def.c_name; } }; template struct tuple_element : tuple_element {}; template auto get(event_def const& def) -> decltype(tuple_element::get(def)) { return tuple_element::get(def); } template auto get(event_def& def) -> decltype(tuple_element::get(def)) { return tuple_element::get(def); } struct part_def { klass_name klass; std::string name; documentation_def documentation; //bool beta, protect; // can it be applied?? friend inline bool operator==(part_def const& lhs, part_def const& rhs) { return lhs.klass == rhs.klass && lhs.name == rhs.name; } friend inline bool operator!=(part_def const& lhs, part_def const& rhs) { return !(lhs == rhs); } friend inline bool operator<(part_def const& lhs, part_def const& rhs) { return lhs.name < rhs.name || lhs.klass < rhs.klass; } part_def(Eolian_Part const* part, Eolian_Unit const*) : klass(klass_name(::eolian_part_class_get(part), {attributes::qualifier_info::is_none, std::string()})) , name(::eolian_part_name_get(part)) , documentation(::eolian_part_documentation_get(part)) {} }; inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit); struct klass_def { std::string eolian_name; std::string cxx_name; std::string filename; documentation_def documentation; std::vector namespaces; std::vector functions; std::set inherits; class_type type; std::vector events; std::set immediate_inherits; std::set parts; Eolian_Unit const* unit; friend inline bool operator==(klass_def const& lhs, klass_def const& rhs) { return lhs.eolian_name == rhs.eolian_name && lhs.cxx_name == rhs.cxx_name && lhs.filename == lhs.filename && lhs.namespaces == rhs.namespaces && lhs.functions == rhs.functions && lhs.inherits == rhs.inherits && lhs.type == rhs.type && lhs.events == rhs.events && lhs.parts == rhs.parts; } friend inline bool operator!=(klass_def const& lhs, klass_def const& rhs) { return !(lhs == rhs); } friend inline bool operator<(klass_def const& lhs, klass_def const& rhs) { return lhs.eolian_name < rhs.eolian_name || lhs.cxx_name < rhs.cxx_name || lhs.namespaces < rhs.namespaces || lhs.parts < rhs.parts; } klass_def(std::string eolian_name, std::string cxx_name, std::string filename , documentation_def documentation , std::vector namespaces , std::vector functions , std::set inherits , class_type type , std::set immediate_inherits) : eolian_name(eolian_name), cxx_name(cxx_name), filename(filename) , documentation(documentation) , namespaces(namespaces) , functions(functions), inherits(inherits), type(type) , immediate_inherits(immediate_inherits) {} klass_def(std::string _eolian_name, std::string _cxx_name , std::vector _namespaces , std::vector _functions , std::set _inherits , class_type _type, Eolian_Unit const* unit) : eolian_name(_eolian_name), cxx_name(_cxx_name) , namespaces(_namespaces) , functions(_functions), inherits(_inherits), type(_type), unit(unit) {} klass_def(Eolian_Class const* klass, Eolian_Unit const* unit) : unit(unit) { for(efl::eina::iterator namespace_iterator( ::eolian_class_namespaces_get(klass)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) { this->namespaces.push_back(&*namespace_iterator); } cxx_name = eolian_name = eolian_class_short_name_get(klass); filename = eolian_object_file_get((const Eolian_Object *)klass); for(efl::eina::iterator eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_PROPERTY)) , functions_last; eolian_functions != functions_last; ++eolian_functions) { Eolian_Function const* function = &*eolian_functions; Eolian_Function_Type func_type = ::eolian_function_type_get(function); if(func_type == EOLIAN_PROPERTY) { try { if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET) && ::eolian_function_scope_get(function, EOLIAN_PROP_GET) != EOLIAN_SCOPE_PRIVATE) functions.push_back({function, EOLIAN_PROP_GET, NULL, unit}); } catch(std::exception const&) {} try { if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_SET) && ::eolian_function_scope_get(function, EOLIAN_PROP_SET) != EOLIAN_SCOPE_PRIVATE) functions.push_back({function, EOLIAN_PROP_SET, NULL, unit}); } catch(std::exception const&) {} } else try { if(! ::eolian_function_is_legacy_only(function, func_type) && ::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE) functions.push_back({function, func_type, NULL, unit}); } catch(std::exception const&) {} } for(efl::eina::iterator eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD)) , functions_last; eolian_functions != functions_last; ++eolian_functions) { try { Eolian_Function const* function = &*eolian_functions; Eolian_Function_Type func_type = eolian_function_type_get(function); if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD) && ::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE) functions.push_back({function, EOLIAN_METHOD, NULL, unit}); } catch(std::exception const&) {} } if(::eolian_class_parent_get(klass)) immediate_inherits.insert({::eolian_class_parent_get(klass), {}}); for(efl::eina::iterator inherit_iterator ( ::eolian_class_extensions_get(klass)) , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator) { Eolian_Class const* inherit = &*inherit_iterator; immediate_inherits.insert({inherit, {}}); } std::function inherit_algo = [&] (Eolian_Class const* inherit_klass) { if(::eolian_class_parent_get(inherit_klass)) { Eolian_Class const* inherit = ::eolian_class_parent_get(inherit_klass); inherits.insert({inherit, {}}); inherit_algo(inherit); } for(efl::eina::iterator inherit_iterator ( ::eolian_class_extensions_get(inherit_klass)) , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator) { Eolian_Class const* inherit = &*inherit_iterator; inherits.insert({inherit, {}}); inherit_algo(inherit); } }; inherit_algo(klass); for(efl::eina::iterator parts_itr ( ::eolian_class_parts_get(klass)) , parts_last; parts_itr != parts_last; ++parts_itr) { parts.insert({&*parts_itr, unit}); } switch(eolian_class_type_get(klass)) { case EOLIAN_CLASS_REGULAR: type = class_type::regular; break; case EOLIAN_CLASS_ABSTRACT: type = class_type::abstract_; break; case EOLIAN_CLASS_MIXIN: type = class_type::mixin; break; case EOLIAN_CLASS_INTERFACE: type = class_type::interface_; break; default: throw std::runtime_error("Class with unknown type"); } for(efl::eina::iterator event_iterator( ::eolian_class_events_get(klass)) , event_last; event_iterator != event_last; ++event_iterator) { try { events.push_back({&*event_iterator, klass, unit}); } catch(std::exception const&) {} } documentation = eolian_class_documentation_get(klass); } // TODO memoize the return? std::vector get_all_methods() const { std::vector ret; std::copy(functions.cbegin(), functions.cend(), std::back_inserter(ret)); for (auto inherit : inherits) { klass_def klass(get_klass(inherit, unit), unit); std::copy(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret)); } return ret; } std::vector get_all_parts() const { std::vector ret; std::copy(parts.cbegin(), parts.cend(), std::back_inserter(ret)); for (auto inherit : inherits) { klass_def klass(get_klass(inherit, unit), unit); std::copy(klass.parts.cbegin(), klass.parts.cend(), std::back_inserter(ret)); } return ret; } std::vector get_all_events() const { std::vector ret; std::copy(events.cbegin(), events.cend(), std::back_inserter(ret)); for (auto inherit : inherits) { klass_def klass(get_klass(inherit, unit), unit); std::copy(klass.events.cbegin(), klass.events.cend(), std::back_inserter(ret)); } return ret; } }; struct value_def { typedef eina::variant variant_type; // FIXME support other types variant_type value; std::string literal; type_def type; value_def() {} value_def(Eolian_Value value_obj) { type.set(value_obj.type); value = value_obj.value.i; literal = eolian_expression_value_to_literal(&value_obj); } }; struct enum_value_def { value_def value; std::string name; std::string c_name; documentation_def documentation; enum_value_def(Eolian_Enum_Type_Field const* enum_field, Eolian_Unit const*) { name = eolian_typedecl_enum_field_name_get(enum_field); c_name = eolian_typedecl_enum_field_c_name_get(enum_field); auto exp = eolian_typedecl_enum_field_value_get(enum_field, EINA_TRUE); value = eolian_expression_eval(exp, EOLIAN_MASK_INT); // FIXME hardcoded int documentation = eolian_typedecl_enum_field_documentation_get(enum_field); } }; struct enum_def { std::string eolian_name; std::string cxx_name; std::vector namespaces; std::vector fields; documentation_def documentation; enum_def(Eolian_Typedecl const* enum_obj, Eolian_Unit const* unit) { for(efl::eina::iterator namespace_iterator( ::eolian_typedecl_namespaces_get(enum_obj)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) { this->namespaces.push_back((&*namespace_iterator)); } cxx_name = eolian_name = eolian_typedecl_short_name_get(enum_obj); for (efl::eina::iterator field_iterator(::eolian_typedecl_enum_fields_get(enum_obj)) , field_last; field_iterator != field_last; ++field_iterator) { // Fill the types enum_value_def field_def(&*field_iterator, unit); this->fields.push_back(field_def); } documentation = ::eolian_typedecl_documentation_get(enum_obj); } }; struct struct_field_def { type_def type; std::string name; documentation_def documentation; struct_field_def(Eolian_Struct_Type_Field const* struct_field, Eolian_Unit const* unit) { name = eolian_typedecl_struct_field_name_get(struct_field); try { type.set(eolian_typedecl_struct_field_type_get(struct_field), unit, EOLIAN_C_TYPE_DEFAULT); } catch(std::runtime_error const&) { /* Silently skip pointer fields*/ } documentation = ::eolian_typedecl_struct_field_documentation_get(struct_field); } }; struct struct_def { std::string eolian_name; std::string cxx_name; std::vector namespaces; std::vector fields; documentation_def documentation; struct_def(Eolian_Typedecl const* struct_obj, Eolian_Unit const* unit) { for(efl::eina::iterator namespace_iterator( ::eolian_typedecl_namespaces_get(struct_obj)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) { this->namespaces.push_back((&*namespace_iterator)); } cxx_name = eolian_name = eolian_typedecl_short_name_get(struct_obj); for(efl::eina::iterator field_iterator(::eolian_typedecl_struct_fields_get(struct_obj)) , field_last; field_iterator != field_last; ++field_iterator) { struct_field_def field_def(&*field_iterator, unit); this->fields.push_back(field_def); } documentation = ::eolian_typedecl_documentation_get(struct_obj); } }; inline klass_name get_klass_name(klass_def const& klass) { return {klass.namespaces, klass.eolian_name, {qualifier_info::is_none, {}}, klass.type}; } inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit) { std::string klass_name; if(!as_generator(*(string << ".") << string) .generate(std::back_insert_iterator(klass_name) , std::make_tuple(klass_name_.namespaces, klass_name_.eolian_name) , context_null{})) return nullptr; else return ::eolian_unit_class_by_name_get(unit, klass_name.c_str()); } inline std::vector cpp_namespaces(std::vector namespaces) { if(namespaces.empty()) namespaces.push_back("nonamespace"); return namespaces; } inline bool has_events(klass_def const &klass) { for (auto&& e : klass.events) { (void)e; return true; } for (auto&& c : klass.inherits) { attributes::klass_def parent(get_klass(c, klass.unit), klass.unit); for (auto&& e : parent.events) { (void)e; return true; } } return false; } template inline bool has_type_return(klass_def const &klass, T visitor) { for (auto&& f : klass.functions) { if (f.return_type.original_type.visit(visitor)) return true; } for (auto&& c : klass.inherits) { attributes::klass_def parent(get_klass(c, klass.unit), klass.unit); if (has_type_return(parent, visitor)) return true; } return false; } struct string_return_visitor { typedef string_return_visitor visitor_type; typedef bool result_type; template bool operator()(T const&) const { return false; } bool operator()(regular_type_def const& regular) const { return regular.base_type == "string"; } }; struct stringshare_return_visitor { typedef stringshare_return_visitor visitor_type; typedef bool result_type; template bool operator()(T const&) const { return false; } bool operator()(regular_type_def const& regular) const { return regular.base_type == "stringshare"; } }; inline bool has_string_return(klass_def const &klass) { return has_type_return(klass, string_return_visitor{}); } inline bool has_stringshare_return(klass_def const &klass) { return has_type_return(klass, stringshare_return_visitor{}); } } namespace type_traits { template <> struct is_tuple : std::true_type {}; template <> struct is_tuple : std::true_type {}; } } } } #endif