use std::collections::HashMap;
use crate::{
Error,
Expression,
};
pub struct Environment {
variables: HashMap<String, Expression>,
}
impl Environment {
pub fn new() -> Self {
Self {
variables: HashMap::new(),
}
}
fn register(&mut self, name: &String, value: &Expression) {
self.variables.insert(name.to_owned(), value.to_owned());
}
fn lookup(&self, name: &String) -> Expression {
match self.variables.get(name) {
Some (expr) => expr.to_owned(),
None => {
Error::UndeclaredVariable (name).warn();
Expression::Null
},
}
}
fn simplify(&mut self, expr: &Expression) -> Expression {
use Expression::*;
match expr {
Assignment {
left,
right,
} => {
let sr = self.simplify(right);
self.register(&left, &sr);
sr.to_owned()
},
Reassignment {
left,
right,
} => {
let _ = self.lookup(&left);
let sr = self.simplify(right);
self.register(&left, &sr);
sr.to_owned()
},
Float {
value: _,
kg: _,
m: _,
s: _,
a: _,
k: _,
mol: _,
} => expr.to_owned(),
Identifier (s) => self.lookup(&s),
BinOp {
left,
oper,
right,
} => {
let sl = self.simplify(left);
let sr = self.simplify(right);
oper.simplify(&sl, &sr)
},
Null => Null,
}
}
pub fn evaluate(&mut self, expressions: &Vec<Expression>) -> String {
let mut output = String::new();
for expr in expressions {
let out = self.simplify(expr);
output.push_str(&format!("{}\n", out));
}
output
}
}