GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeCheckerCheck.cpp
Date: 2024-12-24 01:17:15
Exec Total Coverage
Lines: 122 122 100.0%
Functions: 4 4 100.0%
Branches: 151 226 66.8%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #include "TypeChecker.h"
4
5 #include <SourceFile.h>
6 #include <exception/SemanticError.h>
7 #include <symboltablebuilder/SymbolTableBuilder.h>
8 #include <typechecker/TypeMatcher.h>
9
10 namespace spice::compiler {
11
12 380 std::any TypeChecker::visitMainFctDefCheck(MainFctDefNode *node) {
13 // Skip if already type-checked
14
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 341 times.
380 if (typeCheckedMainFct)
15
1/2
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
39 return nullptr;
16
17 341 node->resizeToNumberOfManifestations(1);
18
19 // Change to function body scope
20 341 currentScope = node->bodyScope;
21 // Visit statements in new scope
22
2/2
✓ Branch 1 taken 313 times.
✓ Branch 2 taken 28 times.
341 visit(node->body);
23 // Leave main function body scope
24 313 currentScope = rootScope;
25
26 // Set to type-checked
27 313 typeCheckedMainFct = true;
28
1/2
✓ Branch 1 taken 313 times.
✗ Branch 2 not taken.
313 return nullptr;
29 }
30
31 27470 std::any TypeChecker::visitFctDefCheck(FctDefNode *node) {
32 27470 node->resizeToNumberOfManifestations(node->manifestations.size());
33 27470 manIdx = 0; // Reset the manifestation index
34
35 // Get all manifestations for this function definition
36
2/2
✓ Branch 5 taken 36717 times.
✓ Branch 6 taken 27469 times.
64186 for (Function *manifestation : node->manifestations) {
37 // Skip non-substantiated or already checked functions
38
7/8
✓ Branch 1 taken 36717 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28382 times.
✓ Branch 4 taken 8335 times.
✓ Branch 5 taken 24297 times.
✓ Branch 6 taken 4085 times.
✓ Branch 7 taken 32632 times.
✓ Branch 8 taken 4085 times.
36717 if (!manifestation->isFullySubstantiated() || manifestation->alreadyTypeChecked) {
39 32632 manIdx++; // Increase the manifestation index
40 32632 continue;
41 }
42
43 // Change scope to concrete struct specialization scope
44
2/2
✓ Branch 0 taken 2611 times.
✓ Branch 1 taken 1474 times.
4085 if (node->isMethod) {
45
2/4
✓ Branch 1 taken 2611 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2611 times.
✗ Branch 5 not taken.
2611 const auto structSignature = Struct::getSignature(node->name->structName, manifestation->thisType.getTemplateTypes());
46
2/4
✓ Branch 1 taken 2611 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2611 times.
✗ Branch 5 not taken.
2611 changeToScope(STRUCT_SCOPE_PREFIX + structSignature, ScopeType::STRUCT);
47 2611 }
48
49 // Change to function scope
50
1/2
✓ Branch 1 taken 4085 times.
✗ Branch 2 not taken.
4085 changeToScope(manifestation->bodyScope, ScopeType::FUNC_PROC_BODY);
51
52 // Mount type mapping for this manifestation
53
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4085 times.
4085 assert(typeMapping.empty());
54
1/2
✓ Branch 1 taken 4085 times.
✗ Branch 2 not taken.
4085 typeMapping = manifestation->typeMapping;
55
56 // Set return type to the result variable
57
1/2
✓ Branch 1 taken 4085 times.
✗ Branch 2 not taken.
12255 SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4085 times.
4085 assert(resultVarEntry != nullptr);
59
1/2
✓ Branch 1 taken 4085 times.
✗ Branch 2 not taken.
4085 resultVarEntry->updateType(manifestation->returnType, false);
60 4085 resultVarEntry->used = true;
61
62 // Visit parameters
63 // This happens once in the type checker prepare stage. This second time is only required if we have a generic function
64
2/2
✓ Branch 0 taken 2964 times.
✓ Branch 1 taken 1121 times.
4085 if (node->hasParams)
65
1/2
✓ Branch 1 taken 2964 times.
✗ Branch 2 not taken.
2964 visit(node->paramLst);
66
67 // Visit statements in new scope
68
2/2
✓ Branch 1 taken 4084 times.
✓ Branch 2 taken 1 times.
4085 visit(node->body);
69
70 // Clear type mapping
71 4084 typeMapping.clear();
72
73 // Change to root scope
74 4084 currentScope = rootScope;
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4084 times.
4084 assert(currentScope->type == ScopeType::GLOBAL);
76
77 // Do not type-check this manifestation again
78 4084 manifestation->alreadyTypeChecked = true;
79
80 4084 manIdx++; // Increase the manifestation index
81 }
82 27469 manIdx = 0; // Reset the manifestation index
83
84
1/2
✓ Branch 1 taken 27469 times.
✗ Branch 2 not taken.
27469 return nullptr;
85 }
86
87 18560 std::any TypeChecker::visitProcDefCheck(ProcDefNode *node) {
88 18560 node->resizeToNumberOfManifestations(node->manifestations.size());
89 18560 manIdx = 0; // Reset the manifestation index
90
91 // Get all manifestations for this procedure definition
92
2/2
✓ Branch 5 taken 24139 times.
✓ Branch 6 taken 18559 times.
42698 for (Function *manifestation : node->manifestations) {
93 // Skip non-substantiated or already checked procedures
94
7/8
✓ Branch 1 taken 24139 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18218 times.
✓ Branch 4 taken 5921 times.
✓ Branch 5 taken 15863 times.
✓ Branch 6 taken 2355 times.
✓ Branch 7 taken 21784 times.
✓ Branch 8 taken 2355 times.
24139 if (!manifestation->isFullySubstantiated() || manifestation->alreadyTypeChecked) {
95 21784 manIdx++; // Increase the manifestation index
96 21784 continue;
97 }
98
99 // Change scope to concrete struct specialization scope
100
2/2
✓ Branch 0 taken 2167 times.
✓ Branch 1 taken 188 times.
2355 if (node->isMethod) {
101
2/4
✓ Branch 1 taken 2167 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2167 times.
✗ Branch 5 not taken.
2167 const auto structSignature = Struct::getSignature(node->name->structName, manifestation->thisType.getTemplateTypes());
102
2/4
✓ Branch 1 taken 2167 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2167 times.
✗ Branch 5 not taken.
2167 changeToScope(STRUCT_SCOPE_PREFIX + structSignature, ScopeType::STRUCT);
103 2167 }
104
105 // Change to procedure scope
106
1/2
✓ Branch 1 taken 2355 times.
✗ Branch 2 not taken.
2355 changeToScope(manifestation->bodyScope, ScopeType::FUNC_PROC_BODY);
107
108 // Mount type mapping for this manifestation
109
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2355 times.
2355 assert(typeMapping.empty());
110
1/2
✓ Branch 1 taken 2355 times.
✗ Branch 2 not taken.
2355 typeMapping = manifestation->typeMapping;
111
112 // Visit parameters
113 // This happens once in the type checker prepare stage. This second time is only required if we have a generic procedure
114
2/2
✓ Branch 0 taken 1608 times.
✓ Branch 1 taken 747 times.
2355 if (node->hasParams)
115
1/2
✓ Branch 1 taken 1608 times.
✗ Branch 2 not taken.
1608 visit(node->paramLst);
116
117 // Prepare generation of special ctor preamble to store VTable, default field values, etc. if required
118
2/2
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 1310 times.
2355 if (node->isCtor)
119
1/2
✓ Branch 1 taken 1045 times.
✗ Branch 2 not taken.
1045 createCtorBodyPreamble(node->scope);
120
121 // Visit statements in new scope
122
2/2
✓ Branch 1 taken 2354 times.
✓ Branch 2 taken 1 times.
2355 visit(node->body);
123
124 // Clear type mapping
125 2354 typeMapping.clear();
126
127 // Change to root scope
128 2354 currentScope = rootScope;
129
2/4
✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2354 times.
✗ Branch 3 not taken.
2354 assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL);
130
131 // Do not type-check this manifestation again
132 2354 manifestation->alreadyTypeChecked = true;
133
134 2354 manIdx++; // Increase the manifestation index
135 }
136 18559 manIdx = 0; // Reset the manifestation index
137
138
1/2
✓ Branch 1 taken 18559 times.
✗ Branch 2 not taken.
18559 return nullptr;
139 }
140
141 3039 std::any TypeChecker::visitStructDefCheck(StructDefNode *node) {
142 3039 node->resizeToNumberOfManifestations(node->structManifestations.size());
143 3039 manIdx = 0; // Reset the manifestation index
144
145 // Get all manifestations for this procedure definition
146
2/2
✓ Branch 5 taken 5762 times.
✓ Branch 6 taken 3039 times.
8801 for (Struct *manifestation : node->structManifestations) {
147 // Skip non-substantiated or already checked procedures
148
3/4
✓ Branch 1 taken 5762 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1144 times.
✓ Branch 4 taken 4618 times.
5762 if (!manifestation->isFullySubstantiated()) {
149 1144 manIdx++; // Increase the manifestation index
150 1144 continue;
151 }
152
153 // Change to struct scope
154
1/2
✓ Branch 1 taken 4618 times.
✗ Branch 2 not taken.
4618 changeToScope(manifestation->scope, ScopeType::STRUCT);
155
156 // Re-visit all default values. This is required, since the type of the default value might vary for different manifestations
157
2/2
✓ Branch 5 taken 10110 times.
✓ Branch 6 taken 4618 times.
14728 for (const FieldNode *field : node->fields)
158
2/2
✓ Branch 0 taken 681 times.
✓ Branch 1 taken 9429 times.
10110 if (field->defaultValue != nullptr)
159
1/2
✓ Branch 1 taken 681 times.
✗ Branch 2 not taken.
681 visit(field->defaultValue);
160
161 // Build struct type
162
1/2
✓ Branch 1 taken 4618 times.
✗ Branch 2 not taken.
4618 const QualType structType = manifestation->entry->getQualType();
163
164 // Check if the struct implements all methods of all attached interfaces
165 4618 size_t vtableIndex = 0;
166
2/2
✓ Branch 5 taken 504 times.
✓ Branch 6 taken 4618 times.
5122 for (const QualType &interfaceType : manifestation->interfaceTypes) {
167 // Retrieve interface instance
168
2/4
✓ Branch 1 taken 504 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 504 times.
✗ Branch 5 not taken.
504 const std::string interfaceName = interfaceType.getSubType();
169
1/2
✓ Branch 1 taken 504 times.
✗ Branch 2 not taken.
504 Scope *matchScope = interfaceType.getBodyScope()->parent;
170
2/4
✓ Branch 1 taken 504 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 504 times.
✗ Branch 5 not taken.
504 const Interface *interface = InterfaceManager::match(matchScope, interfaceName, interfaceType.getTemplateTypes(), node);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 assert(interface != nullptr);
172
173 // Check for all methods, that it is implemented by the struct
174
2/2
✓ Branch 5 taken 1270 times.
✓ Branch 6 taken 504 times.
1774 for (const Function *expMethod : interface->methods) {
175
1/2
✓ Branch 1 taken 1270 times.
✗ Branch 2 not taken.
1270 const std::string methodName = expMethod->name;
176
1/2
✓ Branch 1 taken 1270 times.
✗ Branch 2 not taken.
1270 QualTypeList params = expMethod->getParamTypes();
177 1270 QualType returnType = expMethod->returnType;
178
179 // Substantiate param and return types
180
1/2
✓ Branch 1 taken 1270 times.
✗ Branch 2 not taken.
1270 TypeMatcher::substantiateTypesWithTypeMapping(params, interface->typeMapping, node);
181
3/4
✓ Branch 1 taken 1270 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 738 times.
✓ Branch 4 taken 532 times.
1270 if (returnType.hasAnyGenericParts())
182
1/2
✓ Branch 1 taken 738 times.
✗ Branch 2 not taken.
738 TypeMatcher::substantiateTypeWithTypeMapping(returnType, interface->typeMapping, node);
183
184 // Build args list
185 1270 ArgList args;
186
1/2
✓ Branch 2 taken 1270 times.
✗ Branch 3 not taken.
1270 args.reserve(params.size());
187
2/2
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 1270 times.
1284 for (const QualType &param : params)
188
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 args.emplace_back(param, nullptr);
189
190 // Search for method that has the required signature
191
1/2
✓ Branch 2 taken 1270 times.
✗ Branch 3 not taken.
1270 Function *spiceFunction = FunctionManager::match(this, currentScope, methodName, structType, args, {}, true, node);
192
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1266 times.
1270 if (spiceFunction == nullptr) {
193
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 softError(node, INTERFACE_METHOD_NOT_IMPLEMENTED,
194
5/10
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
8 "The struct '" + node->structName + "' does not implement method '" + expMethod->getSignature() +
195 "'. The signature does not match.");
196 4 continue;
197 }
198
199 // Check return type
200
5/6
✓ Branch 1 taken 1266 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 232 times.
✓ Branch 4 taken 1034 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1264 times.
1498 if (spiceFunction->returnType != returnType &&
201
3/4
✓ Branch 1 taken 232 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 230 times.
232 !returnType.matchesInterfaceImplementedByStruct(spiceFunction->returnType)) {
202
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 softError(node, INTERFACE_METHOD_NOT_IMPLEMENTED,
203
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
4 "The struct '" + node->structName + "' does not implement method '" + expMethod->getSignature() +
204 "'. The return type does not match.");
205 2 continue;
206 }
207 // Set to virtual, since it overrides the interface method
208 1264 spiceFunction->isVirtual = true;
209 1264 spiceFunction->vtableIndex = vtableIndex++;
210
6/6
✓ Branch 1 taken 1264 times.
✓ Branch 2 taken 6 times.
✓ Branch 4 taken 1264 times.
✓ Branch 5 taken 6 times.
✓ Branch 7 taken 1264 times.
✓ Branch 8 taken 6 times.
1282 }
211 504 }
212
213 // Generate default ctor body if required
214
2/4
✓ Branch 2 taken 4618 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4618 times.
✗ Branch 6 not taken.
13854 const Function *ctorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, structType, {}, true);
215
4/4
✓ Branch 0 taken 1875 times.
✓ Branch 1 taken 2743 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 1805 times.
4618 if (ctorFunc != nullptr && ctorFunc->implicitDefault)
216
1/2
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
70 createCtorBodyPreamble(ctorFunc->bodyScope);
217
218 // Generate default copy ctor body if required
219
2/4
✓ Branch 1 taken 4618 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4618 times.
✗ Branch 6 not taken.
13854 const ArgList args = {{structType.toConstRef(node), false /* always non-temporary */}};
220
2/4
✓ Branch 1 taken 4618 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4618 times.
✗ Branch 5 not taken.
4618 const Function *copyCtorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, structType, args, true);
221
4/4
✓ Branch 0 taken 1323 times.
✓ Branch 1 taken 3295 times.
✓ Branch 2 taken 528 times.
✓ Branch 3 taken 795 times.
4618 if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault)
222
1/2
✓ Branch 1 taken 528 times.
✗ Branch 2 not taken.
528 createCopyCtorBodyPreamble(copyCtorFunc->bodyScope);
223
224 // Generate default dtor body if required
225
2/4
✓ Branch 2 taken 4618 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4618 times.
✗ Branch 6 not taken.
13854 const Function *dtorFunc = FunctionManager::lookup(currentScope, DTOR_FUNCTION_NAME, structType, {}, true);
226
4/4
✓ Branch 0 taken 1034 times.
✓ Branch 1 taken 3584 times.
✓ Branch 2 taken 379 times.
✓ Branch 3 taken 655 times.
4618 if (dtorFunc != nullptr && dtorFunc->implicitDefault)
227
1/2
✓ Branch 1 taken 379 times.
✗ Branch 2 not taken.
379 createDtorBodyPreamble(dtorFunc->bodyScope);
228
229 // Return to the root scope
230 4618 currentScope = rootScope;
231
2/4
✓ Branch 0 taken 4618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4618 times.
✗ Branch 3 not taken.
4618 assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL);
232
233 4618 manIdx++; // Increase the manifestation index
234 4618 }
235 3039 manIdx = 0; // Reset the manifestation index
236
237
1/2
✓ Branch 1 taken 3039 times.
✗ Branch 2 not taken.
3039 return nullptr;
238 }
239
240 } // namespace spice::compiler
241