oxur-ast 0.2.0

Rust AST ↔ S-expression conversion for Oxur
Documentation
use super::*;

/// Capture mode for closures and async blocks
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CaptureBy {
    /// By-value capture: `move`
    Value,
    /// By-reference capture (default)
    Ref,
}

/// Expression
#[derive(Debug, Clone, PartialEq)]
pub struct Expr {
    pub id: NodeId,
    pub kind: ExprKind,
    pub span: Span,
    pub attrs: AttrVec,
    pub tokens: Option<TokenStream>,
}

/// Expression kind
#[derive(Debug, Clone, PartialEq)]
pub enum ExprKind {
    // Phase 1: Macro calls, literals, paths
    MacCall(MacCall),
    Lit(Lit),
    Path(Option<QSelf>, Path),

    // Stage 2: Control flow
    If {
        cond: Box<Expr>,
        then_branch: Block,
        else_branch: Option<Box<Expr>>,
    },
    Match {
        expr: Box<Expr>,
        arms: Vec<Arm>,
    },
    While {
        label: Option<Label>,
        cond: Box<Expr>,
        body: Block,
    },
    ForLoop {
        label: Option<Label>,
        pat: Pat,
        iter: Box<Expr>,
        body: Block,
    },
    Loop {
        label: Option<Label>,
        body: Block,
    },

    // Stage 3: Operations and calls
    Binary {
        left: Box<Expr>,
        op: BinOp,
        right: Box<Expr>,
    },
    Unary {
        op: UnOp,
        expr: Box<Expr>,
    },
    Call {
        func: Box<Expr>,
        args: Vec<Expr>,
    },
    MethodCall {
        receiver: Box<Expr>,
        method: Ident,
        args: Vec<Expr>,
    },

    // Stage 7: Remaining expressions
    /// Array literal: `[1, 2, 3]` or `[0; 10]`
    Array(Vec<Expr>),

    /// Tuple literal: `(a, b, c)`
    Tuple(Vec<Expr>),

    /// Field access: `obj.field`
    Field {
        expr: Box<Expr>,
        field: Ident,
    },

    /// Index: `arr[i]`
    Index {
        expr: Box<Expr>,
        index: Box<Expr>,
    },

    /// Assignment: `x = 5`
    Assign {
        left: Box<Expr>,
        right: Box<Expr>,
    },

    /// Struct literal: `Point { x: 1, y: 2 }`
    Struct {
        path: Path,
        fields: Vec<ExprField>,
    },

    /// Closure: `|x| x + 1`
    Closure {
        params: Vec<Param>,
        body: Box<Expr>,
    },

    /// Range: `0..10`, `..10`, `0..`, `..=10`, etc.
    Range {
        start: Option<Box<Expr>>,
        end: Option<Box<Expr>>,
        inclusive: bool,
    },

    // Phase 5: Priority 3 - Expression gap filling
    /// Parenthesized expression: `(expr)`
    Paren(Box<Expr>),

    /// Try operator: `expr?`
    Try(Box<Expr>),

    /// Type cast: `expr as Type`
    Cast {
        expr: Box<Expr>,
        ty: Box<Ty>,
    },

    /// Break with optional label and value: `break`, `break 'label`, `break value`
    Break {
        label: Option<Label>,
        value: Option<Box<Expr>>,
    },

    /// Continue with optional label: `continue`, `continue 'label`
    Continue {
        label: Option<Label>,
    },

    /// Return with optional value: `return`, `return expr`
    Return {
        value: Option<Box<Expr>>,
    },

    // Phase 13: Async/await and modern features
    /// Async block: `async { ... }` or `async move { ... }`
    Async {
        capture: CaptureBy,
        body: Block,
    },

    /// Await: `expr.await`
    Await {
        expr: Box<Expr>,
    },

    /// Let expression: `let pat = expr` (in if-let, while-let)
    Let {
        pat: Pat,
        expr: Box<Expr>,
    },

    /// Array repeat: `[expr; count]`
    Repeat {
        expr: Box<Expr>,
        count: Box<Expr>,
    },

    /// Unsafe block: `unsafe { ... }`
    Unsafe {
        body: Block,
    },

    /// Yield: `yield expr` (generators - unstable)
    Yield {
        value: Option<Box<Expr>>,
    },

    /// Const block: `const { ... }`
    Const {
        body: Block,
    },
}

/// Macro call
#[derive(Debug, Clone, PartialEq)]
pub struct MacCall {
    pub path: Path,
    pub args: MacArgs,
    pub prior_type_ascription: Option<(usize, bool)>,
}

impl MacCall {
    pub fn new(path: Path, args: MacArgs) -> Self {
        Self { path, args, prior_type_ascription: None }
    }
}

/// Macro arguments
#[derive(Debug, Clone, PartialEq)]
pub enum MacArgs {
    Empty,
    Delimited { dspan: DelSpan, delim: Delimiter, tokens: TokenStream },
    Eq { eq_span: Span, tokens: TokenStream },
}

/// Delimiter
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Delimiter {
    Paren,
    Brace,
    Bracket,
    Invisible,
}

/// Literal
#[derive(Debug, Clone, PartialEq)]
pub struct Lit {
    pub kind: LitKind,
    pub span: Span,
}

/// Literal kind
#[derive(Debug, Clone, PartialEq)]
pub enum LitKind {
    /// String literal: `"hello"`
    Str(String),
    /// Integer literal: `42`, `0xFF`, `0o755`, `0b1010`
    Int(i128),
    /// Boolean literal: `true`, `false`
    Bool(bool),
    /// Floating point literal: `3.14`, `1.0e-5`
    Float(String),
    /// Character literal: `'a'`, `'\n'`, `'\u{1F600}'`
    Char(char),
    /// Byte literal: `b'A'`, `b'\n'`
    Byte(u8),
    /// Byte string literal: `b"hello"`
    ByteStr(Vec<u8>),
    /// C string literal: `c"hello"`
    CStr(Vec<u8>),
    /// Error or unknown literal (for forward compatibility)
    Verbatim(String),
}

/// Match arm
#[derive(Debug, Clone, PartialEq)]
pub struct Arm {
    pub attrs: AttrVec,
    pub pat: Pat,
    pub guard: Option<Box<Expr>>,
    pub body: Box<Expr>,
    pub span: Span,
    pub id: NodeId,
}

/// Loop label (e.g., 'outer in 'outer: loop { ... })
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Label {
    pub ident: Ident,
}

/// Binary operator
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
    Add,    // +
    Sub,    // -
    Mul,    // *
    Div,    // /
    Rem,    // %
    And,    // &&
    Or,     // ||
    BitAnd, // &
    BitOr,  // |
    BitXor, // ^
    Shl,    // <<
    Shr,    // >>
    Eq,     // ==
    Ne,     // !=
    Lt,     // <
    Le,     // <=
    Gt,     // >
    Ge,     // >=
}

/// Unary operator
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnOp {
    Not,    // !
    Neg,    // -
    Deref,  // *
    Ref,    // & (immutable borrow)
    RefMut, // &mut (mutable borrow)
}

/// Expression field (for struct literals)
#[derive(Debug, Clone, PartialEq)]
pub struct ExprField {
    pub attrs: AttrVec,
    pub ident: Ident,
    pub expr: Expr,
    pub is_shorthand: bool, // true for `Point { x, y }` vs `Point { x: x, y: y }`
    pub span: Span,
}