//! Abstract Syntax Tree (AST) definitions for the Ruchy programming language.
//!
//! This module contains the complete AST representation used by the Ruchy compiler.
//! The AST is the primary intermediate representation produced by the parser and consumed
//! by subsequent compilation phases including type checking, optimization, and code generation.
//!
//! # Architecture
//!
//! The AST follows a traditional expression-based design where most constructs are
//! represented as expressions that can be composed. Key design principles:
//!
//! - **Location tracking**: Every AST node carries a `Span` for precise error reporting
//! - **Attributes**: Nodes can be decorated with attributes for metadata and directives
//! - **Pattern matching**: First-class support for destructuring and pattern matching
//! - **Type annotations**: Optional type annotations for gradual typing
//!
//! # Example
//!
//! ```ignore
//! use ruchy::frontend::ast::{Expr, ExprKind, Literal, Span};
//!
//! // Create a simple literal expression
//! let expr = Expr::new(
//!     ExprKind::Literal(Literal::Integer(42, None)),
//!     Span::new(0, 2)
//! );
//! ```

use serde::{Deserialize, Serialize};
use std::fmt;

/// Comment information for AST nodes.
///
/// Comments are preserved during parsing to enable accurate code formatting
/// that maintains documentation and developer intent. Each comment tracks its
/// text content, position, and association with AST nodes.
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::{Comment, CommentKind, Span};
///
/// // Create a line comment
/// let comment = Comment::new(
///     CommentKind::Line("This is a comment".to_string()),
///     Span::new(0, 20)
/// );
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Comment {
    /// The type and content of this comment.
    pub kind: CommentKind,
    /// Source location information for this comment.
    pub span: Span,
}

impl Comment {
    /// Creates a new comment with the given kind and span.
    #[must_use]
    pub fn new(kind: CommentKind, span: Span) -> Self {
        Self { kind, span }
    }
}

/// The type of comment.
///
/// Ruchy supports three types of comments:
/// - Line comments starting with `//`
/// - Doc comments starting with `///` for documentation
/// - Block comments enclosed in `/* ... */`
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CommentKind {
    /// A single-line comment: `// comment text`
    Line(String),
    /// A documentation comment: `/// doc comment text`
    Doc(String),
    /// A block comment: `/* comment text */`
    Block(String),
}

/// Source location information for AST nodes.
///
/// A `Span` represents a contiguous range of characters in the source code,
/// enabling precise error reporting and source mapping. All AST nodes carry
/// span information to maintain the connection between the abstract representation
/// and the original source text.
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::Span;
///
/// // Create a span for characters 10-15 in the source
/// let span = Span::new(10, 15);
///
/// // Merge two spans to get their combined range
/// let span1 = Span::new(10, 20);
/// let span2 = Span::new(15, 25);
/// let merged = span1.merge(span2); // Span { start: 10, end: 25 }
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub struct Span {
    /// The byte offset of the first character in this span.
    pub start: usize,
    /// The byte offset one past the last character in this span.
    pub end: usize,
}
impl Span {
    /// Creates a new span with the given start and end positions.
    ///
    /// # Arguments
    ///
    /// * `start` - The byte offset of the first character
    /// * `end` - The byte offset one past the last character
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use ruchy::frontend::ast::Span;
    ///
    /// let span = Span::new(0, 10);
    /// assert_eq!(span.start, 0);
    /// assert_eq!(span.end, 10);
    /// ```
    #[must_use]
    pub fn new(start: usize, end: usize) -> Self {
        Self { start, end }
    }
    /// Merges two spans to create a new span covering both ranges.
    ///
    /// This is useful when combining multiple tokens or expressions into
    /// a larger syntactic construct. The resulting span starts at the
    /// minimum of both start positions and ends at the maximum of both
    /// end positions.
    ///
    /// # Arguments
    ///
    /// * `other` - The span to merge with this one
    ///
    /// # Returns
    ///
    /// A new span covering the entire range of both input spans
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use ruchy::frontend::ast::Span;
    ///
    /// let span1 = Span::new(10, 20);
    /// let span2 = Span::new(15, 25);
    /// let merged = span1.merge(span2);
    /// assert_eq!(merged.start, 10);
    /// assert_eq!(merged.end, 25);
    /// ```
    #[must_use]
    pub fn merge(self, other: Self) -> Self {
        Self {
            start: self.start.min(other.start),
            end: self.end.max(other.end),
        }
    }
}
/// A catch clause in a try-catch expression.
///
/// Catch clauses provide pattern-based error handling, allowing different
/// error types or patterns to be handled with specific recovery logic.
///
/// # Examples
///
/// ```ignore
/// // Catch a specific error pattern
/// try {
///     risky_operation()
/// } catch IOError(msg) {
///     println("IO error: {msg}")
/// } catch e {
///     println("Unknown error: {e}")
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CatchClause {
    /// The pattern to match against the caught error.
    pub pattern: Pattern,
    /// The expression to execute when this pattern matches.
    pub body: Box<Expr>,
}

/// A single clause in a comprehension (for and optional if).
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ComprehensionClause {
    /// The variable or pattern to bind
    pub variable: String,
    /// The iterable to iterate over
    pub iterable: Box<Expr>,
    /// Optional filter condition (if clause)
    pub condition: Option<Box<Expr>>,
}

/// The primary AST node representing an expression in Ruchy.
///
/// `Expr` is the fundamental building block of Ruchy's AST. Nearly all language
/// constructs are represented as expressions, including statements, declarations,
/// and control flow. This expression-oriented design enables powerful composition
/// and simplifies the language semantics.
///
/// Each expression consists of:
/// - `kind`: The specific type of expression (literal, binary op, function, etc.)
/// - `span`: Source location information for error reporting
/// - `attributes`: Optional metadata and compiler directives
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::{Expr, ExprKind, BinaryOp, Literal, Span};
///
/// // Create a binary expression: 2 + 3
/// let left = Box::new(Expr::new(
///     ExprKind::Literal(Literal::Integer(2, None)),
///     Span::new(0, 1)
/// ));
/// let right = Box::new(Expr::new(
///     ExprKind::Literal(Literal::Integer(3, None)),
///     Span::new(4, 5)
/// ));
/// let expr = Expr::new(
///     ExprKind::Binary { left, op: BinaryOp::Add, right },
///     Span::new(0, 5)
/// );
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Expr {
    /// The specific type of expression.
    pub kind: ExprKind,
    /// Source location information for this expression.
    pub span: Span,
    /// Compiler attributes and metadata attached to this expression.
    pub attributes: Vec<Attribute>,
    /// Comments that appear before this expression.
    ///
    /// Leading comments are associated with the expression they precede.
    /// These typically include documentation comments and explanatory notes.
    pub leading_comments: Vec<Comment>,
    /// Optional comment that appears at the end of the same line as this expression.
    ///
    /// Trailing comments are inline comments that provide context for the
    /// specific line of code they follow.
    pub trailing_comment: Option<Comment>,
}
impl Expr {
    /// Creates a new expression with the given kind and span.
    ///
    /// This is the primary constructor for building AST nodes. The expression
    /// starts with no attributes; use `with_attributes` if attributes are needed.
    ///
    /// # Arguments
    ///
    /// * `kind` - The specific type of expression
    /// * `span` - The source location of this expression
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use ruchy::frontend::ast::{Expr, ExprKind, Literal, Span};
    ///
    /// let expr = Expr::new(
    ///     ExprKind::Literal(Literal::Boolean(true)),
    ///     Span::new(0, 4)
    /// );
    /// ```
    #[must_use]
    pub fn new(kind: ExprKind, span: Span) -> Self {
        Self {
            kind,
            span,
            attributes: Vec::new(),
            leading_comments: Vec::new(),
            trailing_comment: None,
        }
    }

    /// Creates a new expression with comments attached.
    ///
    /// This constructor is used during parsing to associate comments with
    /// their corresponding AST nodes, enabling accurate code formatting that
    /// preserves documentation.
    ///
    /// # Arguments
    ///
    /// * `kind` - The specific type of expression
    /// * `span` - The source location of this expression
    /// * `leading_comments` - Comments that appear before this expression
    /// * `trailing_comment` - Optional comment at the end of the line
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use ruchy::frontend::ast::{Expr, ExprKind, Comment, CommentKind, Span};
    ///
    /// let comment = Comment::new(
    ///     CommentKind::Line("Important value".to_string()),
    ///     Span::new(0, 18)
    /// );
    ///
    /// let expr = Expr::with_comments(
    ///     ExprKind::Literal(Literal::Integer(42, None)),
    ///     Span::new(20, 22),
    ///     vec![],
    ///     Some(comment)
    /// );
    /// ```
    #[must_use]
    pub fn with_comments(
        kind: ExprKind,
        span: Span,
        leading_comments: Vec<Comment>,
        trailing_comment: Option<Comment>,
    ) -> Self {
        Self {
            kind,
            span,
            attributes: Vec::new(),
            leading_comments,
            trailing_comment,
        }
    }
    /// Creates a new expression with attributes attached.
    ///
    /// Attributes provide metadata and compiler directives that modify
    /// how an expression is processed. Common uses include optimization
    /// hints, debugging information, and feature flags.
    ///
    /// # Arguments
    ///
    /// * `kind` - The specific type of expression
    /// * `span` - The source location of this expression
    /// * `attributes` - Compiler attributes to attach
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use ruchy::frontend::ast::{Expr, ExprKind, Attribute, Literal, Span};
    ///
    /// let expr = Expr::with_attributes(
    ///     ExprKind::Literal(Literal::Integer(42, None)),
    ///     Span::new(0, 2),
    ///     vec![Attribute::inline()]
    /// );
    /// ```
    #[must_use]
    pub fn with_attributes(kind: ExprKind, span: Span, attributes: Vec<Attribute>) -> Self {
        Self {
            kind,
            span,
            attributes,
            leading_comments: Vec::new(),
            trailing_comment: None,
        }
    }
}
/// The specific type of expression represented by an AST node.
///
/// `ExprKind` is a comprehensive enumeration of all expression types supported
/// by the Ruchy language. This includes literals, operators, control flow,
/// declarations, and advanced features like actors and dataframes.
///
/// # Expression Categories
///
/// ## Literals and Identifiers
/// - `Literal`: Constant values (integers, strings, booleans, etc.)
/// - `Identifier`: Variable references
/// - `QualifiedName`: Module-qualified identifiers
///
/// ## Operations
/// - `Binary`: Binary operations (arithmetic, logical, comparison)
/// - `Unary`: Unary operations (negation, not)
/// - `Pipeline`: Functional pipeline operations
///
/// ## Control Flow
/// - `If`, `IfLet`: Conditional expressions
/// - `Match`: Pattern matching
/// - `For`, `While`, `Loop`: Iteration constructs
/// - `TryCatch`, `Throw`: Exception handling
///
/// ## Declarations
/// - `Let`, `LetPattern`: Variable bindings
/// - `Function`, `Lambda`: Function definitions
/// - `Struct`, `Enum`, `Trait`: Type definitions
///
/// ## Advanced Features
/// - `Actor`: Actor model for concurrency
/// - `DataFrame`: Tabular data operations
/// - `Async`, `Await`: Asynchronous programming
/// - `Command`: System command execution
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ExprKind {
    /// A literal value (integer, string, boolean, etc.).
    Literal(Literal),
    /// A simple identifier reference.
    Identifier(String),
    /// A module-qualified identifier (e.g., `std::println`).
    QualifiedName {
        /// The module path.
        module: String,
        /// The identifier within the module.
        name: String,
    },
    /// An interpolated string with embedded expressions.
    StringInterpolation {
        /// The parts of the interpolated string.
        parts: Vec<StringPart>,
    },
    /// A binary operation (e.g., `a + b`, `x && y`).
    Binary {
        /// The left operand.
        left: Box<Expr>,
        /// The binary operator.
        op: BinaryOp,
        /// The right operand.
        right: Box<Expr>,
    },
    /// A unary operation (e.g., `-x`, `!flag`).
    Unary {
        /// The unary operator.
        op: UnaryOp,
        /// The operand expression.
        operand: Box<Expr>,
    },
    /// Throws an exception.
    Throw {
        /// The exception value to throw.
        expr: Box<Expr>,
    },
    /// Exception handling with pattern-based catch clauses.
    TryCatch {
        /// The expression to try.
        try_block: Box<Expr>,
        /// Pattern-based catch handlers.
        catch_clauses: Vec<CatchClause>,
        /// Optional finally block executed regardless of success/failure.
        finally_block: Option<Box<Expr>>,
    },
    Ok {
        value: Box<Expr>,
    },
    Err {
        error: Box<Expr>,
    },
    Some {
        value: Box<Expr>,
    },
    None,
    TypeCast {
        expr: Box<Expr>,
        target_type: String,
    },
    /// Ternary conditional expression (condition ? `true_expr` : `false_expr`)
    Ternary {
        condition: Box<Expr>,
        true_expr: Box<Expr>,
        false_expr: Box<Expr>,
    },
    Try {
        expr: Box<Expr>,
    },
    Await {
        expr: Box<Expr>,
    },
    Spawn {
        actor: Box<Expr>,
    },
    AsyncBlock {
        body: Box<Expr>,
    },
    If {
        condition: Box<Expr>,
        then_branch: Box<Expr>,
        else_branch: Option<Box<Expr>>,
    },
    IfLet {
        pattern: Pattern,
        expr: Box<Expr>,
        then_branch: Box<Expr>,
        else_branch: Option<Box<Expr>>,
    },
    Let {
        name: String,
        type_annotation: Option<Type>,
        value: Box<Expr>,
        body: Box<Expr>,
        is_mutable: bool,
        else_block: Option<Box<Expr>>,  // For let-else: `let x = val else { diverging }`
    },
    LetPattern {
        pattern: Pattern,
        type_annotation: Option<Type>,
        value: Box<Expr>,
        body: Box<Expr>,
        is_mutable: bool,
        else_block: Option<Box<Expr>>,  // For let-else: `let Some(x) = val else { diverging }`
    },
    Function {
        name: String,
        type_params: Vec<String>,
        params: Vec<Param>,
        return_type: Option<Type>,
        body: Box<Expr>,
        is_async: bool,
        is_pub: bool,
    },
    Lambda {
        params: Vec<Param>,
        body: Box<Expr>,
    },
    AsyncLambda {
        params: Vec<String>,
        body: Box<Expr>,
    },
    Struct {
        name: String,
        type_params: Vec<String>,
        fields: Vec<StructField>,
        derives: Vec<String>, // #[derive(Debug, Clone, ...)]
        is_pub: bool,
    },
    TupleStruct {
        name: String,
        type_params: Vec<String>,
        fields: Vec<Type>, // Just types, no names
        derives: Vec<String>,
        is_pub: bool,
    },
    Class {
        name: String,
        type_params: Vec<String>,
        superclass: Option<String>, // inheritance
        traits: Vec<String>,        // + Trait1 + Trait2
        fields: Vec<StructField>,
        constructors: Vec<Constructor>, // new() methods
        methods: Vec<ClassMethod>,
        constants: Vec<ClassConstant>,  // const NAME: TYPE = VALUE
        properties: Vec<ClassProperty>, // property NAME: TYPE { get => ..., set(v) => ... }
        derives: Vec<String>,           // #[derive(Debug, Clone, ...)]
        decorators: Vec<Decorator>,     // @Serializable, @Table("users"), etc.
        is_pub: bool,
        is_sealed: bool,   // sealed class (no external subclassing)
        is_abstract: bool, // abstract class (cannot be instantiated)
    },
    Enum {
        name: String,
        type_params: Vec<String>,
        variants: Vec<EnumVariant>,
        is_pub: bool,
    },
    StructLiteral {
        name: String,
        fields: Vec<(String, Expr)>,
        base: Option<Box<Expr>>, // For ..expr update syntax
    },
    ObjectLiteral {
        fields: Vec<ObjectField>,
    },
    FieldAccess {
        object: Box<Expr>,
        field: String,
    },
    OptionalFieldAccess {
        object: Box<Expr>,
        field: String,
    },
    IndexAccess {
        object: Box<Expr>,
        index: Box<Expr>,
    },
    Slice {
        object: Box<Expr>,
        start: Option<Box<Expr>>,
        end: Option<Box<Expr>>,
    },
    Trait {
        name: String,
        type_params: Vec<String>,
        associated_types: Vec<String>, // type Item, type Output, etc.
        methods: Vec<TraitMethod>,
        is_pub: bool,
    },
    Impl {
        type_params: Vec<String>,
        trait_name: Option<String>,
        for_type: String,
        methods: Vec<ImplMethod>,
        is_pub: bool,
    },
    Actor {
        name: String,
        state: Vec<StructField>,
        handlers: Vec<ActorHandler>,
    },
    Send {
        actor: Box<Expr>,
        message: Box<Expr>,
    },
    Command {
        program: String,
        args: Vec<String>,
        env: Vec<(String, String)>,
        working_dir: Option<String>,
    },
    Ask {
        actor: Box<Expr>,
        message: Box<Expr>,
        timeout: Option<Box<Expr>>,
    },
    /// Fire-and-forget actor send (left <- right)
    ActorSend {
        actor: Box<Expr>,
        message: Box<Expr>,
    },
    /// Actor query with reply (left <? right)
    ActorQuery {
        actor: Box<Expr>,
        message: Box<Expr>,
    },
    Call {
        func: Box<Expr>,
        args: Vec<Expr>,
    },
    Macro {
        name: String,
        args: Vec<Expr>,
    },
    MethodCall {
        receiver: Box<Expr>,
        method: String,
        args: Vec<Expr>,
    },
    OptionalMethodCall {
        receiver: Box<Expr>,
        method: String,
        args: Vec<Expr>,
    },
    Block(Vec<Expr>),
    Pipeline {
        expr: Box<Expr>,
        stages: Vec<PipelineStage>,
    },
    Match {
        expr: Box<Expr>,
        arms: Vec<MatchArm>,
    },
    List(Vec<Expr>),
    Set(Vec<Expr>),
    ArrayInit {
        value: Box<Expr>,
        size: Box<Expr>,
    },
    Tuple(Vec<Expr>),
    Spread {
        expr: Box<Expr>,
    },
    ListComprehension {
        element: Box<Expr>,
        clauses: Vec<ComprehensionClause>,
    },
    SetComprehension {
        element: Box<Expr>,
        clauses: Vec<ComprehensionClause>,
    },
    DictComprehension {
        key: Box<Expr>,
        value: Box<Expr>,
        clauses: Vec<ComprehensionClause>,
    },
    DataFrame {
        columns: Vec<DataFrameColumn>,
    },
    DataFrameOperation {
        source: Box<Expr>,
        operation: DataFrameOp,
    },
    For {
        label: Option<String>,
        var: String,              // Keep for backward compatibility
        pattern: Option<Pattern>, // New: Support destructuring patterns
        iter: Box<Expr>,
        body: Box<Expr>,
    },
    While {
        label: Option<String>,
        condition: Box<Expr>,
        body: Box<Expr>,
    },
    WhileLet {
        label: Option<String>,
        pattern: Pattern,
        expr: Box<Expr>,
        body: Box<Expr>,
    },
    Loop {
        label: Option<String>,
        body: Box<Expr>,
    },
    Range {
        start: Box<Expr>,
        end: Box<Expr>,
        inclusive: bool,
    },
    Module {
        name: String,
        body: Box<Expr>,
    },
    /// ISSUE-106: External module declaration (mod name;)
    /// Represents a module that should be loaded from an external file
    ModuleDeclaration {
        name: String,
    },
    Break {
        label: Option<String>,
        value: Option<Box<Expr>>,
    },
    Continue {
        label: Option<String>,
    },
    Return {
        value: Option<Box<Expr>>,
    },
    Assign {
        target: Box<Expr>,
        value: Box<Expr>,
    },
    CompoundAssign {
        target: Box<Expr>,
        op: BinaryOp,
        value: Box<Expr>,
    },
    PreIncrement {
        target: Box<Expr>,
    },
    PostIncrement {
        target: Box<Expr>,
    },
    PreDecrement {
        target: Box<Expr>,
    },
    PostDecrement {
        target: Box<Expr>,
    },
    Extension {
        target_type: String,
        methods: Vec<ImplMethod>,
    },
    /// Import statement for modules
    Import {
        module: String,
        items: Option<Vec<String>>,
    },
    /// Import all items with an alias (import * as name)
    ImportAll {
        module: String,
        alias: String,
    },
    /// Import default export
    ImportDefault {
        module: String,
        name: String,
    },
    /// Export a declaration
    Export {
        expr: Box<Expr>,
        is_default: bool,
    },
    /// Export a list of identifiers
    ExportList {
        names: Vec<String>,
    },
    /// Re-export from another module
    ReExport {
        items: Vec<String>,
        module: String,
    },
    /// Export default declaration
    ExportDefault {
        expr: Box<Expr>,
    },
    /// Type alias declaration (type Name = Type)
    TypeAlias {
        name: String,
        target_type: Type,
    },
    /// Macro invocation (e.g., `println!("hello")`)
    MacroInvocation {
        name: String,
        args: Vec<Expr>,
    },
}
/// Literal values that can appear in the source code.
///
/// Literals represent compile-time constant values that are directly
/// embedded in the program. These form the base values from which
/// more complex expressions are constructed.
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::Literal;
///
/// let int = Literal::Integer(42, None);
/// let float = Literal::Float(3.14);
/// let string = Literal::String("hello".to_string());
/// let boolean = Literal::Bool(true);
/// let character = Literal::Char('a');
/// let unit = Literal::Unit;
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
    /// A signed 64-bit integer literal with optional type suffix (e.g., i32, i64, u32).
    Integer(i64, Option<String>),
    /// A 64-bit floating-point literal.
    Float(f64),
    /// A string literal.
    String(String),
    /// A boolean literal (`true` or `false`).
    Bool(bool),
    /// A character literal.
    Char(char),
    /// A byte literal (0-255).
    Byte(u8),
    /// The unit value `()`.
    Unit,
    /// A null value.
    Null,
}
impl Literal {
    /// Convert a REPL Value to a Literal (for synthetic expressions)
    pub fn from_value(value: &crate::runtime::interpreter::Value) -> Self {
        use crate::runtime::interpreter::Value;
        match value {
            Value::Integer(i) => Literal::Integer(*i, None),
            Value::Float(f) => Literal::Float(*f),
            Value::String(s) => Literal::String(s.to_string()),
            Value::Bool(b) => Literal::Bool(*b),
            Value::Nil => Literal::Unit,
            _ => Literal::Unit, // Fallback for complex types
        }
    }
}
/// String interpolation parts - either literal text or an expression
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StringPart {
    /// Literal text portion of the string
    Text(String),
    /// Expression to be interpolated without format specifier
    Expr(Box<Expr>),
    /// Expression with format specifier (e.g., {value:.2})
    ExprWithFormat {
        expr: Box<Expr>,
        format_spec: String,
    },
}
/// Binary operators for two-operand expressions.
///
/// These operators cover arithmetic, comparison, logical, and bitwise operations.
/// Each operator has specific precedence and associativity rules defined in the parser.
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::BinaryOp;
///
/// // Arithmetic: a + b * c
/// let add = BinaryOp::Add;
/// let mul = BinaryOp::Multiply;
///
/// // Comparison: x >= y
/// let ge = BinaryOp::GreaterEqual;
///
/// // Logical: flag1 && flag2
/// let and = BinaryOp::And;
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum BinaryOp {
    // Arithmetic
    Add,
    Subtract,
    Multiply,
    Divide,
    Modulo,
    Power,
    // Comparison
    Equal,
    NotEqual,
    Less,
    LessEqual,
    Greater,
    GreaterEqual,
    Gt, // Alias for Greater (for compatibility)
    // Logical
    And,
    Or,
    NullCoalesce,
    // Bitwise
    BitwiseAnd,
    BitwiseOr,
    BitwiseXor,
    LeftShift,
    RightShift,
    // Actor operations
    Send, // Actor message passing: actor ! message
}
/// Unary operators for single-operand expressions.
///
/// These operators include logical negation, arithmetic negation,
/// bitwise complement, and reference operations.
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::UnaryOp;
///
/// // Logical negation: !flag
/// let not = UnaryOp::Not;
///
/// // Arithmetic negation: -value
/// let neg = UnaryOp::Negate;
///
/// // Bitwise complement: ~bits
/// let complement = UnaryOp::BitwiseNot;
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum UnaryOp {
    Not,
    Negate,
    BitwiseNot,
    Reference,
    MutableReference,  // PARSER-085: Added for &mut support (GitHub Issue #71)
    Deref,
}
/// A function or method parameter.
///
/// Parameters support pattern matching for destructuring, type annotations
/// for type checking, default values for optional parameters, and mutability
/// modifiers.
///
/// # Examples
///
/// ```ignore
/// // Simple parameter: x: int
/// // Pattern parameter: (a, b): (int, int)
/// // Optional parameter: name: string = "default"
/// // Mutable parameter: mut buffer: Vec<u8>
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Param {
    /// The pattern for destructuring the parameter.
    pub pattern: Pattern,
    /// The type annotation for this parameter.
    pub ty: Type,
    /// Source location of this parameter.
    pub span: Span,
    /// Whether this parameter is mutable.
    pub is_mutable: bool,
    /// Optional default value for this parameter.
    pub default_value: Option<Box<Expr>>,
}
impl Param {
    /// Get the primary name from this parameter pattern.
    /// For complex patterns, this returns the first/primary identifier.
    /// For simple patterns, this returns the identifier itself.
    #[must_use]
    pub fn name(&self) -> String {
        self.pattern.primary_name()
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Visibility {
    Private,
    Public,
    PubCrate,
    PubSuper,
    Protected, // For future inheritance support
}

impl Visibility {
    pub fn is_public(&self) -> bool {
        matches!(
            self,
            Visibility::Public | Visibility::PubCrate | Visibility::PubSuper
        )
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StructField {
    pub name: String,
    pub ty: Type,
    pub visibility: Visibility,
    pub is_mut: bool,                // mut field modifier
    pub default_value: Option<Expr>, // Default value for class fields
    pub decorators: Vec<Decorator>,  // @PrimaryKey, @Column("name"), etc.
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EnumVariant {
    pub name: String,
    pub kind: EnumVariantKind,
    pub discriminant: Option<i64>, // Explicit discriminant value for TypeScript compatibility
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum EnumVariantKind {
    Unit,                        // Quit
    Tuple(Vec<Type>),            // Write(String)
    Struct(Vec<StructField>),    // Move { x: i32, y: i32 }
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ObjectField {
    KeyValue { key: String, value: Expr },
    Spread { expr: Expr },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TraitMethod {
    pub name: String,
    pub params: Vec<Param>,
    pub return_type: Option<Type>,
    pub body: Option<Box<Expr>>, // None for method signatures, Some for default implementations
    pub is_pub: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImplMethod {
    pub name: String,
    pub params: Vec<Param>,
    pub return_type: Option<Type>,
    pub body: Box<Expr>,
    pub is_pub: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ActorHandler {
    pub message_type: String,
    pub params: Vec<Param>,
    pub body: Box<Expr>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClassMethod {
    pub name: String,
    pub params: Vec<Param>,
    pub return_type: Option<Type>,
    pub body: Box<Expr>,
    pub is_pub: bool,
    pub is_static: bool,     // static method (no self)
    pub is_override: bool,   // override keyword for explicit overriding
    pub is_final: bool,      // final method (cannot be overridden)
    pub is_abstract: bool,   // abstract method (no implementation)
    pub self_type: SelfType, // &self, &mut self, or self (move)
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClassConstant {
    pub name: String,
    pub ty: Type,
    pub value: Expr,
    pub is_pub: bool,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClassProperty {
    pub name: String,
    pub ty: Type,
    pub getter: Option<Box<Expr>>,
    pub setter: Option<PropertySetter>,
    pub is_pub: bool,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PropertySetter {
    pub param_name: String,
    pub body: Box<Expr>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SelfType {
    None,        // static method
    Owned,       // self (move)
    Borrowed,    // &self
    MutBorrowed, // &mut self
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Constructor {
    pub name: Option<String>, // None for primary constructor, Some(name) for named constructors
    pub params: Vec<Param>,
    pub return_type: Option<Type>, // Optional return type for named constructors (e.g., Result<Self>)
    pub body: Box<Expr>,
    pub is_pub: bool,
}
/// Type annotations in the AST.
///
/// Types provide static type information for type checking and code generation.
/// Ruchy supports a rich type system including generics, optionals, references,
/// and specialized types for dataframes and async operations.
///
/// # Examples
///
/// ```ignore
/// use ruchy::frontend::ast::{Type, TypeKind, Span};
///
/// // Simple named type: int
/// let int_type = Type {
///     kind: TypeKind::Named("int".to_string()),
///     span: Span::new(0, 3),
/// };
///
/// // Generic type: Vec<string>
/// let vec_type = Type {
///     kind: TypeKind::Generic {
///         base: "Vec".to_string(),
///         params: vec![string_type],
///     },
///     span: Span::new(0, 11),
/// };
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Type {
    /// The specific type variant.
    pub kind: TypeKind,
    /// Source location of this type annotation.
    pub span: Span,
}
/// Specific type variants supported by Ruchy.
///
/// This enumeration covers all type forms from simple named types
/// to complex generic, functional, and structural types.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum TypeKind {
    Named(String),
    Generic {
        base: String,
        params: Vec<Type>,
    },
    Optional(Box<Type>),
    List(Box<Type>),
    Array {
        elem_type: Box<Type>,
        size: usize,
    },
    Tuple(Vec<Type>),
    Function {
        params: Vec<Type>,
        ret: Box<Type>,
    },
    DataFrame {
        columns: Vec<(String, Type)>,
    },
    Series {
        dtype: Box<Type>,
    },
    Reference {
        is_mut: bool,
        lifetime: Option<String>,
        inner: Box<Type>,
    },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PipelineStage {
    pub op: Box<Expr>,
    pub span: Span,
}
/// An arm in a match expression.
///
/// Match arms consist of a pattern to match against, an optional guard
/// condition for additional filtering, and a body expression to execute
/// when the pattern matches.
///
/// # Examples
///
/// ```ignore
/// match value {
///     Some(x) if x > 0 => x * 2,  // Pattern with guard
///     None => 0,                   // Simple pattern
///     _ => -1,                     // Wildcard pattern
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MatchArm {
    /// The pattern to match against.
    pub pattern: Pattern,
    /// Optional guard condition that must be true for this arm to match.
    pub guard: Option<Box<Expr>>,
    /// The expression to execute when this arm matches.
    pub body: Box<Expr>,
    /// Source location of this match arm.
    pub span: Span,
}
/// Patterns for destructuring and matching values.
///
/// Patterns are used in match expressions, let bindings, function parameters,
/// and other contexts where values need to be destructured or tested against
/// a structure. Ruchy supports a rich pattern language including literals,
/// destructuring, ranges, and alternative patterns.
///
/// # Pattern Types
///
/// - **Wildcard**: `_` matches anything
/// - **Literal**: Matches exact values
/// - **Identifier**: Binds matched value to a name
/// - **Tuple/List**: Destructures sequences
/// - **Struct**: Destructures struct fields
/// - **Or**: Matches any of several patterns
/// - **Rest**: Captures remaining elements
///
/// # Examples
///
/// ```ignore
/// match value {
///     0 => "zero",                    // Literal pattern
///     1..=10 => "small",              // Range pattern
///     Some(x) => format!("value: {x}"), // Enum pattern
///     [first, ..rest] => "list",     // List pattern with rest
///     _ => "other",                   // Wildcard
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Pattern {
    Wildcard,
    Literal(Literal),
    Identifier(String),
    QualifiedName(Vec<String>), // For patterns like Ordering::Less
    Tuple(Vec<Pattern>),
    List(Vec<Pattern>),
    Struct {
        name: String,
        fields: Vec<StructPatternField>,
        has_rest: bool,
    },
    TupleVariant {
        path: Vec<String>,      // e.g., ["Message", "Text"]
        patterns: Vec<Pattern>, // Arguments like (n) or (a, b)
    }, // For enum tuple variants like Message::Text(n)
    Range {
        start: Box<Pattern>,
        end: Box<Pattern>,
        inclusive: bool,
    },
    Or(Vec<Pattern>),
    Rest,              // For ... patterns
    RestNamed(String), // For ..name patterns
    AtBinding {
        name: String,
        pattern: Box<Pattern>,
    }, // For @ bindings like name @ pattern
    WithDefault {
        pattern: Box<Pattern>,
        default: Box<Expr>,
    }, // For patterns with default values like a = 10
    Mut(Box<Pattern>), // For mutable bindings in destructuring like (mut x, mut y)
    Ok(Box<Pattern>),
    Err(Box<Pattern>),
    Some(Box<Pattern>),
    None,
}
impl Pattern {
    /// Get the primary identifier name from this pattern.
    /// For complex patterns, returns the first/most significant identifier.
    #[must_use]
    pub fn primary_name(&self) -> String {
        match self {
            Pattern::Identifier(name) => name.clone(),
            Pattern::QualifiedName(path) => path.join("::"),
            Pattern::Tuple(patterns) => {
                // Return the name of the first pattern
                patterns
                    .first()
                    .map_or_else(|| "_tuple".to_string(), Pattern::primary_name)
            }
            Pattern::List(patterns) => {
                // Return the name of the first pattern
                patterns
                    .first()
                    .map_or_else(|| "_list".to_string(), Pattern::primary_name)
            }
            Pattern::Struct { name, fields, .. } => {
                // Return the struct type name, or first field name if anonymous
                if name.is_empty() {
                    fields
                        .first()
                        .map_or_else(|| "_struct".to_string(), |f| f.name.clone())
                } else {
                    name.clone()
                }
            }
            Pattern::TupleVariant { path, patterns } => {
                // For enum tuple variants, get first pattern's name or variant path
                patterns
                    .first()
                    .map_or_else(|| path.join("::"), Pattern::primary_name)
            }
            Pattern::Ok(inner) | Pattern::Err(inner) | Pattern::Some(inner) => inner.primary_name(),
            Pattern::None => "_none".to_string(),
            Pattern::Or(patterns) => {
                // Return the name of the first pattern
                patterns
                    .first()
                    .map_or_else(|| "_or".to_string(), Pattern::primary_name)
            }
            Pattern::Wildcard => "_".to_string(),
            Pattern::Rest => "_rest".to_string(),
            Pattern::RestNamed(name) => name.clone(),
            Pattern::AtBinding { name, .. } => name.clone(),
            Pattern::WithDefault { pattern, .. } => pattern.primary_name(),
            Pattern::Mut(inner) => inner.primary_name(),
            Pattern::Literal(lit) => format!("_literal_{lit:?}"),
            Pattern::Range { .. } => "_range".to_string(),
        }
    }
}
/// A field in a struct destructuring pattern.
///
/// Supports both explicit field patterns (`field: pattern`) and
/// shorthand syntax (`field` as shorthand for `field: field`).
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StructPatternField {
    /// The field name to match.
    pub name: String,
    /// The pattern for this field's value (None for shorthand syntax).
    pub pattern: Option<Pattern>,
}
/// Definition of a custom error type.
///
/// Custom error types allow defining domain-specific error structures
/// with typed fields and optional inheritance from base error types.
///
/// # Examples
///
/// ```ignore
/// error NetworkError {
///     code: int,
///     message: string,
/// } extends IOError
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ErrorTypeDef {
    /// The name of this error type.
    pub name: String,
    /// Fields contained in this error type.
    pub fields: Vec<StructField>,
    /// Optional parent error type to inherit from.
    pub extends: Option<String>,
}
/// Compiler attributes for annotating expressions.
///
/// Attributes provide metadata that influences compilation, optimization,
/// and runtime behavior. They use the `#[name(args)]` syntax similar to Rust.
///
/// # Common Attributes
///
/// - `#[inline]`: Hint for function inlining
/// - `#[test]`: Mark function as a test
/// - `#[property]`: Mark as a property accessor
/// - `#[deprecated("message")]`: Mark as deprecated
///
/// # Examples
///
/// ```ignore
/// #[inline]
/// #[property]
/// fn get_value() -> int {
///     self.value
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Attribute {
    pub name: String,
    pub args: Vec<String>,
    pub span: Span,
}

/// Represents a decorator (@name or @name(...))
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Decorator {
    pub name: String,
    pub args: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DataFrameColumn {
    pub name: String,
    pub values: Vec<Expr>,
}
/// Operations on `DataFrame` values.
///
/// `DataFrames` are Ruchy's built-in tabular data structure, similar to
/// pandas `DataFrames` or SQL tables. These operations provide a fluent
/// API for data manipulation and analysis.
///
/// # Examples
///
/// ```ignore
/// df.filter(x => x.age > 18)
///   .select(["name", "email"])
///   .sort(["name"])
///   .limit(10)
/// ```
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DataFrameOp {
    Filter(Box<Expr>),
    Select(Vec<String>),
    GroupBy(Vec<String>),
    Sort(Vec<String>),
    Join {
        other: Box<Expr>,
        on: Vec<String>,
        how: JoinType,
    },
    Aggregate(Vec<AggregateOp>),
    Limit(usize),
    Head(usize),
    Tail(usize),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum JoinType {
    Inner,
    Left,
    Right,
    Outer,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ImportItem {
    /// Import a specific name: `use std::collections::HashMap`
    Named(String),
    /// Import with alias: `use std::collections::HashMap as Map`
    Aliased { name: String, alias: String },
    /// Import all: `use std::collections::*`
    Wildcard,
}
impl ImportItem {
    /// Check if this import is for a URL module
    pub fn is_url_import(path: &str) -> bool {
        path.starts_with("https://") || path.starts_with("http://")
    }
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AggregateOp {
    Sum(String),
    Mean(String),
    Min(String),
    Max(String),
    Count(String),
    Std(String),
    Var(String),
}
impl fmt::Display for BinaryOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Add => write!(f, "+"),
            Self::Subtract => write!(f, "-"),
            Self::Multiply => write!(f, "*"),
            Self::Divide => write!(f, "/"),
            Self::Modulo => write!(f, "%"),
            Self::Power => write!(f, "**"),
            Self::Equal => write!(f, "=="),
            Self::NotEqual => write!(f, "!="),
            Self::Less => write!(f, "<"),
            Self::LessEqual => write!(f, "<="),
            Self::Greater => write!(f, ">"),
            Self::GreaterEqual => write!(f, ">="),
            Self::And => write!(f, "&&"),
            Self::Or => write!(f, "||"),
            Self::NullCoalesce => write!(f, "??"),
            Self::BitwiseAnd => write!(f, "&"),
            Self::BitwiseOr => write!(f, "|"),
            Self::BitwiseXor => write!(f, "^"),
            Self::LeftShift => write!(f, "<<"),
            Self::RightShift => write!(f, ">>"),
            Self::Gt => write!(f, ">"),
            Self::Send => write!(f, "!"),
        }
    }
}
impl fmt::Display for UnaryOp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Not => write!(f, "!"),
            Self::Negate => write!(f, "-"),
            Self::BitwiseNot => write!(f, "~"),
            Self::Reference => write!(f, "&"),
            Self::MutableReference => write!(f, "&mut "),  // PARSER-085: Issue #71
            Self::Deref => write!(f, "*"),
        }
    }
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::panic, clippy::expect_used)]
mod tests {
    use super::*;
    use proptest::prelude::*;
    proptest! {
        #[test]
        fn test_span_merge(start1 in 0usize..1000, end1 in 0usize..1000,
                          start2 in 0usize..1000, end2 in 0usize..1000) {
            let span1 = Span::new(start1, end1);
            let span2 = Span::new(start2, end2);
            let merged = span1.merge(span2);
            prop_assert!(merged.start <= span1.start);
            prop_assert!(merged.start <= span2.start);
            prop_assert!(merged.end >= span1.end);
            prop_assert!(merged.end >= span2.end);
        }
    }
    #[test]
    fn test_ast_size() {
        // Track AST node sizes for optimization
        let expr_size = std::mem::size_of::<Expr>();
        let kind_size = std::mem::size_of::<ExprKind>();
        // Current sizes are larger than ideal but acceptable for MVP
        // Future optimization: Use arena allocation and indices
        // Increased limits after adding more OOP features and comment tracking
        assert!(expr_size <= 400, "Expr too large: {expr_size} bytes");
        assert!(kind_size <= 280, "ExprKind too large: {kind_size} bytes");
    }
    #[test]
    fn test_span_creation() {
        let span = Span::new(10, 20);
        assert_eq!(span.start, 10);
        assert_eq!(span.end, 20);
    }
    #[test]
    fn test_span_merge_simple() {
        let span1 = Span::new(5, 10);
        let span2 = Span::new(8, 15);
        let merged = span1.merge(span2);
        assert_eq!(merged.start, 5);
        assert_eq!(merged.end, 15);
    }
    #[test]
    fn test_span_merge_disjoint() {
        let span1 = Span::new(0, 5);
        let span2 = Span::new(10, 15);
        let merged = span1.merge(span2);
        assert_eq!(merged.start, 0);
        assert_eq!(merged.end, 15);
    }
    #[test]
    fn test_expr_creation() {
        let span = Span::new(0, 10);
        let expr = Expr::new(ExprKind::Literal(Literal::Integer(42, None)), span);
        assert_eq!(expr.span.start, 0);
        assert_eq!(expr.span.end, 10);
        match expr.kind {
            ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 42),
            _ => panic!("Wrong expression kind"),
        }
    }
    #[test]
    fn test_literal_variants() {
        let literals = vec![
            Literal::Integer(42, None),
            #[allow(clippy::approx_constant)]
            Literal::Float(3.14), // Not PI, just a test value
            Literal::String("hello".to_string()),
            Literal::Bool(true),
            Literal::Unit,
        ];
        for lit in literals {
            let expr = Expr::new(ExprKind::Literal(lit.clone()), Span::new(0, 0));
            match expr.kind {
                ExprKind::Literal(l) => assert_eq!(l, lit),
                _ => panic!("Expected literal"),
            }
        }
    }
    #[test]
    fn test_binary_op_display() {
        assert_eq!(BinaryOp::Add.to_string(), "+");
        assert_eq!(BinaryOp::Subtract.to_string(), "-");
        assert_eq!(BinaryOp::Multiply.to_string(), "*");
        assert_eq!(BinaryOp::Divide.to_string(), "/");
        assert_eq!(BinaryOp::Modulo.to_string(), "%");
        assert_eq!(BinaryOp::Power.to_string(), "**");
        assert_eq!(BinaryOp::Equal.to_string(), "==");
        assert_eq!(BinaryOp::NotEqual.to_string(), "!=");
        assert_eq!(BinaryOp::Less.to_string(), "<");
        assert_eq!(BinaryOp::LessEqual.to_string(), "<=");
        assert_eq!(BinaryOp::Greater.to_string(), ">");
        assert_eq!(BinaryOp::GreaterEqual.to_string(), ">=");
        assert_eq!(BinaryOp::And.to_string(), "&&");
        assert_eq!(BinaryOp::Or.to_string(), "||");
        assert_eq!(BinaryOp::BitwiseAnd.to_string(), "&");
        assert_eq!(BinaryOp::BitwiseOr.to_string(), "|");
        assert_eq!(BinaryOp::BitwiseXor.to_string(), "^");
        assert_eq!(BinaryOp::LeftShift.to_string(), "<<");
    }
    #[test]
    fn test_unary_op_display() {
        assert_eq!(UnaryOp::Not.to_string(), "!");
        assert_eq!(UnaryOp::Negate.to_string(), "-");
        assert_eq!(UnaryOp::BitwiseNot.to_string(), "~");
        assert_eq!(UnaryOp::Reference.to_string(), "&");
    }
    #[test]
    fn test_binary_expression() {
        let left = Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(1, None)),
            Span::new(0, 1),
        ));
        let right = Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(2, None)),
            Span::new(4, 5),
        ));
        let expr = Expr::new(
            ExprKind::Binary {
                left,
                op: BinaryOp::Add,
                right,
            },
            Span::new(0, 5),
        );
        match expr.kind {
            ExprKind::Binary {
                left: l,
                op,
                right: r,
            } => {
                assert_eq!(op, BinaryOp::Add);
                match l.kind {
                    ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
                    _ => panic!("Wrong left operand"),
                }
                match r.kind {
                    ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 2),
                    _ => panic!("Wrong right operand"),
                }
            }
            _ => panic!("Expected binary expression"),
        }
    }
    #[test]
    fn test_unary_expression() {
        let operand = Box::new(Expr::new(
            ExprKind::Literal(Literal::Bool(true)),
            Span::new(1, 5),
        ));
        let expr = Expr::new(
            ExprKind::Unary {
                op: UnaryOp::Not,
                operand,
            },
            Span::new(0, 5),
        );
        match expr.kind {
            ExprKind::Unary { op, operand } => {
                assert_eq!(op, UnaryOp::Not);
                match operand.kind {
                    ExprKind::Literal(Literal::Bool(b)) => assert!(b),
                    _ => panic!("Wrong operand"),
                }
            }
            _ => panic!("Expected unary expression"),
        }
    }
    #[test]
    fn test_if_expression() {
        let condition = Box::new(Expr::new(
            ExprKind::Literal(Literal::Bool(true)),
            Span::new(3, 7),
        ));
        let then_branch = Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(1, None)),
            Span::new(10, 11),
        ));
        let else_branch = Some(Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(2, None)),
            Span::new(17, 18),
        )));
        let expr = Expr::new(
            ExprKind::If {
                condition,
                then_branch,
                else_branch,
            },
            Span::new(0, 18),
        );
        match expr.kind {
            ExprKind::If {
                condition: c,
                then_branch: t,
                else_branch: e,
            } => {
                match c.kind {
                    ExprKind::Literal(Literal::Bool(b)) => assert!(b),
                    _ => panic!("Wrong condition"),
                }
                match t.kind {
                    ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
                    _ => panic!("Wrong then branch"),
                }
                assert!(e.is_some());
                if let Some(else_expr) = e {
                    match else_expr.kind {
                        ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 2),
                        _ => panic!("Wrong else branch"),
                    }
                }
            }
            _ => panic!("Expected if expression"),
        }
    }
    #[test]
    fn test_let_expression() {
        let value = Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(42, None)),
            Span::new(8, 10),
        ));
        let body = Box::new(Expr::new(
            ExprKind::Identifier("x".to_string()),
            Span::new(14, 15),
        ));
        let expr = Expr::new(
            ExprKind::Let {
                name: "x".to_string(),
                type_annotation: None,
                value,
                body,
                is_mutable: false,
                else_block: None,
            },
            Span::new(0, 15),
        );
        match expr.kind {
            ExprKind::Let {
                name,
                value: v,
                body: b,
                ..
            } => {
                assert_eq!(name, "x");
                match v.kind {
                    ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 42),
                    _ => panic!("Wrong value"),
                }
                match b.kind {
                    ExprKind::Identifier(id) => assert_eq!(id, "x"),
                    _ => panic!("Wrong body"),
                }
            }
            _ => panic!("Expected let expression"),
        }
    }
    #[test]
    fn test_function_expression() {
        let params = vec![Param {
            pattern: Pattern::Identifier("x".to_string()),
            ty: Type {
                kind: TypeKind::Named("i32".to_string()),
                span: Span::new(10, 13),
            },
            span: Span::new(8, 13),
            is_mutable: false,
            default_value: None,
        }];
        let body = Box::new(Expr::new(
            ExprKind::Identifier("x".to_string()),
            Span::new(20, 21),
        ));
        let expr = Expr::new(
            ExprKind::Function {
                name: "identity".to_string(),
                type_params: vec![],
                params,
                return_type: Some(Type {
                    kind: TypeKind::Named("i32".to_string()),
                    span: Span::new(16, 19),
                }),
                body,
                is_async: false,
                is_pub: false,
            },
            Span::new(0, 22),
        );
        match expr.kind {
            ExprKind::Function {
                name,
                params: p,
                return_type,
                body: b,
                ..
            } => {
                assert_eq!(name, "identity");
                assert_eq!(p.len(), 1);
                assert_eq!(p[0].name(), "x");
                assert!(return_type.is_some());
                match b.kind {
                    ExprKind::Identifier(id) => assert_eq!(id, "x"),
                    _ => panic!("Wrong body"),
                }
            }
            _ => panic!("Expected function expression"),
        }
    }
    #[test]
    fn test_call_expression() {
        let func = Box::new(Expr::new(
            ExprKind::Identifier("add".to_string()),
            Span::new(0, 3),
        ));
        let args = vec![
            Expr::new(
                ExprKind::Literal(Literal::Integer(1, None)),
                Span::new(4, 5),
            ),
            Expr::new(
                ExprKind::Literal(Literal::Integer(2, None)),
                Span::new(7, 8),
            ),
        ];
        let expr = Expr::new(ExprKind::Call { func, args }, Span::new(0, 9));
        match expr.kind {
            ExprKind::Call { func: f, args: a } => {
                match f.kind {
                    ExprKind::Identifier(name) => assert_eq!(name, "add"),
                    _ => panic!("Wrong function"),
                }
                assert_eq!(a.len(), 2);
            }
            _ => panic!("Expected call expression"),
        }
    }
    #[test]
    fn test_block_expression() {
        let exprs = vec![
            Expr::new(
                ExprKind::Literal(Literal::Integer(1, None)),
                Span::new(2, 3),
            ),
            Expr::new(
                ExprKind::Literal(Literal::Integer(2, None)),
                Span::new(5, 6),
            ),
        ];
        let expr = Expr::new(ExprKind::Block(exprs), Span::new(0, 8));
        match expr.kind {
            ExprKind::Block(block) => {
                assert_eq!(block.len(), 2);
            }
            _ => panic!("Expected block expression"),
        }
    }
    #[test]
    fn test_list_expression() {
        let items = vec![
            Expr::new(
                ExprKind::Literal(Literal::Integer(1, None)),
                Span::new(1, 2),
            ),
            Expr::new(
                ExprKind::Literal(Literal::Integer(2, None)),
                Span::new(4, 5),
            ),
            Expr::new(
                ExprKind::Literal(Literal::Integer(3, None)),
                Span::new(7, 8),
            ),
        ];
        let expr = Expr::new(ExprKind::List(items), Span::new(0, 9));
        match expr.kind {
            ExprKind::List(list) => {
                assert_eq!(list.len(), 3);
            }
            _ => panic!("Expected list expression"),
        }
    }
    #[test]
    fn test_for_expression() {
        let iter = Box::new(Expr::new(
            ExprKind::Range {
                start: Box::new(Expr::new(
                    ExprKind::Literal(Literal::Integer(0, None)),
                    Span::new(10, 11),
                )),
                end: Box::new(Expr::new(
                    ExprKind::Literal(Literal::Integer(10, None)),
                    Span::new(13, 15),
                )),
                inclusive: false,
            },
            Span::new(10, 15),
        ));
        let body = Box::new(Expr::new(
            ExprKind::Identifier("i".to_string()),
            Span::new(20, 21),
        ));
        let expr = Expr::new(
            ExprKind::For {
                label: None,
                var: "i".to_string(),
                pattern: None,
                iter,
                body,
            },
            Span::new(0, 22),
        );
        match expr.kind {
            ExprKind::For {
                label: None,
                var,
                iter: it,
                body: b,
                ..
            } => {
                assert_eq!(var, "i");
                match it.kind {
                    ExprKind::Range { .. } => {}
                    _ => panic!("Wrong iterator"),
                }
                match b.kind {
                    ExprKind::Identifier(id) => assert_eq!(id, "i"),
                    _ => panic!("Wrong body"),
                }
            }
            _ => panic!("Expected for expression"),
        }
    }
    #[test]
    fn test_range_expression() {
        let start = Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(1, None)),
            Span::new(0, 1),
        ));
        let end = Box::new(Expr::new(
            ExprKind::Literal(Literal::Integer(10, None)),
            Span::new(3, 5),
        ));
        let expr = Expr::new(
            ExprKind::Range {
                start,
                end,
                inclusive: false,
            },
            Span::new(0, 5),
        );
        match expr.kind {
            ExprKind::Range {
                start: s,
                end: e,
                inclusive,
            } => {
                assert!(!inclusive);
                match s.kind {
                    ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
                    _ => panic!("Wrong start"),
                }
                match e.kind {
                    ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 10),
                    _ => panic!("Wrong end"),
                }
            }
            _ => panic!("Expected range expression"),
        }
    }
    // Test disabled: Import AST structure pending redesign
    // #[test]
    // fn test_import_expression() {
    //     let expr = Expr::new(
    //         ExprKind::Import {
    //             module: "std::collections".to_string(),
    //             items: Some(vec!["HashMap".to_string(), "HashSet".to_string()]),
    //         },
    //         Span::new(0, 30),
    //     );
    //     match expr.kind {
    //         ExprKind::Import { module, items } => {
    //             assert_eq!(module, "std::collections");
    //             assert!(items.is_some());
    //         }
    //         _ => panic!("Expected import expression"),
    //     }
    // }
    #[test]
    fn test_pipeline_expression() {
        let expr_start = Box::new(Expr::new(
            ExprKind::List(vec![
                Expr::new(
                    ExprKind::Literal(Literal::Integer(1, None)),
                    Span::new(1, 2),
                ),
                Expr::new(
                    ExprKind::Literal(Literal::Integer(2, None)),
                    Span::new(4, 5),
                ),
            ]),
            Span::new(0, 6),
        ));
        let stages = vec![PipelineStage {
            op: Box::new(Expr::new(
                ExprKind::Identifier("filter".to_string()),
                Span::new(10, 16),
            )),
            span: Span::new(10, 16),
        }];
        let expr = Expr::new(
            ExprKind::Pipeline {
                expr: expr_start,
                stages,
            },
            Span::new(0, 16),
        );
        match expr.kind {
            ExprKind::Pipeline { expr: e, stages: s } => {
                assert_eq!(s.len(), 1);
                match e.kind {
                    ExprKind::List(list) => assert_eq!(list.len(), 2),
                    _ => panic!("Wrong pipeline start"),
                }
            }
            _ => panic!("Expected pipeline expression"),
        }
    }
    #[test]
    fn test_match_expression() {
        let expr_to_match = Box::new(Expr::new(
            ExprKind::Identifier("x".to_string()),
            Span::new(6, 7),
        ));
        let arms = vec![
            MatchArm {
                pattern: Pattern::Literal(Literal::Integer(1, None)),
                guard: None,
                body: Box::new(Expr::new(
                    ExprKind::Literal(Literal::String("one".to_string())),
                    Span::new(15, 20),
                )),
                span: Span::new(10, 20),
            },
            MatchArm {
                pattern: Pattern::Wildcard,
                guard: None,
                body: Box::new(Expr::new(
                    ExprKind::Literal(Literal::String("other".to_string())),
                    Span::new(28, 35),
                )),
                span: Span::new(25, 35),
            },
        ];
        let expr = Expr::new(
            ExprKind::Match {
                expr: expr_to_match,
                arms,
            },
            Span::new(0, 36),
        );
        match expr.kind {
            ExprKind::Match { expr: e, arms: a } => {
                assert_eq!(a.len(), 2);
                match e.kind {
                    ExprKind::Identifier(id) => assert_eq!(id, "x"),
                    _ => panic!("Wrong match expression"),
                }
            }
            _ => panic!("Expected match expression"),
        }
    }
    #[test]
    fn test_pattern_variants() {
        let patterns = vec![
            Pattern::Wildcard,
            Pattern::Literal(Literal::Integer(42, None)),
            Pattern::Identifier("x".to_string()),
            Pattern::Tuple(vec![
                Pattern::Literal(Literal::Integer(1, None)),
                Pattern::Identifier("x".to_string()),
            ]),
            Pattern::List(vec![
                Pattern::Literal(Literal::Integer(1, None)),
                Pattern::Literal(Literal::Integer(2, None)),
            ]),
            Pattern::Struct {
                name: "Point".to_string(),
                fields: vec![StructPatternField {
                    name: "x".to_string(),
                    pattern: Some(Pattern::Identifier("x".to_string())),
                }],
                has_rest: false,
            },
            Pattern::Range {
                start: Box::new(Pattern::Literal(Literal::Integer(1, None))),
                end: Box::new(Pattern::Literal(Literal::Integer(10, None))),
                inclusive: true,
            },
            Pattern::Or(vec![
                Pattern::Literal(Literal::Integer(1, None)),
                Pattern::Literal(Literal::Integer(2, None)),
            ]),
            Pattern::Rest,
        ];
        for pattern in patterns {
            match pattern {
                Pattern::Tuple(list) | Pattern::List(list) => assert!(!list.is_empty()),
                Pattern::Struct { fields, .. } => assert!(!fields.is_empty()),
                Pattern::Or(patterns) => assert!(!patterns.is_empty()),
                Pattern::Range { .. }
                | Pattern::Wildcard
                | Pattern::Literal(_)
                | Pattern::Identifier(_)
                | Pattern::Rest
                | Pattern::RestNamed(_)
                | Pattern::Ok(_)
                | Pattern::Err(_)
                | Pattern::Some(_)
                | Pattern::None
                | Pattern::QualifiedName(_)
                | Pattern::AtBinding { .. }
                | Pattern::WithDefault { .. }
                | Pattern::Mut(_)
                | Pattern::TupleVariant { .. } => {} // Simple patterns
            }
        }
    }
    #[test]
    fn test_type_kinds() {
        let types = vec![
            Type {
                kind: TypeKind::Named("i32".to_string()),
                span: Span::new(0, 3),
            },
            Type {
                kind: TypeKind::Optional(Box::new(Type {
                    kind: TypeKind::Named("String".to_string()),
                    span: Span::new(0, 6),
                })),
                span: Span::new(0, 7),
            },
            Type {
                kind: TypeKind::List(Box::new(Type {
                    kind: TypeKind::Named("f64".to_string()),
                    span: Span::new(1, 4),
                })),
                span: Span::new(0, 5),
            },
            Type {
                kind: TypeKind::Function {
                    params: vec![Type {
                        kind: TypeKind::Named("i32".to_string()),
                        span: Span::new(0, 3),
                    }],
                    ret: Box::new(Type {
                        kind: TypeKind::Named("String".to_string()),
                        span: Span::new(7, 13),
                    }),
                },
                span: Span::new(0, 13),
            },
        ];
        for ty in types {
            match ty.kind {
                TypeKind::Named(name) => assert!(!name.is_empty()),
                TypeKind::Generic { base, params } => {
                    assert!(!base.is_empty());
                    assert!(!params.is_empty());
                }
                TypeKind::Optional(_) | TypeKind::List(_) | TypeKind::Series { .. } => {}
                TypeKind::Function { params, .. } => assert!(!params.is_empty()),
                TypeKind::DataFrame { columns } => assert!(!columns.is_empty()),
                TypeKind::Tuple(ref types) => assert!(!types.is_empty()),
                TypeKind::Reference {
                    is_mut: _,
                    lifetime: _,
                    ref inner,
                } => {
                    // Reference types should have a valid inner type
                    if let TypeKind::Named(ref name) = inner.kind {
                        assert!(!name.is_empty());
                    }
                }
                TypeKind::Array { elem_type: _, size } => {
                    // Array types should have a valid size
                    assert!(size > 0);
                }
            }
        }
    }
    #[test]
    fn test_param_creation() {
        let param = Param {
            pattern: Pattern::Identifier("count".to_string()),
            ty: Type {
                kind: TypeKind::Named("usize".to_string()),
                span: Span::new(6, 11),
            },
            span: Span::new(0, 11),
            is_mutable: false,
            default_value: None,
        };
        assert_eq!(param.name(), "count");
        match param.ty.kind {
            TypeKind::Named(name) => assert_eq!(name, "usize"),
            _ => panic!("Wrong type kind"),
        }
    }

    #[test]
    fn test_string_interpolation_parts() {
        // Test string interpolation with mixed parts
        let parts = vec![
            StringPart::Text("Hello, ".to_string()),
            StringPart::Expr(Box::new(Expr::new(
                ExprKind::Identifier("name".to_string()),
                Span::new(8, 12),
            ))),
            StringPart::Text("!".to_string()),
        ];

        let expr = Expr::new(ExprKind::StringInterpolation { parts }, Span::new(0, 13));

        if let ExprKind::StringInterpolation { parts } = expr.kind {
            assert_eq!(parts.len(), 3);
            match &parts[0] {
                StringPart::Text(s) => assert_eq!(s, "Hello, "),
                _ => panic!("Expected static part"),
            }
            match &parts[1] {
                StringPart::Expr(e) => {
                    if let ExprKind::Identifier(id) = &e.kind {
                        assert_eq!(id, "name");
                    }
                }
                _ => panic!("Expected dynamic part"),
            }
        }
    }

    #[test]
    fn test_async_function_creation() {
        // Test async function with await
        let func = Expr::new(
            ExprKind::Function {
                name: "fetch_data".to_string(),
                type_params: vec![],
                params: vec![],
                return_type: None,
                body: Box::new(Expr::new(
                    ExprKind::Await {
                        expr: Box::new(Expr::new(
                            ExprKind::Identifier("api_call".to_string()),
                            Span::new(0, 8),
                        )),
                    },
                    Span::new(0, 14),
                )),
                is_async: true,
                is_pub: false,
            },
            Span::new(0, 30),
        );

        if let ExprKind::Function { is_async, body, .. } = func.kind {
            assert!(is_async);
            if let ExprKind::Await { .. } = body.kind {
                // Correctly contains await expression
            } else {
                panic!("Expected await in async function");
            }
        }
    }

    #[test]
    fn test_try_catch_finally() {
        // Test try-catch-finally structure
        let try_catch = Expr::new(
            ExprKind::TryCatch {
                try_block: Box::new(Expr::new(
                    ExprKind::Identifier("risky_operation".to_string()),
                    Span::new(4, 19),
                )),
                catch_clauses: vec![CatchClause {
                    pattern: Pattern::Identifier("e".to_string()),
                    body: Box::new(Expr::new(
                        ExprKind::Identifier("handle_error".to_string()),
                        Span::new(25, 37),
                    )),
                }],
                finally_block: Some(Box::new(Expr::new(
                    ExprKind::Identifier("cleanup".to_string()),
                    Span::new(45, 52),
                ))),
            },
            Span::new(0, 52),
        );

        if let ExprKind::TryCatch {
            catch_clauses,
            finally_block,
            ..
        } = try_catch.kind
        {
            assert_eq!(catch_clauses.len(), 1);
            assert!(finally_block.is_some());
        }
    }

    #[test]
    fn test_result_option_types() {
        // Test Result and Option type constructors
        let ok_val = Expr::new(
            ExprKind::Ok {
                value: Box::new(Expr::new(
                    ExprKind::Literal(Literal::Integer(42, None)),
                    Span::new(3, 5),
                )),
            },
            Span::new(0, 6),
        );

        let err_val = Expr::new(
            ExprKind::Err {
                error: Box::new(Expr::new(
                    ExprKind::Literal(Literal::String("error".to_string())),
                    Span::new(4, 11),
                )),
            },
            Span::new(0, 12),
        );

        let some_val = Expr::new(
            ExprKind::Some {
                value: Box::new(Expr::new(
                    ExprKind::Literal(Literal::Integer(1, None)),
                    Span::new(5, 6),
                )),
            },
            Span::new(0, 7),
        );

        let none_val = Expr::new(ExprKind::None, Span::new(0, 4));

        assert!(matches!(ok_val.kind, ExprKind::Ok { .. }));
        assert!(matches!(err_val.kind, ExprKind::Err { .. }));
        assert!(matches!(some_val.kind, ExprKind::Some { .. }));
        assert!(matches!(none_val.kind, ExprKind::None));
    }

    // Test disabled: Pipeline operator enum variant pending
    // #[test]
    // fn test_pipeline_operator() {
    //     // Test pipeline operator expression
    //     let pipeline = Expr::new(
    //         ExprKind::Binary {
    //             left: Box::new(Expr::new(
    //                 ExprKind::Literal(Literal::Integer(5, None)),
    //                 Span::new(0, 1),
    //             )),
    //             op: BinaryOp::Pipeline,
    //             right: Box::new(Expr::new(
    //                 ExprKind::Identifier("double".to_string()),
    //                 Span::new(5, 11),
    //             )),
    //         },
    //         Span::new(0, 11),
    //     );
    //
    //     if let ExprKind::Binary { op, .. } = pipeline.kind {
    //         assert_eq!(op, BinaryOp::Pipeline);
    //     }
    // }

    #[test]
    fn test_destructuring_patterns() {
        // Test tuple and struct destructuring
        let tuple_pattern = Pattern::Tuple(vec![
            Pattern::Identifier("x".to_string()),
            Pattern::Identifier("y".to_string()),
            Pattern::Rest,
        ]);

        let struct_pattern = Pattern::Struct {
            name: "User".to_string(),
            fields: vec![
                StructPatternField {
                    name: "name".to_string(),
                    pattern: Some(Pattern::Identifier("n".to_string())),
                },
                StructPatternField {
                    name: "age".to_string(),
                    pattern: None,
                },
            ],
            has_rest: true,
        };

        if let Pattern::Tuple(elements) = tuple_pattern {
            assert_eq!(elements.len(), 3);
            assert!(matches!(elements[2], Pattern::Rest));
        }

        if let Pattern::Struct {
            fields, has_rest, ..
        } = struct_pattern
        {
            assert_eq!(fields.len(), 2);
            assert!(has_rest);
        }
    }

    #[test]
    fn test_qualified_names() {
        // Test module-qualified names
        let qualified = Expr::new(
            ExprKind::QualifiedName {
                module: "std".to_string(),
                name: "println".to_string(),
            },
            Span::new(0, 11),
        );

        if let ExprKind::QualifiedName { module, name } = qualified.kind {
            assert_eq!(module, "std");
            assert_eq!(name, "println");
        }
    }

    // Test disabled: Import AST structure pending redesign
    // #[test]
    // fn test_import_export_statements() {
    //     // Test import and export statements
    //     let import = Expr::new(
    //         ExprKind::Import {
    //             module: "std::collections".to_string(),
    //             items: Some(vec!["HashMap".to_string()]),
    //         },
    //         Span::new(0, 30),
    //     );
    // }

    #[test]
    fn test_decorator_attributes() {
        // Test decorator/attribute attachment
        let decorated = Expr::with_attributes(
            ExprKind::Function {
                name: "test_func".to_string(),
                type_params: vec![],
                params: vec![],
                return_type: None,
                body: Box::new(Expr::new(ExprKind::Literal(Literal::Unit), Span::new(0, 0))),
                is_async: false,
                is_pub: false,
            },
            Span::new(0, 20),
            vec![
                Attribute {
                    name: "test".to_string(),
                    args: vec![],
                    span: Span::new(0, 5),
                },
                Attribute {
                    name: "bench".to_string(),
                    args: vec![],
                    span: Span::new(0, 6),
                },
            ],
        );

        assert_eq!(decorated.attributes.len(), 2);
        assert_eq!(decorated.attributes[0].name, "test");
        assert_eq!(decorated.attributes[1].name, "bench");
    }

    // Test removed - CompClause type not defined

    #[test]
    fn test_dataframe_operations() {
        // Test DataFrame literal and operations
        let df = Expr::new(
            ExprKind::DataFrame {
                columns: vec![
                    DataFrameColumn {
                        name: "name".to_string(),
                        values: vec![
                            Expr::new(
                                ExprKind::Literal(Literal::String("Alice".to_string())),
                                Span::new(0, 7),
                            ),
                            Expr::new(
                                ExprKind::Literal(Literal::String("Bob".to_string())),
                                Span::new(8, 13),
                            ),
                        ],
                    },
                    DataFrameColumn {
                        name: "age".to_string(),
                        values: vec![
                            Expr::new(
                                ExprKind::Literal(Literal::Integer(25, None)),
                                Span::new(14, 16),
                            ),
                            Expr::new(
                                ExprKind::Literal(Literal::Integer(30, None)),
                                Span::new(17, 19),
                            ),
                        ],
                    },
                ],
            },
            Span::new(0, 50),
        );

        if let ExprKind::DataFrame { columns } = df.kind {
            assert_eq!(columns.len(), 2);
            assert_eq!(columns[0].name, "name");
            assert_eq!(columns[0].values.len(), 2);
            assert_eq!(columns[1].name, "age");
            assert_eq!(columns[1].values.len(), 2);
        }
    }

    #[test]
    fn test_type_cast_operations() {
        // Test type casting
        let cast = Expr::new(
            ExprKind::TypeCast {
                expr: Box::new(Expr::new(
                    ExprKind::Literal(Literal::Integer(42, None)),
                    Span::new(0, 2),
                )),
                target_type: "f64".to_string(),
            },
            Span::new(0, 10),
        );

        if let ExprKind::TypeCast { target_type, .. } = cast.kind {
            assert_eq!(target_type, "f64");
        }
    }

    #[test]
    fn test_binary_operators_complete() {
        // Test all binary operators
        let ops = vec![
            BinaryOp::Add,
            BinaryOp::Subtract,
            BinaryOp::Multiply,
            BinaryOp::Divide,
            BinaryOp::Modulo,
            BinaryOp::Power,
            BinaryOp::Equal,
            BinaryOp::NotEqual,
            BinaryOp::Less,
            BinaryOp::Greater,
            BinaryOp::LessEqual,
            BinaryOp::GreaterEqual,
            BinaryOp::And,
            BinaryOp::Or,
            // BinaryOp::Pipeline, // Enum variant pending
            BinaryOp::BitwiseAnd,
            BinaryOp::BitwiseOr,
            BinaryOp::BitwiseXor,
            BinaryOp::LeftShift,
            // BinaryOp::RightShift, // Enum variant pending
        ];

        for op in ops {
            let expr = Expr::new(
                ExprKind::Binary {
                    left: Box::new(Expr::new(
                        ExprKind::Literal(Literal::Integer(1, None)),
                        Span::new(0, 1),
                    )),
                    op,
                    right: Box::new(Expr::new(
                        ExprKind::Literal(Literal::Integer(2, None)),
                        Span::new(2, 3),
                    )),
                },
                Span::new(0, 3),
            );

            if let ExprKind::Binary { op: test_op, .. } = expr.kind {
                assert_eq!(test_op, op);
            }
        }
    }

    #[test]
    fn test_span_operations() {
        // Test span merging and creation
        let span1 = Span::new(0, 10);
        let span2 = Span::new(5, 15);
        let merged = span1.merge(span2);

        assert_eq!(merged.start, 0);
        assert_eq!(merged.end, 15);

        // Test with reverse order
        let merged2 = span2.merge(span1);
        assert_eq!(merged2.start, 0);
        assert_eq!(merged2.end, 15);
    }

    #[test]
    fn test_pattern_with_default() {
        // Test pattern with default value
        let pattern = Pattern::WithDefault {
            pattern: Box::new(Pattern::Identifier("count".to_string())),
            default: Box::new(Expr::new(
                ExprKind::Literal(Literal::Integer(0, None)),
                Span::new(0, 1),
            )),
        };

        if let Pattern::WithDefault { pattern, default } = pattern {
            match *pattern {
                Pattern::Identifier(name) => assert_eq!(name, "count"),
                _ => panic!("Expected identifier pattern"),
            }
            match default.kind {
                ExprKind::Literal(Literal::Integer(val, None)) => assert_eq!(val, 0),
                _ => panic!("Expected integer literal"),
            }
        }
    }

    // Test removed - Generator and CompClause types not defined

    #[test]
    fn test_mutable_parameter() {
        // Test mutable parameter
        let param = Param {
            pattern: Pattern::Identifier("data".to_string()),
            ty: Type {
                kind: TypeKind::List(Box::new(Type {
                    kind: TypeKind::Named("i32".to_string()),
                    span: Span::new(0, 3),
                })),
                span: Span::new(0, 6),
            },
            span: Span::new(0, 10),
            is_mutable: true,
            default_value: None,
        };

        assert!(param.is_mutable);
        assert_eq!(param.name(), "data");
    }

    #[test]
    fn test_reference_types() {
        // Test reference and mutable reference types
        let ref_type = Type {
            kind: TypeKind::Reference {
                is_mut: false,
                lifetime: None,
                inner: Box::new(Type {
                    kind: TypeKind::Named("String".to_string()),
                    span: Span::new(1, 7),
                }),
            },
            span: Span::new(0, 7),
        };

        let mut_ref_type = Type {
            kind: TypeKind::Reference {
                is_mut: true,
                lifetime: None,
                inner: Box::new(Type {
                    kind: TypeKind::Named("Vec".to_string()),
                    span: Span::new(4, 7),
                }),
            },
            span: Span::new(0, 7),
        };

        if let TypeKind::Reference {
            is_mut,
            lifetime: _,
            inner,
        } = ref_type.kind
        {
            assert!(!is_mut);
            if let TypeKind::Named(name) = inner.kind {
                assert_eq!(name, "String");
            }
        }

        if let TypeKind::Reference { is_mut, .. } = mut_ref_type.kind {
            assert!(is_mut);
        }
    }

    // EXTREME COVERAGE TESTS FOR 100% AST.RS HOT FILE COVERAGE
    #[test]
    fn test_all_expr_kinds_systematic() {
        // Test every single ExprKind variant for complete coverage

        // Test Literal variants
        let literals = vec![
            ExprKind::Literal(Literal::Integer(42, None)),
            ExprKind::Literal(Literal::Float(3.15)),
            ExprKind::Literal(Literal::Bool(true)),
            ExprKind::Literal(Literal::Bool(false)),
            ExprKind::Literal(Literal::String("test".to_string())),
            ExprKind::Literal(Literal::Char('a')),
            ExprKind::Literal(Literal::Unit),
        ];

        for literal in literals {
            let expr = Expr {
                kind: literal,
                span: Span::new(0, 1),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            };
            // Just test creation and access
            assert!(matches!(expr.kind, ExprKind::Literal(_)));
        }

        // Test Binary operations
        let left = Box::new(Expr {
            kind: ExprKind::Literal(Literal::Integer(1, None)),
            span: Span::new(0, 1),
            attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
        });
        let right = Box::new(Expr {
            kind: ExprKind::Literal(Literal::Integer(2, None)),
            span: Span::new(2, 3),
            attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
        });

        let binary_ops = vec![
            BinaryOp::Add,
            BinaryOp::Subtract,
            BinaryOp::Multiply,
            BinaryOp::Divide,
            BinaryOp::Modulo,
            BinaryOp::Power,
            BinaryOp::Equal,
            BinaryOp::NotEqual,
            BinaryOp::Less,
            BinaryOp::LessEqual,
            BinaryOp::Greater,
            BinaryOp::GreaterEqual,
            BinaryOp::Gt,
            BinaryOp::And,
            BinaryOp::Or,
            BinaryOp::BitwiseAnd,
            BinaryOp::BitwiseOr,
            BinaryOp::BitwiseXor,
            BinaryOp::LeftShift,
            BinaryOp::NullCoalesce,
        ];

        for op in binary_ops {
            let binary_expr = ExprKind::Binary {
                op,
                left: left.clone(),
                right: right.clone(),
            };
            let expr = Expr {
                kind: binary_expr,
                span: Span::new(0, 3),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            };
            assert!(matches!(expr.kind, ExprKind::Binary { .. }));
        }

        // Test Unary operations
        let operand = Box::new(Expr {
            kind: ExprKind::Literal(Literal::Integer(42, None)),
            span: Span::new(1, 3),
            attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
        });

        let unary_ops = vec![
            UnaryOp::Not,
            UnaryOp::Negate,
            UnaryOp::BitwiseNot,
            UnaryOp::Reference,
        ];

        for op in unary_ops {
            let unary_expr = ExprKind::Unary {
                op,
                operand: operand.clone(),
            };
            let expr = Expr {
                kind: unary_expr,
                span: Span::new(0, 3),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            };
            assert!(matches!(expr.kind, ExprKind::Unary { .. }));
        }
    }

    #[test]
    fn test_all_type_kinds_comprehensive() {
        // Test every TypeKind variant for complete coverage

        let type_kinds = vec![
            TypeKind::Named("String".to_string()),
            TypeKind::Generic {
                base: "Vec".to_string(),
                params: vec![Type {
                    kind: TypeKind::Named("i32".to_string()),
                    span: Span::new(0, 3),
                }],
            },
            TypeKind::Function {
                params: vec![Type {
                    kind: TypeKind::Named("i32".to_string()),
                    span: Span::new(0, 3),
                }],
                ret: Box::new(Type {
                    kind: TypeKind::Named("String".to_string()),
                    span: Span::new(7, 13),
                }),
            },
            TypeKind::Tuple(vec![
                Type {
                    kind: TypeKind::Named("i32".to_string()),
                    span: Span::new(0, 3),
                },
                Type {
                    kind: TypeKind::Named("String".to_string()),
                    span: Span::new(5, 11),
                },
            ]),
            TypeKind::Array {
                elem_type: Box::new(Type {
                    kind: TypeKind::Named("i32".to_string()),
                    span: Span::new(0, 3),
                }),
                size: 10,
            },
            TypeKind::Reference {
                is_mut: false,
                lifetime: None,
                inner: Box::new(Type {
                    kind: TypeKind::Named("String".to_string()),
                    span: Span::new(1, 7),
                }),
            },
            TypeKind::Reference {
                is_mut: true,
                lifetime: None,
                inner: Box::new(Type {
                    kind: TypeKind::Named("String".to_string()),
                    span: Span::new(5, 11),
                }),
            },
            TypeKind::Optional(Box::new(Type {
                kind: TypeKind::Named("i32".to_string()),
                span: Span::new(0, 3),
            })),
            TypeKind::List(Box::new(Type {
                kind: TypeKind::Named("String".to_string()),
                span: Span::new(0, 6),
            })),
            TypeKind::DataFrame {
                columns: vec![
                    (
                        "id".to_string(),
                        Type {
                            kind: TypeKind::Named("i32".to_string()),
                            span: Span::new(0, 3),
                        },
                    ),
                    (
                        "name".to_string(),
                        Type {
                            kind: TypeKind::Named("String".to_string()),
                            span: Span::new(0, 6),
                        },
                    ),
                ],
            },
            TypeKind::Series {
                dtype: Box::new(Type {
                    kind: TypeKind::Named("f64".to_string()),
                    span: Span::new(0, 3),
                }),
            },
        ];

        for type_kind in type_kinds {
            let ty = Type {
                kind: type_kind,
                span: Span::new(0, 10),
            };
            // Test construction and basic operations
            assert!(ty.span.start <= ty.span.end);
        }
    }

    #[test]
    fn test_all_pattern_kinds_comprehensive() {
        // Test every Pattern variant for complete coverage

        let patterns = vec![
            Pattern::Wildcard,
            Pattern::Literal(Literal::Integer(42, None)),
            Pattern::Literal(Literal::String("test".to_string())),
            Pattern::Literal(Literal::Bool(true)),
            Pattern::Identifier("variable".to_string()),
            Pattern::QualifiedName(vec!["Module".to_string(), "Type".to_string()]),
            Pattern::Tuple(vec![
                Pattern::Identifier("x".to_string()),
                Pattern::Identifier("y".to_string()),
            ]),
            Pattern::List(vec![
                Pattern::Identifier("head".to_string()),
                Pattern::Wildcard,
            ]),
            Pattern::Struct {
                name: "Point".to_string(),
                fields: vec![
                    StructPatternField {
                        name: "x".to_string(),
                        pattern: Some(Pattern::Identifier("x_val".to_string())),
                    },
                    StructPatternField {
                        name: "y".to_string(),
                        pattern: None, // Shorthand
                    },
                ],
                has_rest: false,
            },
            Pattern::Struct {
                name: "Point".to_string(),
                fields: vec![],
                has_rest: true, // With rest pattern
            },
        ];

        for pattern in patterns {
            // Test pattern construction and basic operations
            match pattern {
                Pattern::Wildcard => {}
                Pattern::Literal(_) => {}
                Pattern::Identifier(ref name) => assert!(!name.is_empty()),
                Pattern::QualifiedName(ref names) => assert!(!names.is_empty()),
                Pattern::Tuple(ref patterns) => assert!(!patterns.is_empty()),
                Pattern::List(ref patterns) => assert!(!patterns.is_empty()),
                Pattern::Struct { ref name, .. } => assert!(!name.is_empty()),
                _ => {} // Handle all other pattern variants
            }
        }
    }

    #[test]
    fn test_complex_expr_constructions() {
        // Test complex expression constructions for edge case coverage

        // Complex nested call
        let complex_call = ExprKind::Call {
            func: Box::new(Expr {
                kind: ExprKind::FieldAccess {
                    object: Box::new(Expr {
                        kind: ExprKind::Identifier("obj".to_string()),
                        span: Span::new(0, 3),
                        attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                    }),
                    field: "method".to_string(),
                },
                span: Span::new(0, 10),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            }),
            args: vec![
                Expr {
                    kind: ExprKind::Literal(Literal::Integer(42, None)),
                    span: Span::new(11, 13),
                    attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                },
                Expr {
                    kind: ExprKind::Literal(Literal::String("arg".to_string())),
                    span: Span::new(15, 20),
                    attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                },
            ],
        };

        let expr = Expr {
            kind: complex_call,
            span: Span::new(0, 21),
            attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
        };
        assert!(matches!(expr.kind, ExprKind::Call { .. }));

        // Complex if expression
        let complex_if = ExprKind::If {
            condition: Box::new(Expr {
                kind: ExprKind::Binary {
                    op: BinaryOp::Greater,
                    left: Box::new(Expr {
                        kind: ExprKind::Identifier("x".to_string()),
                        span: Span::new(3, 4),
                        attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                    }),
                    right: Box::new(Expr {
                        kind: ExprKind::Literal(Literal::Integer(0, None)),
                        span: Span::new(7, 8),
                        attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                    }),
                },
                span: Span::new(3, 8),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            }),
            then_branch: Box::new(Expr {
                kind: ExprKind::Block(vec![Expr {
                    kind: ExprKind::Literal(Literal::String("positive".to_string())),
                    span: Span::new(11, 21),
                    attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                }]),
                span: Span::new(9, 23),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            }),
            else_branch: Some(Box::new(Expr {
                kind: ExprKind::Literal(Literal::String("negative".to_string())),
                span: Span::new(29, 39),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            })),
        };

        let if_expr = Expr {
            kind: complex_if,
            span: Span::new(0, 40),
            attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
        };
        assert!(matches!(if_expr.kind, ExprKind::If { .. }));
    }

    #[test]
    fn test_attribute_and_span_coverage() {
        // Test attribute and span functionality comprehensively

        // Test various attribute types
        let attributes = vec![
            Attribute {
                name: "inline".to_string(),
                args: vec![],
                span: Span::new(0, 8),
            },
            Attribute {
                name: "deprecated".to_string(),
                args: vec!["Use new_function instead".to_string()],
                span: Span::new(0, 40),
            },
            Attribute {
                name: "derive".to_string(),
                args: vec!["Debug".to_string(), "Clone".to_string()],
                span: Span::new(0, 20),
            },
        ];

        for attr in attributes {
            assert!(!attr.name.is_empty());
            assert!(attr.span.start <= attr.span.end);
        }

        // Test expression with attributes
        let expr_with_attrs = Expr::with_attributes(
            ExprKind::Literal(Literal::Integer(42, None)),
            Span::new(0, 2),
            vec![Attribute {
                name: "test_attr".to_string(),
                args: vec![],
                span: Span::new(0, 10),
            }],
        );

        assert_eq!(expr_with_attrs.attributes.len(), 1);
        assert_eq!(expr_with_attrs.attributes[0].name, "test_attr");

        // Test span operations
        let span1 = Span::new(0, 10);
        let span2 = Span::new(5, 15);

        assert_eq!(span1.start, 0);
        assert_eq!(span1.end, 10);
        assert!(span1.start <= span1.end);
        assert!(span2.start <= span2.end);

        // Test default span
        let default_span = Span::default();
        assert_eq!(default_span.start, 0);
        assert_eq!(default_span.end, 0);
    }

    #[test]
    fn test_all_remaining_expr_kinds() {
        // Test remaining ExprKind variants for 100% coverage

        // Test collections
        let list_expr = ExprKind::List(vec![
            Expr {
                kind: ExprKind::Literal(Literal::Integer(1, None)),
                span: Span::new(1, 2),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            },
            Expr {
                kind: ExprKind::Literal(Literal::Integer(2, None)),
                span: Span::new(4, 5),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            },
        ]);

        let tuple_expr = ExprKind::Tuple(vec![
            Expr {
                kind: ExprKind::Literal(Literal::String("first".to_string())),
                span: Span::new(1, 8),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            },
            Expr {
                kind: ExprKind::Literal(Literal::Integer(42, None)),
                span: Span::new(10, 12),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            },
        ]);

        // Test assignments
        let assign_expr = ExprKind::Assign {
            target: Box::new(Expr {
                kind: ExprKind::Identifier("x".to_string()),
                span: Span::new(0, 1),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            }),
            value: Box::new(Expr {
                kind: ExprKind::Literal(Literal::Integer(42, None)),
                span: Span::new(4, 6),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            }),
        };

        // Test function definitions
        let func_expr = ExprKind::Function {
            name: "add".to_string(),
            type_params: vec![],
            params: vec![
                Param {
                    pattern: Pattern::Identifier("a".to_string()),
                    ty: Type {
                        kind: TypeKind::Named("i32".to_string()),
                        span: Span::new(0, 3),
                    },
                    default_value: None,
                    is_mutable: false,
                    span: Span::new(0, 5),
                },
                Param {
                    pattern: Pattern::Identifier("b".to_string()),
                    ty: Type {
                        kind: TypeKind::Named("i32".to_string()),
                        span: Span::new(0, 3),
                    },
                    default_value: None,
                    is_mutable: false,
                    span: Span::new(0, 5),
                },
            ],
            return_type: Some(Type {
                kind: TypeKind::Named("i32".to_string()),
                span: Span::new(0, 3),
            }),
            body: Box::new(Expr {
                kind: ExprKind::Binary {
                    op: BinaryOp::Add,
                    left: Box::new(Expr {
                        kind: ExprKind::Identifier("a".to_string()),
                        span: Span::new(0, 1),
                        attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                    }),
                    right: Box::new(Expr {
                        kind: ExprKind::Identifier("b".to_string()),
                        span: Span::new(4, 5),
                        attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
                    }),
                },
                span: Span::new(0, 5),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            }),
            is_async: false,
            is_pub: false,
        };

        // Test all constructions
        let expressions = vec![list_expr, tuple_expr, assign_expr, func_expr];

        for expr_kind in expressions {
            let expr = Expr {
                kind: expr_kind,
                span: Span::new(0, 10),
                attributes: vec![],
            leading_comments: vec![],
            trailing_comment: None,
            };
            // Verify construction succeeded
            assert!(expr.span.start <= expr.span.end);
        }
    }
}
