1
2
3
4
5
6 #include <cmajor/binder/BoundConstraint.hpp>
7 #include <cmajor/binder/BoundNodeVisitor.hpp>
8 #include <cmajor/symbols/Exception.hpp>
9
10 namespace cmajor { namespace binder {
11
12 BoundConstraint::BoundConstraint(const Span& span_, const boost::uuids::uuid& moduleId_, BoundNodeType boundNodeType_) : BoundNode(span_, moduleId_, boundNodeType_)
13 {
14 }
15
16 void BoundConstraint::Load(Emitter& emitter, OperationFlags flags)
17 {
18 throw Exception("cannot load constraint", GetSpan(), ModuleId());
19 }
20
21 void BoundConstraint::Store(Emitter& emitter, OperationFlags flags)
22 {
23 throw Exception("cannot store constraint", GetSpan(), ModuleId());
24 }
25
26 BoundAtomicConstraint::BoundAtomicConstraint(const Span& span_, const boost::uuids::uuid& moduleId_, bool satisfied_) :
27 BoundConstraint(span_, moduleId_, BoundNodeType::boundAtomicConstraint), satisfied(satisfied_), conceptSymbol(nullptr)
28 {
29 }
30
31 void BoundAtomicConstraint::Accept(BoundNodeVisitor& visitor)
32 {
33 visitor.Visit(*this);
34 }
35
36 bool BoundAtomicConstraint::Subsume(BoundConstraint* that) const
37 {
38 if (that->IsBinaryConstraint())
39 {
40 BoundBinaryConstraint* thatBinaryConstraint = static_cast<BoundBinaryConstraint*>(that);
41 BoundConstraint* thatLeft = thatBinaryConstraint->Left();
42 BoundConstraint* thatRight = thatBinaryConstraint->Right();
43 bool subsumeLeft = Subsume(thatLeft);
44 bool subsumeRight = Subsume(thatRight);
45 if (that->GetBoundNodeType() == BoundNodeType::boundConjunctiveConstraint)
46 {
47 return subsumeLeft && subsumeRight;
48 }
49 else if (that->GetBoundNodeType() == BoundNodeType::boundDisjunctiveConstraint)
50 {
51 return subsumeLeft || subsumeRight;
52 }
53 else
54 {
55 Assert(false, "unknown binary constraint type");
56 return false;
57 }
58 }
59 else if (that->GetBoundNodeType() == BoundNodeType::boundAtomicConstraint)
60 {
61 BoundAtomicConstraint* thatAtomic = static_cast<BoundAtomicConstraint*>(that);
62 if (satisfied && !thatAtomic->Satisfied())
63 {
64 return true;
65 }
66 else if (!satisfied && thatAtomic->Satisfied())
67 {
68 return false;
69 }
70 else
71 {
72 if (conceptSymbol && !thatAtomic->conceptSymbol)
73 {
74 return true;
75 }
76 else if (!conceptSymbol && thatAtomic->conceptSymbol)
77 {
78 return false;
79 }
80 else if (!conceptSymbol && !thatAtomic->conceptSymbol)
81 {
82 return true;
83 }
84 else
85 {
86 if (conceptSymbol == thatAtomic->conceptSymbol)
87 {
88 return true;
89 }
90 ConceptSymbol* refinedConcept = conceptSymbol->RefinedConcept();
91 while (refinedConcept)
92 {
93 if (refinedConcept == thatAtomic->conceptSymbol)
94 {
95 return true;
96 }
97 else
98 {
99 refinedConcept = refinedConcept->RefinedConcept();
100 }
101 }
102 return false;
103 }
104 }
105 }
106 else
107 {
108 return false;
109 }
110 }
111
112 BoundConstraint* BoundAtomicConstraint::Clone() const
113 {
114 return new BoundAtomicConstraint(*this);
115 }
116
117 BoundBinaryConstraint::BoundBinaryConstraint(const Span& span_, const boost::uuids::uuid& moduleId_, BoundNodeType boundNodeType_, BoundConstraint* left_, BoundConstraint* right_) :
118 BoundConstraint(span_, moduleId_, boundNodeType_), left(left_), right(right_)
119 {
120 }
121
122 BoundBinaryConstraint::BoundBinaryConstraint(const BoundBinaryConstraint& that) : BoundConstraint(that), left(that.left->Clone()), right(that.right->Clone())
123 {
124 }
125
126 BoundDisjunctiveConstraint::BoundDisjunctiveConstraint(const Span& span_, const boost::uuids::uuid& moduleId_, BoundConstraint* left_, BoundConstraint* right_) :
127 BoundBinaryConstraint(span_, moduleId_, BoundNodeType::boundDisjunctiveConstraint, left_, right_)
128 {
129 }
130
131 BoundDisjunctiveConstraint::BoundDisjunctiveConstraint(const BoundDisjunctiveConstraint& that) : BoundBinaryConstraint(that)
132 {
133 }
134
135 bool BoundDisjunctiveConstraint::Subsume(BoundConstraint* that) const
136 {
137 BoundConstraint* left = Left();
138 BoundConstraint* right = Right();
139 if (that->IsBinaryConstraint())
140 {
141 BoundBinaryConstraint* thatBinaryConstraint = static_cast<BoundBinaryConstraint*>(that);
142 BoundConstraint* thatLeft = thatBinaryConstraint->Left();
143 BoundConstraint* thatRight = thatBinaryConstraint->Right();
144 bool leftSubsumeThatLeft = left->Subsume(thatLeft);
145 bool leftSubsumeThatRight = left->Subsume(thatRight);
146 bool rightSubsumeThatLeft = right->Subsume(thatLeft);
147 bool rightSubsumeThatRight = right->Subsume(thatRight);
148 bool leftSubsumeThatLeftOrThatRight = leftSubsumeThatLeft || leftSubsumeThatRight;
149 bool rightSubsumeThatLeftOrThatRight = rightSubsumeThatLeft || rightSubsumeThatRight;
150 if (that->GetBoundNodeType() == BoundNodeType::boundConjunctiveConstraint)
151 {
152 return leftSubsumeThatLeftOrThatRight && rightSubsumeThatLeftOrThatRight;
153 }
154 else if (that->GetBoundNodeType() == BoundNodeType::boundDisjunctiveConstraint)
155 {
156 return leftSubsumeThatLeftOrThatRight || rightSubsumeThatLeftOrThatRight;
157 }
158 else
159 {
160 Assert(false, "unknown binary constraint type");
161 return false;
162 }
163 }
164 else
165 {
166 bool leftSubsumeThat = left->Subsume(that);
167 bool rightSubsumeThat = right->Subsume(that);
168 return leftSubsumeThat && rightSubsumeThat;
169 }
170 }
171
172 void BoundDisjunctiveConstraint::Accept(BoundNodeVisitor& visitor)
173 {
174 visitor.Visit(*this);
175 }
176
177 BoundConstraint* BoundDisjunctiveConstraint::Clone() const
178 {
179 return new BoundDisjunctiveConstraint(*this);
180 }
181
182 BoundConjunctiveConstraint::BoundConjunctiveConstraint(const Span& span_, const boost::uuids::uuid& moduleId_, BoundConstraint* left_, BoundConstraint* right_) :
183 BoundBinaryConstraint(span_, moduleId_, BoundNodeType::boundConjunctiveConstraint, left_, right_)
184 {
185 }
186
187 BoundConjunctiveConstraint::BoundConjunctiveConstraint(const BoundConjunctiveConstraint& that) : BoundBinaryConstraint(that)
188 {
189 }
190
191 bool BoundConjunctiveConstraint::Subsume(BoundConstraint* that) const
192 {
193 BoundConstraint* left = Left();
194 BoundConstraint* right = Right();
195 if (that->IsBinaryConstraint())
196 {
197 BoundBinaryConstraint* thatBinaryConstraint = static_cast<BoundBinaryConstraint*>(that);
198 BoundConstraint* thatLeft = thatBinaryConstraint->Left();
199 BoundConstraint* thatRight = thatBinaryConstraint->Right();
200 bool leftSubsumeThatLeft = left->Subsume(thatLeft);
201 bool rightSubsumeThatLeft = right->Subsume(thatLeft);
202 bool leftSubsumeThatRight = left->Subsume(thatRight);
203 bool rightSubsumeThatRight = right->Subsume(thatRight);
204 bool leftOrRightSubsumeThatLeft = leftSubsumeThatLeft || rightSubsumeThatLeft;
205 bool leftOrRightSubsumeThatRight = leftSubsumeThatRight || rightSubsumeThatRight;
206 if (that->GetBoundNodeType() == BoundNodeType::boundConjunctiveConstraint)
207 {
208 return leftOrRightSubsumeThatLeft && leftOrRightSubsumeThatRight;
209 }
210 else if (that->GetBoundNodeType() == BoundNodeType::boundDisjunctiveConstraint)
211 {
212 return leftOrRightSubsumeThatLeft || leftOrRightSubsumeThatRight;
213 }
214 else
215 {
216 Assert(false, "unknown binary constraint type");
217 return false;
218 }
219 }
220 else
221 {
222 bool leftSubsumeThat = left->Subsume(that);
223 bool righSubsumeThat = right->Subsume(that);
224 return leftSubsumeThat || righSubsumeThat;
225 }
226 }
227
228 void BoundConjunctiveConstraint::Accept(BoundNodeVisitor& visitor)
229 {
230 visitor.Visit(*this);
231 }
232
233 BoundConstraint* BoundConjunctiveConstraint::Clone() const
234 {
235 return new BoundConjunctiveConstraint(*this);
236 }
237
238 std::u32string MakeBoundConceptName(ConceptSymbol* conceptSymbol, const std::std::vector<TypeSymbol*>&typeArguments)
239 {
240 std::u32string s = conceptSymbol->GroupName();
241 s.append(1, '<');
242 int n = typeArguments.size();
243 for (int i = 0; i < n; ++i)
244 {
245 if (i > 0)
246 {
247 s.append(U", ");
248 }
249 TypeSymbol* typeSymbol = typeArguments[i];
250 s.append(typeSymbol->FullName());
251 }
252 s.append(1, '>');
253 return s;
254 }
255
256 BoundConcept::BoundConcept(ConceptSymbol* conceptSymbol_, const std::std::vector<TypeSymbol*>&typeArguments_, constSpan&span_, constboost::uuids::uuid&moduleId_) :
257 BoundNode(span_, moduleId_, BoundNodeType::boundConcept), name(MakeBoundConceptName(conceptSymbol_, typeArguments_)), conceptSymbol(conceptSymbol_), typeArguments(typeArguments_),
258 commonType(nullptr)
259 {
260 }
261
262 void BoundConcept::Load(Emitter& emitter, OperationFlags flags)
263 {
264 throw Exception("cannot load bound concept", GetSpan(), ModuleId());
265 }
266
267 void BoundConcept::Store(Emitter& emitter, OperationFlags flags)
268 {
269 throw Exception("cannot store bound concept", GetSpan(), ModuleId());
270 }
271
272 void BoundConcept::Accept(BoundNodeVisitor& visitor)
273 {
274 throw Exception("cannot visit bound concept", GetSpan(), ModuleId());
275 }
276
277 void BoundConcept::SetBoundConstraint(std::std::unique_ptr<BoundConstraint>&&boundConstraint_)
278 {
279 boundConstraint = std::move(boundConstraint_);
280 }
281
282 void BoundConcept::AddBoundTemplateParameter(std::std::unique_ptr<BoundTemplateParameterSymbol>&&boundTemplateParameter)
283 {
284 boundTemplateParameters.push_back(std::move(boundTemplateParameter));
285 }
286
287 bool operator==(const BoundConceptKey& left, const BoundConceptKey& right)
288 {
289 if (left.conceptSymbol != right.conceptSymbol) return false;
290 if (left.Arity() != right.Arity()) return false;
291 int n = left.Arity();
292 for (int i = 0; i < n; ++i)
293 {
294 if (!TypesEqual(left.typeArguments[i], right.typeArguments[i])) return false;
295 }
296 return true;
297 }
298
299 } }