1 /** 2 * Copyright (c) 2021-2024 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 "varbinder/enumMemberResult.h" 20 #include "varbinder/variableFlags.h" 21 #include "ir/irnode.h" 22 #include "macros.h" 23 #include "util/ustring.h" 24 25 #include <limits> 26 27 namespace ark::es2panda::checker { 28 class Type; 29 enum class PropertyType; 30 // NOLINTBEGIN(readability-redundant-declaration) 31 bool IsTypeError(Type const *tp); 32 [[noreturn]] void ThrowEmptyError(); 33 // NOLINTEND(readability-redundant-declaration) 34 } // namespace ark::es2panda::checker 35 36 namespace ark::es2panda::varbinder { 37 class Decl; 38 class Scope; 39 class VariableScope; 40 41 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 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 VariableType virtual Type() const = 0; 53 54 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 55 #define DECLARE_CHECKS_CASTS(variableType, className) \ 56 bool Is##className() const \ 57 { \ 58 return Type() == VariableType::variableType; \ 59 } \ 60 className *As##className() \ 61 { \ 62 ASSERT(Is##className()); \ 63 return reinterpret_cast<className *>(this); \ 64 } \ 65 const className *As##className() const \ 66 { \ 67 ASSERT(Is##className()); \ 68 return reinterpret_cast<const className *>(this); \ 69 } 70 VARIABLE_TYPES(DECLARE_CHECKS_CASTS) 71 #undef DECLARE_CHECKS_CASTS 72 73 [[nodiscard]] const Decl *Declaration() const noexcept 74 { 75 return decl_; 76 } 77 78 [[nodiscard]] Decl *Declaration() noexcept 79 { 80 return decl_; 81 } 82 83 [[nodiscard]] VariableFlags Flags() const noexcept 84 { 85 return flags_; 86 } 87 TsType() const88 [[nodiscard]] checker::Type *TsType() const 89 { 90 if (UNLIKELY(IsTypeError(tsType_))) { 91 checker::ThrowEmptyError(); 92 } 93 return tsType_; 94 } 95 96 [[nodiscard]] checker::Type *TsTypeOrError() const noexcept 97 { 98 return tsType_; 99 } 100 101 [[nodiscard]] Scope *GetScope() const noexcept 102 { 103 return scope_; 104 } 105 106 void SetTsType(checker::Type *tsType) noexcept 107 { 108 tsType_ = tsType; 109 } 110 111 void SetScope(varbinder::Scope *scope) noexcept 112 { 113 scope_ = scope; 114 } 115 116 void AddFlag(VariableFlags flag) noexcept 117 { 118 flags_ |= flag; 119 } 120 121 [[nodiscard]] bool HasFlag(VariableFlags flag) const noexcept 122 { 123 return (flags_ & flag) != 0; 124 } 125 126 void RemoveFlag(VariableFlags flag) noexcept 127 { 128 flags_ &= ~flag; 129 } 130 131 void Reset(Decl *decl, VariableFlags flags) noexcept 132 { 133 decl_ = decl; 134 flags_ = flags; 135 } 136 137 [[nodiscard]] bool LexicalBound() const noexcept 138 { 139 return HasFlag(VariableFlags::LEXICAL_BOUND); 140 } 141 142 [[nodiscard]] const util::StringView &Name() const; 143 virtual void SetLexical(Scope *scope) = 0; 144 145 protected: Variable(Decl *decl, VariableFlags flags)146 explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {} Variable(VariableFlags flags)147 explicit Variable(VariableFlags flags) : flags_(flags) {} 148 149 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 150 Decl *decl_ {}; 151 VariableFlags flags_ {}; 152 // NOLINTEND(misc-non-private-member-variables-in-classes) 153 154 private: 155 checker::Type *tsType_ {}; 156 Scope *scope_ {}; 157 }; 158 159 class LocalVariable : public Variable { 160 public: 161 explicit LocalVariable(Decl *decl, VariableFlags flags); 162 explicit LocalVariable(VariableFlags flags); 163 164 VariableType Type() const override 165 { 166 return VariableType::LOCAL; 167 } 168 BindVReg(compiler::VReg vreg)169 void BindVReg(compiler::VReg vreg) 170 { 171 ASSERT(!LexicalBound()); 172 vreg_ = vreg; 173 } 174 BindLexEnvSlot(uint32_t slot)175 void BindLexEnvSlot(uint32_t slot) 176 { 177 ASSERT(!LexicalBound()); 178 AddFlag(VariableFlags::LEXICAL_BOUND); 179 vreg_.SetIndex(slot); 180 } 181 Vreg() const182 compiler::VReg Vreg() const 183 { 184 return vreg_; 185 } 186 Vreg()187 compiler::VReg &Vreg() 188 { 189 return vreg_; 190 } 191 LexIdx() const192 uint32_t LexIdx() const 193 { 194 ASSERT(LexicalBound()); 195 return vreg_.GetIndex(); 196 } 197 198 void SetLexical([[maybe_unused]] Scope *scope) override; 199 LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const; 200 201 private: 202 compiler::VReg vreg_ {}; 203 }; 204 205 class GlobalVariable : public Variable { 206 public: GlobalVariable(Decl *decl, VariableFlags flags)207 explicit GlobalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 208 209 VariableType Type() const override 210 { 211 return VariableType::GLOBAL; 212 } 213 214 void SetLexical([[maybe_unused]] Scope *scope) override; 215 }; 216 217 class ModuleVariable : public Variable { 218 public: ModuleVariable(Decl *decl, VariableFlags flags)219 explicit ModuleVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 220 221 VariableType Type() const override 222 { 223 return VariableType::MODULE; 224 } 225 ModuleReg()226 compiler::VReg &ModuleReg() 227 { 228 return moduleReg_; 229 } 230 ModuleReg() const231 compiler::VReg ModuleReg() const 232 { 233 return moduleReg_; 234 } 235 ExoticName() const236 const util::StringView &ExoticName() const 237 { 238 return exoticName_; 239 } 240 ExoticName()241 util::StringView &ExoticName() 242 { 243 return exoticName_; 244 } 245 246 void SetLexical([[maybe_unused]] Scope *scope) override; 247 248 private: 249 compiler::VReg moduleReg_ {}; 250 util::StringView exoticName_ {}; 251 }; 252 253 class EnumVariable : public Variable { 254 public: EnumVariable(Decl *decl, bool backReference = false)255 explicit EnumVariable(Decl *decl, bool backReference = false) 256 : Variable(decl, VariableFlags::NONE), backReference_(backReference) 257 { 258 } 259 260 VariableType Type() const override 261 { 262 return VariableType::ENUM; 263 } 264 SetValue(EnumMemberResult value)265 void SetValue(EnumMemberResult value) 266 { 267 value_ = value; 268 } 269 Value() const270 const EnumMemberResult &Value() const 271 { 272 return value_; 273 } 274 BackReference() const275 bool BackReference() const 276 { 277 return backReference_; 278 } 279 SetBackReference()280 void SetBackReference() 281 { 282 backReference_ = true; 283 } 284 285 void ResetDecl(Decl *decl); 286 287 void SetLexical([[maybe_unused]] Scope *scope) override; 288 289 private: 290 EnumMemberResult value_ {}; 291 bool backReference_ {}; 292 }; 293 } // namespace ark::es2panda::varbinder 294 #endif 295