t-ree 0.1.0

AST definitions for the T programming language
Documentation
use crate::declaration::Parameter;
use crate::operator::{ArithmeticOperator, BinaryOperator, UnaryOperator};
use crate::types::Type;

/// Source location in the input.
#[derive(Copy, Clone, Debug, Default)]
pub struct Span {
    /// Line number (1-based, 0 = unknown).
    pub line: u32,
    /// Column number (1-based, 0 = unknown).
    pub column: u32,
}

impl std::fmt::Display for Span {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(formatter, "{}:{}", self.line, self.column)
    }
}

/// Variable binding mode.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Binding {
    /// Immutable value (moved or copied).
    Value,
    /// Immutable reference.
    Reference,
    /// Mutable variable reference.
    Variable,
}

/// Literal values.
#[derive(Clone, Debug, PartialEq)]
pub enum Literal {
    /// Boolean literal.
    Bool(bool),
    /// Integer literal.
    Integer(u128),
    /// Floating-point literal.
    Float(f64),
    /// Byte string literal.
    String(Vec<u8>),
    /// Null pointer literal.
    Null,
}

/// A typed expression node.
#[derive(Clone, Debug)]
pub struct Expression {
    /// The expression variant.
    pub kind: ExpressionKind,
    /// The resolved type of this expression (`None` until resolution).
    pub resolved_type: Option<Type>,
    /// Source location.
    pub span: Span,
}

impl Expression {
    /// Creates a new expression with the given kind and type.
    pub fn new(kind: ExpressionKind, resolved_type: Option<Type>) -> Self {
        Self {
            kind,
            resolved_type,
            span: Span::default(),
        }
    }

    /// Creates a new expression with the given kind, type, and source location.
    pub fn with_span(kind: ExpressionKind, resolved_type: Option<Type>, span: Span) -> Self {
        Self {
            kind,
            resolved_type,
            span,
        }
    }
}

/// A sequence of statements with an optional trailing expression.
#[derive(Clone, Debug)]
pub struct Block {
    /// Statements in the block.
    pub statements: Vec<Statement>,
    /// Optional result expression.
    pub result: Option<Box<Expression>>,
}

impl Block {
    /// Creates an empty block with no statements or result.
    pub fn empty() -> Self {
        Self {
            statements: Vec::new(),
            result: None,
        }
    }

    /// Creates a block containing only a result expression.
    pub fn expression(expression: Expression) -> Self {
        Self {
            statements: Vec::new(),
            result: Some(Box::new(expression)),
        }
    }
}

/// A single arm in a match expression.
#[derive(Clone, Debug)]
pub struct MatchArm {
    /// The pattern to match against.
    pub pattern: MatchPattern,
    /// The body to execute if the pattern matches.
    pub body: Block,
}

/// Pattern for match arms.
#[derive(Clone, Debug)]
pub enum MatchPattern {
    /// Match a specific integer value.
    Integer(u128),
    /// Bind the matched value to a variable.
    Variable(String),
    /// Match anything (wildcard `_`).
    Wildcard,
    /// Match an enum variant by type name, binding the inner value.
    Variant(String, String),
}

/// Statement nodes within a block.
#[derive(Clone, Debug)]
pub enum Statement {
    /// Expression evaluated for side effects.
    Expression(Expression),
    /// Local variable declaration.
    Let {
        /// Variable name.
        name: String,
        /// Binding mode.
        binding: Binding,
        /// Optional explicit type annotation.
        declared_type: Option<Type>,
        /// Initializer expression.
        value: Expression,
    },
    /// Assignment to a place expression.
    Assign(Expression, Expression),
    /// Return from the current function.
    Return(Option<Expression>),
    /// Label definition (jump target with parameters).
    Label {
        /// Label name.
        name: String,
        /// Label parameters.
        parameters: Vec<Parameter>,
        /// Initial arguments passed when entering the label.
        initial_arguments: Vec<Expression>,
    },
    /// Jump to a label with arguments.
    Jump {
        /// Target label name.
        label: String,
        /// Arguments passed to the label.
        arguments: Vec<Expression>,
    },
    /// Simultaneous multi-replacement with optional old-value capture.
    MultiReplace {
        /// Optional new bindings for old values.
        bindings: Vec<Option<(String, Binding)>>,
        /// Place expressions to assign to.
        targets: Vec<Expression>,
        /// New values (evaluated before any assignment).
        values: Vec<Expression>,
    },
    /// Deferred statement, executed at the end of the enclosing block (LIFO).
    Defer(Box<Self>),
}

/// Expression variants.
#[derive(Clone, Debug)]
pub enum ExpressionKind {
    /// Literal value.
    Literal(Literal),
    /// Variable reference.
    Variable(String),

    /// Binary operation (e.g. `a + b`).
    BinaryOperation(BinaryOperator, Box<Expression>, Box<Expression>),
    /// Unary operation (e.g. `-x`).
    UnaryOperation(UnaryOperator, Box<Expression>),

    /// Function call with arguments.
    Call(Box<Expression>, Vec<Expression>),
    /// Field access (e.g. `x.field`).
    Field(Box<Expression>, String),
    /// Index access (e.g. `a[i]`).
    Index(Box<Expression>, Box<Expression>),

    /// Pointer dereference.
    Dereference(Box<Expression>),

    /// Newtype conversion (`Type: value`, `value.Type`). Safe, type-checked.
    Convert(Box<Expression>, Type),
    /// Unsafe pointer transmute (`value as Type`). Pointer ↔ integer/pointer only.
    Transmute(Box<Expression>, Type),
    /// Size of a type.
    SizeOf(Type),

    /// Newtype construction with named fields (e.g. `point: (x: 1.0, y: 2.0)`).
    TypeConstruction(String, Vec<(String, Expression)>),
    /// Array literal.
    ArrayLiteral(Vec<Expression>),
    /// Tuple literal.
    TupleLiteral(Vec<Expression>),

    /// Block expression.
    Block(Block),
    /// Conditional expression.
    If {
        /// Condition.
        condition: Box<Expression>,
        /// Then branch.
        then_branch: Block,
        /// Optional else branch.
        else_branch: Option<Block>,
    },
    /// Match expression.
    Match {
        /// Value being matched.
        value: Box<Expression>,
        /// Match arms.
        arms: Vec<MatchArm>,
    },

    /// Replace: assigns new value, returns old value (like `std::mem::replace`).
    Replace(Box<Expression>, Box<Expression>),
    /// Compound assignment (`+=`, `-=`, `*=`, `/=`).
    OpAssign(ArithmeticOperator, Box<Expression>, Box<Expression>),

    /// Slice operation: converts array to slice.
    /// Full slice (no bounds) or sub-slice (start, end).
    Slice(
        Box<Expression>,
        Option<Box<Expression>>,
        Option<Box<Expression>>,
    ),

    /// Debug print (temporary intrinsic).
    Print(Vec<Expression>),
}