1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_TORQUE_PARAMETER_DIFFERENCE_H_
6 #define V8_TORQUE_PARAMETER_DIFFERENCE_H_
7 
8 #include <vector>
9 
10 #include "src/torque/types.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace torque {
15 
16 class ParameterDifference {
17  public:
ParameterDifference(const TypeVector & to,const TypeVector & from)18   ParameterDifference(const TypeVector& to, const TypeVector& from) {
19     DCHECK_EQ(to.size(), from.size());
20     for (size_t i = 0; i < to.size(); ++i) {
21       AddParameter(to[i], from[i]);
22     }
23   }
24 
25   // An overload is selected if it is strictly better than all alternatives.
26   // This means that it has to be strictly better in at least one parameter,
27   // and better or equally good in all others.
28   //
29   // When comparing a pair of corresponding parameters of two overloads...
30   // ... they are considered equally good if:
31   //     - They are equal.
32   //     - Both require some implicit conversion.
33   // ... one is considered better if:
34   //     - It is a strict subtype of the other.
35   //     - It doesn't require an implicit conversion, while the other does.
StrictlyBetterThan(const ParameterDifference & other)36   bool StrictlyBetterThan(const ParameterDifference& other) const {
37     DCHECK_EQ(difference_.size(), other.difference_.size());
38     bool better_parameter_found = false;
39     for (size_t i = 0; i < difference_.size(); ++i) {
40       base::Optional<const Type*> a = difference_[i];
41       base::Optional<const Type*> b = other.difference_[i];
42       if (a == b) {
43         continue;
44       } else if (a && b && a != b && (*a)->IsSubtypeOf(*b)) {
45         DCHECK(!(*b)->IsSubtypeOf(*a));
46         better_parameter_found = true;
47       } else if (a && !b) {
48         better_parameter_found = true;
49       } else {
50         return false;
51       }
52     }
53     return better_parameter_found;
54   }
55 
56  private:
57   // Pointwise difference between call arguments and a signature.
58   // {base::nullopt} means that an implicit conversion was necessary,
59   // otherwise we store the supertype found in the signature.
60   std::vector<base::Optional<const Type*>> difference_;
61 
AddParameter(const Type * to,const Type * from)62   void AddParameter(const Type* to, const Type* from) {
63     if (from->IsSubtypeOf(to)) {
64       difference_.push_back(to);
65     } else if (IsAssignableFrom(to, from)) {
66       difference_.push_back(base::nullopt);
67     } else {
68       UNREACHABLE();
69     }
70   }
71 };
72 
73 }  // namespace torque
74 }  // namespace internal
75 }  // namespace v8
76 
77 #endif  // V8_TORQUE_PARAMETER_DIFFERENCE_H_
78