* Copyright (c) 2021-2025 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_EXPRESSION_H
#define ES2PANDA_IR_EXPRESSION_H
#include "ir/typed.h"
namespace ark::es2panda::ir {
class Literal;
class TypeNode;
class AnnotatedExpression;
class Expression : public TypedAstNode {
public:
Expression() = delete;
~Expression() override = default;
Expression &operator=(const Expression &) = delete;
NO_MOVE_SEMANTIC(Expression);
[[nodiscard]] bool IsGrouped() const noexcept
{
return AstNode::GetHistoryNodeAs<Expression>()->HasAstNodeFlags(AstNodeFlags::IS_GROUPED);
}
void SetGrouped() noexcept
{
if (!IsGrouped()) {
AstNode::GetOrCreateHistoryNodeAs<Expression>()->SetAstNodeFlags(AstNodeFlags::IS_GROUPED);
}
}
[[nodiscard]] const Literal *AsLiteral() const
{
ES2PANDA_ASSERT(IsLiteral());
return reinterpret_cast<const Literal *>(GetHistoryNodeAs<Expression>());
}
[[nodiscard]] Literal *AsLiteral()
{
ES2PANDA_ASSERT(IsLiteral());
return reinterpret_cast<Literal *>(GetHistoryNodeAs<Expression>());
}
[[nodiscard]] virtual bool IsLiteral() const noexcept
{
return false;
}
[[nodiscard]] virtual bool IsTypeNode() const noexcept
{
return false;
}
[[nodiscard]] virtual bool IsAnnotatedExpression() const noexcept
{
return false;
}
[[nodiscard]] bool IsExpression() const noexcept override
{
return true;
}
[[nodiscard]] TypeNode *AsTypeNode()
{
ES2PANDA_ASSERT(IsTypeNode());
return reinterpret_cast<TypeNode *>(GetHistoryNodeAs<Expression>());
}
[[nodiscard]] const TypeNode *AsTypeNode() const
{
ES2PANDA_ASSERT(IsTypeNode());
return reinterpret_cast<const TypeNode *>(GetHistoryNodeAs<Expression>());
}
[[nodiscard]] AnnotatedExpression *AsAnnotatedExpression()
{
ES2PANDA_ASSERT(IsAnnotatedExpression());
return reinterpret_cast<AnnotatedExpression *>(GetHistoryNodeAs<Expression>());
}
[[nodiscard]] const AnnotatedExpression *AsAnnotatedExpression() const
{
ES2PANDA_ASSERT(IsAnnotatedExpression());
return reinterpret_cast<const AnnotatedExpression *>(GetHistoryNodeAs<Expression>());
}
bool IsBrokenExpression() const noexcept;
[[nodiscard]] virtual std::string ToString() const;
void CopyTo(AstNode *other) const override;
protected:
explicit Expression(AstNodeType const type) : TypedAstNode(type) {}
explicit Expression(AstNodeType const type, ModifierFlags const flags) : TypedAstNode(type, flags) {}
Expression(Expression const &other) : TypedAstNode(static_cast<TypedAstNode const &>(other)) {}
private:
friend class SizeOfNodeTest;
};
class AnnotatedExpression : public Annotated<Expression> {
public:
AnnotatedExpression() = delete;
~AnnotatedExpression() override = default;
NO_COPY_SEMANTIC(AnnotatedExpression);
NO_MOVE_SEMANTIC(AnnotatedExpression);
[[nodiscard]] bool IsAnnotatedExpression() const noexcept override
{
return true;
}
void SetTypeAnnotation(TypeNode *typeAnnotation);
protected:
explicit AnnotatedExpression(AstNodeType const type, TypeNode *const typeAnnotation)
: Annotated<Expression>(type, typeAnnotation)
{
}
explicit AnnotatedExpression(AstNodeType const type) : Annotated<Expression>(type) {}
explicit AnnotatedExpression(AnnotatedExpression const &other, ArenaAllocator *allocator);
};
class MaybeOptionalExpression : public Expression {
public:
MaybeOptionalExpression() = delete;
~MaybeOptionalExpression() override = default;
MaybeOptionalExpression &operator=(const MaybeOptionalExpression &) = delete;
NO_MOVE_SEMANTIC(MaybeOptionalExpression);
[[nodiscard]] bool IsOptional() const noexcept
{
return GetHistoryNodeAs<MaybeOptionalExpression>()->optional_;
}
void ClearOptional() noexcept
{
GetOrCreateHistoryNodeAs<MaybeOptionalExpression>()->optional_ = false;
}
protected:
explicit MaybeOptionalExpression(AstNodeType type, bool optional) : Expression(type), optional_(optional) {}
explicit MaybeOptionalExpression(AstNodeType type, ModifierFlags flags, bool optional)
: Expression(type, flags), optional_(optional)
{
}
MaybeOptionalExpression(MaybeOptionalExpression const &other) : Expression(static_cast<Expression const &>(other))
{
optional_ = other.optional_;
}
private:
bool optional_;
};
}
#endif