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