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_IR_AST_NODE_H
17#define ES2PANDA_IR_AST_NODE_H
18
19#include "astNodeFlags.h"
20#include "astNodeMapping.h"
21#include "ir/visitor/AstVisitor.h"
22#include "lexer/token/sourceLocation.h"
23#include "macros.h"
24
25namespace ark::es2panda::compiler {
26class PandaGen;
27class ETSGen;
28}  // namespace ark::es2panda::compiler
29
30namespace ark::es2panda::checker {
31class TSChecker;
32class ETSChecker;
33class Type;
34}  // namespace ark::es2panda::checker
35
36namespace ark::es2panda::varbinder {
37class Variable;
38class Scope;
39}  // namespace ark::es2panda::varbinder
40
41namespace ark::es2panda::ir {
42// NOLINTBEGIN(modernize-avoid-c-arrays)
43inline constexpr char const CLONE_ALLOCATION_ERROR[] = "Unsuccessful allocation during cloning.";
44// NOLINTEND(modernize-avoid-c-arrays)
45
46class AstNode;
47class TypeNode;
48
49using NodeTransformer = std::function<AstNode *(AstNode *)>;
50using NodeTraverser = std::function<void(AstNode *)>;
51using NodePredicate = std::function<bool(AstNode *)>;
52
53enum class AstNodeType {
54// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
55#define DECLARE_NODE_TYPES(nodeType, className) nodeType,
56    AST_NODE_MAPPING(DECLARE_NODE_TYPES)
57#undef DECLARE_NODE_TYPES
58// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
59#define DECLARE_NODE_TYPES(nodeType1, nodeType2, baseClass, reinterpretClass) nodeType1, nodeType2,
60        AST_NODE_REINTERPRET_MAPPING(DECLARE_NODE_TYPES)
61#undef DECLARE_NODE_TYPES
62};
63
64// Forward declarations
65class AstDumper;
66class Expression;
67class SrcDumper;
68class Statement;
69class ClassElement;
70template <typename T>
71class Typed;
72
73// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
74#define DECLARE_CLASSES(nodeType, className) class className;
75AST_NODE_MAPPING(DECLARE_CLASSES)
76#undef DECLARE_CLASSES
77
78// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
79#define DECLARE_CLASSES(nodeType1, nodeType2, baseClass, reinterpretClass) class baseClass;
80AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES)
81#undef DECLARE_CLASSES
82
83class AstNode {
84public:
85    explicit AstNode(AstNodeType type) : type_(type) {};
86    explicit AstNode(AstNodeType type, ModifierFlags flags) : type_(type), flags_(flags) {};
87    virtual ~AstNode() = default;
88
89    AstNode() = delete;
90    NO_MOVE_SEMANTIC(AstNode);
91
92    bool IsProgram() const
93    {
94        return parent_ == nullptr;
95    }
96
97// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
98#define DECLARE_IS_CHECKS(nodeType, className) \
99    bool Is##className() const                 \
100    {                                          \
101        return type_ == AstNodeType::nodeType; \
102    }
103    AST_NODE_MAPPING(DECLARE_IS_CHECKS)
104#undef DECLARE_IS_CHECKS
105
106// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
107#define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \
108    bool Is##baseClass() const                                               \
109    {                                                                        \
110        return type_ == AstNodeType::nodeType1;                              \
111    }                                                                        \
112    bool Is##reinterpretClass() const                                        \
113    {                                                                        \
114        return type_ == AstNodeType::nodeType2;                              \
115    }
116    AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS)
117#undef DECLARE_IS_CHECKS
118
119    [[nodiscard]] virtual bool IsStatement() const noexcept
120    {
121        return false;
122    }
123
124    [[nodiscard]] virtual bool IsExpression() const noexcept
125    {
126        return false;
127    }
128
129    virtual bool IsTyped() const
130    {
131        return false;
132    }
133
134    Typed<AstNode> *AsTyped()
135    {
136        ASSERT(IsTyped());
137        return reinterpret_cast<Typed<AstNode> *>(this);
138    }
139
140    Typed<AstNode> const *AsTyped() const
141    {
142        ASSERT(IsTyped());
143        return reinterpret_cast<Typed<AstNode> const *>(this);
144    }
145
146// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
147#define DECLARE_AS_CASTS(nodeType, className)             \
148    className *As##className()                            \
149    {                                                     \
150        ASSERT(Is##className());                          \
151        return reinterpret_cast<className *>(this);       \
152    }                                                     \
153    const className *As##className() const                \
154    {                                                     \
155        ASSERT(Is##className());                          \
156        return reinterpret_cast<const className *>(this); \
157    }
158    AST_NODE_MAPPING(DECLARE_AS_CASTS)
159#undef DECLARE_AS_CASTS
160
161// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
162#define DECLARE_AS_CASTS(nodeType1, nodeType2, baseClass, reinterpretClass) \
163    baseClass *As##baseClass()                                              \
164    {                                                                       \
165        ASSERT(Is##baseClass());                                            \
166        return reinterpret_cast<baseClass *>(this);                         \
167    }                                                                       \
168    baseClass *As##reinterpretClass()                                       \
169    {                                                                       \
170        ASSERT(Is##reinterpretClass());                                     \
171        return reinterpret_cast<baseClass *>(this);                         \
172    }                                                                       \
173    const baseClass *As##baseClass() const                                  \
174    {                                                                       \
175        ASSERT(Is##baseClass());                                            \
176        return reinterpret_cast<const baseClass *>(this);                   \
177    }                                                                       \
178    const baseClass *As##reinterpretClass() const                           \
179    {                                                                       \
180        ASSERT(Is##reinterpretClass());                                     \
181        return reinterpret_cast<const baseClass *>(this);                   \
182    }
183    AST_NODE_REINTERPRET_MAPPING(DECLARE_AS_CASTS)
184#undef DECLARE_AS_CASTS
185
186    Expression *AsExpression()
187    {
188        ASSERT(IsExpression());
189        return reinterpret_cast<Expression *>(this);
190    }
191
192    const Expression *AsExpression() const
193    {
194        ASSERT(IsExpression());
195        return reinterpret_cast<const Expression *>(this);
196    }
197
198    Statement *AsStatement()
199    {
200        ASSERT(IsStatement());
201        return reinterpret_cast<Statement *>(this);
202    }
203
204    const Statement *AsStatement() const
205    {
206        ASSERT(IsStatement());
207        return reinterpret_cast<const Statement *>(this);
208    }
209
210    void SetRange(const lexer::SourceRange &loc) noexcept
211    {
212        range_ = loc;
213    }
214
215    void SetStart(const lexer::SourcePosition &start) noexcept
216    {
217        range_.start = start;
218    }
219
220    void SetEnd(const lexer::SourcePosition &end) noexcept
221    {
222        range_.end = end;
223    }
224
225    [[nodiscard]] const lexer::SourcePosition &Start() const noexcept
226    {
227        return range_.start;
228    }
229
230    [[nodiscard]] const lexer::SourcePosition &End() const noexcept
231    {
232        return range_.end;
233    }
234
235    [[nodiscard]] const lexer::SourceRange &Range() const noexcept
236    {
237        return range_;
238    }
239
240    [[nodiscard]] AstNodeType Type() const noexcept
241    {
242        return type_;
243    }
244
245    [[nodiscard]] AstNode *Parent() noexcept
246    {
247        return parent_;
248    }
249
250    [[nodiscard]] const AstNode *Parent() const noexcept
251    {
252        return parent_;
253    }
254
255    void SetParent(AstNode *const parent) noexcept
256    {
257        parent_ = parent;
258    }
259
260    [[nodiscard]] varbinder::Variable *Variable() const noexcept
261    {
262        return variable_;
263    }
264
265    void SetVariable(varbinder::Variable *variable) noexcept
266    {
267        variable_ = variable;
268    }
269
270    // When no decorators are allowed, we cannot return a reference to an empty vector.
271    virtual const ArenaVector<ir::Decorator *> *DecoratorsPtr() const
272    {
273        return nullptr;
274    }
275
276    virtual void AddDecorators([[maybe_unused]] ArenaVector<ir::Decorator *> &&decorators)
277    {
278        UNREACHABLE();
279    }
280
281    virtual bool CanHaveDecorator([[maybe_unused]] bool inTs) const
282    {
283        return false;
284    }
285
286    [[nodiscard]] bool IsReadonly() const noexcept
287    {
288        return (flags_ & ModifierFlags::READONLY) != 0;
289    }
290
291    [[nodiscard]] bool IsOptionalDeclaration() const noexcept
292    {
293        return (flags_ & ModifierFlags::OPTIONAL) != 0;
294    }
295
296    [[nodiscard]] bool IsDefinite() const noexcept
297    {
298        return (flags_ & ModifierFlags::DEFINITE) != 0;
299    }
300
301    [[nodiscard]] bool IsConstructor() const noexcept
302    {
303        return (flags_ & ModifierFlags::CONSTRUCTOR) != 0;
304    }
305
306    [[nodiscard]] bool IsOverride() const noexcept
307    {
308        return (flags_ & ModifierFlags::OVERRIDE) != 0;
309    }
310
311    void SetOverride() noexcept
312    {
313        flags_ |= ModifierFlags::OVERRIDE;
314    }
315
316    [[nodiscard]] bool IsAsync() const noexcept
317    {
318        return (flags_ & ModifierFlags::ASYNC) != 0;
319    }
320
321    [[nodiscard]] bool IsSynchronized() const noexcept
322    {
323        return (flags_ & ModifierFlags::SYNCHRONIZED) != 0;
324    }
325
326    [[nodiscard]] bool IsNative() const noexcept
327    {
328        return (flags_ & ModifierFlags::NATIVE) != 0;
329    }
330
331    [[nodiscard]] bool IsConst() const noexcept
332    {
333        return (flags_ & ModifierFlags::CONST) != 0;
334    }
335
336    [[nodiscard]] bool IsStatic() const noexcept
337    {
338        return (flags_ & ModifierFlags::STATIC) != 0;
339    }
340
341    [[nodiscard]] bool IsFinal() const noexcept
342    {
343        return (flags_ & ModifierFlags::FINAL) != 0U;
344    }
345
346    [[nodiscard]] bool IsAbstract() const noexcept
347    {
348        return (flags_ & ModifierFlags::ABSTRACT) != 0;
349    }
350
351    [[nodiscard]] bool IsPublic() const noexcept
352    {
353        return (flags_ & ModifierFlags::PUBLIC) != 0;
354    }
355
356    [[nodiscard]] bool IsProtected() const noexcept
357    {
358        return (flags_ & ModifierFlags::PROTECTED) != 0;
359    }
360
361    [[nodiscard]] bool IsPrivate() const noexcept
362    {
363        return (flags_ & ModifierFlags::PRIVATE) != 0;
364    }
365
366    [[nodiscard]] bool IsInternal() const noexcept
367    {
368        return (flags_ & ModifierFlags::INTERNAL) != 0;
369    }
370
371    [[nodiscard]] bool IsExported() const noexcept;
372
373    [[nodiscard]] bool IsDefaultExported() const noexcept;
374
375    [[nodiscard]] bool IsExportedType() const noexcept;
376
377    [[nodiscard]] bool IsDeclare() const noexcept
378    {
379        return (flags_ & ModifierFlags::DECLARE) != 0;
380    }
381
382    [[nodiscard]] bool IsIn() const noexcept
383    {
384        return (flags_ & ModifierFlags::IN) != 0;
385    }
386
387    [[nodiscard]] bool IsOut() const noexcept
388    {
389        return (flags_ & ModifierFlags::OUT) != 0;
390    }
391
392    [[nodiscard]] bool IsSetter() const noexcept
393    {
394        return (flags_ & ModifierFlags::SETTER) != 0;
395    }
396
397    void AddModifier(ModifierFlags const flags) noexcept
398    {
399        flags_ |= flags;
400    }
401
402    void ClearModifier(ModifierFlags const flags) noexcept
403    {
404        flags_ &= ~flags;
405    }
406
407    [[nodiscard]] ModifierFlags Modifiers() noexcept
408    {
409        return flags_;
410    }
411
412    [[nodiscard]] ModifierFlags Modifiers() const noexcept
413    {
414        return flags_;
415    }
416
417    [[nodiscard]] bool HasExportAlias() const noexcept;
418
419    // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
420#define DECLARE_FLAG_OPERATIONS(flag_type, member_name)     \
421    void Set##flag_type(flag_type flags) const noexcept     \
422    {                                                       \
423        (member_name) = flags;                              \
424    }                                                       \
425                                                            \
426    void Add##flag_type(flag_type flag) const noexcept      \
427    {                                                       \
428        (member_name) |= flag;                              \
429    }                                                       \
430                                                            \
431    [[nodiscard]] flag_type Get##flag_type() const noexcept \
432    {                                                       \
433        return (member_name);                               \
434    }                                                       \
435                                                            \
436    bool Has##flag_type(flag_type flag) const noexcept      \
437    {                                                       \
438        return ((member_name)&flag) != 0U;                  \
439    }                                                       \
440    void Remove##flag_type(flag_type flag) const noexcept   \
441    {                                                       \
442        (member_name) &= ~flag;                             \
443    }
444
445    DECLARE_FLAG_OPERATIONS(BoxingUnboxingFlags, boxingUnboxingFlags_);
446    DECLARE_FLAG_OPERATIONS(AstNodeFlags, astNodeFlags_);
447#undef DECLARE_FLAG_OPERATIONS
448
449    ir::ClassElement *AsClassElement();
450    const ir::ClassElement *AsClassElement() const;
451
452    static varbinder::Scope *EnclosingScope(const ir::AstNode *expr);
453
454    [[nodiscard]] virtual bool IsScopeBearer() const noexcept;
455    [[nodiscard]] virtual varbinder::Scope *Scope() const noexcept;
456
457    virtual void ClearScope() noexcept;
458
459    [[nodiscard]] ir::BlockStatement *GetTopStatement();
460    [[nodiscard]] const ir::BlockStatement *GetTopStatement() const;
461
462    [[nodiscard]] virtual AstNode *Clone(ArenaAllocator *const allocator, AstNode *const parent);
463
464    virtual void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) = 0;
465    virtual void Iterate(const NodeTraverser &cb) const = 0;
466
467    void TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName);
468    void TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName);
469    void TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName);
470
471    void IterateRecursively(const NodeTraverser &cb) const;
472    void IterateRecursivelyPreorder(const NodeTraverser &cb) const;
473    void IterateRecursivelyPostorder(const NodeTraverser &cb) const;
474
475    bool IsAnyChild(const NodePredicate &cb) const;
476    AstNode *FindChild(const NodePredicate &cb) const;
477
478    std::string DumpJSON() const;
479    std::string DumpEtsSrc() const;
480
481    virtual void Dump(ir::AstDumper *dumper) const = 0;
482    virtual void Dump(ir::SrcDumper *dumper) const = 0;
483    virtual void Compile([[maybe_unused]] compiler::PandaGen *pg) const = 0;
484    virtual void Compile([[maybe_unused]] compiler::ETSGen *etsg) const {};
485    virtual checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) = 0;
486    virtual checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) = 0;
487
488    void SetTransformedNode(std::string_view transformationName, AstNode *transformedNode);
489
490    using ASTVisitorT = visitor::ASTAbstractVisitor;
491
492    virtual void Accept(ASTVisitorT *v) = 0;
493
494    /**
495     * On each node you should implement:
496     *  void accept(AV* v) override {
497     *      ASTVisitorT::accept(this, v);
498     *  }
499     */
500    void SetOriginalNode(AstNode *originalNode);
501
502protected:
503    AstNode(AstNode const &other);
504
505    void SetType(AstNodeType const type) noexcept
506    {
507        type_ = type;
508    }
509
510    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
511    AstNode *parent_ {};
512    lexer::SourceRange range_ {};
513    AstNodeType type_;
514    ModifierFlags flags_ {};
515    mutable AstNodeFlags astNodeFlags_ {};
516    mutable BoxingUnboxingFlags boxingUnboxingFlags_ {};
517    // NOLINTEND(misc-non-private-member-variables-in-classes)
518
519private:
520    AstNode &operator=(const AstNode &) = default;
521
522    varbinder::Variable *variable_ {};
523    AstNode *originalNode_ = nullptr;
524    // {lowering_phase_name, new_generated_node}
525    std::optional<std::pair<std::string_view, AstNode *>> transformedNode_ = std::nullopt;
526};
527
528template <typename T>
529class Annotated : public T {
530public:
531    Annotated() = delete;
532    ~Annotated() override = default;
533
534    NO_COPY_OPERATOR(Annotated);
535    NO_MOVE_SEMANTIC(Annotated);
536
537    [[nodiscard]] TypeNode *TypeAnnotation() const noexcept
538    {
539        return typeAnnotation_;
540    }
541
542    void SetTsTypeAnnotation(TypeNode *const typeAnnotation) noexcept
543    {
544        typeAnnotation_ = typeAnnotation;
545    }
546
547protected:
548    explicit Annotated(AstNodeType const type, TypeNode *const typeAnnotation)
549        : T(type), typeAnnotation_(typeAnnotation)
550    {
551    }
552    explicit Annotated(AstNodeType const type) : T(type) {}
553    explicit Annotated(AstNodeType const type, ModifierFlags const flags) : T(type, flags) {}
554
555    Annotated(Annotated const &other) : T(static_cast<T const &>(other)) {}
556
557private:
558    TypeNode *typeAnnotation_ {};
559};
560
561}  // namespace ark::es2panda::ir
562#endif
563