use std::ops; use std::collections::HashMap; use crate::parser; use parser::Atom; pub struct Env<'a> { pub parent: Option<&'a Env<'a>>, pub values: HashMap } impl<'a> Env<'a> { pub fn global() -> Self { Env { parent: None, values: HashMap::new(), } } pub fn child(parent: &'a Env<'a>) -> Self { Env { parent: Some(parent), values: HashMap::new(), } } } pub fn eval(ast: &parser::Expr, env: &mut Env) -> parser::Atom { match ast { parser::Expr::Atom(a) => a.clone(), parser::Expr::UnaryMinus(a) => -eval(&a, env), parser::Expr::Plus(a, b) => eval(&a, env) + eval(&b, env), parser::Expr::Minus(a, b) => eval(&a, env) - eval(&b, env), parser::Expr::Mult(a, b) => eval(&a, env) * eval(&b, env), parser::Expr::Div(a, b) => eval(&a, env) / eval(&b, env), _ => panic!("Couldn't evalute expression {{ {:?} }}", ast), } } impl ops::Neg for Atom { type Output = Self; fn neg(self) -> Self { match self { Atom::Num(a) => Atom::Num(-a), _ => panic!("Can't negate non-numeral type!"), } } } impl ops::Add for Atom { type Output = Self; fn add(self, other: Self) -> Self { match (self, other) { (Atom::Num(a), Atom::Num(b)) => Atom::Num(a + b), _ => panic!("Can't add non-numeral types!"), } } } impl ops::Sub for Atom { type Output = Self; fn sub(self, other: Self) -> Self { match (self, other) { (Atom::Num(a), Atom::Num(b)) => Atom::Num(a - b), _ => panic!("Can't subtract non-numeral types!"), } } } impl ops::Mul for Atom { type Output = Self; fn mul(self, other: Self) -> Self { match (self, other) { (Atom::Num(a), Atom::Num(b)) => Atom::Num(a * b), _ => panic!("Can't multiply non-numeral types!"), } } } impl ops::Div for Atom { type Output = Self; fn div(self, other: Self) -> Self { match (self, other) { (Atom::Num(a), Atom::Num(b)) => Atom::Num(a / b), _ => panic!("Can't divide non-numeral types!"), } } }