1 /** 2 * Copyright (c) 2021 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_COMPILER_SCOPES_VARIABLE_H 17 #define ES2PANDA_COMPILER_SCOPES_VARIABLE_H 18 19 #include <binder/enumMemberResult.h> 20 #include <binder/variableFlags.h> 21 #include <ir/irnode.h> 22 #include <macros.h> 23 #include <util/patchFix.h> 24 #include <util/ustring.h> 25 26 #include <limits> 27 28 namespace panda::es2panda::checker { 29 class Type; 30 } // namespace panda::es2panda::checker 31 32 namespace panda::es2panda::binder { 33 34 class Decl; 35 class Scope; 36 class VariableScope; 37 class ExportBindings; 38 class Variable; 39 40 using VariableMap = ArenaMap<util::StringView, Variable *>; 41 42 #define DECLARE_CLASSES(type, className) class className; 43 VARIABLE_TYPES(DECLARE_CLASSES) 44 #undef DECLARE_CLASSES 45 46 class Variable { 47 public: 48 virtual ~Variable() = default; 49 NO_COPY_SEMANTIC(Variable); 50 NO_MOVE_SEMANTIC(Variable); 51 52 virtual VariableType Type() const = 0; 53 54 #define DECLARE_CHECKS_CASTS(variableType, className) \ 55 bool Is##className() const \ 56 { \ 57 return Type() == VariableType::variableType; \ 58 } \ 59 className *As##className() \ 60 { \ 61 ASSERT(Is##className()); \ 62 return reinterpret_cast<className *>(this); \ 63 } \ 64 const className *As##className() const \ 65 { \ 66 ASSERT(Is##className()); \ 67 return reinterpret_cast<const className *>(this); \ 68 } 69 VARIABLE_TYPES(DECLARE_CHECKS_CASTS) 70 #undef DECLARE_CHECKS_CASTS 71 Declaration() const72 Decl *Declaration() const 73 { 74 return decl_; 75 } 76 Flags() const77 VariableFlags Flags() const 78 { 79 return flags_; 80 } 81 TsType() const82 checker::Type *TsType() const 83 { 84 return tsType_; 85 } 86 SetTsType(checker::Type *tsType)87 void SetTsType(checker::Type *tsType) 88 { 89 tsType_ = tsType; 90 } 91 AddFlag(VariableFlags flag)92 void AddFlag(VariableFlags flag) 93 { 94 flags_ |= flag; 95 } 96 HasFlag(VariableFlags flag) const97 bool HasFlag(VariableFlags flag) const 98 { 99 return (flags_ & flag) != 0; 100 } 101 RemoveFlag(VariableFlags flag)102 void RemoveFlag(VariableFlags flag) 103 { 104 flags_ &= ~flag; 105 } 106 Reset(Decl *decl, VariableFlags flags)107 void Reset(Decl *decl, VariableFlags flags) 108 { 109 decl_ = decl; 110 flags_ = flags; 111 } 112 LexicalBound() const113 bool LexicalBound() const 114 { 115 return HasFlag(VariableFlags::LEXICAL_BOUND); 116 } 117 InSendableEnv() const118 bool InSendableEnv() const 119 { 120 return HasFlag(VariableFlags::IN_SENDABLE_ENV); 121 } 122 123 const util::StringView &Name() const; 124 virtual void SetLexical(Scope *scope, util::PatchFix *patchFixHelper = nullptr) = 0; 125 126 protected: Variable(Decl *decl, VariableFlags flags)127 explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {} 128 129 Decl *decl_; 130 VariableFlags flags_ {}; 131 checker::Type *tsType_ {}; 132 }; 133 134 class LocalVariable : public Variable { 135 public: 136 explicit LocalVariable(Decl *decl, VariableFlags flags); 137 138 VariableType Type() const override 139 { 140 return VariableType::LOCAL; 141 } 142 BindVReg(compiler::VReg vreg)143 void BindVReg(compiler::VReg vreg) 144 { 145 ASSERT(!LexicalBound()); 146 vreg_ = vreg; 147 } 148 BindLexEnvSlot(uint32_t slot)149 void BindLexEnvSlot(uint32_t slot) 150 { 151 ASSERT(!LexicalBound()); 152 AddFlag(VariableFlags::LEXICAL_BOUND); 153 vreg_ = slot; 154 } 155 Vreg() const156 compiler::VReg Vreg() const 157 { 158 return vreg_; 159 } 160 LexIdx() const161 uint32_t LexIdx() const 162 { 163 ASSERT(LexicalBound()); 164 return vreg_; 165 } 166 167 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 168 LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const; 169 170 private: 171 uint32_t vreg_ {}; 172 }; 173 174 class GlobalVariable : public Variable { 175 public: GlobalVariable(Decl *decl, VariableFlags flags)176 explicit GlobalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 177 178 VariableType Type() const override 179 { 180 return VariableType::GLOBAL; 181 } 182 183 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 184 }; 185 186 class ModuleVariable : public Variable { 187 public: ModuleVariable(Decl *decl, VariableFlags flags)188 explicit ModuleVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 189 190 VariableType Type() const override 191 { 192 return VariableType::MODULE; 193 } 194 195 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 196 AssignIndex(uint32_t index)197 void AssignIndex(uint32_t index) 198 { 199 index_ = index; 200 } 201 Index() const202 uint32_t Index() const 203 { 204 return index_; 205 } 206 207 private: 208 uint32_t index_ {0}; 209 }; 210 211 class EnumVariable : public Variable { 212 public: EnumVariable(Decl *decl, bool backReference = false)213 explicit EnumVariable(Decl *decl, bool backReference = false) 214 : Variable(decl, VariableFlags::NONE), backReference_(backReference) 215 { 216 } 217 218 VariableType Type() const override 219 { 220 return VariableType::ENUM; 221 } 222 SetValue(EnumMemberResult value)223 void SetValue(EnumMemberResult value) 224 { 225 value_ = value; 226 } 227 Value() const228 const EnumMemberResult &Value() const 229 { 230 return value_; 231 } 232 BackReference() const233 bool BackReference() const 234 { 235 return backReference_; 236 } 237 SetBackReference()238 void SetBackReference() 239 { 240 backReference_ = true; 241 } 242 IsVisited() const243 bool IsVisited() const 244 { 245 return isVisited_; 246 } 247 SetVisited()248 void SetVisited() 249 { 250 isVisited_ = true; 251 } 252 StringInit() const253 bool StringInit() const 254 { 255 return isStringInit_; 256 } 257 SetStringInit()258 void SetStringInit() 259 { 260 isStringInit_ = true; 261 } 262 263 void ResetDecl(Decl *decl); 264 265 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 266 267 private: 268 EnumMemberResult value_ {false}; 269 bool backReference_ {}; 270 bool isVisited_ {false}; 271 bool isStringInit_ {false}; 272 }; 273 274 class NamespaceVariable : public Variable { 275 public: NamespaceVariable(Decl *decl, VariableFlags flags)276 explicit NamespaceVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 277 278 VariableType Type() const override 279 { 280 return VariableType::NAMESPACE; 281 } 282 283 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 284 GetExportBindings()285 ExportBindings *GetExportBindings() 286 { 287 return exportBindings_; 288 } 289 GetExportBindings() const290 const ExportBindings *GetExportBindings() const 291 { 292 return exportBindings_; 293 } 294 SetExportBindings(ExportBindings *exportBindings)295 void SetExportBindings(ExportBindings *exportBindings) 296 { 297 exportBindings_ = exportBindings; 298 } 299 300 private: 301 ExportBindings *exportBindings_ {nullptr}; 302 }; 303 304 class EnumLiteralVariable : public Variable { 305 public: EnumLiteralVariable(Decl *decl, VariableFlags flags)306 explicit EnumLiteralVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 307 308 VariableType Type() const override 309 { 310 return VariableType::ENUMLITERAL; 311 } 312 313 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 314 GetEnumMembers() const315 VariableMap *GetEnumMembers() const 316 { 317 return enumMemberBindings_; 318 } 319 FindEnumMemberVariable(const util::StringView &name) const320 Variable *FindEnumMemberVariable(const util::StringView &name) const 321 { 322 auto res = enumMemberBindings_->find(name); 323 if (res == enumMemberBindings_->end()) { 324 return nullptr; 325 } 326 return res->second; 327 } 328 SetEnumMembers(VariableMap *enumMemberBindings)329 void SetEnumMembers(VariableMap *enumMemberBindings) 330 { 331 enumMemberBindings_ = enumMemberBindings; 332 } 333 334 private: 335 VariableMap *enumMemberBindings_ {nullptr}; 336 }; 337 338 class ImportEqualsVariable : public Variable { 339 public: ImportEqualsVariable(Decl *decl, VariableFlags flags)340 explicit ImportEqualsVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 341 342 VariableType Type() const override 343 { 344 return VariableType::IMPORT_EQUALS; 345 } 346 347 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override; 348 GetScope()349 Scope *GetScope() 350 { 351 return scope_; 352 } 353 SetScope(Scope *scope)354 void SetScope(Scope *scope) 355 { 356 scope_ = scope; 357 } 358 359 private: 360 Scope *scope_ {nullptr}; 361 }; 362 363 } // namespace panda::es2panda::binder 364 #endif 365