Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2025 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 | #include <util/CompilerWarning.h> | ||
12 | |||
13 | namespace spice::compiler { | ||
14 | |||
15 | // Forward declarations | ||
16 | class FctDefNode; | ||
17 | class ProcDefNode; | ||
18 | class SourceFile; | ||
19 | |||
20 | enum class ScopeType : uint8_t { | ||
21 | GLOBAL, | ||
22 | FUNC_PROC_BODY, | ||
23 | LAMBDA_BODY, | ||
24 | STRUCT, | ||
25 | INTERFACE, | ||
26 | ENUM, | ||
27 | IF_ELSE_BODY, | ||
28 | WHILE_BODY, | ||
29 | FOR_BODY, | ||
30 | FOREACH_BODY, | ||
31 | CASE_BODY, | ||
32 | DEFAULT_BODY, | ||
33 | UNSAFE_BODY, | ||
34 | ANONYMOUS_BLOCK_BODY | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * Represents an enclosed group of instructions, which are semantically separated from other scopes. | ||
39 | * In the source code, scopes usually are written as curly braces. | ||
40 | * | ||
41 | * Following language structures use scopes: | ||
42 | * - global scope | ||
43 | * - functions/procedures | ||
44 | * - structs | ||
45 | * - enums | ||
46 | * - interfaces | ||
47 | * - thread blocks | ||
48 | * - unsafe blocks | ||
49 | * - for loops | ||
50 | * - foreach loops | ||
51 | * - while loops | ||
52 | * - if statements | ||
53 | * - anonymous scopes | ||
54 | */ | ||
55 | class Scope { | ||
56 | public: | ||
57 | // Constructors | ||
58 | 19644 | Scope(Scope *parent, SourceFile *sourceFile, ScopeType scopeType, const CodeLoc *codeLoc) | |
59 |
2/2✓ Branch 0 (3→4) taken 18630 times.
✓ Branch 1 (3→5) taken 1014 times.
|
19644 | : parent(parent), sourceFile(sourceFile), codeLoc(codeLoc), type(scopeType) {} |
60 | |||
61 | // Friend classes | ||
62 | friend class FunctionManager; | ||
63 | friend class StructManager; | ||
64 | friend class InterfaceManager; | ||
65 | |||
66 | // Public methods | ||
67 | // Scope management | ||
68 | Scope *createChildScope(const std::string &scopeName, ScopeType scopeType, const CodeLoc *declCodeLoc); | ||
69 | void renameChildScope(const std::string &oldName, const std::string &newName); | ||
70 | Scope *copyChildScope(const std::string &oldName, const std::string &newName); | ||
71 | std::shared_ptr<Scope> deepCopyScope(); | ||
72 | [[nodiscard]] Scope *getChildScope(const std::string &scopeName) const; | ||
73 | [[nodiscard]] std::vector<SymbolTableEntry *> getVarsGoingOutOfScope(); | ||
74 | |||
75 | // Generic types | ||
76 | void insertGenericType(const std::string &typeName, const GenericType &genericType); | ||
77 | GenericType *lookupGenericType(const std::string &typeName); | ||
78 | |||
79 | // Util | ||
80 | void collectWarnings(std::vector<CompilerWarning> &warnings) const; | ||
81 | void ensureSuccessfulTypeInference() const; | ||
82 | [[nodiscard]] size_t getFieldCount() const; | ||
83 | [[nodiscard]] std::vector<Function *> getVirtualMethods(); | ||
84 | [[nodiscard]] std::vector<const Struct *> getAllStructManifestationsInDeclarationOrder() const; | ||
85 | [[nodiscard]] bool hasRefFields(); | ||
86 | [[nodiscard]] unsigned int getLoopNestingDepth() const; | ||
87 | [[nodiscard]] bool isInCaseBranch() const; | ||
88 | [[nodiscard]] bool isInAsyncScope() const; | ||
89 | [[nodiscard]] bool doesAllowUnsafeOperations() const; | ||
90 | [[nodiscard]] bool isImportedBy(const Scope *askingScope) const; | ||
91 | [[nodiscard]] nlohmann::json getSymbolTableJSON() const; | ||
92 | |||
93 | // Wrapper methods for symbol table | ||
94 | ALWAYS_INLINE SymbolTableEntry *insert(const std::string &name, ASTNode *declNode) { | ||
95 |
12/24✓ Branch 0 (30→31) taken 764 times.
✗ Branch 1 (30→62) not taken.
✓ Branch 2 (13→14) taken 1017 times.
✗ Branch 3 (13→41) not taken.
✓ Branch 4 (31→32) taken 46 times.
✗ Branch 5 (31→65) not taken.
✓ Branch 6 (36→37) taken 46 times.
✗ Branch 7 (36→63) not taken.
✓ Branch 8 (26→27) taken 93 times.
✗ Branch 9 (26→74) not taken.
✓ Branch 10 (57→58) taken 2457 times.
✗ Branch 11 (57→111) not taken.
✓ Branch 12 (70→71) taken 2952 times.
✗ Branch 13 (70→119) not taken.
✓ Branch 14 (52→53) taken 2673 times.
✗ Branch 15 (52→112) not taken.
✓ Branch 16 (61→62) taken 6007 times.
✗ Branch 17 (61→118) not taken.
✓ Branch 18 (73→74) taken 6007 times.
✗ Branch 19 (73→126) not taken.
✓ Branch 20 (26→27) taken 370 times.
✗ Branch 21 (26→67) not taken.
✓ Branch 22 (36→37) taken 370 times.
✗ Branch 23 (36→73) not taken.
|
43240 | return symbolTable.insert(name, declNode); |
96 | } | ||
97 |
3/6✓ Branch 0 (28→29) taken 25649 times.
✗ Branch 1 (28→547) not taken.
✓ Branch 2 (22→23) taken 44389 times.
✗ Branch 3 (22→243) not taken.
✓ Branch 4 (5→6) taken 7862 times.
✗ Branch 5 (5→66) not taken.
|
77930 | ALWAYS_INLINE SymbolTableEntry *lookup(const std::string &symbolName) { return symbolTable.lookup(symbolName); } |
98 |
11/22✓ Branch 0 (35→36) taken 14588 times.
✗ Branch 1 (35→74) not taken.
✓ Branch 2 (77→78) taken 3585 times.
✗ Branch 3 (77→227) not taken.
✓ Branch 4 (123→124) taken 5554 times.
✗ Branch 5 (123→254) not taken.
✓ Branch 6 (51→52) taken 9648 times.
✗ Branch 7 (51→271) not taken.
✓ Branch 8 (72→73) taken 8624 times.
✗ Branch 9 (72→202) not taken.
✓ Branch 10 (114→115) taken 4114 times.
✗ Branch 11 (114→229) not taken.
✓ Branch 12 (56→57) taken 16022 times.
✗ Branch 13 (56→374) not taken.
✓ Branch 14 (77→78) taken 2672 times.
✗ Branch 15 (77→265) not taken.
✓ Branch 16 (145→146) taken 32862 times.
✗ Branch 17 (145→309) not taken.
✓ Branch 18 (7→8) taken 441 times.
✗ Branch 19 (7→45) not taken.
✓ Branch 20 (33→34) taken 354 times.
✗ Branch 21 (33→59) not taken.
|
120358 | ALWAYS_INLINE SymbolTableEntry *lookupStrict(const std::string &symbolName) { return symbolTable.lookupStrict(symbolName); } |
99 | ALWAYS_INLINE SymbolTableEntry *lookupField(unsigned int n) { | ||
100 |
6/12✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 21345 times.
✗ Branch 2 (6→7) not taken.
✓ Branch 3 (6→8) taken 1216 times.
✗ Branch 4 (6→7) not taken.
✓ Branch 5 (6→8) taken 5899 times.
✗ Branch 6 (16→17) not taken.
✓ Branch 7 (16→18) taken 1076 times.
✗ Branch 8 (30→31) not taken.
✓ Branch 9 (30→32) taken 992 times.
✗ Branch 10 (23→24) not taken.
✓ Branch 11 (23→25) taken 302 times.
|
30830 | assert(type == ScopeType::STRUCT); |
101 |
6/12✓ Branch 0 (8→9) taken 5083 times.
✗ Branch 1 (8→59) not taken.
✓ Branch 2 (8→9) taken 3898 times.
✗ Branch 3 (8→76) not taken.
✓ Branch 4 (8→9) taken 3099 times.
✗ Branch 5 (8→64) not taken.
✓ Branch 6 (18→19) taken 1076 times.
✗ Branch 7 (18→141) not taken.
✓ Branch 8 (32→33) taken 992 times.
✗ Branch 9 (32→151) not taken.
✓ Branch 10 (25→26) taken 302 times.
✗ Branch 11 (25→114) not taken.
|
30830 | return symbolTable.lookupStrictByIndex(n); |
102 | } | ||
103 | |||
104 | // Public members | ||
105 | Scope *parent; | ||
106 | SourceFile *sourceFile; | ||
107 | std::unordered_map<std::string, std::shared_ptr<Scope>> children; | ||
108 | SymbolTable symbolTable = SymbolTable(parent == nullptr ? nullptr : &parent->symbolTable, this); | ||
109 | const CodeLoc *codeLoc = nullptr; | ||
110 | const ScopeType type; | ||
111 | bool isGenericScope = false; | ||
112 | bool isAsyncScope = false; | ||
113 | bool isDtorScope = false; | ||
114 | |||
115 | private: | ||
116 | // Private members | ||
117 | FunctionRegistry functions; | ||
118 | StructRegistry structs; | ||
119 | InterfaceRegistry interfaces; | ||
120 | std::unordered_map<std::string, GenericType> genericTypes; | ||
121 | }; | ||
122 | |||
123 | } // namespace spice::compiler | ||
124 |