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