use crate::{
    ast::untyped::{self, BinOp, Ident, NodeId, UnaryOp},
    lexer::token::Literal,
    typecheck::{TyCtx, TyKind},
};

#[derive(Debug, Clone)]
pub struct Expr {
    pub kind: ExprKind,
    pub ty: TyKind,
}

#[derive(Debug, Clone)]
pub enum ExprKind {
    Literal(Literal),
    Ident(Ident),
    /// `callee(args)`  — callee is any expression (covers plain `foo()` and chained `foo()()`)
    CallExpr {
        callee: Box<Expr>,
        args: Vec<Expr>,
    },
    /// `receiver.method(args)`
    MethodCall {
        receiver: Box<Expr>,
        method: Ident,
        args: Vec<Expr>,
    },
    /// `receiver.field`
    Field {
        receiver: Box<Expr>,
        name: Ident,
    },
    Grouping(Box<Expr>),
    Binary {
        lhs: Box<Expr>,
        rhs: Box<Expr>,
        op: BinOp,
    },
    Unary {
        rhs: Box<Expr>,
        op: UnaryOp,
    },
}
