use crate::token::Span; // ── Operators ────────────────────────────────────────────────────────────────── #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum UnaryOp { Neg, // `-` Not, // `!` BitNot, // `~` Deref, // `*` AddrOf, // `&` } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CompoundAssignOp { Add, // `+=` Sub, // `-=` Mul, // `*=` Div, // `/=` Rem, // `%=` BitAnd, // `&=` BitOr, // `|=` BitXor, // `^=` Shl, // `<<=` Shr, // `>>=` } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BinaryOp { // Logical Or, // `or` And, // `and` // Bitwise BitOr, // `|` BitXor, // `^` BitAnd, // `&` // Comparison Eq, // `==` Ne, // `!=` Lt, // `<` Gt, // `>` Le, // `<=` Ge, // `>=` // Arithmetic Add, // `+` Sub, // `-` Mul, // `*` Div, // `/` Rem, // `%` // Shift Shl, // `<<` Shr, // `>>` // Assignment (lowest precedence, right-associative) Assign, // `=` } // ── Types ────────────────────────────────────────────────────────────────────── #[derive(Debug, Clone)] pub enum Type { // Unsigned integers U8, U16, U32, U64, // Signed integers I8, I16, I32, I64, // Floating-point F32, F64, // Other primitives Bool, Char, // User-defined named type (e.g. a struct) Named(String, Span), // Typed pointer: `*type` (immutable) or `*mut type` (mutable) Pointer { mutable: bool, pointee: Box }, // Opaque (untyped) pointer: `*opaque` (immutable) or `*mut opaque` (mutable) OpaquePointer { mutable: bool }, // Fixed-size array: `[type; INT_LIT]` Array { elem: Box, size: String }, // Error placeholder for recovery Error, } // ── Struct literal field ─────────────────────────────────────────────────────── #[derive(Debug, Clone)] pub struct StructField { pub name: String, pub name_span: Span, pub value: Expr, } // ── Expression ──────────────────────────────────────────────────────────────── #[derive(Debug, Clone)] pub struct Expr { pub kind: ExprKind, pub span: Span, } impl Expr { pub fn new(kind: ExprKind, span: Span) -> Self { Self { kind, span } } } #[derive(Debug, Clone)] pub enum ExprKind { // Literals IntLit(String), FloatLit(String), StringLit(String), CharLit(String), Bool(bool), // Identifier Ident(String), // Struct literal: `Foo { x: 1, y: 2 }` StructLit { name: String, name_span: Span, fields: Vec, }, // Operators Unary { op: UnaryOp, op_span: Span, expr: Box, }, Binary { op: BinaryOp, op_span: Span, lhs: Box, rhs: Box, }, // Compound assignment: `lhs op= rhs` (expands to `lhs = lhs op rhs`) CompoundAssign { op: CompoundAssignOp, op_span: Span, lhs: Box, rhs: Box, }, // Postfix Field { expr: Box, field: String, field_span: Span, }, Index { expr: Box, index: Box, }, Call { callee: Box, args: Vec, }, // Parenthesised expression Group(Box), // Placeholder for parse errors — allows parsing to continue Error, } // ── Block ────────────────────────────────────────────────────────────────────── #[derive(Debug, Clone)] pub struct Block { pub stmts: Vec, pub span: Span, } // ── Else branch ─────────────────────────────────────────────────────────────── #[derive(Debug, Clone)] pub enum ElseBranch { If(Box), // `else if …` Block(Block), // `else { … }` } // ── Statement ───────────────────────────────────────────────────────────────── #[derive(Debug, Clone)] pub struct Stmt { pub kind: StmtKind, pub span: Span, } #[derive(Debug, Clone)] pub enum StmtKind { /// `let [mut] name [: type] [= expr] ;` Let { mutable: bool, name: String, name_span: Span, ty: Option, init: Option, }, /// `return [expr] ;` Return(Option), /// `if expr_ns block [else else_branch]` If { cond: Expr, then_block: Block, else_branch: Option, }, /// `while expr_ns block` While { cond: Expr, body: Block }, /// `loop block` Loop { body: Block }, /// `break ;` Break, /// `continue ;` Continue, /// `{ stmts }` Block(Block), /// `expr ;` Expr(Expr), /// Error placeholder — emitted during recovery so the parent can continue. Error, } // ── Top-level definitions ────────────────────────────────────────────────────── /// A function parameter: `[mut] name : type`. #[derive(Debug, Clone)] pub struct Param { pub mutable: bool, pub name: String, pub name_span: Span, pub ty: Type, } /// A struct definition field: `name : type`. /// /// Named `FieldDef` to distinguish from `StructField`, which is a /// field in a struct *literal expression*. #[derive(Debug, Clone)] pub struct FieldDef { pub name: String, pub name_span: Span, pub ty: Type, } /// `fn name ( params ) [ -> type ] block` #[derive(Debug, Clone)] pub struct FuncDef { pub name: String, pub name_span: Span, pub params: Vec, pub ret_ty: Option, pub body: Block, } /// `struct name { fields }` #[derive(Debug, Clone)] pub struct StructDef { pub name: String, pub name_span: Span, pub fields: Vec, } #[derive(Debug, Clone)] pub struct TopLevelDef { pub kind: TopLevelDefKind, pub span: Span, } #[derive(Debug, Clone)] pub enum TopLevelDefKind { Func(FuncDef), Struct(StructDef), /// Error placeholder for recovery. Error, } /// The root of the AST — a sequence of top-level definitions. #[derive(Debug, Clone)] pub struct Program { pub defs: Vec, pub span: Span, }