use std::{fmt, rc::Rc}; use crate::{token::{Token, OpType}, Position, value::{Type, func::Func}}; #[derive(Clone)] pub enum Stmt { Expr { expr: Expr }, Let { lhs: Token, rhs: Option }, Block { stmts: Vec }, If { if_clauses: Vec<(Expr, Stmt)>, else_clause: Option> }, For { var: Token, expr: Expr, stmt: Box, iter_pos: Position }, While { expr: Expr, stmt: Box }, Break { pos: Position }, Continue { pos: Position }, Return { pos: Position, expr: Expr }, Fn { name: Token, args: Vec>, body: Box }, StructDef { name: Token, ty: Type }, } impl fmt::Debug for Stmt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::Expr { expr } => write!(f, "{:?}", expr), Self::Let { lhs, rhs } => write!(f, "(let {:?} = {:?})", lhs, rhs), Self::Block { stmts } => write!(f, "(block {:?})", stmts), Self::If { if_clauses, else_clause } => write!(f, "(if {:?} else {:?})", if_clauses, else_clause), Self::For { var, expr, stmt, .. } => write!(f, "(for {:?} : {:?} do {:?})", var, expr, stmt), Self::While { expr, stmt } => write!(f, "(while {:?} do {:?})", expr, stmt), Self::Break { .. } => write!(f, "(break)"), Self::Continue { .. } => write!(f, "(continue)"), Self::Return { expr, .. } => write!(f, "(return {:?})", expr), Self::Fn { name, args, body } => write!(f, "(fn {:?} {:?} {:?})", name, args, body), Self::StructDef { name, ty } => write!(f, "(struct {:?} #{:?})", name, ty.id), } } } #[derive(Clone)] pub enum Expr { Binary { lhs: Box, rhs: Box, op: Token }, Ternary { arg1: Box, arg2: Box, arg3: Box, op: Token }, Unary { arg: Box, op: Token }, Range { start: Box, end: Option>, step: Option>, incl: bool }, FieldAccess { target: Box, name: Rc, pos: Position }, BoxedInfix { func: Func }, Ident { value: Token }, Literal { value: Token }, List { items: Vec }, Map { items: Vec<(Expr,Expr)> }, Fn { args: Vec>, body: Box }, FuncCall { func: Box, args: Vec, pos: Position }, Index { lhs: Box, index: Box, pos: Position }, StructInit { ty: Box, args: Vec, pos: Position }, } impl fmt::Debug for Expr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Self::Binary { lhs: left, rhs: right, op} => write!(f, "({:?} {:?} {:?})", op, left, right), Self::Ternary { arg1, arg2, arg3, op} => write!(f, "({:?} {:?} {:?} {:?})", op, arg1, arg2, arg3), Self::Unary { arg, op } => write!(f, "({:?} {:?})", op, arg), Self::Range { start, end, step, incl } => write!(f, "(range {:?}..{:?} step {:?} incl {:?})", start, end, step, incl), Self::FieldAccess { target, name, .. } => write!(f, "(fieldaccess {:?} {:?})", target, name), Self::BoxedInfix { func } => write!(f, "(boxed-infix {:?})", func), Self::Ident { value } => write!(f, "(ident {:?})", value), Self::Literal { value } => write!(f, "(lit {:?})", value), Self::List { items } => write!(f, "(list {:?})", items), Self::Map { items } => write!(f, "(map {:?})", items), Self::FuncCall { func, args, .. } => write!(f, "(call {:?} {:?})", func, args), Self::Index { lhs, index, .. } => write!(f, "(index {:?} {:?})", lhs, index), Self::Fn { args, body } => write!(f, "(fn {:?} {:?})", args, body), Self::StructInit { ty, args, .. } => write!(f, "(mk-struct {:?} {:?})", ty, args), } } } impl Expr { pub fn is_lvalue(&self) -> bool { matches!(self, Expr::Ident{..} | Expr::Index{..} | Expr::FieldAccess{..}) } pub fn is_assignment(&self) -> bool { matches!(self, Expr::Binary{op, ..} if op.ty.get_op_type() == Some(OpType::Assignment)) } }