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