1 /**
2 * Copyright (c) 2021 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 <binder/enumMemberResult.h>
20 #include <binder/variableFlags.h>
21 #include <ir/irnode.h>
22 #include <macros.h>
23 #include <util/patchFix.h>
24 #include <util/ustring.h>
25
26 #include <limits>
27
28 namespace panda::es2panda::checker {
29 class Type;
30 } // namespace panda::es2panda::checker
31
32 namespace panda::es2panda::binder {
33
34 class Decl;
35 class Scope;
36 class VariableScope;
37 class ExportBindings;
38 class Variable;
39
40 using VariableMap = ArenaMap<util::StringView, Variable *>;
41
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 virtual VariableType Type() const = 0;
53
54 #define DECLARE_CHECKS_CASTS(variableType, className) \
55 bool Is##className() const \
56 { \
57 return Type() == VariableType::variableType; \
58 } \
59 className *As##className() \
60 { \
61 ASSERT(Is##className()); \
62 return reinterpret_cast<className *>(this); \
63 } \
64 const className *As##className() const \
65 { \
66 ASSERT(Is##className()); \
67 return reinterpret_cast<const className *>(this); \
68 }
69 VARIABLE_TYPES(DECLARE_CHECKS_CASTS)
70 #undef DECLARE_CHECKS_CASTS
71
72 Decl *Declaration() const
73 {
74 return decl_;
75 }
76
77 VariableFlags Flags() const
78 {
79 return flags_;
80 }
81
82 checker::Type *TsType() const
83 {
84 return tsType_;
85 }
86
87 void SetTsType(checker::Type *tsType)
88 {
89 tsType_ = tsType;
90 }
91
92 void AddFlag(VariableFlags flag)
93 {
94 flags_ |= flag;
95 }
96
97 bool HasFlag(VariableFlags flag) const
98 {
99 return (flags_ & flag) != 0;
100 }
101
102 void RemoveFlag(VariableFlags flag)
103 {
104 flags_ &= ~flag;
105 }
106
107 void Reset(Decl *decl, VariableFlags flags)
108 {
109 decl_ = decl;
110 flags_ = flags;
111 }
112
113 bool LexicalBound() const
114 {
115 return HasFlag(VariableFlags::LEXICAL_BOUND);
116 }
117
118 bool InSendableEnv() const
119 {
120 return HasFlag(VariableFlags::IN_SENDABLE_ENV);
121 }
122
123 const util::StringView &Name() const;
124 virtual void SetLexical(Scope *scope, util::PatchFix *patchFixHelper = nullptr) = 0;
125
126 protected:
127 explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {}
128
129 Decl *decl_;
130 VariableFlags flags_ {};
131 checker::Type *tsType_ {};
132 };
133
134 class LocalVariable : public Variable {
135 public:
136 explicit LocalVariable(Decl *decl, VariableFlags flags);
137
Type()138 VariableType Type() const override
139 {
140 return VariableType::LOCAL;
141 }
142
BindVReg(compiler::VReg vreg)143 void BindVReg(compiler::VReg vreg)
144 {
145 ASSERT(!LexicalBound());
146 vreg_ = vreg;
147 }
148
BindLexEnvSlot(uint32_t slot)149 void BindLexEnvSlot(uint32_t slot)
150 {
151 ASSERT(!LexicalBound());
152 AddFlag(VariableFlags::LEXICAL_BOUND);
153 vreg_ = slot;
154 }
155
Vreg()156 compiler::VReg Vreg() const
157 {
158 return vreg_;
159 }
160
LexIdx()161 uint32_t LexIdx() const
162 {
163 ASSERT(LexicalBound());
164 return vreg_;
165 }
166
167 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
168 LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const;
169
170 private:
171 uint32_t vreg_ {};
172 };
173
174 class GlobalVariable : public Variable {
175 public:
GlobalVariable(Decl * decl,VariableFlags flags)176 explicit GlobalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
177
Type()178 VariableType Type() const override
179 {
180 return VariableType::GLOBAL;
181 }
182
183 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
184 };
185
186 class ModuleVariable : public Variable {
187 public:
ModuleVariable(Decl * decl,VariableFlags flags)188 explicit ModuleVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
189
Type()190 VariableType Type() const override
191 {
192 return VariableType::MODULE;
193 }
194
195 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
196
AssignIndex(uint32_t index)197 void AssignIndex(uint32_t index)
198 {
199 index_ = index;
200 }
201
Index()202 uint32_t Index() const
203 {
204 return index_;
205 }
206
207 private:
208 uint32_t index_ {0};
209 };
210
211 class EnumVariable : public Variable {
212 public:
213 explicit EnumVariable(Decl *decl, bool backReference = false)
Variable(decl,VariableFlags::NONE)214 : Variable(decl, VariableFlags::NONE), backReference_(backReference)
215 {
216 }
217
Type()218 VariableType Type() const override
219 {
220 return VariableType::ENUM;
221 }
222
SetValue(EnumMemberResult value)223 void SetValue(EnumMemberResult value)
224 {
225 value_ = value;
226 }
227
Value()228 const EnumMemberResult &Value() const
229 {
230 return value_;
231 }
232
BackReference()233 bool BackReference() const
234 {
235 return backReference_;
236 }
237
SetBackReference()238 void SetBackReference()
239 {
240 backReference_ = true;
241 }
242
IsVisited()243 bool IsVisited() const
244 {
245 return isVisited_;
246 }
247
SetVisited()248 void SetVisited()
249 {
250 isVisited_ = true;
251 }
252
StringInit()253 bool StringInit() const
254 {
255 return isStringInit_;
256 }
257
SetStringInit()258 void SetStringInit()
259 {
260 isStringInit_ = true;
261 }
262
263 void ResetDecl(Decl *decl);
264
265 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
266
267 private:
268 EnumMemberResult value_ {false};
269 bool backReference_ {};
270 bool isVisited_ {false};
271 bool isStringInit_ {false};
272 };
273
274 class NamespaceVariable : public Variable {
275 public:
NamespaceVariable(Decl * decl,VariableFlags flags)276 explicit NamespaceVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
277
Type()278 VariableType Type() const override
279 {
280 return VariableType::NAMESPACE;
281 }
282
283 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
284
GetExportBindings()285 ExportBindings *GetExportBindings()
286 {
287 return exportBindings_;
288 }
289
GetExportBindings()290 const ExportBindings *GetExportBindings() const
291 {
292 return exportBindings_;
293 }
294
SetExportBindings(ExportBindings * exportBindings)295 void SetExportBindings(ExportBindings *exportBindings)
296 {
297 exportBindings_ = exportBindings;
298 }
299
300 private:
301 ExportBindings *exportBindings_ {nullptr};
302 };
303
304 class EnumLiteralVariable : public Variable {
305 public:
EnumLiteralVariable(Decl * decl,VariableFlags flags)306 explicit EnumLiteralVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
307
Type()308 VariableType Type() const override
309 {
310 return VariableType::ENUMLITERAL;
311 }
312
313 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
314
GetEnumMembers()315 VariableMap *GetEnumMembers() const
316 {
317 return enumMemberBindings_;
318 }
319
FindEnumMemberVariable(const util::StringView & name)320 Variable *FindEnumMemberVariable(const util::StringView &name) const
321 {
322 auto res = enumMemberBindings_->find(name);
323 if (res == enumMemberBindings_->end()) {
324 return nullptr;
325 }
326 return res->second;
327 }
328
SetEnumMembers(VariableMap * enumMemberBindings)329 void SetEnumMembers(VariableMap *enumMemberBindings)
330 {
331 enumMemberBindings_ = enumMemberBindings;
332 }
333
334 private:
335 VariableMap *enumMemberBindings_ {nullptr};
336 };
337
338 class ImportEqualsVariable : public Variable {
339 public:
ImportEqualsVariable(Decl * decl,VariableFlags flags)340 explicit ImportEqualsVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
341
Type()342 VariableType Type() const override
343 {
344 return VariableType::IMPORT_EQUALS;
345 }
346
347 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
348
GetScope()349 Scope *GetScope()
350 {
351 return scope_;
352 }
353
SetScope(Scope * scope)354 void SetScope(Scope *scope)
355 {
356 scope_ = scope;
357 }
358
359 private:
360 Scope *scope_ {nullptr};
361 };
362
363 } // namespace panda::es2panda::binder
364 #endif
365