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/hotfix.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
39 #define DECLARE_CLASSES(type, className) class className;
VARIABLE_TYPES(DECLARE_CLASSES)40 VARIABLE_TYPES(DECLARE_CLASSES)
41 #undef DECLARE_CLASSES
42
43 class Variable {
44 public:
45 virtual ~Variable() = default;
46 NO_COPY_SEMANTIC(Variable);
47 NO_MOVE_SEMANTIC(Variable);
48
49 VariableType virtual Type() const = 0;
50
51 #define DECLARE_CHECKS_CASTS(variableType, className) \
52 bool Is##className() const \
53 { \
54 return Type() == VariableType::variableType; \
55 } \
56 className *As##className() \
57 { \
58 ASSERT(Is##className()); \
59 return reinterpret_cast<className *>(this); \
60 } \
61 const className *As##className() const \
62 { \
63 ASSERT(Is##className()); \
64 return reinterpret_cast<const className *>(this); \
65 }
66 VARIABLE_TYPES(DECLARE_CHECKS_CASTS)
67 #undef DECLARE_CHECKS_CASTS
68
69 Decl *Declaration() const
70 {
71 return decl_;
72 }
73
74 VariableFlags Flags() const
75 {
76 return flags_;
77 }
78
79 checker::Type *TsType() const
80 {
81 return tsType_;
82 }
83
84 void SetTsType(checker::Type *tsType)
85 {
86 tsType_ = tsType;
87 }
88
89 void AddFlag(VariableFlags flag)
90 {
91 flags_ |= flag;
92 }
93
94 bool HasFlag(VariableFlags flag) const
95 {
96 return (flags_ & flag) != 0;
97 }
98
99 void RemoveFlag(VariableFlags flag)
100 {
101 flags_ &= ~flag;
102 }
103
104 void Reset(Decl *decl, VariableFlags flags)
105 {
106 decl_ = decl;
107 flags_ = flags;
108 }
109
110 bool LexicalBound() const
111 {
112 return HasFlag(VariableFlags::LEXICAL_BOUND);
113 }
114
115 const util::StringView &Name() const;
116 virtual void SetLexical(Scope *scope, util::Hotfix *hotfixHelper = nullptr) = 0;
117
118 protected:
119 explicit Variable(Decl *decl, VariableFlags flags) : decl_(decl), flags_(flags) {}
120
121 Decl *decl_;
122 VariableFlags flags_ {};
123 checker::Type *tsType_ {};
124 };
125
126 class LocalVariable : public Variable {
127 public:
128 explicit LocalVariable(Decl *decl, VariableFlags flags);
129
Type()130 VariableType Type() const override
131 {
132 return VariableType::LOCAL;
133 }
134
BindVReg(compiler::VReg vreg)135 void BindVReg(compiler::VReg vreg)
136 {
137 ASSERT(!LexicalBound());
138 vreg_ = vreg;
139 }
140
BindLexEnvSlot(uint32_t slot)141 void BindLexEnvSlot(uint32_t slot)
142 {
143 ASSERT(!LexicalBound());
144 AddFlag(VariableFlags::LEXICAL_BOUND);
145 vreg_ = slot;
146 }
147
Vreg()148 compiler::VReg Vreg() const
149 {
150 return vreg_;
151 }
152
LexIdx()153 uint32_t LexIdx() const
154 {
155 ASSERT(LexicalBound());
156 return vreg_;
157 }
158
159 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override;
160 LocalVariable *Copy(ArenaAllocator *allocator, Decl *decl) const;
161
162 private:
163 uint32_t vreg_ {};
164 };
165
166 class GlobalVariable : public Variable {
167 public:
GlobalVariable(Decl * decl,VariableFlags flags)168 explicit GlobalVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
169
Type()170 VariableType Type() const override
171 {
172 return VariableType::GLOBAL;
173 }
174
175 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override;
176 };
177
178 class ModuleVariable : public Variable {
179 public:
ModuleVariable(Decl * decl,VariableFlags flags)180 explicit ModuleVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
181
Type()182 VariableType Type() const override
183 {
184 return VariableType::MODULE;
185 }
186
187 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override;
188
AssignIndex(uint32_t index)189 void AssignIndex(uint32_t index)
190 {
191 index_ = index;
192 }
193
Index()194 uint32_t Index() const
195 {
196 return index_;
197 }
198
199 private:
200 uint32_t index_;
201 };
202
203 class EnumVariable : public Variable {
204 public:
205 explicit EnumVariable(Decl *decl, bool backReference = false)
Variable(decl,VariableFlags::NONE)206 : Variable(decl, VariableFlags::NONE), backReference_(backReference)
207 {
208 }
209
Type()210 VariableType Type() const override
211 {
212 return VariableType::ENUM;
213 }
214
SetValue(EnumMemberResult value)215 void SetValue(EnumMemberResult value)
216 {
217 value_ = value;
218 }
219
Value()220 const EnumMemberResult &Value() const
221 {
222 return value_;
223 }
224
BackReference()225 bool BackReference() const
226 {
227 return backReference_;
228 }
229
SetBackReference()230 void SetBackReference()
231 {
232 backReference_ = true;
233 }
234
235 void ResetDecl(Decl *decl);
236
237 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override;
238
239 private:
240 EnumMemberResult value_ {false};
241 bool backReference_ {};
242 };
243
244 class NamespaceVariable : public Variable {
245 public:
NamespaceVariable(Decl * decl,VariableFlags flags)246 explicit NamespaceVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
247
Type()248 VariableType Type() const override
249 {
250 return VariableType::NAMESPACE;
251 }
252
253 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override;
254
GetExportBindings()255 ExportBindings *GetExportBindings()
256 {
257 return exportBindings_;
258 }
259
SetExportBindings(ExportBindings * exportBindings)260 void SetExportBindings(ExportBindings *exportBindings)
261 {
262 exportBindings_ = exportBindings;
263 }
264
265 private:
266 ExportBindings *exportBindings_ {nullptr};
267 };
268
269 class ImportEqualsVariable : public Variable {
270 public:
ImportEqualsVariable(Decl * decl,VariableFlags flags)271 explicit ImportEqualsVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {}
272
Type()273 VariableType Type() const override
274 {
275 return VariableType::IMPORT_EQUALS;
276 }
277
278 void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override;
279
GetScope()280 Scope *GetScope()
281 {
282 return scope_;
283 }
284
SetScope(Scope * scope)285 void SetScope(Scope *scope)
286 {
287 scope_ = scope;
288 }
289
290 private:
291 Scope *scope_ {nullptr};
292 };
293
294 } // namespace panda::es2panda::binder
295 #endif
296