1
2
3
4
5
6 #ifndef CMAJOR_BINDER_OVERLOAD_RESOLUTION_INCLUDED
7 #define CMAJOR_BINDER_OVERLOAD_RESOLUTION_INCLUDED
8 #include <cmajor/binder/BoundExpression.hpp>
9 #include <cmajor/symbols/Scope.hpp>
10 #include <cmajor/symbols/Exception.hpp>
11 #include <cmajor/symbols/FunctionSymbol.hpp>
12
13 namespace cmajor { namespace binder {
14
15 class BoundExpression;
16 class BoundFunctionCall;
17 class BoundCompileUnit;
18 class BoundFunction;
19 class BoundConstraint;
20
21 using namespace cmajor::symbols;
22
23 enum class OverloadResolutionFlags : uint8_t
24 {
25 none= 0,
26 dontThrow= 1 << 0,
27 dontInstantiate= 1 << 1,
28 noTemplates= 1 << 2,
29 noRvalueRef= 1 << 3,
30 includeSystemDefaultFunctions= 1 << 4
31 };
32
33 inline OverloadResolutionFlags operator&(OverloadResolutionFlags left, OverloadResolutionFlags right)
34 {
35 return OverloadResolutionFlags(uint8_t(left) & uint8_t(right));
36 }
37
38 inline OverloadResolutionFlags operator|(OverloadResolutionFlags left, OverloadResolutionFlags right)
39 {
40 return OverloadResolutionFlags(uint8_t(left) | uint8_t(right));
41 }
42
43 struct FunctionScopeLookup
44 {
45 FunctionScopeLookup(ScopeLookup scopeLookup_) : scopeLookup(scopeLookup_), scope(nullptr) {}
46 FunctionScopeLookup(ScopeLookup scopeLookup_, ContainerScope* scope_) : scopeLookup(scopeLookup_), scope(scope_) {}
47 ScopeLookup scopeLookup;
48 ContainerScope* scope;
49 };
50
51 struct ArgumentMatch
52 {
53 ArgumentMatch() : preReferenceConversionFlags(OperationFlags::none), conversionFun(nullptr), postReferenceConversionFlags(OperationFlags::none), conversionDistance(0) {}
54 ArgumentMatch(OperationFlags preReferenceConversionFlags_, FunctionSymbol* conversionFun_, OperationFlags postReferenceConversionFlags_, int conversionDistance_) :
55 preReferenceConversionFlags(preReferenceConversionFlags_), conversionFun(conversionFun_), postReferenceConversionFlags(postReferenceConversionFlags_), conversionDistance(conversionDistance_) {}
56 OperationFlags preReferenceConversionFlags;
57 FunctionSymbol* conversionFun;
58 OperationFlags postReferenceConversionFlags;
59 int conversionDistance;
60 };
61
62 inline bool BetterArgumentMatch(const ArgumentMatch& left, const ArgumentMatch& right)
63 {
64 if (left.preReferenceConversionFlags == OperationFlags::none && right.preReferenceConversionFlags != OperationFlags::none) return true;
65 if (left.preReferenceConversionFlags != OperationFlags::none && right.preReferenceConversionFlags == OperationFlags::none) return false;
66 if (left.conversionFun == nullptr && right.conversionFun != nullptr) return true;
67 if (right.conversionFun == nullptr && left.conversionFun != nullptr) return false;
68 if (left.postReferenceConversionFlags == OperationFlags::none && right.postReferenceConversionFlags != OperationFlags::none) return true;
69 if (left.postReferenceConversionFlags != OperationFlags::none && right.postReferenceConversionFlags == OperationFlags::none) return false;
70 if (left.conversionDistance < right.conversionDistance) return true;
71 if (left.conversionDistance > right.conversionDistance) return false;
72 return false;
73 }
74
75 struct FunctionMatch
76 {
77 FunctionMatch(FunctionSymbol* fun_) :
78 fun(fun_), numConversions(0), numQualifyingConversions(0), referenceMustBeInitialized(false), castRequired(false), cannotBindConstArgToNonConstParam(false), cannotAssignToConstObject(false),
79 sourceType(nullptr), targetType(nullptr), conceptCheckException(nullptr), boundConstraint(nullptr) {}
80 FunctionSymbol* fun;
81 std::vector<ArgumentMatch> argumentMatches;
82 int numConversions;
83 int numQualifyingConversions;
84 bool referenceMustBeInitialized;
85 bool castRequired;
86 bool cannotBindConstArgToNonConstParam;
87 bool cannotAssignToConstObject;
88 TypeSymbol* sourceType;
89 TypeSymbol* targetType;
90 std::unordered_map<TemplateParameterSymbol*, TypeSymbol*> templateParameterMap;
91 Exception* conceptCheckException;
92 BoundConstraint* boundConstraint;
93 };
94
95 struct BetterFunctionMatch
96 {
97 bool operator()(const FunctionMatch& left, const FunctionMatch& right) const;
98 };
99
100 bool FindConversions(BoundCompileUnit& boundCompileUnit, FunctionSymbol* function, std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, FunctionMatch&functionMatch,
101 ConversionType conversionType, ContainerScope* containerScope, BoundFunction* currentFunction, const Span& span, const boost::uuids::uuid& moduleId);
102
103 std::unique_ptr<BoundFunctionCall> ResolveOverload(const std::u32string& groupName, ContainerScope* containerScope, const std::std::vector<FunctionScopeLookup>&functionScopeLookups,
104 std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundCompileUnit&boundCompileUnit, BoundFunction*currentFunction, constSpan&span, constboost::uuids::uuid&moduleId);
105
106 std::unique_ptr<BoundFunctionCall> ResolveOverload(const std::u32string& groupName, ContainerScope* containerScope, const std::std::vector<FunctionScopeLookup>&functionScopeLookups,
107 std::std::vector<std::std::unique_ptr<BoundExpression>>&arguments, BoundCompileUnit&boundCompileUnit, BoundFunction*currentFunction, constSpan&span, constboost::uuids::uuid&moduleId,
108 OverloadResolutionFlags flags, std::std::vector<TypeSymbol*>&templateArgumentTypes, std::std::unique_ptr<Exception>&exception);
109
110 } }
111
112 #endif // CMAJOR_BINDER_OVERLOAD_RESOLUTION_INCLUDED