use std::fmt::Display; use super::Expr; pub enum Stmt { ExprStmt { expr: Box }, Print { expr: Box }, VarDecl { name: String, initializer: Box }, Block { statements: Vec }, } impl Stmt { pub fn expr_stmt(expr: Expr) -> Self { let expr = Box::new(expr); Stmt::ExprStmt { expr } } pub fn print_stmt(expr: Expr) -> Self { let expr = Box::new(expr); Stmt::Print { expr } } pub fn var_decl(name: String, initializer: Expr) -> Self { let initializer = Box::new(initializer); Stmt::VarDecl { name, initializer } } } impl Display for Stmt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Stmt::ExprStmt { expr } => write!(f, "{expr}"), Stmt::Print { expr } => write!(f, "print {expr}"), Stmt::VarDecl { name, initializer } => write!(f, "var {name} = {initializer}"), Stmt::Block { statements } => { writeln!(f, "{{")?; for statement in statements { // for each statement: statement to string, split by lines, preprend each line with tab, print // return first error or, on success, "collect" the resulting () into a Vec (ZST, so no allocation) format!("{statement}") .split("\n") .map(|line| writeln!(f, "\t{line}")) .collect::, std::fmt::Error>>()?; } write!(f, "}}") } } } }