• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = ArenaUnorderedMap<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     const util::StringView &Name() const;
119     virtual void SetLexical(Scope *scope, util::PatchFix *patchFixHelper = nullptr) = 0;
120 
121 protected:
122     explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {}
123 
124     Decl *decl_;
125     VariableFlags flags_ {};
126     checker::Type *tsType_ {};
127 };
128 
129 class LocalVariable : public Variable {
130 public:
131     explicit LocalVariable(Decl *decl, VariableFlags flags);
132 
Type()133     VariableType Type() const override
134     {
135         return VariableType::LOCAL;
136     }
137 
BindVReg(compiler::VReg vreg)138     void BindVReg(compiler::VReg vreg)
139     {
140         ASSERT(!LexicalBound());
141         vreg_ = vreg;
142     }
143 
BindLexEnvSlot(uint32_t slot)144     void BindLexEnvSlot(uint32_t slot)
145     {
146         ASSERT(!LexicalBound());
147         AddFlag(VariableFlags::LEXICAL_BOUND);
148         vreg_ = slot;
149     }
150 
Vreg()151     compiler::VReg Vreg() const
152     {
153         return vreg_;
154     }
155 
LexIdx()156     uint32_t LexIdx() const
157     {
158         ASSERT(LexicalBound());
159         return vreg_;
160     }
161 
162     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
163     LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const;
164 
165 private:
166     uint32_t vreg_ {};
167 };
168 
169 class GlobalVariable : public Variable {
170 public:
GlobalVariable(Decl * decl,VariableFlags flags)171     explicit GlobalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
172 
Type()173     VariableType Type() const override
174     {
175         return VariableType::GLOBAL;
176     }
177 
178     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
179 };
180 
181 class ModuleVariable : public Variable {
182 public:
ModuleVariable(Decl * decl,VariableFlags flags)183     explicit ModuleVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
184 
Type()185     VariableType Type() const override
186     {
187         return VariableType::MODULE;
188     }
189 
190     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
191 
AssignIndex(uint32_t index)192     void AssignIndex(uint32_t index)
193     {
194         index_ = index;
195     }
196 
Index()197     uint32_t Index() const
198     {
199         return index_;
200     }
201 
202 private:
203     uint32_t index_;
204 };
205 
206 class EnumVariable : public Variable {
207 public:
208     explicit EnumVariable(Decl *decl, bool backReference = false)
Variable(decl,VariableFlags::NONE)209         : Variable(decl, VariableFlags::NONE), backReference_(backReference)
210     {
211     }
212 
Type()213     VariableType Type() const override
214     {
215         return VariableType::ENUM;
216     }
217 
SetValue(EnumMemberResult value)218     void SetValue(EnumMemberResult value)
219     {
220         value_ = value;
221     }
222 
Value()223     const EnumMemberResult &Value() const
224     {
225         return value_;
226     }
227 
BackReference()228     bool BackReference() const
229     {
230         return backReference_;
231     }
232 
SetBackReference()233     void SetBackReference()
234     {
235         backReference_ = true;
236     }
237 
IsVisited()238     bool IsVisited() const
239     {
240         return isVisited_;
241     }
242 
SetVisited()243     void SetVisited()
244     {
245         isVisited_ = true;
246     }
247 
StringInit()248     bool StringInit() const
249     {
250         return isStringInit_;
251     }
252 
SetStringInit()253     void SetStringInit()
254     {
255         isStringInit_ = true;
256     }
257 
258     void ResetDecl(Decl *decl);
259 
260     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
261 
262 private:
263     EnumMemberResult value_ {false};
264     bool backReference_ {};
265     bool isVisited_ {false};
266     bool isStringInit_ {false};
267 };
268 
269 class NamespaceVariable : public Variable {
270 public:
NamespaceVariable(Decl * decl,VariableFlags flags)271     explicit NamespaceVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
272 
Type()273     VariableType Type() const override
274     {
275         return VariableType::NAMESPACE;
276     }
277 
278     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
279 
GetExportBindings()280     ExportBindings *GetExportBindings()
281     {
282         return exportBindings_;
283     }
284 
GetExportBindings()285     const ExportBindings *GetExportBindings() const
286     {
287         return exportBindings_;
288     }
289 
SetExportBindings(ExportBindings * exportBindings)290     void SetExportBindings(ExportBindings *exportBindings)
291     {
292         exportBindings_ = exportBindings;
293     }
294 
295 private:
296     ExportBindings *exportBindings_ {nullptr};
297 };
298 
299 class EnumLiteralVariable : public Variable {
300 public:
EnumLiteralVariable(Decl * decl,VariableFlags flags)301     explicit EnumLiteralVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
302 
Type()303     VariableType Type() const override
304     {
305         return VariableType::ENUMLITERAL;
306     }
307 
308     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
309 
GetEnumMembers()310     VariableMap *GetEnumMembers() const
311     {
312         return enumMemberBindings_;
313     }
314 
FindEnumMemberVariable(const util::StringView & name)315     Variable *FindEnumMemberVariable(const util::StringView &name) const
316     {
317         auto res = enumMemberBindings_->find(name);
318         if (res == enumMemberBindings_->end()) {
319             return nullptr;
320         }
321         return res->second;
322     }
323 
SetEnumMembers(VariableMap * enumMemberBindings)324     void SetEnumMembers(VariableMap *enumMemberBindings)
325     {
326         enumMemberBindings_ = enumMemberBindings;
327     }
328 
329 private:
330     VariableMap *enumMemberBindings_ {nullptr};
331 };
332 
333 class ImportEqualsVariable : public Variable {
334 public:
ImportEqualsVariable(Decl * decl,VariableFlags flags)335     explicit ImportEqualsVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
336 
Type()337     VariableType Type() const override
338     {
339         return VariableType::IMPORT_EQUALS;
340     }
341 
342     void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::PatchFix *patchFixHelper = nullptr) override;
343 
GetScope()344     Scope *GetScope()
345     {
346         return scope_;
347     }
348 
SetScope(Scope * scope)349     void SetScope(Scope *scope)
350     {
351         scope_ = scope;
352     }
353 
354 private:
355     Scope *scope_ {nullptr};
356 };
357 
358 }  // namespace panda::es2panda::binder
359 #endif
360