#ifndef EOLIAN_MONO_NAME_HELPERS_HH #define EOLIAN_MONO_NAME_HELPERS_HH #include #include #include #include #include #include #include "utils.hh" #include "grammar/integral.hpp" #include "grammar/generator.hpp" #include "grammar/klass_def.hpp" #include "grammar/list.hpp" #include "grammar/string.hpp" #include "grammar/integral.hpp" using efl::eolian::grammar::as_generator; using efl::eolian::grammar::string; using efl::eolian::grammar::lit; using efl::eolian::grammar::operator*; namespace eolian_mono { /* Utility functions for naming things. Compared to the utils.hh, this header has higher level * functions, dealing with the knowledge of how to convert the items to the C# style we are using, for * example, while being too short to be implemented as full-fledged generators. */ 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 bool is_equal(std::string const& lhs, std::string const& rhs) { return lhs == rhs; } } inline std::string identity(std::string const& str) { return str; } inline std::string escape_keyword(std::string const& name) { using detail::is_equal; if(is_equal(name, "delete") || is_equal(name, "do") || is_equal(name, "lock") || is_equal(name, "event") || is_equal(name, "in") || is_equal(name, "object") || is_equal(name, "interface") || is_equal(name, "string") || is_equal(name, "internal") || is_equal(name, "fixed") || is_equal(name, "base")) return "kw_" + name; if (is_equal(name, "Finalize")) return name + "Add"; // Eo's Finalize is actually the end of efl_add. return name; } typedef std::function string_transform_func; inline std::string join_namespaces(std::vector const& namespaces, char separator, string_transform_func func=identity) { std::stringstream s; for (auto&& n : namespaces) s << func(n) << separator; return s.str(); } static const std::vector verbs = { "add", "get", "is", "del", "thaw", "freeze", "save", "wait", "eject", "raise", "lower", "load", "dup", "reset", "unload", "close", "set", "interpolate", "has", "grab", "check", "find", "ungrab", "unset", "clear", "pop", "new", "peek", "push", "update", "show", "move", "hide", "calculate", "resize", "attach", "pack", "unpack", "emit", "call", "append" }; const std::vector not_verbs = { "below", "above", "name", "unfreezable", "value", "r", "g", "b", "a", "finalize", "destructor", "to", "circle", "rect", "path", "commands", "type", "colorspace" "op", "type", "properties", "status", "status", "relative", "ptr", "pair", "pos", "end" }; void reorder_verb(std::vector &names) { if (names.size() <= 1) return; std::string verb = names.back(); if (std::find(verbs.begin(), verbs.end(), verb) != verbs.end()) { names.pop_back(); names.insert(names.begin(), verb); } } inline std::string managed_namespace(std::string const& ns) { return escape_keyword(utils::remove_all(ns, '_')); } inline std::string managed_method_name(attributes::function_def const& f) { std::vector names = utils::split(f.name, '_'); name_helpers::reorder_verb(names); std::string candidate = escape_keyword(utils::to_pascal_case(names)); // Some eolian methods have the same name as their parent class if (candidate == f.klass.eolian_name) candidate = "Do" + candidate; return candidate; } inline std::string alias_full_eolian_name(attributes::alias_def const& alias) { return join_namespaces(alias.namespaces, '.') + alias.eolian_name; } inline std::string managed_async_method_name(attributes::function_def const& f) { return managed_method_name(f) + "Async"; } inline std::string function_ptr_full_eolian_name(attributes::function_def const& func) { return join_namespaces(func.namespaces, '.') + func.name; } inline std::string type_full_eolian_name(attributes::regular_type_def const& type) { return join_namespaces(type.namespaces, '.') + type.base_type; } inline std::string type_full_managed_name(attributes::regular_type_def const& type) { return join_namespaces(type.namespaces, '.', managed_namespace) + utils::remove_all(type.base_type, '_'); } inline std::string struct_full_eolian_name(attributes::struct_def const& struct_) { return join_namespaces(struct_.namespaces, '.') + struct_.cxx_name; } template inline std::string typedecl_managed_name(T const& item) { return utils::remove_all(item.cxx_name, '_'); } inline std::string typedecl_managed_name(attributes::function_def const& func) { return utils::remove_all(func.name, '_'); } inline std::string enum_field_managed_name(std::string name) { std::vector names = utils::split(name, '_'); return utils::to_pascal_case(names); } inline std::string to_field_name(std::string const& in) { return utils::capitalize(in); } inline std::string managed_part_name(attributes::part_def const& part) { std::vector names = utils::split(part.name, '_'); return utils::to_pascal_case(names); } // Class name translation (interface/concrete/inherit/etc) struct klass_interface_name_generator { template std::string operator()(T const& klass) const { return utils::remove_all(klass.eolian_name, '_'); } template bool generate(OutputIterator sink, Attr const& attribute, Context const& context) const { return as_generator((*this).operator()(attribute)).generate(sink, attributes::unused, context); } } klass_interface_name; struct klass_full_interface_name_generator { template std::string operator()(T const& klass) const { return join_namespaces(klass.namespaces, '.', managed_namespace) + klass_interface_name(klass); } template bool generate(OutputIterator sink, Attr const& attribute, Context const& context) const { return as_generator((*this).operator()(attribute)).generate(sink, attributes::unused, context); } } klass_full_interface_name; template inline std::string klass_concrete_name(T const& klass) { std::string name = utils::remove_all(klass.eolian_name, '_'); if (klass.type == attributes::class_type::regular || klass.type == attributes::class_type::abstract_) return name; return name + "Concrete"; } struct klass_full_concrete_name_generator { template std::string operator()(T const& klass) const { return join_namespaces(klass.namespaces, '.', managed_namespace) + klass_concrete_name(klass); } template bool generate(OutputIterator sink, Attr const& attribute, Context const& context) const { return as_generator((*this).operator()(attribute)).generate(sink, attributes::unused, context); } } klass_full_concrete_name; struct klass_full_concrete_or_interface_name_generator { template std::string operator()(T const& klass) const { switch(klass.type) { case attributes::class_type::abstract_: case attributes::class_type::regular: return klass_full_concrete_name(klass); } return klass_full_interface_name(klass); } template bool generate(OutputIterator, attributes::unused_type, Context const&) const { return true; } template bool generate(OutputIterator sink, Attr const& attribute, Context const& context) const { return as_generator((*this).operator()(attribute)).generate(sink, attributes::unused, context); } } klass_full_concrete_or_interface_name; template inline std::string klass_inherit_name(T const& klass) { return klass_concrete_name(klass); } template inline std::string klass_native_inherit_name(T const& klass) { return klass_concrete_name(klass) + "NativeInherit"; } template inline std::string klass_get_name(T const& clsname) { return utils::to_lowercase(join_namespaces(clsname.namespaces, '_') + clsname.eolian_name + "_class_get"); } inline std::string klass_get_full_name(attributes::klass_name const& clsname) { return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname); } // Events 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 const& evt) { std::string ret; ret = klass_interface_name(evt.klass); return ret + name_helpers::managed_event_name(evt.name) + "_Args"; } inline std::string managed_event_args_name(attributes::event_def evt) { return join_namespaces(evt.klass.namespaces, '.', managed_namespace) + managed_event_args_short_name(evt); } inline std::string translate_inherited_event_name(const attributes::event_def &evt, const attributes::klass_def &klass) { return join_namespaces(klass.namespaces, '_') + klass_interface_name(klass) + "_" + managed_event_name(evt.name); } // Open/close namespaces template bool open_namespaces(OutputIterator sink, std::vector namespaces, Context context) { std::transform(namespaces.begin(), namespaces.end(), namespaces.begin(), managed_namespace); auto open_namespace = *("namespace " << string << " { ") << "\n"; return as_generator(open_namespace).generate(sink, namespaces, context); } template bool close_namespaces(OutputIterator sink, std::vector const& namespaces, Context context) { auto close_namespace = *(lit("} ")) << "\n"; return as_generator(close_namespace).generate(sink, namespaces, context); } } // namespace name_helpers } // namespace eolian_mono namespace efl { namespace eolian { namespace grammar { template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; template <> struct is_eager_generator : std::true_type {}; template <> struct is_generator : std::true_type {}; namespace type_traits { template <> struct attributes_needed : std::integral_constant {}; } } } } #endif