#[derive(Debug, Clone)] pub enum Op { Add, Sub, Mul, Div, Mod, Pow, Eq, Neq, Lt, Gt, Lte, Gte, And, Or, Not, Neg, Strip, } #[derive(Debug, Clone)] pub enum Stmt { Let(String, Option, Expr), Assign(String, Expr), PathAssign(Expr, Expr), While(Expr, Vec), IfElse(Expr, Vec, Option>), ForLoop(String, Expr, Vec), FnDef { name: String, params: Vec<(String, Option)>, return_type: Option, body: Vec, }, Return(Expr), Use(Vec, bool), CellAssign { block: Option, table: String, cell: (u32, u32), value: Expr, }, SolveDef { name: String, params: Vec, target_var: String, source_fn: String, source_args: Vec, result_var: String, }, ExprStmt(Expr), TraitDef { name: String, methods: Vec, }, ImplBlock { type_name: String, trait_name: Option, methods: Vec, }, } #[derive(Debug, Clone, PartialEq)] pub enum CellRefTarget { Whole, Cell(u32, u32), Range(u32, u32, u32, u32), } #[derive(Debug, Clone)] pub enum Expr { Num(f64), Spice(f64, String), Str(String), Bool(bool), Ident(String), BinOp(Op, Box, Box), UnaryOp(Op, Box), Call(String, Vec), Array(Vec), Index(Box, Box), Range(Box, Box), IsCheck(Box, String), CellRef { block: Option, table: Option, target: CellRefTarget, }, SolveMacro { var: String, source_fn: String, }, Struct(Vec<(String, Expr)>), Field(Box, String), MethodCall(Box, String, Vec), StaticCall(String, String, Vec), } /// checks whether an expression names a writable lvalue. pub(crate) fn is_lvalue(expr: &Expr) -> bool { match expr { Expr::Ident(_) => true, Expr::Field(inner, _) => is_lvalue(inner), Expr::Index(inner, _) => is_lvalue(inner), _ => false, } }