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_DECLARATION_H
17 #define ES2PANDA_COMPILER_SCOPES_DECLARATION_H
18 
19 #include "varbinder/variableFlags.h"
20 #include "macros.h"
21 #include "util/ustring.h"
22 
23 namespace ark::es2panda::ir {
24 class AstNode;
25 class ScriptFunction;
26 class TSInterfaceDeclaration;
27 class ImportDeclaration;
28 class ETSImportDeclaration;
29 }  // namespace ark::es2panda::ir
30 
31 namespace ark::es2panda::varbinder {
32 class Scope;
33 class LocalScope;
34 
35 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
36 #define DECLARE_CLASSES(decl_kind, className) class className;
37 DECLARATION_KINDS(DECLARE_CLASSES)
38 #undef DECLARE_CLASSES
39 
40 class Decl {
41 public:
42     virtual ~Decl() = default;
43     NO_COPY_SEMANTIC(Decl);
44     NO_MOVE_SEMANTIC(Decl);
45 
46     virtual DeclType Type() const = 0;
47 
Name() const48     const util::StringView &Name() const
49     {
50         return name_;
51     }
52 
Node()53     ir::AstNode *Node()
54     {
55         return node_;
56     }
57 
Node() const58     const ir::AstNode *Node() const
59     {
60         return node_;
61     }
62 
63 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
64 #define DECLARE_CHECKS_CASTS(declKind, className)         \
65     bool Is##className() const                            \
66     {                                                     \
67         return Type() == DeclType::declKind;              \
68     }                                                     \
69     className *As##className()                            \
70     {                                                     \
71         ASSERT(Is##className());                          \
72         return reinterpret_cast<className *>(this);       \
73     }                                                     \
74     const className *As##className() const                \
75     {                                                     \
76         ASSERT(Is##className());                          \
77         return reinterpret_cast<const className *>(this); \
78     }
79     DECLARATION_KINDS(DECLARE_CHECKS_CASTS)
80 #undef DECLARE_CHECKS_CASTS
81 
BindNode(ir::AstNode *node)82     void BindNode(ir::AstNode *node)
83     {
84         node_ = node;
85     }
86 
IsLetOrConstDecl() const87     bool IsLetOrConstDecl() const
88     {
89         return IsLetDecl() || IsConstDecl();
90     }
91 
PossibleTDZ() const92     bool PossibleTDZ() const
93     {
94         return IsLetOrConstDecl() || IsParameterDecl();
95     }
96 
97 protected:
Decl(util::StringView name)98     explicit Decl(util::StringView name) : name_(name) {}
Decl(util::StringView name, ir::AstNode *declNode)99     explicit Decl(util::StringView name, ir::AstNode *declNode) : name_(name), node_(declNode) {}
100 
101     // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
102     util::StringView name_;
103     ir::AstNode *node_ {};
104     // NOLINTEND(misc-non-private-member-variables-in-classes)
105 };
106 
107 template <typename T>
108 class MultiDecl : public Decl {
109 public:
MultiDecl(ArenaAllocator *allocator, util::StringView name)110     explicit MultiDecl(ArenaAllocator *allocator, util::StringView name)
111         : Decl(name), declarations_(allocator->Adapter())
112     {
113     }
114 
MultiDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *declNode)115     explicit MultiDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *declNode)
116         : Decl(name, declNode), declarations_(allocator->Adapter())
117     {
118     }
119 
Decls() const120     const ArenaVector<T *> &Decls() const
121     {
122         return declarations_;
123     }
124 
Add(T *decl)125     void Add(T *decl)
126     {
127         declarations_.push_back(decl);
128     }
129 
130 private:
131     ArenaVector<T *> declarations_;
132 };
133 
134 class EnumLiteralDecl : public Decl {
135 public:
EnumLiteralDecl(util::StringView name, bool isConst)136     explicit EnumLiteralDecl(util::StringView name, bool isConst) : Decl(name), isConst_(isConst) {}
EnumLiteralDecl(util::StringView name, ir::AstNode *declNode, bool isConst)137     explicit EnumLiteralDecl(util::StringView name, ir::AstNode *declNode, bool isConst)
138         : Decl(name, declNode), isConst_(isConst)
139     {
140     }
141 
142     DeclType Type() const override
143     {
144         return DeclType::ENUM_LITERAL;
145     }
146 
IsConst() const147     bool IsConst() const
148     {
149         return isConst_;
150     }
151 
BindScope(LocalScope *scope)152     void BindScope(LocalScope *scope)
153     {
154         scope_ = scope;
155     }
156 
Scope()157     LocalScope *Scope()
158     {
159         return scope_;
160     }
161 
162 private:
163     LocalScope *scope_ {};
164     bool isConst_ {};
165 };
166 
167 class InterfaceDecl : public MultiDecl<ir::TSInterfaceDeclaration> {
168 public:
InterfaceDecl(ArenaAllocator *allocator, util::StringView name)169     explicit InterfaceDecl(ArenaAllocator *allocator, util::StringView name) : MultiDecl(allocator, name) {}
InterfaceDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *declNode)170     explicit InterfaceDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *declNode)
171         : MultiDecl(allocator, name, declNode)
172     {
173     }
174 
175     DeclType Type() const override
176     {
177         return DeclType::INTERFACE;
178     }
179 };
180 
181 class ClassDecl : public Decl {
182 public:
ClassDecl(util::StringView name)183     explicit ClassDecl(util::StringView name) : Decl(name) {}
ClassDecl(util::StringView name, ir::AstNode *node)184     explicit ClassDecl(util::StringView name, ir::AstNode *node) : Decl(name, node) {}
185 
186     DeclType Type() const override
187     {
188         return DeclType::CLASS;
189     }
190 };
191 
192 class FunctionDecl : public MultiDecl<ir::ScriptFunction> {
193 public:
FunctionDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *node)194     explicit FunctionDecl(ArenaAllocator *allocator, util::StringView name, ir::AstNode *node)
195         : MultiDecl(allocator, name)
196     {
197         node_ = node;
198     }
199 
200     DeclType Type() const override
201     {
202         return DeclType::FUNC;
203     }
204 };
205 
206 class TypeParameterDecl : public Decl {
207 public:
TypeParameterDecl(util::StringView name)208     explicit TypeParameterDecl(util::StringView name) : Decl(name) {}
209 
210     DeclType Type() const override
211     {
212         return DeclType::TYPE_PARAMETER;
213     }
214 };
215 
216 class PropertyDecl : public Decl {
217 public:
PropertyDecl(util::StringView name)218     explicit PropertyDecl(util::StringView name) : Decl(name) {}
219 
220     DeclType Type() const override
221     {
222         return DeclType::PROPERTY;
223     }
224 };
225 
226 class MethodDecl : public Decl {
227 public:
MethodDecl(util::StringView name)228     explicit MethodDecl(util::StringView name) : Decl(name) {}
229 
230     DeclType Type() const override
231     {
232         return DeclType::METHOD;
233     }
234 };
235 
236 class EnumDecl : public Decl {
237 public:
EnumDecl(util::StringView name)238     explicit EnumDecl(util::StringView name) : Decl(name) {}
239 
240     DeclType Type() const override
241     {
242         return DeclType::ENUM;
243     }
244 };
245 
246 class TypeAliasDecl : public Decl {
247 public:
TypeAliasDecl(util::StringView name)248     explicit TypeAliasDecl(util::StringView name) : Decl(name) {}
TypeAliasDecl(util::StringView name, ir::AstNode *node)249     explicit TypeAliasDecl(util::StringView name, ir::AstNode *node) : Decl(name, node) {}
250 
251     DeclType Type() const override
252     {
253         return DeclType::TYPE_ALIAS;
254     }
255 };
256 
257 class NameSpaceDecl : public Decl {
258 public:
NameSpaceDecl(util::StringView name)259     explicit NameSpaceDecl(util::StringView name) : Decl(name) {}
260 
261     DeclType Type() const override
262     {
263         return DeclType::NAMESPACE;
264     }
265 };
266 
267 class VarDecl : public Decl {
268 public:
VarDecl(util::StringView name)269     explicit VarDecl(util::StringView name) : Decl(name) {}
270 
271     DeclType Type() const override
272     {
273         return DeclType::VAR;
274     }
275 };
276 
277 class LetDecl : public Decl {
278 public:
LetDecl(util::StringView name)279     explicit LetDecl(util::StringView name) : Decl(name) {}
LetDecl(util::StringView name, ir::AstNode *declNode)280     explicit LetDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
281 
282     DeclType Type() const override
283     {
284         return DeclType::LET;
285     }
286 };
287 
288 class ConstDecl : public Decl {
289 public:
ConstDecl(util::StringView name)290     explicit ConstDecl(util::StringView name) : Decl(name) {}
ConstDecl(util::StringView name, ir::AstNode *declNode)291     explicit ConstDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
292 
293     DeclType Type() const override
294     {
295         return DeclType::CONST;
296     }
297 };
298 
299 class LabelDecl : public Decl {
300 public:
LabelDecl(util::StringView name)301     explicit LabelDecl(util::StringView name) : Decl(name) {}
LabelDecl(util::StringView name, ir::AstNode *declNode)302     explicit LabelDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
303 
304     DeclType Type() const override
305     {
306         return DeclType::LABEL;
307     }
308 };
309 
310 class ReadonlyDecl : public Decl {
311 public:
ReadonlyDecl(util::StringView name)312     explicit ReadonlyDecl(util::StringView name) : Decl(name) {}
ReadonlyDecl(util::StringView name, ir::AstNode *declNode)313     explicit ReadonlyDecl(util::StringView name, ir::AstNode *declNode) : Decl(name, declNode) {}
314 
315     DeclType Type() const override
316     {
317         return DeclType::READONLY;
318     }
319 };
320 
321 class ParameterDecl : public Decl {
322 public:
ParameterDecl(util::StringView name)323     explicit ParameterDecl(util::StringView name) : Decl(name) {}
324 
325     DeclType Type() const override
326     {
327         return DeclType::PARAM;
328     }
329 };
330 
331 class ImportDecl : public Decl {
332 public:
ImportDecl(util::StringView importName, util::StringView localName)333     explicit ImportDecl(util::StringView importName, util::StringView localName)
334         : Decl(localName), importName_(importName)
335     {
336     }
337 
ImportDecl(util::StringView importName, util::StringView localName, ir::AstNode *node)338     explicit ImportDecl(util::StringView importName, util::StringView localName, ir::AstNode *node)
339         : Decl(localName), importName_(importName)
340     {
341         BindNode(node);
342     }
343 
ImportName() const344     const util::StringView &ImportName() const
345     {
346         return importName_;
347     }
348 
LocalName() const349     const util::StringView &LocalName() const
350     {
351         return name_;
352     }
353 
354     DeclType Type() const override
355     {
356         return DeclType::IMPORT;
357     }
358 
359 private:
360     util::StringView importName_;
361 };
362 
363 class ExportDecl : public Decl {
364 public:
ExportDecl(util::StringView exportName, util::StringView localName)365     explicit ExportDecl(util::StringView exportName, util::StringView localName)
366         : Decl(localName), exportName_(exportName)
367     {
368     }
369 
ExportDecl(util::StringView exportName, util::StringView localName, ir::AstNode *node)370     explicit ExportDecl(util::StringView exportName, util::StringView localName, ir::AstNode *node)
371         : Decl(localName), exportName_(exportName)
372     {
373         BindNode(node);
374     }
375 
ExportName() const376     const util::StringView &ExportName() const
377     {
378         return exportName_;
379     }
380 
LocalName() const381     const util::StringView &LocalName() const
382     {
383         return name_;
384     }
385 
386     DeclType Type() const override
387     {
388         return DeclType::EXPORT;
389     }
390 
391 private:
392     util::StringView exportName_;
393 };
394 }  // namespace ark::es2panda::varbinder
395 
396 #endif
397