use std::collections::HashMap; use std::hash::Hash; use std::cmp::Eq; use std::ops::Deref; pub fn deref_optional_box(x: &Option>) -> Option<&T> { x.as_ref().map(|b: &Box| Deref::deref(b)) } #[derive(Default, Debug)] pub struct ScopeStack<'a, T: 'a, V: 'a> where T: Hash + Eq { parent: Option<&'a ScopeStack<'a, T, V>>, values: HashMap, scope_name: Option } impl<'a, T, V> ScopeStack<'a, T, V> where T: Hash + Eq { pub fn new(name: Option) -> ScopeStack<'a, T, V> where T: Hash + Eq { ScopeStack { parent: None, values: HashMap::new(), scope_name: name } } pub fn insert(&mut self, key: T, value: V) where T: Hash + Eq { self.values.insert(key, value); } pub fn lookup(&self, key: &T) -> Option<&V> where T: Hash + Eq { match (self.values.get(key), self.parent) { (None, None) => None, (None, Some(parent)) => parent.lookup(key), (Some(value), _) => Some(value), } } pub fn new_scope(&'a self, name: Option) -> ScopeStack<'a, T, V> where T: Hash + Eq { ScopeStack { parent: Some(self), values: HashMap::default(), scope_name: name, } } #[allow(dead_code)] pub fn get_name(&self) -> Option<&String> { self.scope_name.as_ref() } } /// this is intended for use in tests, and does no error-handling whatsoever #[allow(dead_code)] pub fn quick_ast(input: &str) -> (crate::ast::AST, crate::source_map::SourceMap) { use std::cell::RefCell; use std::rc::Rc; let source_map = crate::source_map::SourceMap::new(); let source_map_handle = Rc::new(RefCell::new(source_map)); let tokens = crate::tokenizing::tokenize(input); let mut parser = crate::parsing::Parser::new(source_map_handle.clone()); parser.add_new_tokens(tokens); let output = parser.parse(); std::mem::drop(parser); (output.unwrap(), Rc::try_unwrap(source_map_handle).map_err(|_| ()).unwrap().into_inner()) } #[allow(unused_macros)] macro_rules! rc { ($string:tt) => { Rc::new(stringify!($string).to_string()) } }