13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#ifndef ES2PANDA_COMPILER_SCOPES_VARIABLE_H 173af6ab5fSopenharmony_ci#define ES2PANDA_COMPILER_SCOPES_VARIABLE_H 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_ci#include "varbinder/enumMemberResult.h" 203af6ab5fSopenharmony_ci#include "varbinder/variableFlags.h" 213af6ab5fSopenharmony_ci#include "ir/irnode.h" 223af6ab5fSopenharmony_ci#include "macros.h" 233af6ab5fSopenharmony_ci#include "util/ustring.h" 243af6ab5fSopenharmony_ci 253af6ab5fSopenharmony_ci#include <limits> 263af6ab5fSopenharmony_ci 273af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 283af6ab5fSopenharmony_ciclass Type; 293af6ab5fSopenharmony_cienum class PropertyType; 303af6ab5fSopenharmony_ci// NOLINTBEGIN(readability-redundant-declaration) 313af6ab5fSopenharmony_cibool IsTypeError(Type const *tp); 323af6ab5fSopenharmony_ci[[noreturn]] void ThrowEmptyError(); 333af6ab5fSopenharmony_ci// NOLINTEND(readability-redundant-declaration) 343af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 353af6ab5fSopenharmony_ci 363af6ab5fSopenharmony_cinamespace ark::es2panda::varbinder { 373af6ab5fSopenharmony_ciclass Decl; 383af6ab5fSopenharmony_ciclass Scope; 393af6ab5fSopenharmony_ciclass VariableScope; 403af6ab5fSopenharmony_ci 413af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 423af6ab5fSopenharmony_ci#define DECLARE_CLASSES(type, className) class className; 433af6ab5fSopenharmony_ciVARIABLE_TYPES(DECLARE_CLASSES) 443af6ab5fSopenharmony_ci#undef DECLARE_CLASSES 453af6ab5fSopenharmony_ci 463af6ab5fSopenharmony_ciclass Variable { 473af6ab5fSopenharmony_cipublic: 483af6ab5fSopenharmony_ci virtual ~Variable() = default; 493af6ab5fSopenharmony_ci NO_COPY_SEMANTIC(Variable); 503af6ab5fSopenharmony_ci NO_MOVE_SEMANTIC(Variable); 513af6ab5fSopenharmony_ci 523af6ab5fSopenharmony_ci VariableType virtual Type() const = 0; 533af6ab5fSopenharmony_ci 543af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 553af6ab5fSopenharmony_ci#define DECLARE_CHECKS_CASTS(variableType, className) \ 563af6ab5fSopenharmony_ci bool Is##className() const \ 573af6ab5fSopenharmony_ci { \ 583af6ab5fSopenharmony_ci return Type() == VariableType::variableType; \ 593af6ab5fSopenharmony_ci } \ 603af6ab5fSopenharmony_ci className *As##className() \ 613af6ab5fSopenharmony_ci { \ 623af6ab5fSopenharmony_ci ASSERT(Is##className()); \ 633af6ab5fSopenharmony_ci return reinterpret_cast<className *>(this); \ 643af6ab5fSopenharmony_ci } \ 653af6ab5fSopenharmony_ci const className *As##className() const \ 663af6ab5fSopenharmony_ci { \ 673af6ab5fSopenharmony_ci ASSERT(Is##className()); \ 683af6ab5fSopenharmony_ci return reinterpret_cast<const className *>(this); \ 693af6ab5fSopenharmony_ci } 703af6ab5fSopenharmony_ci VARIABLE_TYPES(DECLARE_CHECKS_CASTS) 713af6ab5fSopenharmony_ci#undef DECLARE_CHECKS_CASTS 723af6ab5fSopenharmony_ci 733af6ab5fSopenharmony_ci [[nodiscard]] const Decl *Declaration() const noexcept 743af6ab5fSopenharmony_ci { 753af6ab5fSopenharmony_ci return decl_; 763af6ab5fSopenharmony_ci } 773af6ab5fSopenharmony_ci 783af6ab5fSopenharmony_ci [[nodiscard]] Decl *Declaration() noexcept 793af6ab5fSopenharmony_ci { 803af6ab5fSopenharmony_ci return decl_; 813af6ab5fSopenharmony_ci } 823af6ab5fSopenharmony_ci 833af6ab5fSopenharmony_ci [[nodiscard]] VariableFlags Flags() const noexcept 843af6ab5fSopenharmony_ci { 853af6ab5fSopenharmony_ci return flags_; 863af6ab5fSopenharmony_ci } 873af6ab5fSopenharmony_ci 883af6ab5fSopenharmony_ci [[nodiscard]] checker::Type *TsType() const 893af6ab5fSopenharmony_ci { 903af6ab5fSopenharmony_ci if (UNLIKELY(IsTypeError(tsType_))) { 913af6ab5fSopenharmony_ci checker::ThrowEmptyError(); 923af6ab5fSopenharmony_ci } 933af6ab5fSopenharmony_ci return tsType_; 943af6ab5fSopenharmony_ci } 953af6ab5fSopenharmony_ci 963af6ab5fSopenharmony_ci [[nodiscard]] checker::Type *TsTypeOrError() const noexcept 973af6ab5fSopenharmony_ci { 983af6ab5fSopenharmony_ci return tsType_; 993af6ab5fSopenharmony_ci } 1003af6ab5fSopenharmony_ci 1013af6ab5fSopenharmony_ci [[nodiscard]] Scope *GetScope() const noexcept 1023af6ab5fSopenharmony_ci { 1033af6ab5fSopenharmony_ci return scope_; 1043af6ab5fSopenharmony_ci } 1053af6ab5fSopenharmony_ci 1063af6ab5fSopenharmony_ci void SetTsType(checker::Type *tsType) noexcept 1073af6ab5fSopenharmony_ci { 1083af6ab5fSopenharmony_ci tsType_ = tsType; 1093af6ab5fSopenharmony_ci } 1103af6ab5fSopenharmony_ci 1113af6ab5fSopenharmony_ci void SetScope(varbinder::Scope *scope) noexcept 1123af6ab5fSopenharmony_ci { 1133af6ab5fSopenharmony_ci scope_ = scope; 1143af6ab5fSopenharmony_ci } 1153af6ab5fSopenharmony_ci 1163af6ab5fSopenharmony_ci void AddFlag(VariableFlags flag) noexcept 1173af6ab5fSopenharmony_ci { 1183af6ab5fSopenharmony_ci flags_ |= flag; 1193af6ab5fSopenharmony_ci } 1203af6ab5fSopenharmony_ci 1213af6ab5fSopenharmony_ci [[nodiscard]] bool HasFlag(VariableFlags flag) const noexcept 1223af6ab5fSopenharmony_ci { 1233af6ab5fSopenharmony_ci return (flags_ & flag) != 0; 1243af6ab5fSopenharmony_ci } 1253af6ab5fSopenharmony_ci 1263af6ab5fSopenharmony_ci void RemoveFlag(VariableFlags flag) noexcept 1273af6ab5fSopenharmony_ci { 1283af6ab5fSopenharmony_ci flags_ &= ~flag; 1293af6ab5fSopenharmony_ci } 1303af6ab5fSopenharmony_ci 1313af6ab5fSopenharmony_ci void Reset(Decl *decl, VariableFlags flags) noexcept 1323af6ab5fSopenharmony_ci { 1333af6ab5fSopenharmony_ci decl_ = decl; 1343af6ab5fSopenharmony_ci flags_ = flags; 1353af6ab5fSopenharmony_ci } 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_ci [[nodiscard]] bool LexicalBound() const noexcept 1383af6ab5fSopenharmony_ci { 1393af6ab5fSopenharmony_ci return HasFlag(VariableFlags::LEXICAL_BOUND); 1403af6ab5fSopenharmony_ci } 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_ci [[nodiscard]] const util::StringView &Name() const; 1433af6ab5fSopenharmony_ci virtual void SetLexical(Scope *scope) = 0; 1443af6ab5fSopenharmony_ci 1453af6ab5fSopenharmony_ciprotected: 1463af6ab5fSopenharmony_ci explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {} 1473af6ab5fSopenharmony_ci explicit Variable(VariableFlags flags) : flags_(flags) {} 1483af6ab5fSopenharmony_ci 1493af6ab5fSopenharmony_ci // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 1503af6ab5fSopenharmony_ci Decl *decl_ {}; 1513af6ab5fSopenharmony_ci VariableFlags flags_ {}; 1523af6ab5fSopenharmony_ci // NOLINTEND(misc-non-private-member-variables-in-classes) 1533af6ab5fSopenharmony_ci 1543af6ab5fSopenharmony_ciprivate: 1553af6ab5fSopenharmony_ci checker::Type *tsType_ {}; 1563af6ab5fSopenharmony_ci Scope *scope_ {}; 1573af6ab5fSopenharmony_ci}; 1583af6ab5fSopenharmony_ci 1593af6ab5fSopenharmony_ciclass LocalVariable : public Variable { 1603af6ab5fSopenharmony_cipublic: 1613af6ab5fSopenharmony_ci explicit LocalVariable(Decl *decl, VariableFlags flags); 1623af6ab5fSopenharmony_ci explicit LocalVariable(VariableFlags flags); 1633af6ab5fSopenharmony_ci 1643af6ab5fSopenharmony_ci VariableType Type() const override 1653af6ab5fSopenharmony_ci { 1663af6ab5fSopenharmony_ci return VariableType::LOCAL; 1673af6ab5fSopenharmony_ci } 1683af6ab5fSopenharmony_ci 1693af6ab5fSopenharmony_ci void BindVReg(compiler::VReg vreg) 1703af6ab5fSopenharmony_ci { 1713af6ab5fSopenharmony_ci ASSERT(!LexicalBound()); 1723af6ab5fSopenharmony_ci vreg_ = vreg; 1733af6ab5fSopenharmony_ci } 1743af6ab5fSopenharmony_ci 1753af6ab5fSopenharmony_ci void BindLexEnvSlot(uint32_t slot) 1763af6ab5fSopenharmony_ci { 1773af6ab5fSopenharmony_ci ASSERT(!LexicalBound()); 1783af6ab5fSopenharmony_ci AddFlag(VariableFlags::LEXICAL_BOUND); 1793af6ab5fSopenharmony_ci vreg_.SetIndex(slot); 1803af6ab5fSopenharmony_ci } 1813af6ab5fSopenharmony_ci 1823af6ab5fSopenharmony_ci compiler::VReg Vreg() const 1833af6ab5fSopenharmony_ci { 1843af6ab5fSopenharmony_ci return vreg_; 1853af6ab5fSopenharmony_ci } 1863af6ab5fSopenharmony_ci 1873af6ab5fSopenharmony_ci compiler::VReg &Vreg() 1883af6ab5fSopenharmony_ci { 1893af6ab5fSopenharmony_ci return vreg_; 1903af6ab5fSopenharmony_ci } 1913af6ab5fSopenharmony_ci 1923af6ab5fSopenharmony_ci uint32_t LexIdx() const 1933af6ab5fSopenharmony_ci { 1943af6ab5fSopenharmony_ci ASSERT(LexicalBound()); 1953af6ab5fSopenharmony_ci return vreg_.GetIndex(); 1963af6ab5fSopenharmony_ci } 1973af6ab5fSopenharmony_ci 1983af6ab5fSopenharmony_ci void SetLexical([[maybe_unused]] Scope *scope) override; 1993af6ab5fSopenharmony_ci LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const; 2003af6ab5fSopenharmony_ci 2013af6ab5fSopenharmony_ciprivate: 2023af6ab5fSopenharmony_ci compiler::VReg vreg_ {}; 2033af6ab5fSopenharmony_ci}; 2043af6ab5fSopenharmony_ci 2053af6ab5fSopenharmony_ciclass GlobalVariable : public Variable { 2063af6ab5fSopenharmony_cipublic: 2073af6ab5fSopenharmony_ci explicit GlobalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 2083af6ab5fSopenharmony_ci 2093af6ab5fSopenharmony_ci VariableType Type() const override 2103af6ab5fSopenharmony_ci { 2113af6ab5fSopenharmony_ci return VariableType::GLOBAL; 2123af6ab5fSopenharmony_ci } 2133af6ab5fSopenharmony_ci 2143af6ab5fSopenharmony_ci void SetLexical([[maybe_unused]] Scope *scope) override; 2153af6ab5fSopenharmony_ci}; 2163af6ab5fSopenharmony_ci 2173af6ab5fSopenharmony_ciclass ModuleVariable : public Variable { 2183af6ab5fSopenharmony_cipublic: 2193af6ab5fSopenharmony_ci explicit ModuleVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} 2203af6ab5fSopenharmony_ci 2213af6ab5fSopenharmony_ci VariableType Type() const override 2223af6ab5fSopenharmony_ci { 2233af6ab5fSopenharmony_ci return VariableType::MODULE; 2243af6ab5fSopenharmony_ci } 2253af6ab5fSopenharmony_ci 2263af6ab5fSopenharmony_ci compiler::VReg &ModuleReg() 2273af6ab5fSopenharmony_ci { 2283af6ab5fSopenharmony_ci return moduleReg_; 2293af6ab5fSopenharmony_ci } 2303af6ab5fSopenharmony_ci 2313af6ab5fSopenharmony_ci compiler::VReg ModuleReg() const 2323af6ab5fSopenharmony_ci { 2333af6ab5fSopenharmony_ci return moduleReg_; 2343af6ab5fSopenharmony_ci } 2353af6ab5fSopenharmony_ci 2363af6ab5fSopenharmony_ci const util::StringView &ExoticName() const 2373af6ab5fSopenharmony_ci { 2383af6ab5fSopenharmony_ci return exoticName_; 2393af6ab5fSopenharmony_ci } 2403af6ab5fSopenharmony_ci 2413af6ab5fSopenharmony_ci util::StringView &ExoticName() 2423af6ab5fSopenharmony_ci { 2433af6ab5fSopenharmony_ci return exoticName_; 2443af6ab5fSopenharmony_ci } 2453af6ab5fSopenharmony_ci 2463af6ab5fSopenharmony_ci void SetLexical([[maybe_unused]] Scope *scope) override; 2473af6ab5fSopenharmony_ci 2483af6ab5fSopenharmony_ciprivate: 2493af6ab5fSopenharmony_ci compiler::VReg moduleReg_ {}; 2503af6ab5fSopenharmony_ci util::StringView exoticName_ {}; 2513af6ab5fSopenharmony_ci}; 2523af6ab5fSopenharmony_ci 2533af6ab5fSopenharmony_ciclass EnumVariable : public Variable { 2543af6ab5fSopenharmony_cipublic: 2553af6ab5fSopenharmony_ci explicit EnumVariable(Decl *decl, bool backReference = false) 2563af6ab5fSopenharmony_ci : Variable(decl, VariableFlags::NONE), backReference_(backReference) 2573af6ab5fSopenharmony_ci { 2583af6ab5fSopenharmony_ci } 2593af6ab5fSopenharmony_ci 2603af6ab5fSopenharmony_ci VariableType Type() const override 2613af6ab5fSopenharmony_ci { 2623af6ab5fSopenharmony_ci return VariableType::ENUM; 2633af6ab5fSopenharmony_ci } 2643af6ab5fSopenharmony_ci 2653af6ab5fSopenharmony_ci void SetValue(EnumMemberResult value) 2663af6ab5fSopenharmony_ci { 2673af6ab5fSopenharmony_ci value_ = value; 2683af6ab5fSopenharmony_ci } 2693af6ab5fSopenharmony_ci 2703af6ab5fSopenharmony_ci const EnumMemberResult &Value() const 2713af6ab5fSopenharmony_ci { 2723af6ab5fSopenharmony_ci return value_; 2733af6ab5fSopenharmony_ci } 2743af6ab5fSopenharmony_ci 2753af6ab5fSopenharmony_ci bool BackReference() const 2763af6ab5fSopenharmony_ci { 2773af6ab5fSopenharmony_ci return backReference_; 2783af6ab5fSopenharmony_ci } 2793af6ab5fSopenharmony_ci 2803af6ab5fSopenharmony_ci void SetBackReference() 2813af6ab5fSopenharmony_ci { 2823af6ab5fSopenharmony_ci backReference_ = true; 2833af6ab5fSopenharmony_ci } 2843af6ab5fSopenharmony_ci 2853af6ab5fSopenharmony_ci void ResetDecl(Decl *decl); 2863af6ab5fSopenharmony_ci 2873af6ab5fSopenharmony_ci void SetLexical([[maybe_unused]] Scope *scope) override; 2883af6ab5fSopenharmony_ci 2893af6ab5fSopenharmony_ciprivate: 2903af6ab5fSopenharmony_ci EnumMemberResult value_ {}; 2913af6ab5fSopenharmony_ci bool backReference_ {}; 2923af6ab5fSopenharmony_ci}; 2933af6ab5fSopenharmony_ci} // namespace ark::es2panda::varbinder 2943af6ab5fSopenharmony_ci#endif 295