* Copyright (c) 2021-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ES2PANDA_IR_ASTNODE_H
#define ES2PANDA_IR_ASTNODE_H
#include <functional>
#include <macros.h>
#include <binder/binder.h>
#include <binder/scope.h>
#include <ir/astNodeMapping.h>
#include <lexer/token/sourceLocation.h>
#include <util/enumbitops.h>
namespace panda::es2panda::compiler {
class PandaGen;
}
namespace panda::es2panda::ir {
class AstNode;
using NodeTraverser = std::function<void(AstNode *)>;
using UpdateNodes = std::variant<AstNode *, std::vector<AstNode *>>;
using NodeUpdater = std::function<UpdateNodes(AstNode *)>;
enum class AstNodeType {
#define DECLARE_NODE_TYPES(nodeType, className) nodeType,
AST_NODE_MAPPING(DECLARE_NODE_TYPES)
#undef DECLARE_NODE_TYPES
#define DECLARE_NODE_TYPES(nodeType1, nodeType2, baseClass, reinterpretClass) nodeType1, nodeType2,
AST_NODE_REINTERPRET_MAPPING(DECLARE_NODE_TYPES)
#undef DECLARE_NODE_TYPES
};
enum class AstNodeFlags : uint8_t {
NO_OPTS = 0,
STRICT = (1U << 0U),
PARAMETER = (1U << 1U),
};
DEFINE_BITOPS(AstNodeFlags)
enum class ModifierFlags : uint16_t {
NONE = 0,
STATIC = 1 << 0,
ASYNC = 1 << 1,
PUBLIC = 1 << 2,
PROTECTED = 1 << 3,
PRIVATE = 1 << 4,
DECLARE = 1 << 5,
READONLY = 1 << 6,
OPTIONAL = 1 << 7,
DEFINITE = 1 << 8,
ABSTRACT = 1 << 9,
ACCESSOR = 1 << 10,
OVERRIDE = 1 << 11,
ACCESS = PUBLIC | PROTECTED | PRIVATE,
ALL = STATIC | ASYNC | ACCESS | DECLARE | READONLY | ABSTRACT | ACCESSOR | OVERRIDE,
ALLOWED_IN_CTOR_PARAMETER = ACCESS | READONLY | OVERRIDE,
};
DEFINE_BITOPS(ModifierFlags)
enum class ScriptFunctionFlags : uint16_t {
NONE = 0,
GENERATOR = 1 << 0,
ASYNC = 1 << 1,
ARROW = 1 << 2,
EXPRESSION = 1 << 3,
OVERLOAD = 1 << 4,
CONSTRUCTOR = 1 << 5,
METHOD = 1 << 6,
CONCURRENT = 1 << 7,
STATIC_INITIALIZER = 1 << 8,
INSTANCE_INITIALIZER = 1 << 9,
GENERATED_CONSTRUCTOR = 1 << 10,
SENDABLE = 1 << 11,
};
DEFINE_BITOPS(ScriptFunctionFlags)
enum class TSOperatorType { READONLY, KEYOF, UNIQUE };
enum class MappedOption { NO_OPTS, PLUS, MINUS };
class AstDumper;
class Expression;
class Statement;
#define DECLARE_CLASSES(nodeType, className) class className;
AST_NODE_MAPPING(DECLARE_CLASSES)
#undef DECLARE_CLASSES
#define DECLARE_CLASSES(nodeType1, nodeType2, baseClass, reinterpretClass) class baseClass;
AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES)
#undef DECLARE_CLASSES
class AstNode {
public:
explicit AstNode(AstNodeType type) : type_(type) {};
virtual ~AstNode() = default;
NO_COPY_SEMANTIC(AstNode);
NO_MOVE_SEMANTIC(AstNode);
bool IsProgram() const
{
return parent_ == nullptr;
}
#define DECLARE_IS_CHECKS(nodeType, className) \
bool Is##className() const \
{ \
return type_ == AstNodeType::nodeType; \
}
AST_NODE_MAPPING(DECLARE_IS_CHECKS)
#undef DECLARE_IS_CHECKS
#define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \
bool Is##baseClass() const \
{ \
return type_ == AstNodeType::nodeType1; \
} \
bool Is##reinterpretClass() const \
{ \
return type_ == AstNodeType::nodeType2; \
}
AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS)
#undef DECLARE_IS_CHECKS
virtual bool IsStatement() const
{
return false;
}
virtual bool IsExpression() const
{
return false;
}
#define DECLARE_AS_CASTS(nodeType, className) \
className *As##className() \
{ \
ASSERT(Is##className()); \
return reinterpret_cast<className *>(this); \
} \
const className *As##className() const \
{ \
ASSERT(Is##className()); \
return reinterpret_cast<const className *>(this); \
}
AST_NODE_MAPPING(DECLARE_AS_CASTS)
#undef DECLARE_AS_CASTS
#define DECLARE_AS_CASTS(nodeType1, nodeType2, baseClass, reinterpretClass) \
baseClass *As##baseClass() \
{ \
ASSERT(Is##baseClass()); \
return reinterpret_cast<baseClass *>(this); \
} \
baseClass *As##reinterpretClass() \
{ \
ASSERT(Is##reinterpretClass()); \
return reinterpret_cast<baseClass *>(this); \
} \
const baseClass *As##baseClass() const \
{ \
ASSERT(Is##baseClass()); \
return reinterpret_cast<const baseClass *>(this); \
} \
const baseClass *As##reinterpretClass() const \
{ \
ASSERT(Is##reinterpretClass()); \
return reinterpret_cast<const baseClass *>(this); \
}
AST_NODE_REINTERPRET_MAPPING(DECLARE_AS_CASTS)
#undef DECLARE_AS_CASTS
Expression *AsExpression()
{
ASSERT(IsExpression());
return reinterpret_cast<Expression *>(this);
}
const Expression *AsExpression() const
{
ASSERT(IsExpression());
return reinterpret_cast<const Expression *>(this);
}
Statement *AsStatement()
{
ASSERT(IsStatement());
return reinterpret_cast<Statement *>(this);
}
const Statement *AsStatement() const
{
ASSERT(IsStatement());
return reinterpret_cast<const Statement *>(this);
}
void SetRange(const lexer::SourceRange &loc)
{
range_ = loc;
}
void SetStart(const lexer::SourcePosition &start)
{
range_.start = start;
}
void SetEnd(const lexer::SourcePosition &end)
{
range_.end = end;
}
const lexer::SourcePosition &Start() const
{
return range_.start;
}
const lexer::SourcePosition &End() const
{
return range_.end;
}
const lexer::SourceRange &Range() const
{
return range_;
}
AstNodeType Type() const
{
return type_;
}
AstNode *Parent()
{
return const_cast<AstNode*>(parent_);
}
const AstNode *Parent() const
{
return parent_;
}
void SetParent(const AstNode *parent)
{
parent_ = parent;
}
const AstNode *Original() const
{
return original_;
}
void SetOriginal(const AstNode *original)
{
original_ = original;
}
binder::Variable *Variable() const
{
return variable_;
}
void SetVariable(binder::Variable *variable)
{
variable_ = variable;
}
virtual void Iterate(const NodeTraverser &cb) const = 0;
virtual void Dump(ir::AstDumper *dumper) const = 0;
virtual void Compile([[maybe_unused]] compiler::PandaGen *pg) const = 0;
virtual void UpdateSelf([[maybe_unused]] const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) = 0;
protected:
void SetType(AstNodeType type)
{
type_ = type;
}
const AstNode *parent_ {};
lexer::SourceRange range_ {};
AstNodeType type_;
binder::Variable *variable_ {nullptr};
const AstNode *original_ {nullptr};
};
}
#endif