Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2024 ChilliBits. All rights reserved. | ||
2 | |||
3 | #pragma once | ||
4 | |||
5 | #include <model/Interface.h> | ||
6 | #include <model/Struct.h> | ||
7 | #include <symboltablebuilder/SymbolTable.h> | ||
8 | #include <typechecker/FunctionManager.h> | ||
9 | #include <typechecker/InterfaceManager.h> | ||
10 | #include <typechecker/StructManager.h> | ||
11 | |||
12 | namespace spice::compiler { | ||
13 | |||
14 | // Forward declarations | ||
15 | class FctDefNode; | ||
16 | class ProcDefNode; | ||
17 | class SourceFile; | ||
18 | |||
19 | enum class ScopeType : uint8_t { | ||
20 | GLOBAL, | ||
21 | FUNC_PROC_BODY, | ||
22 | LAMBDA_BODY, | ||
23 | STRUCT, | ||
24 | INTERFACE, | ||
25 | ENUM, | ||
26 | IF_ELSE_BODY, | ||
27 | WHILE_BODY, | ||
28 | FOR_BODY, | ||
29 | FOREACH_BODY, | ||
30 | CASE_BODY, | ||
31 | DEFAULT_BODY, | ||
32 | UNSAFE_BODY, | ||
33 | ANONYMOUS_BLOCK_BODY | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * Represents an enclosed group of instructions, which are semantically separated from other scopes. | ||
38 | * In the source code, scopes usually are written as curly braces. | ||
39 | * | ||
40 | * Following language structures use scopes: | ||
41 | * - global scope | ||
42 | * - functions/procedures | ||
43 | * - structs | ||
44 | * - enums | ||
45 | * - interfaces | ||
46 | * - thread blocks | ||
47 | * - unsafe blocks | ||
48 | * - for loops | ||
49 | * - foreach loops | ||
50 | * - while loops | ||
51 | * - if statements | ||
52 | * - anonymous scopes | ||
53 | */ | ||
54 | class Scope { | ||
55 | public: | ||
56 | // Constructors | ||
57 | 16234 | Scope(Scope *parent, SourceFile *sourceFile, ScopeType scopeType, const CodeLoc *codeLoc) | |
58 |
2/2✓ Branch 1 taken 15340 times.
✓ Branch 2 taken 894 times.
|
16234 | : parent(parent), sourceFile(sourceFile), codeLoc(codeLoc), type(scopeType) {} |
59 | |||
60 | // Friend classes | ||
61 | friend class FunctionManager; | ||
62 | friend class StructManager; | ||
63 | friend class InterfaceManager; | ||
64 | |||
65 | // Public methods | ||
66 | // Scope management | ||
67 | Scope *createChildScope(const std::string &scopeName, ScopeType scopeType, const CodeLoc *declCodeLoc); | ||
68 | void renameChildScope(const std::string &oldName, const std::string &newName); | ||
69 | Scope *copyChildScope(const std::string &oldName, const std::string &newName); | ||
70 | std::shared_ptr<Scope> deepCopyScope(); | ||
71 | [[nodiscard]] Scope *getChildScope(const std::string &scopeName) const; | ||
72 | [[nodiscard]] std::vector<SymbolTableEntry *> getVarsGoingOutOfScope(); | ||
73 | |||
74 | // Generic types | ||
75 | void insertGenericType(const std::string &typeName, const GenericType &genericType); | ||
76 | GenericType *lookupGenericType(const std::string &typeName); | ||
77 | |||
78 | // Util | ||
79 | void collectWarnings(std::vector<CompilerWarning> &warnings) const; | ||
80 | void ensureSuccessfulTypeInference() const; | ||
81 | [[nodiscard]] size_t getFieldCount() const; | ||
82 | [[nodiscard]] std::vector<Function *> getVirtualMethods(); | ||
83 | [[nodiscard]] std::vector<const Struct *> getAllStructManifestationsInDeclarationOrder() const; | ||
84 | [[nodiscard]] bool hasRefFields(); | ||
85 | [[nodiscard]] unsigned int getLoopNestingDepth() const; | ||
86 | [[nodiscard]] bool isInCaseBranch() const; | ||
87 | [[nodiscard]] bool isInAsyncScope() const; | ||
88 | [[nodiscard]] bool doesAllowUnsafeOperations() const; | ||
89 | [[nodiscard]] bool isImportedBy(const Scope *askingScope) const; | ||
90 | [[nodiscard]] nlohmann::json getSymbolTableJSON() const; | ||
91 | |||
92 | // Wrapper methods for symbol table | ||
93 | ALWAYS_INLINE SymbolTableEntry *insert(const std::string &name, ASTNode *declNode) { | ||
94 |
13/26✓ Branch 1 taken 638 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 262 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 437 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 31 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 31 times.
✗ Branch 16 not taken.
✓ Branch 21 taken 87 times.
✗ Branch 22 not taken.
✓ Branch 25 taken 2270 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 2703 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 2364 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 4249 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 4249 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 359 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 359 times.
✗ Branch 44 not taken.
|
34890 | return symbolTable.insert(name, declNode); |
95 | } | ||
96 |
4/8✓ Branch 1 taken 19428 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35758 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5860 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
61048 | ALWAYS_INLINE SymbolTableEntry *lookup(const std::string &symbolName) { return symbolTable.lookup(symbolName); } |
97 |
14/25✓ Branch 1 taken 10680 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 438 times.
✓ Branch 4 taken 3098 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4606 times.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7059 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 6680 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 360 times.
✓ Branch 16 taken 3653 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 12687 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2363 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 25035 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 429 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 343 times.
✗ Branch 32 not taken.
|
95530 | ALWAYS_INLINE SymbolTableEntry *lookupStrict(const std::string &symbolName) { return symbolTable.lookupStrict(symbolName); } |
98 | ALWAYS_INLINE SymbolTableEntry *lookupField(unsigned int n) { | ||
99 |
6/12✗ Branch 0 not taken.
✓ Branch 1 taken 18892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1828 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5528 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1016 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 931 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 289 times.
|
28484 | assert(type == ScopeType::STRUCT); |
100 |
8/14✓ Branch 1 taken 5229 times.
✓ Branch 2 taken 118 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1710 times.
✓ Branch 5 taken 2610 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2918 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1016 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 931 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 289 times.
✗ Branch 17 not taken.
|
28484 | return symbolTable.lookupStrictByIndex(n); |
101 | } | ||
102 | |||
103 | // Public members | ||
104 | Scope *parent; | ||
105 | SourceFile *sourceFile; | ||
106 | std::unordered_map<std::string, std::shared_ptr<Scope>> children; | ||
107 | SymbolTable symbolTable = SymbolTable(parent == nullptr ? nullptr : &parent->symbolTable, this); | ||
108 | const CodeLoc *codeLoc = nullptr; | ||
109 | const ScopeType type; | ||
110 | bool isGenericScope = false; | ||
111 | bool isAsyncScope = false; | ||
112 | bool isDtorScope = false; | ||
113 | |||
114 | private: | ||
115 | // Private members | ||
116 | FunctionRegistry functions; | ||
117 | StructRegistry structs; | ||
118 | InterfaceRegistry interfaces; | ||
119 | std::unordered_map<std::string, GenericType> genericTypes; | ||
120 | }; | ||
121 | |||
122 | } // namespace spice::compiler | ||
123 |