diff --git a/tree_shared/src/expr.rs b/tree_shared/src/expr.rs new file mode 100644 index 000000000..9c3f51362 --- /dev/null +++ b/tree_shared/src/expr.rs @@ -0,0 +1,118 @@ +#[derive(Clone, Debug, PartialEq)] +pub enum Order { + Parallel, + Sequential, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Id { + Unique(i64), + Shared, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Expr { + Num(i64), + Boolean(bool), + Add(Box, Box), + Sub(Box, Box), + Mul(Box, Box), + LessThan(Box, Box), + And(Box, Box), + Or(Box, Box), + Not(Box), + Get(Box, usize), + /// Concat is a convenient built-in way + /// to put two tuples together. + /// It's not strictly necessary, but + /// doing it by constructing a new big tuple is tedius and slow. + Concat(Box, Box), + Print(Box), + Read(Box), + Write(Box, Box), + All(Id, Order, Vec), + /// A pred and a list of branches + Switch(Box, Vec), + /// Should only be a child of `Switch` + /// Represents a single branch of a switch, giving + /// it a unique id + Branch(Id, Box), + Loop(Id, Box, Box), + Let(Id, Box, Box), + Arg(Id), + Function(Id, Box), + /// A list of functions, with the first + /// being the main function. + Program(Vec), + Call(Id, Box), +} + +impl Expr { + /// Runs `func` on every child of this expression. + pub fn for_each_child(&mut self, mut func: impl FnMut(&mut Expr)) { + match self { + Expr::Num(_) | Expr::Boolean(_) | Expr::Arg(_) => {} + Expr::Add(a, b) + | Expr::Sub(a, b) + | Expr::Mul(a, b) + | Expr::LessThan(a, b) + | Expr::And(a, b) + | Expr::Or(a, b) + | Expr::Concat(a, b) + | Expr::Write(a, b) => { + func(a); + func(b); + } + Expr::Not(a) | Expr::Print(a) | Expr::Read(a) => { + func(a); + } + Expr::Get(a, _) | Expr::Function(_, a) | Expr::Call(_, a) => { + func(a); + } + Expr::All(_, _, children) => { + for child in children { + func(child); + } + } + Expr::Switch(input, children) => { + func(input); + for child in children { + func(child); + } + } + Expr::Branch(_id, child) => { + func(child); + } + Expr::Loop(_, pred, output) | Expr::Let(_, pred, output) => { + func(pred); + func(output); + } + Expr::Program(functions) => { + for function in functions { + func(function); + } + } + } + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Value { + Num(i64), + Boolean(bool), + Tuple(Vec), +} + +#[derive(Clone, PartialEq)] +pub enum Type { + Num, + Boolean, + Tuple(Vec), +} + +pub enum TypeError { + ExpectedType(Expr, Type, Type), + ExpectedTupleType(Expr, Type), + ExpectedLoopOutputType(Expr, Type), + NoArg(Expr), +}