sharp 0.1.0

A modern, statically-typed programming language with Python-like syntax, compiled to native code via LLVM. Game engine ready!
// AST definitions for Sharp language

use std::rc::Rc;

/// The root of a Sharp program.
#[derive(Debug, Clone)]
pub struct Program {
    pub items: Vec<TopLevel>,
}

/// Top‑level declarations.
#[derive(Debug, Clone)]
pub enum TopLevel {
    Import(ImportDecl),
    Func(FuncDecl),
    Struct(StructDecl),
    Class(ClassDecl),
    Const(ConstDecl),
    Impl(ImplBlock),
    Enum(EnumDecl),
}

#[derive(Debug, Clone)]
pub struct ImplBlock {
    pub ty: String,  // The struct/type this impl is for
    pub methods: Vec<FuncDecl>,
}

#[derive(Debug, Clone)]
pub struct EnumDecl {
    pub name: String,
    pub variants: Vec<EnumVariant>,
}

#[derive(Debug, Clone)]
pub struct EnumVariant {
    pub name: String,
    pub fields: Vec<Type>,  // For variants with data
}

#[derive(Debug, Clone)]
pub struct ImportDecl {
    pub module_path: Vec<String>,
    pub alias: Option<String>,
}

#[derive(Debug, Clone)]
pub struct FuncDecl {
    pub name: String,
    pub type_params: Vec<String>,
    pub params: Vec<Param>,
    pub ret_type: Option<Type>,
    pub body: Block,
}

#[derive(Debug, Clone)]
pub struct Param {
    pub name: String,
    pub ty: Option<Type>,
    pub mutable: bool,  // for `mut param`
    pub default: Option<Expr>,
}

#[derive(Debug, Clone)]
pub struct StructDecl {
    pub name: String,
    pub type_params: Vec<String>,
    pub fields: Vec<Field>,
}

#[derive(Debug, Clone)]
pub struct ClassDecl {
    pub name: String,
    pub base: Option<String>,
    pub body: Block,
}

#[derive(Debug, Clone)]
pub struct ConstDecl {
    pub name: String,
    pub ty: Option<Type>,
    pub value: Expr,
}

#[derive(Debug, Clone)]
pub struct Field {
    pub name: String,
    pub ty: Type,
    pub default: Option<Expr>,
}

#[derive(Debug, Clone)]
pub struct Block {
    pub statements: Vec<Stmt>,
}

#[derive(Debug, Clone)]
pub enum Stmt {
    VarDecl(VarDecl),
    Expr(Expr),
    If(IfStmt),
    For(ForStmt),
    While(WhileStmt),
    Return(Option<Expr>),
    Match(MatchStmt),
}

#[derive(Debug, Clone)]
pub struct VarDecl {
    pub name: String,
    pub ty: Option<Type>,
    pub init: Expr,
}

#[derive(Debug, Clone)]
pub struct IfStmt {
    pub condition: Expr,
    pub then_branch: Block,
    pub elif_branches: Vec<(Expr, Block)>,
    pub else_branch: Option<Block>,
}

#[derive(Debug, Clone)]
pub struct ForStmt {
    pub init: Option<Box<Stmt>>, // e.g., `let i = 0`
    pub condition: Expr,
    pub update: Option<Box<Stmt>>, // e.g., `i += 1`
    pub body: Block,
}

#[derive(Debug, Clone)]
pub struct WhileStmt {
    pub condition: Expr,
    pub body: Block,
}

#[derive(Debug, Clone)]
pub struct MatchStmt {
    pub expr: Expr,
    pub arms: Vec<(Pattern, Block)>,
}

#[derive(Debug, Clone)]
pub enum Pattern {
    Lit(Literal),
    Ident(String),
    Wildcard,
    // Extend as needed
}

#[derive(Debug, Clone)]
pub enum Expr {
    Literal(Literal),
    Ident(String),
    Binary(Box<Expr>, BinOp, Box<Expr>),
    Unary(UnOp, Box<Expr>),
    Call(Box<Expr>, Vec<Expr>),
    MethodCall(Box<Expr>, String, Vec<Expr>),  // obj.method(args)
    Lambda(Vec<Param>, Box<Expr>),
    List(Vec<Expr>),
    Dict(Vec<(Expr, Expr)>),
    Index(Box<Expr>, Box<Expr>),       // arr[i]
    FieldAccess(Box<Expr>, String),    // obj.field
    StructInit(String, Vec<(String, Expr)>),  // Struct { field: value }
    Assign(Box<Expr>, Box<Expr>),      // x = y
    CompoundAssign(Box<Expr>, BinOp, Box<Expr>), // x += y
    Block(Block),                       // { ... } as expression
}

#[derive(Debug, Clone)]
pub enum Literal {
    Int(i64),
    Float(f64),
    Bool(bool),
    String(Rc<str>),
    Char(char),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
    Eq,
    NotEq,
    Lt,
    Gt,
    LtEq,
    GtEq,
    And,
    Or,
    // ...
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnOp {
    Neg,
    Not,
}

#[derive(Debug, Clone)]
pub enum Type {
    Named(String, Vec<Type>), // e.g., List<int>
    Int,
    Float,
    Bool,
    String,
    Void,
    Auto,
    Array(Box<Type>, Option<usize>),  // [T] or [T; N]
    Function(Vec<Type>, Box<Type>), // (T1, T2) -> R
    Tuple(Vec<Type>),               // (T1, T2, ...)
}