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;
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 // 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
88 [[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:
146 explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(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
Type()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()182 compiler::VReg Vreg() const
183 {
184 return vreg_;
185 }
186
Vreg()187 compiler::VReg &Vreg()
188 {
189 return vreg_;
190 }
191
LexIdx()192 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
Type()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
Type()221 VariableType Type() const override
222 {
223 return VariableType::MODULE;
224 }
225
ModuleReg()226 compiler::VReg &ModuleReg()
227 {
228 return moduleReg_;
229 }
230
ModuleReg()231 compiler::VReg ModuleReg() const
232 {
233 return moduleReg_;
234 }
235
ExoticName()236 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:
255 explicit EnumVariable(Decl *decl, bool backReference = false)
Variable(decl,VariableFlags::NONE)256 : Variable(decl, VariableFlags::NONE), backReference_(backReference)
257 {
258 }
259
Type()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()270 const EnumMemberResult &Value() const
271 {
272 return value_;
273 }
274
BackReference()275 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