Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2024 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include "ImportCollector.h" | ||
4 | |||
5 | #include <SourceFile.h> | ||
6 | #include <ast/ASTNodes.h> | ||
7 | #include <ast/Attributes.h> | ||
8 | #include <exception/SemanticError.h> | ||
9 | #include <util/FileUtil.h> | ||
10 | |||
11 | namespace spice::compiler { | ||
12 | |||
13 | 894 | std::any ImportCollector::visitEntry(EntryNode *node) { | |
14 | // Visit all module attributes | ||
15 |
3/4✓ Branch 1 taken 894 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 277 times.
✓ Branch 8 taken 894 times.
|
1171 | for (ModAttrNode *attr : node->modAttrs()) |
16 |
1/2✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
|
1171 | visit(attr); |
17 | |||
18 | // Visit all import defs | ||
19 |
3/4✓ Branch 1 taken 894 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 371 times.
✓ Branch 8 taken 889 times.
|
1260 | for (ImportDefNode *importDef : node->importDefs()) |
20 |
2/2✓ Branch 1 taken 366 times.
✓ Branch 2 taken 5 times.
|
1260 | visit(importDef); |
21 | |||
22 |
1/2✓ Branch 1 taken 889 times.
✗ Branch 2 not taken.
|
889 | return nullptr; |
23 | } | ||
24 | |||
25 | 371 | std::any ImportCollector::visitImportDef(ImportDefNode *node) { | |
26 | 371 | const bool isStd = node->importPath.starts_with("std/"); | |
27 | 371 | const bool isBootstrap = node->importPath.starts_with("bootstrap/"); | |
28 | |||
29 | 371 | std::filesystem::path basePath; | |
30 |
2/2✓ Branch 0 taken 329 times.
✓ Branch 1 taken 42 times.
|
371 | if (isStd) { // Include source file from standard library |
31 | // Find std library | ||
32 |
1/2✓ Branch 1 taken 329 times.
✗ Branch 2 not taken.
|
329 | const std::filesystem::path stdPath = FileUtil::getStdDir(); |
33 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
|
329 | if (stdPath.empty()) |
34 | ✗ | throw CompilerError(STD_NOT_FOUND, "Standard library could not be found. Check if the env var SPICE_STD_DIR exists"); | |
35 | // Format: /dir/to/path/file | ||
36 |
3/6✓ Branch 2 taken 329 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 329 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 329 times.
✗ Branch 9 not taken.
|
329 | basePath = stdPath / node->importPath.substr(node->importPath.find("std/") + 4); |
37 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 31 times.
|
371 | } else if (isBootstrap) { // Include source file from bootstrap library |
38 | // Find bootstrap library | ||
39 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | const std::filesystem::path bootstrapPath = FileUtil::getBootstrapDir(); |
40 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if (bootstrapPath.empty()) |
41 | ✗ | throw CompilerError(BOOTSTRAP_NOT_FOUND, | |
42 | ✗ | "Bootstrap compiler could not be found. Check if the env var SPICE_BOOTSTRAP_DIR exists"); | |
43 | // Format: /dir/to/path/file | ||
44 |
3/6✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
|
11 | basePath = bootstrapPath / node->importPath.substr(node->importPath.find("bootstrap/") + 10); |
45 | 11 | } else { // Include own source file | |
46 | // Format: /dir/to/path/file | ||
47 |
3/6✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 31 times.
✗ Branch 8 not taken.
|
31 | basePath = sourceFile->filePath.parent_path() / node->importPath; |
48 | } | ||
49 | 371 | basePath.make_preferred(); | |
50 | |||
51 | // Format: /dir/to/path/file.spice | ||
52 |
1/2✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
|
371 | std::filesystem::path defaultPath = basePath; |
53 |
5/10✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 371 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 371 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 371 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 371 times.
✗ Branch 14 not taken.
|
371 | defaultPath.replace_filename(basePath.stem().string() + ".spice"); |
54 | // Format: /dir/to/path/file_linux.spice | ||
55 |
1/2✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
|
371 | std::filesystem::path osPath = basePath; |
56 |
7/14✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 371 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 371 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 371 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 371 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 371 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 371 times.
✗ Branch 20 not taken.
|
371 | osPath.replace_filename(basePath.stem().string() + "_" + cliOptions.targetOs + ".spice"); |
57 | // Format: /dir/to/path/file_linux_x86_64.spice | ||
58 |
1/2✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
|
371 | std::filesystem::path osArchPath = basePath; |
59 |
9/18✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 371 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 371 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 371 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 371 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 371 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 371 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 371 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 371 times.
✗ Branch 26 not taken.
|
371 | osArchPath.replace_filename(basePath.stem().string() + "_" + cliOptions.targetOs + "_" + cliOptions.targetArch + ".spice"); |
60 | |||
61 | // Check which source file to import | ||
62 | 371 | std::filesystem::path importPath; | |
63 |
2/4✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 371 times.
|
371 | if (exists(osArchPath)) // file_os_arch.spice is first choice |
64 | ✗ | importPath = osArchPath; | |
65 |
3/4✓ Branch 1 taken 371 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 351 times.
|
371 | else if (exists(osPath)) // file_os.spice is second choice |
66 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | importPath = osPath; |
67 |
3/4✓ Branch 1 taken 351 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 349 times.
✓ Branch 4 taken 2 times.
|
351 | else if (exists(defaultPath)) // file.spice is third choice |
68 |
1/2✓ Branch 1 taken 349 times.
✗ Branch 2 not taken.
|
349 | importPath = defaultPath; |
69 | else | ||
70 |
3/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | throw SemanticError(node, IMPORTED_FILE_NOT_EXISTING, "The source file '" + node->importPath + ".spice' does not exist"); |
71 | |||
72 | // Check if the import already exists | ||
73 |
1/2✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
|
369 | SymbolTableEntry *importEntry = rootScope->lookupStrict(node->importName); |
74 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 367 times.
|
369 | if (importEntry != nullptr) |
75 |
3/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | throw SemanticError(node, DUPLICATE_IMPORT_NAME, "Duplicate import '" + node->importName + "'"); |
76 | |||
77 | // Create symbol for import | ||
78 |
1/2✓ Branch 1 taken 367 times.
✗ Branch 2 not taken.
|
367 | node->entry = rootScope->insert(node->importName, node); |
79 | |||
80 | // Create the imported source file | ||
81 |
1/2✓ Branch 1 taken 367 times.
✗ Branch 2 not taken.
|
367 | const auto importedSourceFile = resourceManager.createSourceFile(sourceFile, node->importName, importPath, isStd); |
82 | // Register it as a dependency to the current source file | ||
83 |
3/4✓ Branch 1 taken 367 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 366 times.
✓ Branch 5 taken 1 times.
|
368 | sourceFile->addDependency(importedSourceFile, node, node->importName, importPath.generic_string()); |
84 | |||
85 |
1/2✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
|
732 | return nullptr; |
86 | 391 | } | |
87 | |||
88 | 277 | std::any ImportCollector::visitModAttr(ModAttrNode *node) { | |
89 | // Retrieve attributes | ||
90 | 277 | const AttrLstNode *attrs = node->attrLst(); | |
91 | |||
92 | // !!! Only bool attributes allowed here, due to missing attribute value checks being executed in a later stage !!! | ||
93 | |||
94 | // core.compiler.keep-on-name-collision | ||
95 |
4/6✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 277 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 271 times.
✓ Branch 8 taken 6 times.
|
831 | if (attrs->hasAttr(ATTR_CORE_COMPILER_KEEP_ON_NAME_COLLISION)) { |
96 |
2/4✓ Branch 1 taken 271 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 271 times.
✗ Branch 5 not taken.
|
542 | const bool keepOnCollision = attrs->getAttrValueByName(ATTR_CORE_COMPILER_KEEP_ON_NAME_COLLISION)->boolValue; |
97 | 271 | sourceFile->alwaysKeepSymbolsOnNameCollision = keepOnCollision; | |
98 | } | ||
99 | |||
100 | // core.compiler.warnings.ignore | ||
101 |
4/6✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 277 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 276 times.
|
831 | if (attrs->hasAttr(ATTR_CORE_COMPILER_WARNINGS_IGNORE)) { |
102 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | const bool ignoreWarnings = attrs->getAttrValueByName(ATTR_CORE_COMPILER_WARNINGS_IGNORE)->boolValue; |
103 | 1 | sourceFile->ignoreWarnings = ignoreWarnings; | |
104 | } | ||
105 | |||
106 |
1/2✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
|
277 | return nullptr; |
107 | } | ||
108 | |||
109 | } // namespace spice::compiler | ||
110 |