13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#ifndef ES2PANDA_IR_AST_NODE_H
173af6ab5fSopenharmony_ci#define ES2PANDA_IR_AST_NODE_H
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "astNodeFlags.h"
203af6ab5fSopenharmony_ci#include "astNodeMapping.h"
213af6ab5fSopenharmony_ci#include "ir/visitor/AstVisitor.h"
223af6ab5fSopenharmony_ci#include "lexer/token/sourceLocation.h"
233af6ab5fSopenharmony_ci#include "macros.h"
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_cinamespace ark::es2panda::compiler {
263af6ab5fSopenharmony_ciclass PandaGen;
273af6ab5fSopenharmony_ciclass ETSGen;
283af6ab5fSopenharmony_ci}  // namespace ark::es2panda::compiler
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
313af6ab5fSopenharmony_ciclass TSChecker;
323af6ab5fSopenharmony_ciclass ETSChecker;
333af6ab5fSopenharmony_ciclass Type;
343af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
353af6ab5fSopenharmony_ci
363af6ab5fSopenharmony_cinamespace ark::es2panda::varbinder {
373af6ab5fSopenharmony_ciclass Variable;
383af6ab5fSopenharmony_ciclass Scope;
393af6ab5fSopenharmony_ci}  // namespace ark::es2panda::varbinder
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_cinamespace ark::es2panda::ir {
423af6ab5fSopenharmony_ci// NOLINTBEGIN(modernize-avoid-c-arrays)
433af6ab5fSopenharmony_ciinline constexpr char const CLONE_ALLOCATION_ERROR[] = "Unsuccessful allocation during cloning.";
443af6ab5fSopenharmony_ci// NOLINTEND(modernize-avoid-c-arrays)
453af6ab5fSopenharmony_ci
463af6ab5fSopenharmony_ciclass AstNode;
473af6ab5fSopenharmony_ciclass TypeNode;
483af6ab5fSopenharmony_ci
493af6ab5fSopenharmony_ciusing NodeTransformer = std::function<AstNode *(AstNode *)>;
503af6ab5fSopenharmony_ciusing NodeTraverser = std::function<void(AstNode *)>;
513af6ab5fSopenharmony_ciusing NodePredicate = std::function<bool(AstNode *)>;
523af6ab5fSopenharmony_ci
533af6ab5fSopenharmony_cienum class AstNodeType {
543af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
553af6ab5fSopenharmony_ci#define DECLARE_NODE_TYPES(nodeType, className) nodeType,
563af6ab5fSopenharmony_ci    AST_NODE_MAPPING(DECLARE_NODE_TYPES)
573af6ab5fSopenharmony_ci#undef DECLARE_NODE_TYPES
583af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
593af6ab5fSopenharmony_ci#define DECLARE_NODE_TYPES(nodeType1, nodeType2, baseClass, reinterpretClass) nodeType1, nodeType2,
603af6ab5fSopenharmony_ci        AST_NODE_REINTERPRET_MAPPING(DECLARE_NODE_TYPES)
613af6ab5fSopenharmony_ci#undef DECLARE_NODE_TYPES
623af6ab5fSopenharmony_ci};
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_ci// Forward declarations
653af6ab5fSopenharmony_ciclass AstDumper;
663af6ab5fSopenharmony_ciclass Expression;
673af6ab5fSopenharmony_ciclass SrcDumper;
683af6ab5fSopenharmony_ciclass Statement;
693af6ab5fSopenharmony_ciclass ClassElement;
703af6ab5fSopenharmony_citemplate <typename T>
713af6ab5fSopenharmony_ciclass Typed;
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
743af6ab5fSopenharmony_ci#define DECLARE_CLASSES(nodeType, className) class className;
753af6ab5fSopenharmony_ciAST_NODE_MAPPING(DECLARE_CLASSES)
763af6ab5fSopenharmony_ci#undef DECLARE_CLASSES
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
793af6ab5fSopenharmony_ci#define DECLARE_CLASSES(nodeType1, nodeType2, baseClass, reinterpretClass) class baseClass;
803af6ab5fSopenharmony_ciAST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES)
813af6ab5fSopenharmony_ci#undef DECLARE_CLASSES
823af6ab5fSopenharmony_ci
833af6ab5fSopenharmony_ciclass AstNode {
843af6ab5fSopenharmony_cipublic:
853af6ab5fSopenharmony_ci    explicit AstNode(AstNodeType type) : type_(type) {};
863af6ab5fSopenharmony_ci    explicit AstNode(AstNodeType type, ModifierFlags flags) : type_(type), flags_(flags) {};
873af6ab5fSopenharmony_ci    virtual ~AstNode() = default;
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_ci    AstNode() = delete;
903af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(AstNode);
913af6ab5fSopenharmony_ci
923af6ab5fSopenharmony_ci    bool IsProgram() const
933af6ab5fSopenharmony_ci    {
943af6ab5fSopenharmony_ci        return parent_ == nullptr;
953af6ab5fSopenharmony_ci    }
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
983af6ab5fSopenharmony_ci#define DECLARE_IS_CHECKS(nodeType, className) \
993af6ab5fSopenharmony_ci    bool Is##className() const                 \
1003af6ab5fSopenharmony_ci    {                                          \
1013af6ab5fSopenharmony_ci        return type_ == AstNodeType::nodeType; \
1023af6ab5fSopenharmony_ci    }
1033af6ab5fSopenharmony_ci    AST_NODE_MAPPING(DECLARE_IS_CHECKS)
1043af6ab5fSopenharmony_ci#undef DECLARE_IS_CHECKS
1053af6ab5fSopenharmony_ci
1063af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1073af6ab5fSopenharmony_ci#define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \
1083af6ab5fSopenharmony_ci    bool Is##baseClass() const                                               \
1093af6ab5fSopenharmony_ci    {                                                                        \
1103af6ab5fSopenharmony_ci        return type_ == AstNodeType::nodeType1;                              \
1113af6ab5fSopenharmony_ci    }                                                                        \
1123af6ab5fSopenharmony_ci    bool Is##reinterpretClass() const                                        \
1133af6ab5fSopenharmony_ci    {                                                                        \
1143af6ab5fSopenharmony_ci        return type_ == AstNodeType::nodeType2;                              \
1153af6ab5fSopenharmony_ci    }
1163af6ab5fSopenharmony_ci    AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS)
1173af6ab5fSopenharmony_ci#undef DECLARE_IS_CHECKS
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_ci    [[nodiscard]] virtual bool IsStatement() const noexcept
1203af6ab5fSopenharmony_ci    {
1213af6ab5fSopenharmony_ci        return false;
1223af6ab5fSopenharmony_ci    }
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    [[nodiscard]] virtual bool IsExpression() const noexcept
1253af6ab5fSopenharmony_ci    {
1263af6ab5fSopenharmony_ci        return false;
1273af6ab5fSopenharmony_ci    }
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci    virtual bool IsTyped() const
1303af6ab5fSopenharmony_ci    {
1313af6ab5fSopenharmony_ci        return false;
1323af6ab5fSopenharmony_ci    }
1333af6ab5fSopenharmony_ci
1343af6ab5fSopenharmony_ci    Typed<AstNode> *AsTyped()
1353af6ab5fSopenharmony_ci    {
1363af6ab5fSopenharmony_ci        ASSERT(IsTyped());
1373af6ab5fSopenharmony_ci        return reinterpret_cast<Typed<AstNode> *>(this);
1383af6ab5fSopenharmony_ci    }
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci    Typed<AstNode> const *AsTyped() const
1413af6ab5fSopenharmony_ci    {
1423af6ab5fSopenharmony_ci        ASSERT(IsTyped());
1433af6ab5fSopenharmony_ci        return reinterpret_cast<Typed<AstNode> const *>(this);
1443af6ab5fSopenharmony_ci    }
1453af6ab5fSopenharmony_ci
1463af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1473af6ab5fSopenharmony_ci#define DECLARE_AS_CASTS(nodeType, className)             \
1483af6ab5fSopenharmony_ci    className *As##className()                            \
1493af6ab5fSopenharmony_ci    {                                                     \
1503af6ab5fSopenharmony_ci        ASSERT(Is##className());                          \
1513af6ab5fSopenharmony_ci        return reinterpret_cast<className *>(this);       \
1523af6ab5fSopenharmony_ci    }                                                     \
1533af6ab5fSopenharmony_ci    const className *As##className() const                \
1543af6ab5fSopenharmony_ci    {                                                     \
1553af6ab5fSopenharmony_ci        ASSERT(Is##className());                          \
1563af6ab5fSopenharmony_ci        return reinterpret_cast<const className *>(this); \
1573af6ab5fSopenharmony_ci    }
1583af6ab5fSopenharmony_ci    AST_NODE_MAPPING(DECLARE_AS_CASTS)
1593af6ab5fSopenharmony_ci#undef DECLARE_AS_CASTS
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
1623af6ab5fSopenharmony_ci#define DECLARE_AS_CASTS(nodeType1, nodeType2, baseClass, reinterpretClass) \
1633af6ab5fSopenharmony_ci    baseClass *As##baseClass()                                              \
1643af6ab5fSopenharmony_ci    {                                                                       \
1653af6ab5fSopenharmony_ci        ASSERT(Is##baseClass());                                            \
1663af6ab5fSopenharmony_ci        return reinterpret_cast<baseClass *>(this);                         \
1673af6ab5fSopenharmony_ci    }                                                                       \
1683af6ab5fSopenharmony_ci    baseClass *As##reinterpretClass()                                       \
1693af6ab5fSopenharmony_ci    {                                                                       \
1703af6ab5fSopenharmony_ci        ASSERT(Is##reinterpretClass());                                     \
1713af6ab5fSopenharmony_ci        return reinterpret_cast<baseClass *>(this);                         \
1723af6ab5fSopenharmony_ci    }                                                                       \
1733af6ab5fSopenharmony_ci    const baseClass *As##baseClass() const                                  \
1743af6ab5fSopenharmony_ci    {                                                                       \
1753af6ab5fSopenharmony_ci        ASSERT(Is##baseClass());                                            \
1763af6ab5fSopenharmony_ci        return reinterpret_cast<const baseClass *>(this);                   \
1773af6ab5fSopenharmony_ci    }                                                                       \
1783af6ab5fSopenharmony_ci    const baseClass *As##reinterpretClass() const                           \
1793af6ab5fSopenharmony_ci    {                                                                       \
1803af6ab5fSopenharmony_ci        ASSERT(Is##reinterpretClass());                                     \
1813af6ab5fSopenharmony_ci        return reinterpret_cast<const baseClass *>(this);                   \
1823af6ab5fSopenharmony_ci    }
1833af6ab5fSopenharmony_ci    AST_NODE_REINTERPRET_MAPPING(DECLARE_AS_CASTS)
1843af6ab5fSopenharmony_ci#undef DECLARE_AS_CASTS
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci    Expression *AsExpression()
1873af6ab5fSopenharmony_ci    {
1883af6ab5fSopenharmony_ci        ASSERT(IsExpression());
1893af6ab5fSopenharmony_ci        return reinterpret_cast<Expression *>(this);
1903af6ab5fSopenharmony_ci    }
1913af6ab5fSopenharmony_ci
1923af6ab5fSopenharmony_ci    const Expression *AsExpression() const
1933af6ab5fSopenharmony_ci    {
1943af6ab5fSopenharmony_ci        ASSERT(IsExpression());
1953af6ab5fSopenharmony_ci        return reinterpret_cast<const Expression *>(this);
1963af6ab5fSopenharmony_ci    }
1973af6ab5fSopenharmony_ci
1983af6ab5fSopenharmony_ci    Statement *AsStatement()
1993af6ab5fSopenharmony_ci    {
2003af6ab5fSopenharmony_ci        ASSERT(IsStatement());
2013af6ab5fSopenharmony_ci        return reinterpret_cast<Statement *>(this);
2023af6ab5fSopenharmony_ci    }
2033af6ab5fSopenharmony_ci
2043af6ab5fSopenharmony_ci    const Statement *AsStatement() const
2053af6ab5fSopenharmony_ci    {
2063af6ab5fSopenharmony_ci        ASSERT(IsStatement());
2073af6ab5fSopenharmony_ci        return reinterpret_cast<const Statement *>(this);
2083af6ab5fSopenharmony_ci    }
2093af6ab5fSopenharmony_ci
2103af6ab5fSopenharmony_ci    void SetRange(const lexer::SourceRange &loc) noexcept
2113af6ab5fSopenharmony_ci    {
2123af6ab5fSopenharmony_ci        range_ = loc;
2133af6ab5fSopenharmony_ci    }
2143af6ab5fSopenharmony_ci
2153af6ab5fSopenharmony_ci    void SetStart(const lexer::SourcePosition &start) noexcept
2163af6ab5fSopenharmony_ci    {
2173af6ab5fSopenharmony_ci        range_.start = start;
2183af6ab5fSopenharmony_ci    }
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_ci    void SetEnd(const lexer::SourcePosition &end) noexcept
2213af6ab5fSopenharmony_ci    {
2223af6ab5fSopenharmony_ci        range_.end = end;
2233af6ab5fSopenharmony_ci    }
2243af6ab5fSopenharmony_ci
2253af6ab5fSopenharmony_ci    [[nodiscard]] const lexer::SourcePosition &Start() const noexcept
2263af6ab5fSopenharmony_ci    {
2273af6ab5fSopenharmony_ci        return range_.start;
2283af6ab5fSopenharmony_ci    }
2293af6ab5fSopenharmony_ci
2303af6ab5fSopenharmony_ci    [[nodiscard]] const lexer::SourcePosition &End() const noexcept
2313af6ab5fSopenharmony_ci    {
2323af6ab5fSopenharmony_ci        return range_.end;
2333af6ab5fSopenharmony_ci    }
2343af6ab5fSopenharmony_ci
2353af6ab5fSopenharmony_ci    [[nodiscard]] const lexer::SourceRange &Range() const noexcept
2363af6ab5fSopenharmony_ci    {
2373af6ab5fSopenharmony_ci        return range_;
2383af6ab5fSopenharmony_ci    }
2393af6ab5fSopenharmony_ci
2403af6ab5fSopenharmony_ci    [[nodiscard]] AstNodeType Type() const noexcept
2413af6ab5fSopenharmony_ci    {
2423af6ab5fSopenharmony_ci        return type_;
2433af6ab5fSopenharmony_ci    }
2443af6ab5fSopenharmony_ci
2453af6ab5fSopenharmony_ci    [[nodiscard]] AstNode *Parent() noexcept
2463af6ab5fSopenharmony_ci    {
2473af6ab5fSopenharmony_ci        return parent_;
2483af6ab5fSopenharmony_ci    }
2493af6ab5fSopenharmony_ci
2503af6ab5fSopenharmony_ci    [[nodiscard]] const AstNode *Parent() const noexcept
2513af6ab5fSopenharmony_ci    {
2523af6ab5fSopenharmony_ci        return parent_;
2533af6ab5fSopenharmony_ci    }
2543af6ab5fSopenharmony_ci
2553af6ab5fSopenharmony_ci    void SetParent(AstNode *const parent) noexcept
2563af6ab5fSopenharmony_ci    {
2573af6ab5fSopenharmony_ci        parent_ = parent;
2583af6ab5fSopenharmony_ci    }
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_ci    [[nodiscard]] varbinder::Variable *Variable() const noexcept
2613af6ab5fSopenharmony_ci    {
2623af6ab5fSopenharmony_ci        return variable_;
2633af6ab5fSopenharmony_ci    }
2643af6ab5fSopenharmony_ci
2653af6ab5fSopenharmony_ci    void SetVariable(varbinder::Variable *variable) noexcept
2663af6ab5fSopenharmony_ci    {
2673af6ab5fSopenharmony_ci        variable_ = variable;
2683af6ab5fSopenharmony_ci    }
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_ci    // When no decorators are allowed, we cannot return a reference to an empty vector.
2713af6ab5fSopenharmony_ci    virtual const ArenaVector<ir::Decorator *> *DecoratorsPtr() const
2723af6ab5fSopenharmony_ci    {
2733af6ab5fSopenharmony_ci        return nullptr;
2743af6ab5fSopenharmony_ci    }
2753af6ab5fSopenharmony_ci
2763af6ab5fSopenharmony_ci    virtual void AddDecorators([[maybe_unused]] ArenaVector<ir::Decorator *> &&decorators)
2773af6ab5fSopenharmony_ci    {
2783af6ab5fSopenharmony_ci        UNREACHABLE();
2793af6ab5fSopenharmony_ci    }
2803af6ab5fSopenharmony_ci
2813af6ab5fSopenharmony_ci    virtual bool CanHaveDecorator([[maybe_unused]] bool inTs) const
2823af6ab5fSopenharmony_ci    {
2833af6ab5fSopenharmony_ci        return false;
2843af6ab5fSopenharmony_ci    }
2853af6ab5fSopenharmony_ci
2863af6ab5fSopenharmony_ci    [[nodiscard]] bool IsReadonly() const noexcept
2873af6ab5fSopenharmony_ci    {
2883af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::READONLY) != 0;
2893af6ab5fSopenharmony_ci    }
2903af6ab5fSopenharmony_ci
2913af6ab5fSopenharmony_ci    [[nodiscard]] bool IsOptionalDeclaration() const noexcept
2923af6ab5fSopenharmony_ci    {
2933af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::OPTIONAL) != 0;
2943af6ab5fSopenharmony_ci    }
2953af6ab5fSopenharmony_ci
2963af6ab5fSopenharmony_ci    [[nodiscard]] bool IsDefinite() const noexcept
2973af6ab5fSopenharmony_ci    {
2983af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::DEFINITE) != 0;
2993af6ab5fSopenharmony_ci    }
3003af6ab5fSopenharmony_ci
3013af6ab5fSopenharmony_ci    [[nodiscard]] bool IsConstructor() const noexcept
3023af6ab5fSopenharmony_ci    {
3033af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::CONSTRUCTOR) != 0;
3043af6ab5fSopenharmony_ci    }
3053af6ab5fSopenharmony_ci
3063af6ab5fSopenharmony_ci    [[nodiscard]] bool IsOverride() const noexcept
3073af6ab5fSopenharmony_ci    {
3083af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::OVERRIDE) != 0;
3093af6ab5fSopenharmony_ci    }
3103af6ab5fSopenharmony_ci
3113af6ab5fSopenharmony_ci    void SetOverride() noexcept
3123af6ab5fSopenharmony_ci    {
3133af6ab5fSopenharmony_ci        flags_ |= ModifierFlags::OVERRIDE;
3143af6ab5fSopenharmony_ci    }
3153af6ab5fSopenharmony_ci
3163af6ab5fSopenharmony_ci    [[nodiscard]] bool IsAsync() const noexcept
3173af6ab5fSopenharmony_ci    {
3183af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::ASYNC) != 0;
3193af6ab5fSopenharmony_ci    }
3203af6ab5fSopenharmony_ci
3213af6ab5fSopenharmony_ci    [[nodiscard]] bool IsSynchronized() const noexcept
3223af6ab5fSopenharmony_ci    {
3233af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::SYNCHRONIZED) != 0;
3243af6ab5fSopenharmony_ci    }
3253af6ab5fSopenharmony_ci
3263af6ab5fSopenharmony_ci    [[nodiscard]] bool IsNative() const noexcept
3273af6ab5fSopenharmony_ci    {
3283af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::NATIVE) != 0;
3293af6ab5fSopenharmony_ci    }
3303af6ab5fSopenharmony_ci
3313af6ab5fSopenharmony_ci    [[nodiscard]] bool IsConst() const noexcept
3323af6ab5fSopenharmony_ci    {
3333af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::CONST) != 0;
3343af6ab5fSopenharmony_ci    }
3353af6ab5fSopenharmony_ci
3363af6ab5fSopenharmony_ci    [[nodiscard]] bool IsStatic() const noexcept
3373af6ab5fSopenharmony_ci    {
3383af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::STATIC) != 0;
3393af6ab5fSopenharmony_ci    }
3403af6ab5fSopenharmony_ci
3413af6ab5fSopenharmony_ci    [[nodiscard]] bool IsFinal() const noexcept
3423af6ab5fSopenharmony_ci    {
3433af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::FINAL) != 0U;
3443af6ab5fSopenharmony_ci    }
3453af6ab5fSopenharmony_ci
3463af6ab5fSopenharmony_ci    [[nodiscard]] bool IsAbstract() const noexcept
3473af6ab5fSopenharmony_ci    {
3483af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::ABSTRACT) != 0;
3493af6ab5fSopenharmony_ci    }
3503af6ab5fSopenharmony_ci
3513af6ab5fSopenharmony_ci    [[nodiscard]] bool IsPublic() const noexcept
3523af6ab5fSopenharmony_ci    {
3533af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::PUBLIC) != 0;
3543af6ab5fSopenharmony_ci    }
3553af6ab5fSopenharmony_ci
3563af6ab5fSopenharmony_ci    [[nodiscard]] bool IsProtected() const noexcept
3573af6ab5fSopenharmony_ci    {
3583af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::PROTECTED) != 0;
3593af6ab5fSopenharmony_ci    }
3603af6ab5fSopenharmony_ci
3613af6ab5fSopenharmony_ci    [[nodiscard]] bool IsPrivate() const noexcept
3623af6ab5fSopenharmony_ci    {
3633af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::PRIVATE) != 0;
3643af6ab5fSopenharmony_ci    }
3653af6ab5fSopenharmony_ci
3663af6ab5fSopenharmony_ci    [[nodiscard]] bool IsInternal() const noexcept
3673af6ab5fSopenharmony_ci    {
3683af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::INTERNAL) != 0;
3693af6ab5fSopenharmony_ci    }
3703af6ab5fSopenharmony_ci
3713af6ab5fSopenharmony_ci    [[nodiscard]] bool IsExported() const noexcept;
3723af6ab5fSopenharmony_ci
3733af6ab5fSopenharmony_ci    [[nodiscard]] bool IsDefaultExported() const noexcept;
3743af6ab5fSopenharmony_ci
3753af6ab5fSopenharmony_ci    [[nodiscard]] bool IsExportedType() const noexcept;
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_ci    [[nodiscard]] bool IsDeclare() const noexcept
3783af6ab5fSopenharmony_ci    {
3793af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::DECLARE) != 0;
3803af6ab5fSopenharmony_ci    }
3813af6ab5fSopenharmony_ci
3823af6ab5fSopenharmony_ci    [[nodiscard]] bool IsIn() const noexcept
3833af6ab5fSopenharmony_ci    {
3843af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::IN) != 0;
3853af6ab5fSopenharmony_ci    }
3863af6ab5fSopenharmony_ci
3873af6ab5fSopenharmony_ci    [[nodiscard]] bool IsOut() const noexcept
3883af6ab5fSopenharmony_ci    {
3893af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::OUT) != 0;
3903af6ab5fSopenharmony_ci    }
3913af6ab5fSopenharmony_ci
3923af6ab5fSopenharmony_ci    [[nodiscard]] bool IsSetter() const noexcept
3933af6ab5fSopenharmony_ci    {
3943af6ab5fSopenharmony_ci        return (flags_ & ModifierFlags::SETTER) != 0;
3953af6ab5fSopenharmony_ci    }
3963af6ab5fSopenharmony_ci
3973af6ab5fSopenharmony_ci    void AddModifier(ModifierFlags const flags) noexcept
3983af6ab5fSopenharmony_ci    {
3993af6ab5fSopenharmony_ci        flags_ |= flags;
4003af6ab5fSopenharmony_ci    }
4013af6ab5fSopenharmony_ci
4023af6ab5fSopenharmony_ci    void ClearModifier(ModifierFlags const flags) noexcept
4033af6ab5fSopenharmony_ci    {
4043af6ab5fSopenharmony_ci        flags_ &= ~flags;
4053af6ab5fSopenharmony_ci    }
4063af6ab5fSopenharmony_ci
4073af6ab5fSopenharmony_ci    [[nodiscard]] ModifierFlags Modifiers() noexcept
4083af6ab5fSopenharmony_ci    {
4093af6ab5fSopenharmony_ci        return flags_;
4103af6ab5fSopenharmony_ci    }
4113af6ab5fSopenharmony_ci
4123af6ab5fSopenharmony_ci    [[nodiscard]] ModifierFlags Modifiers() const noexcept
4133af6ab5fSopenharmony_ci    {
4143af6ab5fSopenharmony_ci        return flags_;
4153af6ab5fSopenharmony_ci    }
4163af6ab5fSopenharmony_ci
4173af6ab5fSopenharmony_ci    [[nodiscard]] bool HasExportAlias() const noexcept;
4183af6ab5fSopenharmony_ci
4193af6ab5fSopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
4203af6ab5fSopenharmony_ci#define DECLARE_FLAG_OPERATIONS(flag_type, member_name)     \
4213af6ab5fSopenharmony_ci    void Set##flag_type(flag_type flags) const noexcept     \
4223af6ab5fSopenharmony_ci    {                                                       \
4233af6ab5fSopenharmony_ci        (member_name) = flags;                              \
4243af6ab5fSopenharmony_ci    }                                                       \
4253af6ab5fSopenharmony_ci                                                            \
4263af6ab5fSopenharmony_ci    void Add##flag_type(flag_type flag) const noexcept      \
4273af6ab5fSopenharmony_ci    {                                                       \
4283af6ab5fSopenharmony_ci        (member_name) |= flag;                              \
4293af6ab5fSopenharmony_ci    }                                                       \
4303af6ab5fSopenharmony_ci                                                            \
4313af6ab5fSopenharmony_ci    [[nodiscard]] flag_type Get##flag_type() const noexcept \
4323af6ab5fSopenharmony_ci    {                                                       \
4333af6ab5fSopenharmony_ci        return (member_name);                               \
4343af6ab5fSopenharmony_ci    }                                                       \
4353af6ab5fSopenharmony_ci                                                            \
4363af6ab5fSopenharmony_ci    bool Has##flag_type(flag_type flag) const noexcept      \
4373af6ab5fSopenharmony_ci    {                                                       \
4383af6ab5fSopenharmony_ci        return ((member_name)&flag) != 0U;                  \
4393af6ab5fSopenharmony_ci    }                                                       \
4403af6ab5fSopenharmony_ci    void Remove##flag_type(flag_type flag) const noexcept   \
4413af6ab5fSopenharmony_ci    {                                                       \
4423af6ab5fSopenharmony_ci        (member_name) &= ~flag;                             \
4433af6ab5fSopenharmony_ci    }
4443af6ab5fSopenharmony_ci
4453af6ab5fSopenharmony_ci    DECLARE_FLAG_OPERATIONS(BoxingUnboxingFlags, boxingUnboxingFlags_);
4463af6ab5fSopenharmony_ci    DECLARE_FLAG_OPERATIONS(AstNodeFlags, astNodeFlags_);
4473af6ab5fSopenharmony_ci#undef DECLARE_FLAG_OPERATIONS
4483af6ab5fSopenharmony_ci
4493af6ab5fSopenharmony_ci    ir::ClassElement *AsClassElement();
4503af6ab5fSopenharmony_ci    const ir::ClassElement *AsClassElement() const;
4513af6ab5fSopenharmony_ci
4523af6ab5fSopenharmony_ci    static varbinder::Scope *EnclosingScope(const ir::AstNode *expr);
4533af6ab5fSopenharmony_ci
4543af6ab5fSopenharmony_ci    [[nodiscard]] virtual bool IsScopeBearer() const noexcept;
4553af6ab5fSopenharmony_ci    [[nodiscard]] virtual varbinder::Scope *Scope() const noexcept;
4563af6ab5fSopenharmony_ci
4573af6ab5fSopenharmony_ci    virtual void ClearScope() noexcept;
4583af6ab5fSopenharmony_ci
4593af6ab5fSopenharmony_ci    [[nodiscard]] ir::BlockStatement *GetTopStatement();
4603af6ab5fSopenharmony_ci    [[nodiscard]] const ir::BlockStatement *GetTopStatement() const;
4613af6ab5fSopenharmony_ci
4623af6ab5fSopenharmony_ci    [[nodiscard]] virtual AstNode *Clone(ArenaAllocator *const allocator, AstNode *const parent);
4633af6ab5fSopenharmony_ci
4643af6ab5fSopenharmony_ci    virtual void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) = 0;
4653af6ab5fSopenharmony_ci    virtual void Iterate(const NodeTraverser &cb) const = 0;
4663af6ab5fSopenharmony_ci
4673af6ab5fSopenharmony_ci    void TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName);
4683af6ab5fSopenharmony_ci    void TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName);
4693af6ab5fSopenharmony_ci    void TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName);
4703af6ab5fSopenharmony_ci
4713af6ab5fSopenharmony_ci    void IterateRecursively(const NodeTraverser &cb) const;
4723af6ab5fSopenharmony_ci    void IterateRecursivelyPreorder(const NodeTraverser &cb) const;
4733af6ab5fSopenharmony_ci    void IterateRecursivelyPostorder(const NodeTraverser &cb) const;
4743af6ab5fSopenharmony_ci
4753af6ab5fSopenharmony_ci    bool IsAnyChild(const NodePredicate &cb) const;
4763af6ab5fSopenharmony_ci    AstNode *FindChild(const NodePredicate &cb) const;
4773af6ab5fSopenharmony_ci
4783af6ab5fSopenharmony_ci    std::string DumpJSON() const;
4793af6ab5fSopenharmony_ci    std::string DumpEtsSrc() const;
4803af6ab5fSopenharmony_ci
4813af6ab5fSopenharmony_ci    virtual void Dump(ir::AstDumper *dumper) const = 0;
4823af6ab5fSopenharmony_ci    virtual void Dump(ir::SrcDumper *dumper) const = 0;
4833af6ab5fSopenharmony_ci    virtual void Compile([[maybe_unused]] compiler::PandaGen *pg) const = 0;
4843af6ab5fSopenharmony_ci    virtual void Compile([[maybe_unused]] compiler::ETSGen *etsg) const {};
4853af6ab5fSopenharmony_ci    virtual checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) = 0;
4863af6ab5fSopenharmony_ci    virtual checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) = 0;
4873af6ab5fSopenharmony_ci
4883af6ab5fSopenharmony_ci    void SetTransformedNode(std::string_view transformationName, AstNode *transformedNode);
4893af6ab5fSopenharmony_ci
4903af6ab5fSopenharmony_ci    using ASTVisitorT = visitor::ASTAbstractVisitor;
4913af6ab5fSopenharmony_ci
4923af6ab5fSopenharmony_ci    virtual void Accept(ASTVisitorT *v) = 0;
4933af6ab5fSopenharmony_ci
4943af6ab5fSopenharmony_ci    /**
4953af6ab5fSopenharmony_ci     * On each node you should implement:
4963af6ab5fSopenharmony_ci     *  void accept(AV* v) override {
4973af6ab5fSopenharmony_ci     *      ASTVisitorT::accept(this, v);
4983af6ab5fSopenharmony_ci     *  }
4993af6ab5fSopenharmony_ci     */
5003af6ab5fSopenharmony_ci    void SetOriginalNode(AstNode *originalNode);
5013af6ab5fSopenharmony_ci
5023af6ab5fSopenharmony_ciprotected:
5033af6ab5fSopenharmony_ci    AstNode(AstNode const &other);
5043af6ab5fSopenharmony_ci
5053af6ab5fSopenharmony_ci    void SetType(AstNodeType const type) noexcept
5063af6ab5fSopenharmony_ci    {
5073af6ab5fSopenharmony_ci        type_ = type;
5083af6ab5fSopenharmony_ci    }
5093af6ab5fSopenharmony_ci
5103af6ab5fSopenharmony_ci    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
5113af6ab5fSopenharmony_ci    AstNode *parent_ {};
5123af6ab5fSopenharmony_ci    lexer::SourceRange range_ {};
5133af6ab5fSopenharmony_ci    AstNodeType type_;
5143af6ab5fSopenharmony_ci    ModifierFlags flags_ {};
5153af6ab5fSopenharmony_ci    mutable AstNodeFlags astNodeFlags_ {};
5163af6ab5fSopenharmony_ci    mutable BoxingUnboxingFlags boxingUnboxingFlags_ {};
5173af6ab5fSopenharmony_ci    // NOLINTEND(misc-non-private-member-variables-in-classes)
5183af6ab5fSopenharmony_ci
5193af6ab5fSopenharmony_ciprivate:
5203af6ab5fSopenharmony_ci    AstNode &operator=(const AstNode &) = default;
5213af6ab5fSopenharmony_ci
5223af6ab5fSopenharmony_ci    varbinder::Variable *variable_ {};
5233af6ab5fSopenharmony_ci    AstNode *originalNode_ = nullptr;
5243af6ab5fSopenharmony_ci    // {lowering_phase_name, new_generated_node}
5253af6ab5fSopenharmony_ci    std::optional<std::pair<std::string_view, AstNode *>> transformedNode_ = std::nullopt;
5263af6ab5fSopenharmony_ci};
5273af6ab5fSopenharmony_ci
5283af6ab5fSopenharmony_citemplate <typename T>
5293af6ab5fSopenharmony_ciclass Annotated : public T {
5303af6ab5fSopenharmony_cipublic:
5313af6ab5fSopenharmony_ci    Annotated() = delete;
5323af6ab5fSopenharmony_ci    ~Annotated() override = default;
5333af6ab5fSopenharmony_ci
5343af6ab5fSopenharmony_ci    NO_COPY_OPERATOR(Annotated);
5353af6ab5fSopenharmony_ci    NO_MOVE_SEMANTIC(Annotated);
5363af6ab5fSopenharmony_ci
5373af6ab5fSopenharmony_ci    [[nodiscard]] TypeNode *TypeAnnotation() const noexcept
5383af6ab5fSopenharmony_ci    {
5393af6ab5fSopenharmony_ci        return typeAnnotation_;
5403af6ab5fSopenharmony_ci    }
5413af6ab5fSopenharmony_ci
5423af6ab5fSopenharmony_ci    void SetTsTypeAnnotation(TypeNode *const typeAnnotation) noexcept
5433af6ab5fSopenharmony_ci    {
5443af6ab5fSopenharmony_ci        typeAnnotation_ = typeAnnotation;
5453af6ab5fSopenharmony_ci    }
5463af6ab5fSopenharmony_ci
5473af6ab5fSopenharmony_ciprotected:
5483af6ab5fSopenharmony_ci    explicit Annotated(AstNodeType const type, TypeNode *const typeAnnotation)
5493af6ab5fSopenharmony_ci        : T(type), typeAnnotation_(typeAnnotation)
5503af6ab5fSopenharmony_ci    {
5513af6ab5fSopenharmony_ci    }
5523af6ab5fSopenharmony_ci    explicit Annotated(AstNodeType const type) : T(type) {}
5533af6ab5fSopenharmony_ci    explicit Annotated(AstNodeType const type, ModifierFlags const flags) : T(type, flags) {}
5543af6ab5fSopenharmony_ci
5553af6ab5fSopenharmony_ci    Annotated(Annotated const &other) : T(static_cast<T const &>(other)) {}
5563af6ab5fSopenharmony_ci
5573af6ab5fSopenharmony_ciprivate:
5583af6ab5fSopenharmony_ci    TypeNode *typeAnnotation_ {};
5593af6ab5fSopenharmony_ci};
5603af6ab5fSopenharmony_ci
5613af6ab5fSopenharmony_ci}  // namespace ark::es2panda::ir
5623af6ab5fSopenharmony_ci#endif
563