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;
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 
Declaration() const72     Decl *Declaration() const
73     {
74         return decl_;
75     }
76 
Flags() const77     VariableFlags Flags() const
78     {
79         return flags_;
80     }
81 
TsType() const82     checker::Type *TsType() const
83     {
84         return tsType_;
85     }
86 
SetTsType(checker::Type *tsType)87     void SetTsType(checker::Type *tsType)
88     {
89         tsType_ = tsType;
90     }
91 
AddFlag(VariableFlags flag)92     void AddFlag(VariableFlags flag)
93     {
94         flags_ |= flag;
95     }
96 
HasFlag(VariableFlags flag) const97     bool HasFlag(VariableFlags flag) const
98     {
99         return (flags_ & flag) != 0;
100     }
101 
RemoveFlag(VariableFlags flag)102     void RemoveFlag(VariableFlags flag)
103     {
104         flags_ &= ~flag;
105     }
106 
Reset(Decl *decl, VariableFlags flags)107     void Reset(Decl *decl, VariableFlags flags)
108     {
109         decl_ = decl;
110         flags_ = flags;
111     }
112 
LexicalBound() const113     bool LexicalBound() const
114     {
115         return HasFlag(VariableFlags::LEXICAL_BOUND);
116     }
117 
InSendableEnv() const118     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:
Variable(Decl *decl, VariableFlags flags)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 
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() const156     compiler::VReg Vreg() const
157     {
158         return vreg_;
159     }
160 
LexIdx() const161     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 
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 
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() const202     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:
EnumVariable(Decl *decl, bool backReference = false)213     explicit EnumVariable(Decl *decl, bool backReference = false)
214         : Variable(decl, VariableFlags::NONE), backReference_(backReference)
215     {
216     }
217 
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() const228     const EnumMemberResult &Value() const
229     {
230         return value_;
231     }
232 
BackReference() const233     bool BackReference() const
234     {
235         return backReference_;
236     }
237 
SetBackReference()238     void SetBackReference()
239     {
240         backReference_ = true;
241     }
242 
IsVisited() const243     bool IsVisited() const
244     {
245         return isVisited_;
246     }
247 
SetVisited()248     void SetVisited()
249     {
250         isVisited_ = true;
251     }
252 
StringInit() const253     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 
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() const290     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 
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() const315     VariableMap *GetEnumMembers() const
316     {
317         return enumMemberBindings_;
318     }
319 
FindEnumMemberVariable(const util::StringView &name) const320     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 
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