| // Copyright 2018 the V8 project authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef V8_TORQUE_PARAMETER_DIFFERENCE_H_ | |
| #define V8_TORQUE_PARAMETER_DIFFERENCE_H_ | |
| #include <vector> | |
| #include "src/torque/types.h" | |
| namespace v8 { | |
| namespace internal { | |
| namespace torque { | |
| class ParameterDifference { | |
| public: | |
| ParameterDifference(const TypeVector& to, const TypeVector& from) { | |
| DCHECK_EQ(to.size(), from.size()); | |
| for (size_t i = 0; i < to.size(); ++i) { | |
| AddParameter(to[i], from[i]); | |
| } | |
| } | |
| // An overload is selected if it is strictly better than all alternatives. | |
| // This means that it has to be strictly better in at least one parameter, | |
| // and better or equally good in all others. | |
| // | |
| // When comparing a pair of corresponding parameters of two overloads... | |
| // ... they are considered equally good if: | |
| // - They are equal. | |
| // - Both require some implicit conversion. | |
| // ... one is considered better if: | |
| // - It is a strict subtype of the other. | |
| // - It doesn't require an implicit conversion, while the other does. | |
| bool StrictlyBetterThan(const ParameterDifference& other) const { | |
| DCHECK_EQ(difference_.size(), other.difference_.size()); | |
| bool better_parameter_found = false; | |
| for (size_t i = 0; i < difference_.size(); ++i) { | |
| base::Optional<const Type*> a = difference_[i]; | |
| base::Optional<const Type*> b = other.difference_[i]; | |
| if (a == b) { | |
| continue; | |
| } else if (a && b && a != b && (*a)->IsSubtypeOf(*b)) { | |
| DCHECK(!(*b)->IsSubtypeOf(*a)); | |
| better_parameter_found = true; | |
| } else if (a && !b) { | |
| better_parameter_found = true; | |
| } else { | |
| return false; | |
| } | |
| } | |
| return better_parameter_found; | |
| } | |
| private: | |
| // Pointwise difference between call arguments and a signature. | |
| // {base::nullopt} means that an implicit conversion was necessary, | |
| // otherwise we store the supertype found in the signature. | |
| std::vector<base::Optional<const Type*>> difference_; | |
| void AddParameter(const Type* to, const Type* from) { | |
| if (from->IsSubtypeOf(to)) { | |
| difference_.push_back(to); | |
| } else if (IsAssignableFrom(to, from)) { | |
| difference_.push_back(base::nullopt); | |
| } else { | |
| UNREACHABLE(); | |
| } | |
| } | |
| }; | |
| } // namespace torque | |
| } // namespace internal | |
| } // namespace v8 | |
| #endif // V8_TORQUE_PARAMETER_DIFFERENCE_H_ |