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_DECLARATION_H
17#define ES2PANDA_COMPILER_SCOPES_DECLARATION_H
18
19#include <binder/variableFlags.h>
20#include <macros.h>
21#include <util/ustring.h>
22
23namespace panda::es2panda::ir {
24class AstNode;
25class ScriptFunction;
26class TSInterfaceDeclaration;
27class TSModuleDeclaration;
28class TSEnumDeclaration;
29class ImportDeclaration;
30}  // namespace panda::es2panda::ir
31
32namespace panda::es2panda::binder {
33
34class Scope;
35class LocalScope;
36class TSEnumScope;
37
38#define DECLARE_CLASSES(decl_kind, className) class className;
39DECLARATION_KINDS(DECLARE_CLASSES)
40#undef DECLARE_CLASSES
41
42class Decl {
43public:
44    virtual ~Decl() = default;
45    NO_COPY_SEMANTIC(Decl);
46    NO_MOVE_SEMANTIC(Decl);
47
48    virtual DeclType Type() const = 0;
49
50    const util::StringView &Name() const
51    {
52        return name_;
53    }
54
55    const ir::AstNode *Node() const
56    {
57        return node_;
58    }
59
60#define DECLARE_CHECKS_CASTS(declKind, className)         \
61    bool Is##className() const                            \
62    {                                                     \
63        return Type() == DeclType::declKind;              \
64    }                                                     \
65    className *As##className()                            \
66    {                                                     \
67        ASSERT(Is##className());                          \
68        return reinterpret_cast<className *>(this);       \
69    }                                                     \
70    const className *As##className() const                \
71    {                                                     \
72        ASSERT(Is##className());                          \
73        return reinterpret_cast<const className *>(this); \
74    }
75    DECLARATION_KINDS(DECLARE_CHECKS_CASTS)
76#undef DECLARE_CHECKS_CASTS
77
78    void BindNode(const ir::AstNode *node)
79    {
80        node_ = node;
81    }
82
83    bool IsLetOrConstOrClassDecl() const
84    {
85        return IsLetDecl() || IsConstDecl() || IsClassDecl();
86    }
87
88    DeclarationFlags Flags() const
89    {
90        return flags_;
91    }
92
93    void AddFlag(DeclarationFlags flag)
94    {
95        flags_ |= flag;
96    }
97
98    bool HasFlag(DeclarationFlags flag) const
99    {
100        return (flags_ & flag) != 0;
101    }
102
103    bool IsImportDecl() const
104    {
105        return HasFlag(DeclarationFlags::IMPORT);
106    }
107
108    bool IsImportOrExportDecl() const
109    {
110        return HasFlag(DeclarationFlags::IMPORT | DeclarationFlags::EXPORT);
111    }
112
113    bool IsExportDeclInTsModule() const
114    {
115        return HasFlag(DeclarationFlags::EXPORT_IN_TSMODULE);
116    }
117
118    void SetDeclare(bool isDeclare)
119    {
120        isDeclare_ = isDeclare;
121    }
122
123    bool IsDeclare() const
124    {
125        return isDeclare_;
126    }
127
128    bool IsSendableClassDecl() const;
129
130    bool IsSendableFunctionDecl() const;
131
132    bool NeedSetInSendableEnv(Scope *scope) const;
133
134protected:
135    explicit Decl(util::StringView name) : name_(name) {}
136
137    util::StringView name_;
138    DeclarationFlags flags_ {};
139    const ir::AstNode *node_ {};
140    bool isDeclare_ {false};
141};
142
143template <typename T>
144class MultiDecl : public Decl {
145public:
146    explicit MultiDecl(ArenaAllocator *allocator, util::StringView name)
147        : Decl(name), declarations_(allocator->Adapter())
148    {
149    }
150
151    const ArenaVector<T *> &Decls() const
152    {
153        return declarations_;
154    }
155
156    void Add(T *decl)
157    {
158        declarations_.push_back(decl);
159    }
160
161private:
162    ArenaVector<T *> declarations_;
163};
164
165class EnumLiteralDecl : public MultiDecl<ir::TSEnumDeclaration> {
166public:
167    explicit EnumLiteralDecl(ArenaAllocator *allocator, util::StringView name, bool isExport, bool isConst)
168        : MultiDecl(allocator, name), isExport_(isExport), isConst_(isConst) {}
169
170    DeclType Type() const override
171    {
172        return DeclType::ENUM_LITERAL;
173    }
174
175    bool IsExport() const
176    {
177        return isExport_;
178    }
179
180    bool IsConst() const
181    {
182        return isConst_;
183    }
184
185    void BindScope(TSEnumScope *scope)
186    {
187        scope_ = scope;
188    }
189
190    TSEnumScope *Scope()
191    {
192        return scope_;
193    }
194
195private:
196    TSEnumScope *scope_ {nullptr};
197    bool isExport_ {};
198    bool isConst_ {};
199};
200
201class InterfaceDecl : public MultiDecl<ir::TSInterfaceDeclaration> {
202public:
203    explicit InterfaceDecl(ArenaAllocator *allocator, util::StringView name) : MultiDecl(allocator, name) {}
204
205    DeclType Type() const override
206    {
207        return DeclType::INTERFACE;
208    }
209};
210
211class TypeParameterDecl : public Decl {
212public:
213    explicit TypeParameterDecl(util::StringView name, const ir::AstNode *node);
214
215    DeclType Type() const override
216    {
217        return DeclType::TYPE_PARAMETER;
218    }
219};
220
221class PropertyDecl : public Decl {
222public:
223    explicit PropertyDecl(util::StringView name) : Decl(name) {}
224
225    DeclType Type() const override
226    {
227        return DeclType::PROPERTY;
228    }
229};
230
231class MethodDecl : public Decl {
232public:
233    explicit MethodDecl(util::StringView name) : Decl(name) {}
234
235    DeclType Type() const override
236    {
237        return DeclType::METHOD;
238    }
239};
240
241class EnumDecl : public Decl {
242public:
243    explicit EnumDecl(util::StringView name) : Decl(name) {}
244
245    DeclType Type() const override
246    {
247        return DeclType::ENUM;
248    }
249};
250
251class TypeAliasDecl : public Decl {
252public:
253    explicit TypeAliasDecl(util::StringView name) : Decl(name) {}
254
255    DeclType Type() const override
256    {
257        return DeclType::TYPE_ALIAS;
258    }
259};
260
261class NamespaceDecl : public MultiDecl<ir::TSModuleDeclaration> {
262public:
263    explicit NamespaceDecl(ArenaAllocator *allocator, util::StringView name)
264        : MultiDecl(allocator, name)
265    {
266    }
267
268    DeclType Type() const override
269    {
270        return DeclType::NAMESPACE;
271    }
272
273    bool IsInstantiated() const;
274};
275
276class VarDecl : public Decl {
277public:
278    explicit VarDecl(util::StringView name) : Decl(name) {}
279
280    DeclType Type() const override
281    {
282        return DeclType::VAR;
283    }
284};
285
286class LetDecl : public Decl {
287public:
288    explicit LetDecl(util::StringView name) : Decl(name) {}
289
290    DeclType Type() const override
291    {
292        return DeclType::LET;
293    }
294};
295
296class ConstDecl : public Decl {
297public:
298    explicit ConstDecl(util::StringView name) : Decl(name) {}
299
300    DeclType Type() const override
301    {
302        return DeclType::CONST;
303    }
304};
305
306class ClassDecl : public Decl {
307public:
308    explicit ClassDecl(util::StringView name) : Decl(name) {}
309
310    DeclType Type() const override
311    {
312        return DeclType::CLASS;
313    }
314};
315
316class FunctionDecl : public MultiDecl<ir::ScriptFunction> {
317public:
318    explicit FunctionDecl(ArenaAllocator *allocator, util::StringView name, const ir::AstNode *node)
319        : MultiDecl(allocator, name)
320    {
321        node_ = node;
322    }
323
324    DeclType Type() const override
325    {
326        return DeclType::FUNC;
327    }
328
329    void SetDeclClass(ClassDecl *declClass)
330    {
331        declClass_ = declClass;
332    }
333
334    ClassDecl *GetDeclClass()
335    {
336        return declClass_;
337    }
338
339private:
340    ClassDecl *declClass_ {nullptr};
341};
342
343class ParameterDecl : public Decl {
344public:
345    explicit ParameterDecl(util::StringView name) : Decl(name) {}
346
347    DeclType Type() const override
348    {
349        return DeclType::PARAM;
350    }
351};
352
353class ImportEqualsDecl : public Decl {
354public:
355    explicit ImportEqualsDecl(util::StringView name) : Decl(name) {}
356
357    DeclType Type() const override
358    {
359        return DeclType::IMPORT_EQUALS;
360    }
361};
362
363}  // namespace panda::es2panda::binder
364
365#endif
366