Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2024 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include "Function.h" | ||
4 | |||
5 | #include <ast/ASTBuilder.h> | ||
6 | #include <ast/ASTNodes.h> | ||
7 | #include <irgenerator/NameMangling.h> | ||
8 | |||
9 | namespace spice::compiler { | ||
10 | |||
11 | /** | ||
12 | * Retrieve the parameter types of the current function | ||
13 | * | ||
14 | * @return Vector of parameter types | ||
15 | */ | ||
16 | 24909 | QualTypeList Function::getParamTypes() const { | |
17 | 24909 | QualTypeList newParamTypes; | |
18 |
2/2✓ Branch 5 taken 33852 times.
✓ Branch 6 taken 24909 times.
|
58761 | for (const auto &[qualType, isOptional] : paramList) |
19 |
1/2✓ Branch 1 taken 33852 times.
✗ Branch 2 not taken.
|
33852 | newParamTypes.push_back(qualType); |
20 | 24909 | return newParamTypes; | |
21 | ✗ | } | |
22 | |||
23 | /** | ||
24 | * Get a string representation of the current function. | ||
25 | * | ||
26 | * Example: | ||
27 | * string Vector<double>.setData<double>(double) | ||
28 | * | ||
29 | * @param withThisType Include 'this' type in signature | ||
30 | * @param ignorePublic Not include public modifiers in signature | ||
31 | * @return String representation as function signature | ||
32 | */ | ||
33 | 29444 | std::string Function::getSignature(bool withThisType /*=true*/, bool ignorePublic /*=false*/) const { | |
34 | 29444 | QualTypeList concreteTemplateTypes; | |
35 |
1/2✓ Branch 2 taken 29444 times.
✗ Branch 3 not taken.
|
29444 | concreteTemplateTypes.reserve(templateTypes.size()); |
36 |
2/2✓ Branch 5 taken 15551 times.
✓ Branch 6 taken 29444 times.
|
44995 | for (const GenericType &genericType : templateTypes) { |
37 |
6/8✓ Branch 1 taken 15551 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15551 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7172 times.
✓ Branch 7 taken 8379 times.
✓ Branch 8 taken 7172 times.
✓ Branch 9 taken 8379 times.
|
15551 | if (genericType.is(TY_GENERIC) && !typeMapping.empty()) { |
38 |
3/6✓ Branch 1 taken 7172 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7172 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7172 times.
|
7172 | assert(typeMapping.contains(genericType.getSubType())); |
39 |
3/6✓ Branch 1 taken 7172 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7172 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7172 times.
✗ Branch 8 not taken.
|
7172 | concreteTemplateTypes.push_back(typeMapping.at(genericType.getSubType())); |
40 | } else { | ||
41 |
1/2✓ Branch 1 taken 8379 times.
✗ Branch 2 not taken.
|
8379 | concreteTemplateTypes.push_back(genericType); |
42 | } | ||
43 | } | ||
44 | |||
45 |
1/2✓ Branch 1 taken 29444 times.
✗ Branch 2 not taken.
|
58888 | return Function::getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, withThisType, ignorePublic); |
46 | 29444 | } | |
47 | |||
48 | /** | ||
49 | * Get a string representation of the current function. | ||
50 | * | ||
51 | * @param name Function name | ||
52 | * @param thisType This symbol type | ||
53 | * @param returnType Return symbol type | ||
54 | * @param paramList Param symbol types | ||
55 | * @param concreteTemplateTypes Concrete template symbol types | ||
56 | * @param withReturnType Include return type in signature | ||
57 | * @param withThisType Include 'this' type in signature | ||
58 | * @param ignorePublic Not include public modifiers in signature | ||
59 | * @return Function signature | ||
60 | */ | ||
61 | 29456 | std::string Function::getSignature(const std::string &name, const QualType &thisType, const QualType &returnType, | |
62 | const ParamList ¶mList, const QualTypeList &concreteTemplateTypes, | ||
63 | bool withReturnType /*=true*/, bool withThisType /*=true*/, bool ignorePublic /*=false*/) { | ||
64 |
1/2✓ Branch 1 taken 29456 times.
✗ Branch 2 not taken.
|
29456 | std::stringstream signature; |
65 | |||
66 | // Build return type string | ||
67 |
2/2✓ Branch 0 taken 11823 times.
✓ Branch 1 taken 17633 times.
|
29456 | if (withReturnType) { |
68 |
3/4✓ Branch 1 taken 11823 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4864 times.
✓ Branch 4 taken 6959 times.
|
11823 | if (returnType.is(TY_DYN)) { |
69 |
1/2✓ Branch 1 taken 4864 times.
✗ Branch 2 not taken.
|
4864 | signature << "p "; |
70 | } else { | ||
71 |
1/2✓ Branch 1 taken 6959 times.
✗ Branch 2 not taken.
|
6959 | signature << "f<"; |
72 |
1/2✓ Branch 1 taken 6959 times.
✗ Branch 2 not taken.
|
6959 | returnType.getName(signature, false, ignorePublic); |
73 |
1/2✓ Branch 1 taken 6959 times.
✗ Branch 2 not taken.
|
6959 | signature << "> "; |
74 | } | ||
75 | } | ||
76 | |||
77 | // Build this type string | ||
78 |
6/8✓ Branch 0 taken 29456 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 29456 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20596 times.
✓ Branch 6 taken 8860 times.
✓ Branch 7 taken 20596 times.
✓ Branch 8 taken 8860 times.
|
29456 | if (withThisType && !thisType.is(TY_DYN)) { |
79 |
3/6✓ Branch 1 taken 20596 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20596 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20596 times.
✗ Branch 8 not taken.
|
20596 | signature << thisType.getBase().getSubType(); |
80 |
1/2✓ Branch 1 taken 20596 times.
✗ Branch 2 not taken.
|
20596 | const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes(); |
81 |
2/2✓ Branch 1 taken 8805 times.
✓ Branch 2 taken 11791 times.
|
20596 | if (!thisTemplateTypes.empty()) { |
82 |
1/2✓ Branch 1 taken 8805 times.
✗ Branch 2 not taken.
|
8805 | signature << "<"; |
83 |
2/2✓ Branch 1 taken 10967 times.
✓ Branch 2 taken 8805 times.
|
19772 | for (size_t i = 0; i < thisTemplateTypes.size(); i++) { |
84 |
2/2✓ Branch 0 taken 2162 times.
✓ Branch 1 taken 8805 times.
|
10967 | if (i > 0) |
85 |
1/2✓ Branch 1 taken 2162 times.
✗ Branch 2 not taken.
|
2162 | signature << ","; |
86 |
3/6✓ Branch 1 taken 10967 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10967 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10967 times.
✗ Branch 8 not taken.
|
10967 | signature << thisTemplateTypes.at(i).getName(false, ignorePublic); |
87 | } | ||
88 |
1/2✓ Branch 1 taken 8805 times.
✗ Branch 2 not taken.
|
8805 | signature << ">"; |
89 | } | ||
90 |
1/2✓ Branch 1 taken 20596 times.
✗ Branch 2 not taken.
|
20596 | signature << MEMBER_ACCESS_TOKEN; |
91 | } | ||
92 | |||
93 | // Name | ||
94 |
1/2✓ Branch 1 taken 29456 times.
✗ Branch 2 not taken.
|
29456 | signature << name; |
95 | |||
96 | // Build template type string | ||
97 |
2/2✓ Branch 1 taken 12839 times.
✓ Branch 2 taken 16617 times.
|
29456 | if (!concreteTemplateTypes.empty()) { |
98 |
1/2✓ Branch 1 taken 12839 times.
✗ Branch 2 not taken.
|
12839 | signature << "<"; |
99 |
2/2✓ Branch 1 taken 15551 times.
✓ Branch 2 taken 12839 times.
|
28390 | for (size_t i = 0; i < concreteTemplateTypes.size(); i++) { |
100 |
2/2✓ Branch 0 taken 2712 times.
✓ Branch 1 taken 12839 times.
|
15551 | if (i > 0) |
101 |
1/2✓ Branch 1 taken 2712 times.
✗ Branch 2 not taken.
|
2712 | signature << ","; |
102 |
3/6✓ Branch 1 taken 15551 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15551 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 15551 times.
✗ Branch 8 not taken.
|
15551 | signature << concreteTemplateTypes.at(i).getName(false, ignorePublic); |
103 | } | ||
104 |
1/2✓ Branch 1 taken 12839 times.
✗ Branch 2 not taken.
|
12839 | signature << ">"; |
105 | } | ||
106 | |||
107 | // Parameter type string | ||
108 |
1/2✓ Branch 1 taken 29456 times.
✗ Branch 2 not taken.
|
29456 | signature << "("; |
109 |
2/2✓ Branch 1 taken 30264 times.
✓ Branch 2 taken 29456 times.
|
59720 | for (size_t i = 0; i < paramList.size(); i++) { |
110 |
1/2✓ Branch 1 taken 30264 times.
✗ Branch 2 not taken.
|
30264 | const auto &[qualType, isOptional] = paramList.at(i); |
111 |
2/2✓ Branch 0 taken 10156 times.
✓ Branch 1 taken 20108 times.
|
30264 | if (i > 0) |
112 |
1/2✓ Branch 1 taken 10156 times.
✗ Branch 2 not taken.
|
10156 | signature << ","; |
113 |
2/4✓ Branch 1 taken 30264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30264 times.
✗ Branch 5 not taken.
|
30264 | signature << qualType.getName(false, ignorePublic); |
114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30264 times.
|
30264 | if (isOptional) |
115 | ✗ | signature << "?"; | |
116 | } | ||
117 |
1/2✓ Branch 1 taken 29456 times.
✗ Branch 2 not taken.
|
29456 | signature << ")"; |
118 | |||
119 |
1/2✓ Branch 1 taken 29456 times.
✗ Branch 2 not taken.
|
58912 | return signature.str(); |
120 | 29456 | } | |
121 | |||
122 | 17763 | std::string Function::getMangledName() const { | |
123 | // Use predefined mangled name if available | ||
124 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 17762 times.
|
17763 | if (!predefinedMangledName.empty()) |
125 | 1 | return predefinedMangledName; | |
126 | // Use function name if mangling is disabled | ||
127 |
2/2✓ Branch 0 taken 2114 times.
✓ Branch 1 taken 15648 times.
|
17762 | if (!mangleFunctionName) |
128 | 2114 | return name; | |
129 | // Use normal name mangling | ||
130 | 15648 | return NameMangling::mangleFunction(*this); | |
131 | } | ||
132 | |||
133 | 14152 | std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) { | |
134 |
3/6✓ Branch 1 taken 14152 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14152 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14152 times.
✗ Branch 8 not taken.
|
14152 | return functionName + ":" + codeLoc.toString(); |
135 | } | ||
136 | |||
137 | /** | ||
138 | * Checks if a function contains optional parameters. | ||
139 | * This would imply that the function is not substantiated by its optional parameters yet. | ||
140 | * | ||
141 | * @return Substantiated params or not | ||
142 | */ | ||
143 | 602245 | bool Function::hasSubstantiatedParams() const { | |
144 | 1348874 | return std::ranges::none_of(paramList, [](const Param ¶m) { return param.isOptional; }); | |
145 | } | ||
146 | |||
147 | /** | ||
148 | * Checks if a function contains template types. | ||
149 | * This would imply that the function is not substantiated by its generic types yet. | ||
150 | * | ||
151 | * @return Substantiated generics or not | ||
152 | */ | ||
153 | 169878 | bool Function::hasSubstantiatedGenerics() const { | |
154 | 89284 | const auto predicate = [this](const GenericType &genericType) { return typeMapping.contains(genericType.getSubType()); }; | |
155 |
1/2✓ Branch 1 taken 169878 times.
✗ Branch 2 not taken.
|
339756 | return std::ranges::all_of(templateTypes, predicate); |
156 | } | ||
157 | |||
158 | /** | ||
159 | * Checks if a function contains optional parameters or has generic types present. | ||
160 | * This would imply that the function is not fully substantiated yet. | ||
161 | * | ||
162 | * @return Fully substantiated or not | ||
163 | */ | ||
164 |
3/4✓ Branch 1 taken 169878 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 116599 times.
✓ Branch 5 taken 53279 times.
|
169878 | bool Function::isFullySubstantiated() const { return hasSubstantiatedParams() && hasSubstantiatedGenerics(); } |
165 | |||
166 | /** | ||
167 | * Returns, if this function is a substantiation of a generic one. | ||
168 | * | ||
169 | * @return Generic substantiation or not | ||
170 | */ | ||
171 | 321965 | bool Function::isGenericSubstantiation() const { return genericPreset != nullptr; } | |
172 | |||
173 | /** | ||
174 | * Retrieve the declaration code location of this function | ||
175 | * | ||
176 | * @return Declaration code location | ||
177 | */ | ||
178 | 2864 | const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; } | |
179 | |||
180 | } // namespace spice::compiler | ||
181 |