evalit 0.2.0-beta.0

a toy interpreter
Documentation
use std::collections::HashMap;

#[derive(Debug)]
pub struct SymbolTable<T> {
    scopes: Vec<Scope<T>>,
}

impl<T> SymbolTable<T> {
    pub fn new() -> Self {
        SymbolTable::<T> {
            scopes: vec![Scope::<T>::new()],
        }
    }

    pub fn lookup(&self, name: impl AsRef<str>) -> Option<&T> {
        for scope in self.scopes.iter().rev() {
            if let Some(ty) = scope.variables.get(name.as_ref()) {
                return Some(ty);
            }
        }
        None
    }

    pub fn insert(&mut self, name: impl Into<String>, value: T) {
        self.scopes
            .last_mut()
            .unwrap()
            .variables
            .insert(name.into(), value);
    }

    pub fn enter_scope(&mut self) {
        self.scopes.push(Scope::<T>::new());
    }

    pub fn leave_scope(&mut self) {
        self.scopes.pop();
    }
}

impl<T: Clone> Clone for SymbolTable<T> {
    fn clone(&self) -> Self {
        SymbolTable {
            scopes: self.scopes.clone(),
        }
    }
}

#[derive(Debug)]
struct Scope<T> {
    variables: HashMap<String, T>,
}

impl<T> Scope<T> {
    fn new() -> Self {
        Scope {
            variables: HashMap::new(),
        }
    }
}

impl<T: Clone> Clone for Scope<T> {
    fn clone(&self) -> Self {
        Scope {
            variables: self.variables.clone(),
        }
    }
}