#pragma once

#include <string>
#include <vector>
#include <memory>
#include <optional>
#include <cstdint>
#include <variant>

namespace lsp::language::ast
{
    // ===== 基础类型 =====
    struct Location
    {
        uint32_t start_line = 0;
        uint32_t start_column = 0;
        uint32_t end_line = 0;
        uint32_t end_column = 0;
        uint32_t start_byte = 0;
        uint32_t end_byte = 0;
    };

    // ===== 节点类型枚举 =====
    enum class NodeKind
    {
        kProgram,
        // Expressions
        kIdentifier,
        kLiteral,
        kBinaryExpression,
        kUnaryExpression,
        kTernaryExpression,
        kCallExpression,
        kAttributeExpression,
        kSubscriptExpression,
        kArrayExpression,
        kAnonymousFunctionExpression,
        kPrefixIncrementExpression,
        kPrefixDecrementExpression,
        kPostfixIncrementExpression,
        kPostfixDecrementExpression,
        kFunctionPointerExpression,
        kComparisonExpression,

        // Assignment Expressions
        kAssignmentExpression,
        kAugmentedAssignmentExpression,

        // Statements
        kExpressionStatement,
        kVarStatement,
        kStaticStatement,
        kGlobalStatement,
        kConstStatement,
        kAssignmentStatement,
        kBlockStatement,
        kIfStatement,
        kForInStatement,
        kForToStatement,
        kWhileStatement,
        kRepeatStatement,
        kCaseStatement,
        kTryStatement,
        kBreakStatement,
        kContinueStatement,
        kReturnStatement,
        kUsesStatement,
        kInheritedStatement,

        // Declarations
        kVarDeclaration,
        kStaticDeclaration,
        kGlobalDeclaration,
        kFieldDeclaration,
        kFunctionDeclaration,
        kFunctionDefinition,
        kClassDefinition,
        kMethodDeclaration,
        kPropertyDeclaration,
        kExternalMethodDefinition,
        kUnitDefinition,

        // TSSQL 节点
        kTSSQLSelectExpression,
        kTSSQLUpdateExpression,
        kTSSQLDeleteExpression,
        kTSSQLInsertExpression,

        // Special
        kParameter,
        kUnpackPattern,
        kCaseBranch,
        kClassMember,

        kMatrixIterationStatement,

        kCompilerDirectiveStatement,
        kConditionalBlockStatement,
        kConditionalDirectiveStatement,
    };

    // ===== 枚举类型 =====
    enum class LiteralKind
    {
        kNumber,
        kString,
        kBoolean,
        kNil,
        kInfinity,
        kEllipsis
    };

    enum class BinaryOperator
    {
        kAdd,
        kSubtract,
        kMultiply,
        kDivide,
        kIntDivide,
        kModulo,
        kPower,
        kLogarithm,
        kEqual,
        kNotEqual,
        kGreater,
        kGreaterEqual,
        kLess,
        kLessEqual,
        kDotEqual,
        kDotNotEqual,
        kDotGreater,
        kDotGreaterEqual,
        kDotLess,
        kDotLessEqual,
        kLike,
        kIs,
        kIn,
        kLogicalOr,
        kLogicalAnd,
        kDotLogicalOr,
        kDotLogicalAnd,
        kBitwiseOr,
        kBitwiseAnd,
        kBitwiseXor,
        kDotBitwiseOr,
        kDotBitwiseAnd,
        kDotBitwiseXor,
        kShl,
        kShr,
        kRol,
        kRor,
        kMatrixMultiply,
        kMatrixDivide,
        kMatrixIntDivide,
        kMatrixPower,
        kMatrixConcat,
        kMatrixConcatVertical,
        kUnion,
        kUnion2,
        kIntersect,
        kOutersect,
        kMinus,
        kConcatenation,
        kRange,
    };

    enum class UnaryOperator
    {
        kPlus,
        kMinus,
        kNot,
        kBitwiseNot,
        kDotNot,
        kMatrixTranspose,
        kDerivative,
        kExprAt,
        kExprRef,
    };

    enum class AssignmentOperator
    {
        kAssign,
        kAddAssign,
        kSubtractAssign,
        kMultiplyAssign,
        kDivideAssign,
        kIntDivideAssign,
        kPowerAssign,
        kLogarithmAssign,
        kModuloAssign,
        kDivAssign,
        kBitwiseOrAssign,
        kBitwiseAndAssign,
        kMatrixMultiplyAssign,
        kMatrixDivideAssign,
        kMatrixIntDivideAssign,
        kMatrixPowerAssign,
        kMatrixConcatAssign,
        kConcatAssign,
        kDotBitwiseOrAssign,
        kDotBitwiseAndAssign,
        kDotLogicalOrAssign,
        kDotLogicalAndAssign,
        kDotBitwiseXorAssign,
        kUnionAssign,
        kUnion2Assign,
        kIntersectAssign,
        kOutersectAssign,
        kMinusAssign,
    };

    enum class AccessModifier
    {
        kPublic,
        kProtected,
        kPrivate
    };

    enum class ReferenceModifier
    {
        kNone,
        kWeakRef,
        kAutoRef
    };

    enum class MethodModifier
    {
        kNone,
        kVirtual,
        kOverride,
        kOverload
    };

    enum class MethodType
    {
        kNormal,
        kConstructor,
        kDestructor
    };

    enum class TSSQLExpressionType
    {
        kSelect,
        kSSelect,
        kVSelect,
        kMSelect,
        kUpdate,
        kDelete,
        kInsert
    };

    enum class ConditionalCompilationType
    {
        kIfDef,
        kIfNDef,
        kUndef,
        kDef,
    };

    // ===== 前向声明 =====
    class ASTNode;
    class Program;
    class Expression;
    class Statement;
    class Declaration;
    class ASTVisitor;

    class Identifier;
    class Literal;
    class BinaryExpression;
    class UnaryExpression;
    class TernaryExpression;
    class CallExpression;
    class AttributeExpression;
    class SubscriptExpression;
    class ArrayExpression;
    class AnonymousFunctionExpression;
    class PrefixIncrementExpression;
    class PrefixDecrementExpression;
    class PostfixIncrementExpression;
    class PostfixDecrementExpression;
    class FunctionPointerExpression;
    class AssignmentExpression;
    class ComparisonExpression;
    class ExpressionStatement;
    class VarStatement;
    class StaticStatement;
    class GlobalStatement;
    class ConstStatement;
    class AssignmentStatement;
    class BlockStatement;
    class IfStatement;
    class ForInStatement;
    class ForToStatement;
    class WhileStatement;
    class RepeatStatement;
    class CaseStatement;
    class TryStatement;
    class BreakStatement;
    class ContinueStatement;
    class ReturnStatement;
    class UsesStatement;
    class FunctionDefinition;
    class FunctionDeclaration;
    class VarDeclaration;
    class StaticDeclaration;
    class GlobalDeclaration;
    class FieldDeclaration;
    class UnpackPattern;
    class MethodDeclaration;
    class ExternalMethodDefinition;
    class PropertyDeclaration;
    class ClassMember;
    class ClassDefinition;
    class UnitDefinition;
    class TSSQLExpression;
    class MatrixIterationStatement;
    class CompilerDirectiveStatement;
    class ConditionalBlockStatement;
    class ConditionalDirectiveStatement;

    using ASTNodePtr = std::unique_ptr<ASTNode>;
    using ExpressionPtr = std::unique_ptr<Expression>;
    using StatementPtr = std::unique_ptr<Statement>;
    using DeclarationPtr = std::unique_ptr<Declaration>;

    // ===== 访问者接口 =====
    class ASTVisitor
    {
    public:
        virtual ~ASTVisitor() = default;

        virtual void VisitProgram(Program& node) = 0;
        virtual void VisitUnitDefinition(UnitDefinition& node) = 0;
        virtual void VisitMethodDeclaration(MethodDeclaration& node) = 0;
        virtual void VisitPropertyDeclaration(PropertyDeclaration& node) = 0;
        virtual void VisitClassMember(ClassMember& node) = 0;
        virtual void VisitClassDefinition(ClassDefinition& node) = 0;
        virtual void VisitExternalMethodDefinition(ExternalMethodDefinition& node) = 0;
        virtual void VisitIdentifier(Identifier& node) = 0;
        virtual void VisitLiteral(Literal& node) = 0;
        virtual void VisitBinaryExpression(BinaryExpression& node) = 0;
        virtual void VisitUnaryExpression(UnaryExpression& node) = 0;
        virtual void VisitTernaryExpression(TernaryExpression& node) = 0;
        virtual void VisitCallExpression(CallExpression& node) = 0;
        virtual void VisitAttributeExpression(AttributeExpression& node) = 0;
        virtual void VisitSubscriptExpression(SubscriptExpression& node) = 0;
        virtual void VisitArrayExpression(ArrayExpression& node) = 0;
        virtual void VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node) = 0;
        virtual void VisitPrefixIncrementExpression(PrefixIncrementExpression& node) = 0;
        virtual void VisitPrefixDecrementExpression(PrefixDecrementExpression& node) = 0;
        virtual void VisitPostfixIncrementExpression(PostfixIncrementExpression& node) = 0;
        virtual void VisitPostfixDecrementExpression(PostfixDecrementExpression& node) = 0;
        virtual void VisitFunctionPointerExpression(FunctionPointerExpression& node) = 0;
        virtual void VisitAssignmentExpression(AssignmentExpression& node) = 0;
        virtual void VisitComparisonExpression(ComparisonExpression& node) = 0;
        virtual void VisitExpressionStatement(ExpressionStatement& node) = 0;
        virtual void VisitVarStatement(VarStatement& node) = 0;
        virtual void VisitStaticStatement(StaticStatement& node) = 0;
        virtual void VisitGlobalStatement(GlobalStatement& node) = 0;
        virtual void VisitConstStatement(ConstStatement& node) = 0;
        virtual void VisitAssignmentStatement(AssignmentStatement& node) = 0;
        virtual void VisitBlockStatement(BlockStatement& node) = 0;
        virtual void VisitIfStatement(IfStatement& node) = 0;
        virtual void VisitForInStatement(ForInStatement& node) = 0;
        virtual void VisitForToStatement(ForToStatement& node) = 0;
        virtual void VisitWhileStatement(WhileStatement& node) = 0;
        virtual void VisitRepeatStatement(RepeatStatement& node) = 0;
        virtual void VisitCaseStatement(CaseStatement& node) = 0;
        virtual void VisitTryStatement(TryStatement& node) = 0;
        virtual void VisitBreakStatement(BreakStatement& node) = 0;
        virtual void VisitContinueStatement(ContinueStatement& node) = 0;
        virtual void VisitReturnStatement(ReturnStatement& node) = 0;
        virtual void VisitUsesStatement(UsesStatement& node) = 0;
        virtual void VisitFunctionDefinition(FunctionDefinition& node) = 0;
        virtual void VisitFunctionDeclaration(FunctionDeclaration& node) = 0;
        virtual void VisitVarDeclaration(VarDeclaration& node) = 0;
        virtual void VisitStaticDeclaration(StaticDeclaration& node) = 0;
        virtual void VisitGlobalDeclaration(GlobalDeclaration& node) = 0;
        virtual void VisitFieldDeclaration(FieldDeclaration& node) = 0;
        virtual void VisitTSSQLExpression(TSSQLExpression& node) = 0;
        virtual void VisitUnpackPattern(UnpackPattern& node) = 0;
        virtual void VisitMatrixIterationStatement(MatrixIterationStatement& node) = 0;
        virtual void VisitCompilerDirectiveStatement(CompilerDirectiveStatement& node) = 0;
        virtual void VisitConditionalBlockStatement(ConditionalBlockStatement& node) = 0;
        virtual void VisitConditionalDirectiveStatement(ConditionalDirectiveStatement& node) = 0;
    };

    struct TypeAnnotation
    {
        std::string name;
        Location location;
    };

    // ===== 基类 ASTNode =====
    class ASTNode
    {
    public:
        virtual ~ASTNode() = default;
        virtual void Accept(ASTVisitor& visitor) = 0;

    public:
        NodeKind kind;
        Location span;
    };

    // ===== Expression 基类 =====
    class Expression : public ASTNode
    {
    public:
        virtual ~Expression() = default;
        virtual std::optional<std::string> TypeHint() const { return std::nullopt; }
    };

    // ===== 具体节点类型 =====

    class Identifier : public Expression
    {
    public:
        Identifier() { kind = NodeKind::kIdentifier; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitIdentifier(*this); }

    public:
        std::string name;
        Location location;
    };

    class Literal : public Expression
    {
    public:
        Literal() { kind = NodeKind::kLiteral; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitLiteral(*this); }

    public:
        LiteralKind literal_kind;
        std::string name;
        Location location;
    };

    class BinaryExpression : public Expression
    {
    public:
        BinaryExpression() { kind = NodeKind::kBinaryExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitBinaryExpression(*this); }

    public:
        BinaryOperator op;
        ExpressionPtr left;
        ExpressionPtr right;
    };

    class ComparisonExpression : public Expression
    {
    public:
        struct Comparison
        {
            BinaryOperator op;
            ExpressionPtr right;
        };

        ComparisonExpression() { kind = NodeKind::kComparisonExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitComparisonExpression(*this); }

    public:
        ExpressionPtr left;
        std::vector<Comparison> comparisons;
    };

    class UnaryExpression : public Expression
    {
    public:
        UnaryExpression() { kind = NodeKind::kUnaryExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitUnaryExpression(*this); }

    public:
        UnaryOperator op;
        ExpressionPtr argument;
    };

    class TernaryExpression : public Expression
    {
    public:
        TernaryExpression() { kind = NodeKind::kTernaryExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitTernaryExpression(*this); }

    public:
        ExpressionPtr condition;
        ExpressionPtr consequence;
        ExpressionPtr alternative;
    };

    class CallExpression : public Expression
    {
    public:
        struct Argument
        {
            std::optional<std::string> name;
            std::optional<Location> location;
            ExpressionPtr value;
        };

        CallExpression() { kind = NodeKind::kCallExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitCallExpression(*this); }

    public:
        ExpressionPtr callee;
        std::vector<Argument> arguments;
    };

    class AttributeExpression : public Expression
    {
    public:
        AttributeExpression() { kind = NodeKind::kAttributeExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitAttributeExpression(*this); }

    public:
        std::string name;
        Location location;
        ExpressionPtr object;
    };

    class SubscriptExpression : public Expression
    {
    public:
        struct Index
        {
            ExpressionPtr start;
            ExpressionPtr end;
            ExpressionPtr step;
            bool is_slice = false;
            bool is_empty_slice = false;
        };

        SubscriptExpression() { kind = NodeKind::kSubscriptExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitSubscriptExpression(*this); }

    public:
        ExpressionPtr value;
        std::vector<Index> indices;
    };

    class ArrayExpression : public Expression
    {
    public:
        struct Element
        {
            ExpressionPtr key;
            ExpressionPtr value;
            bool is_nested = false;
        };

        ArrayExpression() { kind = NodeKind::kArrayExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitArrayExpression(*this); }

    public:
        std::vector<Element> elements;
    };

    class PrefixIncrementExpression : public Expression
    {
    public:
        PrefixIncrementExpression() { kind = NodeKind::kPrefixIncrementExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitPrefixIncrementExpression(*this); }

    public:
        ExpressionPtr argument;
    };

    class PrefixDecrementExpression : public Expression
    {
    public:
        PrefixDecrementExpression() { kind = NodeKind::kPrefixDecrementExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitPrefixDecrementExpression(*this); }

    public:
        ExpressionPtr argument;
    };

    class PostfixIncrementExpression : public Expression
    {
    public:
        PostfixIncrementExpression() { kind = NodeKind::kPostfixIncrementExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitPostfixIncrementExpression(*this); }

    public:
        ExpressionPtr argument;
    };

    class PostfixDecrementExpression : public Expression
    {
    public:
        PostfixDecrementExpression() { kind = NodeKind::kPostfixDecrementExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitPostfixDecrementExpression(*this); }

    public:
        ExpressionPtr argument;
    };

    class FunctionPointerExpression : public Expression
    {
    public:
        FunctionPointerExpression() { kind = NodeKind::kFunctionPointerExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitFunctionPointerExpression(*this); }

    public:
        ExpressionPtr argument;
    };

    class UnpackPattern : public ASTNode
    {
    public:
        UnpackPattern() { kind = NodeKind::kUnpackPattern; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitUnpackPattern(*this); }

    public:
        std::vector<std::string> names;
    };

    class VarDeclaration : public ASTNode
    {
    public:
        VarDeclaration() { kind = NodeKind::kVarDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitVarDeclaration(*this); }

    public:
        std::string name;
        Location location;
        std::optional<TypeAnnotation> type;
        ExpressionPtr initial_value;
    };

    class StaticDeclaration : public ASTNode
    {
    public:
        StaticDeclaration() { kind = NodeKind::kStaticDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitStaticDeclaration(*this); }

    public:
        ReferenceModifier reference_modifier = ReferenceModifier::kNone;
        std::string name;
        Location location;
        std::optional<TypeAnnotation> type;
        ExpressionPtr initial_value;
    };

    class GlobalDeclaration : public ASTNode
    {
    public:
        GlobalDeclaration() { kind = NodeKind::kGlobalDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitGlobalDeclaration(*this); }

    public:
        std::string name;
        Location location;
        std::optional<TypeAnnotation> type;
        ExpressionPtr initial_value;
    };

    class FieldDeclaration : public ASTNode
    {
    public:
        FieldDeclaration() { kind = NodeKind::kFieldDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitFieldDeclaration(*this); }

    public:
        std::string name;
        std::optional<TypeAnnotation> type;
        ExpressionPtr initial_value;
        ReferenceModifier reference_modifier = ReferenceModifier::kNone;
    };

    using LeftHandSide = std::variant<
        std::unique_ptr<Identifier>,
        std::unique_ptr<AttributeExpression>,
        std::unique_ptr<SubscriptExpression>,
        std::unique_ptr<UnpackPattern>,
        std::unique_ptr<VarDeclaration>,
        std::unique_ptr<StaticDeclaration>,
        std::unique_ptr<GlobalDeclaration>,
        std::unique_ptr<FieldDeclaration>>;

    class AssignmentExpression : public Expression
    {
    public:
        AssignmentExpression() { kind = NodeKind::kAssignmentExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitAssignmentExpression(*this); }

    public:
        LeftHandSide left;
        AssignmentOperator op;
        ExpressionPtr right;
    };

    class TSSQLExpression : public Expression
    {
    public:
        TSSQLExpression() { kind = NodeKind::kTSSQLSelectExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitTSSQLExpression(*this); }

    public:
        TSSQLExpressionType sql_type;
        std::string raw_sql;
    };

    class Statement : public ASTNode
    {
    public:
        virtual ~Statement() = default;
    };

    class ExpressionStatement : public Statement
    {
    public:
        ExpressionStatement() { kind = NodeKind::kExpressionStatement; }

    public:
        void Accept(ASTVisitor& visitor) override { visitor.VisitExpressionStatement(*this); }
        ExpressionPtr expression;
    };

    class AssignmentStatement : public Statement
    {
    public:
        AssignmentStatement() { kind = NodeKind::kAssignmentStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitAssignmentStatement(*this); }

    public:
        LeftHandSide left;
        AssignmentOperator op;
        ExpressionPtr right;
    };

    class BlockStatement : public Statement
    {
    public:
        BlockStatement() { kind = NodeKind::kBlockStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitBlockStatement(*this); }

    public:
        std::vector<StatementPtr> statements;
    };

    class VarStatement : public Statement
    {
    public:
        VarStatement() { kind = NodeKind::kVarStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitVarStatement(*this); }

    public:
        std::vector<std::unique_ptr<VarDeclaration>> declarations;
    };

    class StaticStatement : public Statement
    {
    public:
        StaticStatement() { kind = NodeKind::kStaticStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitStaticStatement(*this); }

    public:
        std::vector<std::unique_ptr<StaticDeclaration>> declarations;
    };

    class GlobalStatement : public Statement
    {
    public:
        GlobalStatement() { kind = NodeKind::kGlobalStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitGlobalStatement(*this); }

    public:
        std::vector<std::unique_ptr<GlobalDeclaration>> declarations;
    };

    class ConstStatement : public Statement
    {
    public:
        ConstStatement() { kind = NodeKind::kConstStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitConstStatement(*this); }

    public:
        std::string name;
        std::optional<std::string> type_name;
        ExpressionPtr value;
    };

    class IfStatement : public Statement
    {
    public:
        struct Branch
        {
            ExpressionPtr condition;
            StatementPtr body;
        };

        IfStatement() { kind = NodeKind::kIfStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitIfStatement(*this); }

    public:
        std::vector<Branch> branches;
    };

    class ForInStatement : public Statement
    {
    public:
        ForInStatement() { kind = NodeKind::kForInStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitForInStatement(*this); }

    public:
        std::string key;
        std::string value;
        ExpressionPtr collection;
        StatementPtr body;
    };

    class ForToStatement : public Statement
    {
    public:
        ForToStatement() { kind = NodeKind::kForToStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitForToStatement(*this); }

    public:
        std::string counter;
        ExpressionPtr start;
        ExpressionPtr end;
        bool is_downto;
        StatementPtr body;
    };

    class WhileStatement : public Statement
    {
    public:
        WhileStatement() { kind = NodeKind::kWhileStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitWhileStatement(*this); }

    public:
        ExpressionPtr condition;
        StatementPtr body;
    };

    class RepeatStatement : public Statement
    {
    public:
        RepeatStatement() { kind = NodeKind::kRepeatStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitRepeatStatement(*this); }

    public:
        std::vector<StatementPtr> body;
        ExpressionPtr condition;
    };

    class CaseStatement : public Statement
    {
    public:
        struct Branch
        {
            std::vector<ExpressionPtr> values;
            StatementPtr body;
        };

        CaseStatement() { kind = NodeKind::kCaseStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitCaseStatement(*this); }

    public:
        ExpressionPtr discriminant;
        std::vector<Branch> branches;
        StatementPtr default_case;
    };

    class TryStatement : public Statement
    {
    public:
        TryStatement() { kind = NodeKind::kTryStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitTryStatement(*this); }

    public:
        StatementPtr try_body;
        StatementPtr except_body;
    };

    class BreakStatement : public Statement
    {
    public:
        BreakStatement() { kind = NodeKind::kBreakStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitBreakStatement(*this); }
    };

    class ContinueStatement : public Statement
    {
    public:
        ContinueStatement() { kind = NodeKind::kContinueStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitContinueStatement(*this); }
    };

    class ReturnStatement : public Statement
    {
    public:
        ReturnStatement() { kind = NodeKind::kReturnStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitReturnStatement(*this); }

    public:
        ExpressionPtr value;
    };

    class UsesStatement : public Statement
    {
    public:
        UsesStatement() { kind = NodeKind::kUsesStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitUsesStatement(*this); }

    public:
        std::vector<std::string> units;
    };

    struct Parameter
    {
        std::string name;
        Location location;
        std::optional<TypeAnnotation> type;
        ExpressionPtr default_value;
        bool is_var = false;
        bool is_out = false;
    };

    struct Signature
    {
        std::vector<Parameter> parameters;
        std::optional<TypeAnnotation> return_type;
    };

    class FunctionDefinition : public Statement
    {
    public:
        FunctionDefinition() { kind = NodeKind::kFunctionDefinition; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitFunctionDefinition(*this); }

    public:
        std::string name;
        Location location;
        Signature signature;
        StatementPtr body;
        bool is_overload;
    };

    class FunctionDeclaration : public Statement
    {
    public:
        FunctionDeclaration() { kind = NodeKind::kFunctionDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitFunctionDeclaration(*this); }

    public:
        std::string name;
        Location location;
        Signature signature;
        bool is_overload;
    };

    class AnonymousFunctionExpression : public Expression
    {
    public:
        AnonymousFunctionExpression() { kind = NodeKind::kAnonymousFunctionExpression; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitAnonymousFunctionExpression(*this); }

    public:
        Signature signature;
        StatementPtr body;
    };

    class MethodDeclaration : public Statement
    {
    public:
        MethodDeclaration() { kind = NodeKind::kMethodDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitMethodDeclaration(*this); }

    public:
        std::string name;
        Location location;
        Signature signature;
        StatementPtr body;
        MethodModifier modifier = MethodModifier::kNone;
        MethodType method_type = MethodType::kNormal;
        bool is_class_method = false;
        bool is_operator_overload = false;
    };

    class PropertyDeclaration : public Statement
    {
    public:
        PropertyDeclaration() { kind = NodeKind::kPropertyDeclaration; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitPropertyDeclaration(*this); }

    public:
        std::string name;
        Location location;
        std::optional<std::string> type_name;
        std::optional<std::string> index_value;
        std::optional<std::string> read_accessor;
        std::optional<std::string> write_accessor;
    };

    class ClassMember : public ASTNode
    {
    public:
        ClassMember() { kind = NodeKind::kClassMember; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitClassMember(*this); }

    public:
        AccessModifier access_modifier = AccessModifier::kPublic;
        std::variant<
            std::unique_ptr<StaticDeclaration>,
            std::unique_ptr<FieldDeclaration>,
            std::unique_ptr<MethodDeclaration>,
            std::unique_ptr<PropertyDeclaration>>
            member;
    };

    class ClassDefinition : public Statement
    {
    public:
        ClassDefinition() { kind = NodeKind::kClassDefinition; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitClassDefinition(*this); }

        struct ParentClass
        {
            std::optional<std::string> qualifier;
            std::optional<Location> qualifier_location;

            std::string name;
            Location location;
        };

    public:
        std::string name;
        Location location;
        std::vector<ParentClass> parent_classes;
        std::vector<std::unique_ptr<ClassMember>> members;
    };

    class UnitDefinition : public Statement
    {
    public:
        UnitDefinition() { kind = NodeKind::kUnitDefinition; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitUnitDefinition(*this); }

    public:
        std::string name;
        Location location;
        std::vector<StatementPtr> interface_statements;
        std::vector<StatementPtr> implementation_statements;
        std::vector<StatementPtr> initialization_statements;
        std::vector<StatementPtr> finalization_statements;
    };

    class ExternalMethodDefinition : public Statement
    {
    public:
        ExternalMethodDefinition() { kind = NodeKind::kExternalMethodDefinition; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitExternalMethodDefinition(*this); }

    public:
        struct
        {
            std::string name;
            Location location;
        } owner_class;
        std::string name;
        Location location;
        Signature signature;
        StatementPtr body;
        MethodModifier modifier = MethodModifier::kNone;
        MethodType method_type = MethodType::kNormal;
        bool is_operator_overload = false;
        bool is_class_method = false;
    };

    class MatrixIterationStatement : public Statement
    {
    public:
        MatrixIterationStatement() { kind = NodeKind::kMatrixIterationStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitMatrixIterationStatement(*this); }

    public:
        ExpressionPtr target;
        StatementPtr body;
    };

    class Program : public ASTNode
    {
    public:
        Program() { kind = NodeKind::kProgram; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitProgram(*this); }

    public:
        std::vector<StatementPtr> statements;
    };

    class CompilerDirectiveStatement : public Statement
    {
    public:
        CompilerDirectiveStatement() { kind = NodeKind::kCompilerDirectiveStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitCompilerDirectiveStatement(*this); }

    public:
        std::string name;
        Location location;
        std::optional<std::string> switch_value; // "+" or "-"
    };

    class ConditionalBlockStatement : public Statement
    {
    public:
        ConditionalBlockStatement() { kind = NodeKind::kConditionalBlockStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitConditionalBlockStatement(*this); }

    public:
        ConditionalCompilationType type;
        std::string name;
        Location location;
        std::vector<StatementPtr> consequence;
        std::vector<StatementPtr> alternative;
    };

    class ConditionalDirectiveStatement : public Statement
    {
    public:
        ConditionalDirectiveStatement() { kind = NodeKind::kConditionalDirectiveStatement; }
        void Accept(ASTVisitor& visitor) override { visitor.VisitConditionalDirectiveStatement(*this); }

    public:
        ConditionalCompilationType type;
        std::string name;
        Location location;
    };

    template<typename T, typename... Args>
    std::unique_ptr<T> MakeNode(Args&&... args)
    {
        return std::make_unique<T>(std::forward<Args>(args)...);
    }

    template<typename T>
    T* CastNode(ASTNode* node)
    {
        return dynamic_cast<T*>(node);
    }

    template<typename T>
    const T* CastNode(const ASTNode* node)
    {
        return dynamic_cast<const T*>(node);
    }

    inline std::string GetBinaryOperatorSymbol(BinaryOperator op)
    {
        switch (op)
        {
        // Arithmetic
        case BinaryOperator::kAdd:
            return "+";
        case BinaryOperator::kSubtract:
            return "-";
        case BinaryOperator::kMultiply:
            return "*";
        case BinaryOperator::kDivide:
            return "/";
        case BinaryOperator::kIntDivide:
            return "\\";
        case BinaryOperator::kModulo:
            return "%";
        case BinaryOperator::kPower:
            return "^";
        case BinaryOperator::kLogarithm:
            return "~";

        // Comparison
        case BinaryOperator::kEqual:
            return "=";
        case BinaryOperator::kNotEqual:
            return "<>";
        case BinaryOperator::kGreater:
            return ">";
        case BinaryOperator::kGreaterEqual:
            return ">=";
        case BinaryOperator::kLess:
            return "<";
        case BinaryOperator::kLessEqual:
            return "<=";
        case BinaryOperator::kDotEqual:
            return ".=";
        case BinaryOperator::kDotNotEqual:
            return ".<>";
        case BinaryOperator::kDotGreater:
            return ".>";
        case BinaryOperator::kDotGreaterEqual:
            return ".>=";
        case BinaryOperator::kDotLess:
            return ".<";
        case BinaryOperator::kDotLessEqual:
            return ".<=";
        case BinaryOperator::kLike:
            return "like";
        case BinaryOperator::kIs:
            return "is";
        case BinaryOperator::kIn:
            return "in";

        // Logical
        case BinaryOperator::kLogicalOr:
            return "or";
        case BinaryOperator::kLogicalAnd:
            return "and";
        case BinaryOperator::kDotLogicalOr:
            return ".||";
        case BinaryOperator::kDotLogicalAnd:
            return ".&&";

        // Bitwise
        case BinaryOperator::kBitwiseOr:
            return ".|";
        case BinaryOperator::kBitwiseAnd:
            return ".&";
        case BinaryOperator::kBitwiseXor:
            return ".^";
        case BinaryOperator::kShl:
            return "shl";
        case BinaryOperator::kShr:
            return "shr";
        case BinaryOperator::kRol:
            return "rol";
        case BinaryOperator::kRor:
            return "ror";

        // Matrix
        case BinaryOperator::kMatrixMultiply:
            return ":*";
        case BinaryOperator::kMatrixDivide:
            return ":/";
        case BinaryOperator::kMatrixIntDivide:
            return ":\\";
        case BinaryOperator::kMatrixPower:
            return ":^";
        case BinaryOperator::kMatrixConcat:
            return ":|";
        case BinaryOperator::kMatrixConcatVertical:
            return "|";

        // Set
        case BinaryOperator::kUnion:
            return "union";
        case BinaryOperator::kUnion2:
            return "union2";
        case BinaryOperator::kIntersect:
            return "intersect";
        case BinaryOperator::kOutersect:
            return "outersect";
        case BinaryOperator::kMinus:
            return "minus";

        // Other
        case BinaryOperator::kConcatenation:
            return "$";
        case BinaryOperator::kRange:
            return "->";

        default:
            return "unknown";
        }
    }

    inline std::string GetAssignmentOperatorSymbol(AssignmentOperator op)
    {
        switch (op)
        {
        case AssignmentOperator::kAssign:
            return ":=";
        case AssignmentOperator::kAddAssign:
            return "+=";
        case AssignmentOperator::kSubtractAssign:
            return "-=";
        default:
            return "unknown";
        }
    }
}
