use std::fmt;
use std::collections::HashMap;
pub struct Env {
vars: HashMap<String, MushRoom>,
parent:Vec<Env>
}
impl Env {
pub fn new() -> Env {
Env{vars:HashMap::new(), parent:Vec::with_capacity(1)}
}
pub fn create_child(self) -> Env {
let mut newchild = Env::new();
newchild.parent.push(self);
newchild
}
pub fn has_parent(&self) -> bool {
!self.parent.is_empty()
}
pub fn get(&self, key:String) -> MushRoom {
match self.vars.get(&key) {
Some(i) => i.clone(),
None => return if self.has_parent() {self.parent[0].get(key)} else {MushRoom::Bool(false)}
}
}
pub fn set(&mut self, key:String, val:MushRoom) {
self.vars.insert(key, val);
}
pub fn has(&self, key:String) -> bool {
self.vars.contains_key(&key)
}
pub fn del(&mut self, key:String) {
self.vars.remove(&key);
}
}
#[derive(Clone)]
pub enum MushRoom {
Int(i32),
Bool(bool),
List(Vec<MushRoom>),
Func(fn(Vec<MushRoom>) -> MushRoom)
}
impl MushRoom {
pub fn repr(value:&MushRoom) -> String {
match *value {
MushRoom::Int(i) => format!("{}", i),
MushRoom::Bool(b) => format!("{}", b),
MushRoom::Func(f) => format!("{:?}", f),
MushRoom::List(ref l) => {
let mut fmt_str = "[ ".to_string();
for elem in l {
fmt_str += MushRoom::repr(elem).as_str();
fmt_str += " ";
}
fmt_str += "]";
fmt_str
}
}
}
}
impl fmt::Debug for MushRoom {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", MushRoom::repr(self))
}
}
impl fmt::Display for MushRoom {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl PartialEq for MushRoom {
fn eq(&self, other: &MushRoom) -> bool {
MushRoom::repr(self) == MushRoom::repr(other)
}
fn ne(&self, other: &MushRoom) -> bool {
MushRoom::repr(self) != MushRoom::repr(other)
}
}
fn main() {
let mut g = Env::new();
g.set("foo".to_string(), MushRoom::List(vec![MushRoom::Int(8)]));
println!("{}", g.get("foo".to_string())); //[ 8 ]
let mut h = g.create_child();
h.set("d".to_string(), MushRoom::Int(8));
println!("{}", h.get("foo".to_string())); //[ 8 ]
}