1 /* 2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ES2PANDA_VARBINDER_RECORDTABLE_H 17 #define ES2PANDA_VARBINDER_RECORDTABLE_H 18 19 #include "util/es2pandaMacros.h" 20 #include "utils/arena_containers.h" 21 #include "util/ustring.h" 22 #include "util/enumbitops.h" 23 24 namespace ark::es2panda::parser { 25 class Program; 26 } // namespace ark::es2panda::parser 27 28 namespace ark::es2panda::checker { 29 class Signature; 30 } // namespace ark::es2panda::checker 31 32 namespace ark::es2panda::ir { 33 class ClassDefinition; 34 class TSInterfaceDeclaration; 35 class AnnotationDeclaration; 36 class Identifier; 37 } // namespace ark::es2panda::ir 38 39 namespace ark::es2panda::varbinder { 40 class FunctionScope; 41 class BoundContext; 42 43 using ENUMBITOPS_OPERATORS; 44 45 enum class RecordTableFlags : uint32_t { 46 NONE = 0U, 47 EXTERNAL = 1U << 0U, 48 }; 49 50 } // namespace ark::es2panda::varbinder 51 52 template <> 53 struct enumbitops::IsAllowedType<ark::es2panda::varbinder::RecordTableFlags> : std::true_type { 54 }; 55 56 namespace ark::es2panda::varbinder { 57 58 class RecordTable { 59 public: 60 explicit RecordTable(ArenaAllocator *allocator, parser::Program *program, RecordTableFlags flags) 61 : classDefinitions_(allocator->Adapter()), 62 interfaceDeclarations_(allocator->Adapter()), 63 annotationDeclarations_(allocator->Adapter()), 64 signatures_(allocator->Adapter()), 65 program_(program), 66 flags_(flags) 67 { 68 } 69 70 NO_COPY_SEMANTIC(RecordTable); 71 NO_MOVE_SEMANTIC(RecordTable); 72 73 ~RecordTable() = default; 74 75 bool IsExternal() const 76 { 77 return (flags_ & RecordTableFlags::EXTERNAL) != 0; 78 } 79 80 ArenaSet<ir::ClassDefinition *> &ClassDefinitions() 81 { 82 return classDefinitions_; 83 } 84 85 const ArenaSet<ir::ClassDefinition *> &ClassDefinitions() const 86 { 87 return classDefinitions_; 88 } 89 90 ArenaSet<ir::TSInterfaceDeclaration *> &InterfaceDeclarations() 91 { 92 return interfaceDeclarations_; 93 } 94 95 const ArenaSet<ir::TSInterfaceDeclaration *> &InterfaceDeclarations() const 96 { 97 return interfaceDeclarations_; 98 } 99 100 ArenaSet<ir::AnnotationDeclaration *> &AnnotationDeclarations() 101 { 102 return annotationDeclarations_; 103 } 104 105 const ArenaSet<ir::AnnotationDeclaration *> &AnnotationDeclarations() const 106 { 107 return annotationDeclarations_; 108 } 109 110 ArenaVector<FunctionScope *> &Signatures() 111 { 112 return signatures_; 113 } 114 115 const ArenaVector<FunctionScope *> &Signatures() const 116 { 117 return signatures_; 118 } 119 120 void SetClassDefinition(ir::ClassDefinition *classDefinition) 121 { 122 record_ = classDefinition; 123 } 124 125 ir::ClassDefinition *ClassDefinition() 126 { 127 return std::holds_alternative<ir::ClassDefinition *>(record_) ? std::get<ir::ClassDefinition *>(record_) 128 : nullptr; 129 } 130 131 const ir::ClassDefinition *ClassDefinition() const 132 { 133 return std::holds_alternative<ir::ClassDefinition *>(record_) ? std::get<ir::ClassDefinition *>(record_) 134 : nullptr; 135 } 136 137 void SetInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDeclaration) 138 { 139 record_ = interfaceDeclaration; 140 } 141 142 ir::TSInterfaceDeclaration *InterfaceDeclaration() 143 { 144 return std::holds_alternative<ir::TSInterfaceDeclaration *>(record_) 145 ? std::get<ir::TSInterfaceDeclaration *>(record_) 146 : nullptr; 147 } 148 149 const ir::TSInterfaceDeclaration *InterfaceDeclaration() const 150 { 151 return std::holds_alternative<ir::TSInterfaceDeclaration *>(record_) 152 ? std::get<ir::TSInterfaceDeclaration *>(record_) 153 : nullptr; 154 } 155 156 void SetAnnotationDeclaration(ir::AnnotationDeclaration *annotationDeclaration) 157 { 158 record_ = annotationDeclaration; 159 } 160 161 ir::AnnotationDeclaration *AnnotationDeclaration() 162 { 163 return std::holds_alternative<ir::AnnotationDeclaration *>(record_) 164 ? std::get<ir::AnnotationDeclaration *>(record_) 165 : nullptr; 166 } 167 168 const ir::AnnotationDeclaration *AnnotationDeclaration() const 169 { 170 return std::holds_alternative<ir::AnnotationDeclaration *>(record_) 171 ? std::get<ir::AnnotationDeclaration *>(record_) 172 : nullptr; 173 } 174 175 void SetProgram(parser::Program *program) 176 { 177 program_ = program; 178 } 179 180 parser::Program *Program() 181 { 182 return program_; 183 } 184 185 const parser::Program *Program() const 186 { 187 return program_; 188 } 189 190 util::StringView RecordName() const; 191 192 void CleanUp() 193 { 194 classDefinitions_.clear(); 195 interfaceDeclarations_.clear(); 196 annotationDeclarations_.clear(); 197 signatures_.clear(); 198 record_ = nullptr; 199 boundCtx_ = nullptr; 200 flags_ = RecordTableFlags::NONE; 201 } 202 203 private: 204 friend class BoundContext; 205 using RecordHolder = 206 std::variant<ir::ClassDefinition *, ir::TSInterfaceDeclaration *, ir::AnnotationDeclaration *, std::nullptr_t>; 207 208 ArenaSet<ir::ClassDefinition *> classDefinitions_; 209 ArenaSet<ir::TSInterfaceDeclaration *> interfaceDeclarations_; 210 ArenaSet<ir::AnnotationDeclaration *> annotationDeclarations_; 211 ArenaVector<varbinder::FunctionScope *> signatures_; 212 RecordHolder record_ {nullptr}; 213 parser::Program *program_ {}; 214 BoundContext *boundCtx_ {}; 215 RecordTableFlags flags_ {}; 216 }; 217 218 class BoundContext { 219 public: 220 explicit BoundContext(RecordTable *recordTable, ir::ClassDefinition *classDef, bool force = false); 221 explicit BoundContext(RecordTable *recordTable, ir::TSInterfaceDeclaration *interfaceDecl, bool force = false); 222 explicit BoundContext(RecordTable *recordTable, ir::AnnotationDeclaration *annotationDecl, bool force = false); 223 ~BoundContext(); 224 225 NO_COPY_SEMANTIC(BoundContext); 226 NO_MOVE_SEMANTIC(BoundContext); 227 228 void *operator new(size_t) = delete; 229 void *operator new[](size_t) = delete; 230 231 util::StringView FormRecordName() const; 232 233 private: 234 BoundContext *prev_; 235 RecordTable *recordTable_; 236 RecordTable::RecordHolder currentRecord_ {nullptr}; 237 RecordTable::RecordHolder savedRecord_ {nullptr}; 238 ir::Identifier *recordIdent_ {nullptr}; 239 }; 240 241 } // namespace ark::es2panda::varbinder 242 243 #endif // ES2PANDA_VARBINDER_RECORDTABLE_H 244