diff --git a/Userland/Libraries/LibIDL/Types.cpp b/Userland/Libraries/LibIDL/Types.cpp index 09df15d7d4e..41eef5e8170 100644 --- a/Userland/Libraries/LibIDL/Types.cpp +++ b/Userland/Libraries/LibIDL/Types.cpp @@ -188,4 +188,35 @@ bool Type::is_distinguishable_from(IDL::Type const& other) const return table[to_underlying(this_distinguishability)][to_underlying(other_distinguishability)]; } +// https://webidl.spec.whatwg.org/#dfn-distinguishing-argument-index +int EffectiveOverloadSet::distinguishing_argument_index() +{ + for (auto argument_index = 0u; argument_index < m_argument_count; ++argument_index) { + bool found_indistinguishable = false; + + for (auto first_item_index = 0u; first_item_index < m_items.size(); ++first_item_index) { + for (auto second_item_index = first_item_index + 1; second_item_index < m_items.size(); ++second_item_index) { + if (!m_items[first_item_index].types[argument_index].is_distinguishable_from(m_items[second_item_index].types[argument_index])) { + found_indistinguishable = true; + break; + } + } + if (found_indistinguishable) + break; + } + + if (!found_indistinguishable) + return argument_index; + } + + VERIFY_NOT_REACHED(); +} + +void EffectiveOverloadSet::remove_all_other_entries() +{ + m_items.remove_all_matching([this](auto const& item) { + return &item != m_last_matching_item; + }); +} + } diff --git a/Userland/Libraries/LibIDL/Types.h b/Userland/Libraries/LibIDL/Types.h index f800203c2ab..133f077f824 100644 --- a/Userland/Libraries/LibIDL/Types.h +++ b/Userland/Libraries/LibIDL/Types.h @@ -394,4 +394,63 @@ private: NonnullRefPtrVector m_member_types; }; +// https://webidl.spec.whatwg.org/#dfn-optionality-value +enum class Optionality { + Required, + Optional, + Variadic, +}; + +// https://webidl.spec.whatwg.org/#dfn-effective-overload-set +class EffectiveOverloadSet { +public: + struct Item { + int callable_id; + NonnullRefPtrVector types; + Vector optionality_values; + }; + + EffectiveOverloadSet(Vector items) + : m_items(move(items)) + , m_argument_count(m_items.is_empty() ? 0 : m_items.first().types.size()) + { + } + + Vector& items() { return m_items; } + Vector const& items() const { return m_items; } + + Item const& only_item() const + { + VERIFY(m_items.size() == 1); + return m_items[0]; + } + + bool is_empty() const { return m_items.is_empty(); } + size_t size() const { return m_items.size(); } + + int distinguishing_argument_index(); + + template + bool has_overload_with_matching_argument_at_index(size_t index, Matches matches) + { + for (auto const& item : m_items) { + if (matches(item.types[index], item.optionality_values[index])) { + m_last_matching_item = &item; + return true; + } + } + m_last_matching_item = nullptr; + return false; + } + + void remove_all_other_entries(); + +private: + // FIXME: This should be an "ordered set". + Vector m_items; + size_t m_argument_count; + + Item const* m_last_matching_item { nullptr }; +}; + }