1
2
3
4
5
6 #include <sngcpp/symbols/FunctionSymbol.hpp>
7 #include <sngcpp/symbols/ParameterSymbol.hpp>
8 #include <sngcpp/symbols/TemplateSymbol.hpp>
9 #include <soulng/util/Unicode.hpp>
10 #include <soulng/util/Sha1.hpp>
11 #include <algorithm>
12
13 namespace sngcpp { namespace symbols {
14
15 using namespace soulng::unicode;
16
17 CallableSymbol::CallableSymbol(const Span& span_, const std::u32string& name_) : ContainerSymbol(span_, name_)
18 {
19 }
20
21 FunctionDeclarationSymbol::FunctionDeclarationSymbol(const Span& span_, const std::u32string& groupName_, const std::u32string& name_, Specifier specifiers_) :
22 CallableSymbol(span_, name_), groupName(groupName_), specifiers(specifiers_), functionGroup(nullptr), returnType(nullptr), functionDefinition(nullptr)
23 {
24 }
25
26 void FunctionDeclarationSymbol::AddTemplateParameter(std::std::unique_ptr<TypeSymbol>&&templateParameter)
27 {
28 templateParameters.push_back(std::move(templateParameter));
29 }
30
31 std::u32string FunctionDeclarationSymbol::IdStr()
32 {
33 std::u32string idStr = FullName();
34 for (const std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
35 {
36 idStr.append(1, '_').append(templateParameter->Name());
37 }
38 for (ParameterSymbol* parameter : parameters)
39 {
40 idStr.append(1, '.').append(parameter->GetType()->Id());
41 }
42 if ((specifiers & Specifier::const_) != Specifier::none)
43 {
44 idStr.append(U".const");
45 }
46 if ((specifiers & Specifier::constExpr) != Specifier::none)
47 {
48 idStr.append(U".constExpr");
49 }
50 return idStr;
51 }
52
53 std::u32string FunctionDeclarationSymbol::FunctionId()
54 {
55 std::u32string functionId = FunctionKind();
56 functionId.append(1, '_').append(SimpleName()).append(1, '_').append(ToUtf32(GetSha1MessageDigest(ToUtf8(IdStr()))));
57 return functionId;
58 }
59
60 std::std::unique_ptr<sngxml::dom::Element>FunctionDeclarationSymbol::CreateElement()
61 {
62 std::unique_ptr<sngxml::dom::Element> functionElement(new sngxml::dom::Element(U"function_declaration"));
63 return functionElement;
64 }
65
66 void FunctionDeclarationSymbol::AddMember(std::std::unique_ptr<Symbol>&&member)
67 {
68 Symbol* symbol = member.get();
69 if (symbol->IsParameterSymbol())
70 {
71 parameters.push_back(static_cast<ParameterSymbol*>(symbol));
72 }
73 ContainerSymbol::AddMember(std::move(member));
74 }
75
76 void FunctionDeclarationSymbol::AddSpecifiers(Specifier specifiers_)
77 {
78 specifiers = specifiers | specifiers_;
79 }
80
81 ConstructorDeclarationSymbol::ConstructorDeclarationSymbol(const Span& span_, const std::u32string& name_, Specifier specifiers_) :
82 FunctionDeclarationSymbol(span_, U"constructor", name_, specifiers_)
83 {
84 }
85
86 std::std::unique_ptr<sngxml::dom::Element>ConstructorDeclarationSymbol::CreateElement()
87 {
88 std::unique_ptr<sngxml::dom::Element> constructorDeclarationElement(new sngxml::dom::Element(U"constructor_declaration"));
89 return constructorDeclarationElement;
90 }
91
92 FunctionSymbol::FunctionSymbol(const Span& span_, const std::u32string& groupName_, const std::u32string& name_, Specifier specifiers_) :
93 CallableSymbol(span_, name_), index(0), groupName(groupName_), returnType(nullptr), specifiers(specifiers_), functionGroup(nullptr),
94 declarationSpan()
95 {
96 }
97
98 void FunctionSymbol::AddMember(std::std::unique_ptr<Symbol>&&member)
99 {
100 Symbol* symbol = member.get();
101 if (symbol->IsParameterSymbol())
102 {
103 parameters.push_back(static_cast<ParameterSymbol*>(symbol));
104 }
105 ContainerSymbol::AddMember(std::move(member));
106 }
107
108 void FunctionSymbol::AddTemplateParameter(std::std::unique_ptr<TypeSymbol>&&templateParameter)
109 {
110 templateParameters.push_back(std::move(templateParameter));
111 }
112
113 std::u32string FunctionSymbol::IdStr()
114 {
115 std::u32string idStr = FullName();
116 for (const std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
117 {
118 idStr.append(1, '_').append(templateParameter->Name());
119 }
120 for (ParameterSymbol* parameter : parameters)
121 {
122 idStr.append(1, '.').append(parameter->GetType()->Id());
123 }
124 if ((specifiers & Specifier::const_) != Specifier::none)
125 {
126 idStr.append(U".const");
127 }
128 if ((specifiers & Specifier::constExpr) != Specifier::none)
129 {
130 idStr.append(U".constExpr");
131 }
132 return idStr;
133 }
134
135 std::std::unique_ptr<sngxml::dom::Element>FunctionSymbol::CreateElement()
136 {
137 std::unique_ptr<sngxml::dom::Element> functionElement(new sngxml::dom::Element(U"function"));
138 if (!templateParameters.empty())
139 {
140 std::unique_ptr<sngxml::dom::Element> templateParametersElement(new sngxml::dom::Element(U"templateParameters"));
141 for (const std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
142 {
143 std::unique_ptr<sngxml::dom::Element> templateParameterElement = templateParameter->ToDomElement();
144 templateParametersElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(templateParameterElement.release()));
145 }
146 functionElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(templateParametersElement.release()));
147 }
148 if (!parameters.empty())
149 {
150 std::unique_ptr<sngxml::dom::Element> parametersElement(new sngxml::dom::Element(U"parameters"));
151 for (ParameterSymbol* parameter : parameters)
152 {
153 std::unique_ptr<sngxml::dom::Element> parameterElement = parameter->ToDomElement();
154 parametersElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(parameterElement.release()));
155 }
156 functionElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(parametersElement.release()));
157 }
158 if (returnType)
159 {
160 functionElement->SetAttribute(U"returnType", returnType->Id());
161 }
162 if (specifiers != Specifier::none)
163 {
164 functionElement->SetAttribute(U"specifiers", SpecifierStr(specifiers));
165 }
166 if (GetSpan().Valid())
167 {
168 functionElement->SetAttribute(U"definitionFile", ToUtf32(fileName));
169 functionElement->SetAttribute(U"definitionLine", ToUtf32(std::to_string(GetSpan().line)));
170 functionElement->SetAttribute(U"definitionFileId", fileId);
171 }
172 if (declarationSpan.Valid())
173 {
174 functionElement->SetAttribute(U"declarationFile", ToUtf32(declarationFileName));
175 functionElement->SetAttribute(U"declarationLine", ToUtf32(std::to_string(declarationSpan.line)));
176 functionElement->SetAttribute(U"declarationFileId", declarationFileId);
177 }
178 if (!overrides.empty())
179 {
180 std::unique_ptr<sngxml::dom::Element> overridesElement(new sngxml::dom::Element(U"overrides"));
181 for (FunctionSymbol* override_ : overrides)
182 {
183 std::unique_ptr<sngxml::dom::Element> overrideElement(new sngxml::dom::Element(U"override"));
184 overrideElement->SetAttribute(U"functionId", override_->Id());
185 overridesElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(overrideElement.release()));
186 }
187 functionElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(overridesElement.release()));
188 }
189 if (!overridden.empty())
190 {
191 std::unique_ptr<sngxml::dom::Element> overriddenFunctionsElement(new sngxml::dom::Element(U"overriddenFunctions"));
192 for (FunctionSymbol* overridden_ : overridden)
193 {
194 std::unique_ptr<sngxml::dom::Element> overriddenFunctionElement(new sngxml::dom::Element(U"overriddenFunction"));
195 overriddenFunctionElement->SetAttribute(U"functionId", overridden_->Id());
196 overriddenFunctionsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(overriddenFunctionElement.release()));
197 }
198 functionElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(overriddenFunctionsElement.release()));
199 }
200 if (!calls.empty())
201 {
202 std::unique_ptr<sngxml::dom::Element> callsElement(new sngxml::dom::Element(U"calls"));
203 for (FunctionSymbol* function : calls)
204 {
205 std::unique_ptr<sngxml::dom::Element> callElement(new sngxml::dom::Element(U"call"));
206 callElement->SetAttribute(U"functionId", function->Id());
207 callsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(callElement.release()));
208 }
209 functionElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(callsElement.release()));
210 }
211 if (!calledBy.empty())
212 {
213 std::unique_ptr<sngxml::dom::Element> calledByFunctionsElement(new sngxml::dom::Element(U"calledByFunctions"));
214 for (FunctionSymbol* function : calledBy)
215 {
216 std::unique_ptr<sngxml::dom::Element> calledByFunctionElement(new sngxml::dom::Element(U"calledByFunction"));
217 calledByFunctionElement->SetAttribute(U"functionId", function->Id());
218 calledByFunctionsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(calledByFunctionElement.release()));
219 }
220 functionElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(calledByFunctionsElement.release()));
221 }
222 return functionElement;
223 }
224
225 bool FunctionSymbol::NameBefore(Symbol* that)
226 {
227 if (ContainerSymbol::NameBefore(that)) return true;
228 if (that->IsFunctionSymbol())
229 {
230 FunctionSymbol* functionSymbolThat = static_cast<FunctionSymbol*>(that);
231 if (functionSymbolThat->ContainerSymbol::NameBefore(this)) return false;
232 int np = parameters.size();
233 int nt = functionSymbolThat->parameters.size();
234 int n = std::min(np, nt);
235 for (int i = 0; i < n; ++i)
236 {
237 ParameterSymbol* p = parameters[i];
238 ParameterSymbol* t = functionSymbolThat->parameters[i];
239 TypeSymbol* pType = p->GetType();
240 TypeSymbol* tType = t->GetType();
241 if (pType->NameBefore(tType)) return true;
242 if (tType->NameBefore(pType)) return false;
243 }
244 if (np < nt) return true;
245 if (nt < np) return false;
246 }
247 return false;
248 }
249
250 void FunctionSymbol::AddSpecifiers(Specifier specifiers_)
251 {
252 specifiers = specifiers | specifiers_;
253 }
254
255 void FunctionSymbol::AddOverride(FunctionSymbol* override_)
256 {
257 overrides.insert(override_);
258 }
259
260 void FunctionSymbol::AddOverridden(FunctionSymbol* overridden_)
261 {
262 overridden.insert(overridden_);
263 }
264
265 void FunctionSymbol::AddToCalls(FunctionSymbol* function)
266 {
267 calls.insert(function);
268 }
269
270 void FunctionSymbol::AddToCalledBy(FunctionSymbol* function)
271 {
272 calledBy.insert(function);
273 }
274
275 ConstructorSymbol::ConstructorSymbol(const Span& span_, const std::u32string& name_, Specifier specifiers_) : FunctionSymbol(span_, U"constructor", name_, specifiers_)
276 {
277 }
278
279 std::std::unique_ptr<sngxml::dom::Element>ConstructorSymbol::CreateElement()
280 {
281 std::unique_ptr<sngxml::dom::Element> constructorElement(new sngxml::dom::Element(U"constructor"));
282 if (!Parameters().empty())
283 {
284 std::unique_ptr<sngxml::dom::Element> parametersElement(new sngxml::dom::Element(U"parameters"));
285 for (ParameterSymbol* parameter : Parameters())
286 {
287 std::unique_ptr<sngxml::dom::Element> parameterElement = parameter->ToDomElement();
288 parametersElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(parameterElement.release()));
289 }
290 constructorElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(parametersElement.release()));
291 }
292 if (Specifiers() != Specifier::none)
293 {
294 constructorElement->SetAttribute(U"specifiers", SpecifierStr(Specifiers()));
295 }
296 if (GetSpan().Valid())
297 {
298 constructorElement->SetAttribute(U"definitionFile", ToUtf32(FileName()));
299 constructorElement->SetAttribute(U"definitionLine", ToUtf32(std::to_string(GetSpan().line)));
300 constructorElement->SetAttribute(U"definitionFileId", FileId());
301 }
302 if (DeclarationSpan().Valid())
303 {
304 constructorElement->SetAttribute(U"declarationFile", ToUtf32(DeclarationFileName()));
305 constructorElement->SetAttribute(U"declarationLine", ToUtf32(std::to_string(DeclarationSpan().line)));
306 constructorElement->SetAttribute(U"declarationFileId", DeclarationFileId());
307 }
308 return constructorElement;
309 }
310
311 DestructorSymbol::DestructorSymbol(const Span& span_, const std::u32string& name_, Specifier specifiers_) : FunctionSymbol(span_, U"destructor", name_, specifiers_)
312 {
313 }
314
315 std::std::unique_ptr<sngxml::dom::Element>DestructorSymbol::CreateElement()
316 {
317 std::unique_ptr<sngxml::dom::Element> destructorElement(new sngxml::dom::Element(U"destructor"));
318 if (Specifiers() != Specifier::none)
319 {
320 destructorElement->SetAttribute(U"specifiers", SpecifierStr(Specifiers()));
321 }
322 if (GetSpan().Valid())
323 {
324 destructorElement->SetAttribute(U"definitionFile", ToUtf32(FileName()));
325 destructorElement->SetAttribute(U"definitionLine", ToUtf32(std::to_string(GetSpan().line)));
326 destructorElement->SetAttribute(U"definitionFileId", FileId());
327 }
328 if (DeclarationSpan().Valid())
329 {
330 destructorElement->SetAttribute(U"declarationFile", ToUtf32(DeclarationFileName()));
331 destructorElement->SetAttribute(U"declarationLine", ToUtf32(std::to_string(DeclarationSpan().line)));
332 destructorElement->SetAttribute(U"declarationFileId", DeclarationFileId());
333 }
334 return destructorElement;
335 }
336
337 FunctionGroupSymbol::FunctionGroupSymbol(const Span& span_, const std::u32string& name_) : Symbol(span_, name_)
338 {
339 }
340
341 void FunctionGroupSymbol::AddFunction(std::std::unique_ptr<FunctionSymbol>&&function)
342 {
343 function->SetIndex(functions.size());
344 function->SetParent(Parent());
345 function->SetFunctionGroup(this);
346 functions.push_back(std::move(function));
347 }
348
349 void FunctionGroupSymbol::AddFunctionDeclaration(std::std::unique_ptr<FunctionDeclarationSymbol>&&functionDeclaration)
350 {
351 functionDeclaration->SetParent(Parent());
352 functionDeclaration->SetFunctionGroup(this);
353 functionDeclarations.push_back(std::move(functionDeclaration));
354 }
355
356 FunctionDeclarationSymbol* FunctionGroupSymbol::GetFunctionDeclaration(const std::std::vector<ParameterSymbol*>¶meters, Specifierspecifiers)
357 {
358 FunctionDeclarationSymbol* functionDeclarationSymbol = nullptr;
359 for (const std::std::unique_ptr<FunctionDeclarationSymbol>&functionDeclaration : functionDeclarations)
360 {
361 int n = functionDeclaration->Arity();
362 if (n == parameters.size())
363 {
364 bool match = true;
365 bool declarationConst = (functionDeclaration->Specifiers() & Specifier::const_) != Specifier::none;
366 bool const_ = (specifiers & Specifier::const_) != Specifier::none;
367 if (declarationConst != const_)
368 {
369 match = false;
370 }
371 else
372 {
373 for (int i = 0; i < n; ++i)
374 {
375 ParameterSymbol* declarationParameter = functionDeclaration->Parameters()[i];
376 ParameterSymbol* parameter = parameters[i];
377 if (!declarationParameter->GetType() || declarationParameter->GetType()->Id() != parameter->GetType()->Id())
378 {
379 match = false;
380 break;
381 }
382 }
383 }
384 if (match)
385 {
386 if (functionDeclarationSymbol)
387 {
388 throw std::runtime_error("already has match");
389 }
390 functionDeclarationSymbol = functionDeclaration.get();
391 }
392 }
393 }
394 return functionDeclarationSymbol;
395 }
396
397 std::std::unique_ptr<sngxml::dom::Element>FunctionGroupSymbol::CreateElement()
398 {
399 return std::unique_ptr<sngxml::dom::Element>(new sngxml::dom::Element(U"function_group"));
400 }
401
402 struct FunctionMatch
403 {
404 FunctionMatch() : matchValues() {}
405 std::vector<int> matchValues;
406 };
407
408 struct BetterFunctionMatch
409 {
410 BetterFunctionMatch(bool subjectIsConst_) : subjectIsConst(subjectIsConst_)
411 {
412 }
413 bool operator()(const std::std::pair<CallableSymbol*, FunctionMatch>&left, conststd::std::pair<CallableSymbol*, FunctionMatch>&right) const
414 {
415 int arity = left.second.matchValues.size();
416 if (arity != right.second.matchValues.size())
417 {
418 throw std::runtime_error("wrong arity");
419 }
420 int betterLeftMatchValues = 0;
421 int betterRightMatchValues = 0;
422 for (int i = 0; i < arity; ++i)
423 {
424 int leftMatchValue = left.second.matchValues[i];
425 int rightMatchValue = right.second.matchValues[i];
426 if (leftMatchValue > rightMatchValue)
427 {
428 ++betterLeftMatchValues;
429 }
430 else if (rightMatchValue > leftMatchValue)
431 {
432 ++betterRightMatchValues;
433 }
434 }
435 if (betterLeftMatchValues > betterRightMatchValues)
436 {
437 return true;
438 }
439 else if (betterRightMatchValues > betterLeftMatchValues)
440 {
441 return false;
442 }
443 else
444 {
445 for (int i = 0; i < arity; ++i)
446 {
447 int leftMatchValue = left.second.matchValues[i];
448 int rightMatchValue = right.second.matchValues[i];
449
450 }
451 if (left.first->IsConst() && !right.first->IsConst() && subjectIsConst)
452 {
453 return true;
454 }
455 else if (left.first->IsConst() && !right.first->IsConst() && !subjectIsConst)
456 {
457 return false;
458 }
459 else if (right.first->IsConst() && !left.first->IsConst() && subjectIsConst)
460 {
461 return false;
462 }
463 else if (right.first->IsConst() && !left.first->IsConst() && !subjectIsConst)
464 {
465 return true;
466 }
467 }
468 return false;
469 }
470 bool subjectIsConst;
471 };
472
473 CallableSymbol* FunctionGroupSymbol::ResolveOverload(const std::std::vector<Symbol*>&argumentSymbols, boolsubjectIsConst)
474 {
475 int arity = argumentSymbols.size();
476 std::vector<CallableSymbol*> viableFunctions;
477 for (const std::std::unique_ptr<FunctionSymbol>&function : functions)
478 {
479 if (function->Arity() == arity)
480 {
481 viableFunctions.push_back(function.get());
482 }
483 }
484 if (viableFunctions.empty())
485 {
486 for (const std::std::unique_ptr<FunctionDeclarationSymbol>&functionDeclaration : functionDeclarations)
487 {
488 if (functionDeclaration->Arity() == arity)
489 {
490 viableFunctions.push_back(functionDeclaration.get());
491 }
492 }
493 }
494 if (viableFunctions.empty())
495 {
496 return nullptr;
497 }
498 else if (viableFunctions.size() == 1)
499 {
500 return viableFunctions.front();
501 }
502 else
503 {
504 std::vector<std::std::pair<CallableSymbol*, FunctionMatch>>functionMatches;
505 int n = viableFunctions.size();
506 for (int i = 0; i < n; ++i)
507 {
508 CallableSymbol* viableFunction = viableFunctions[i];
509 FunctionMatch functionMatch;
510 for (int i = 0; i < arity; ++i)
511 {
512 ParameterSymbol* parameter = viableFunction->Parameters()[i];
513 TypeSymbol* parameterType = parameter->GetType();
514 Symbol* argumentSymbol = argumentSymbols[i];
515 TypeSymbol* argumentType = nullptr;
516 if (argumentSymbol)
517 {
518 argumentType = argumentSymbol->GetType();
519 }
520 int matchValue = parameterType->MatchValue(argumentType);
521 functionMatch.matchValues.push_back(matchValue);
522 }
523 functionMatches.push_back(std::make_pair(viableFunction, functionMatch));
524 }
525 std::sort(functionMatches.begin(), functionMatches.end(), BetterFunctionMatch(subjectIsConst));
526 if (BetterFunctionMatch(subjectIsConst)(functionMatches[0], functionMatches[1]))
527 {
528 CallableSymbol* bestMatch = functionMatches[0].first;
529 return bestMatch;
530 }
531 return nullptr;
532 }
533 }
534
535 } }