schala/schala-lang/src/util.rs
2021-11-20 11:13:21 -08:00

72 lines
2.0 KiB
Rust

use std::{cmp::Eq, collections::HashMap, hash::Hash};
#[derive(Default, Debug)]
pub struct ScopeStack<'a, T: 'a, V: 'a, N = String>
where T: Hash + Eq
{
parent: Option<&'a ScopeStack<'a, T, V, N>>,
values: HashMap<T, V>,
scope_name: Option<N>,
}
impl<'a, T, V, N> ScopeStack<'a, T, V, N>
where T: Hash + Eq
{
pub fn new(scope_name: Option<N>) -> Self
where T: Hash + Eq {
ScopeStack { parent: None, values: HashMap::new(), scope_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, scope_name: Option<N>) -> Self
where T: Hash + Eq {
ScopeStack { parent: Some(self), values: HashMap::default(), scope_name }
}
#[allow(dead_code)]
pub fn lookup_with_scope(&self, key: &T) -> Option<(&V, Option<&N>)>
where T: Hash + Eq {
match (self.values.get(key), self.parent) {
(None, None) => None,
(None, Some(parent)) => parent.lookup_with_scope(key),
(Some(value), _) => Some((value, self.scope_name.as_ref())),
}
}
pub fn get_name(&self) -> Option<&N> {
self.scope_name.as_ref()
}
}
/// Quickly create an AST from a string, with no error checking. For test use only
#[cfg(test)]
pub fn quick_ast(input: &str) -> crate::ast::AST {
let mut parser = crate::parsing::Parser::new();
let output = parser.parse(input);
match output {
Ok(output) => output,
Err(err) => {
println!("Parse error: {}", err.msg);
panic!();
}
}
}
#[allow(unused_macros)]
macro_rules! rc {
($string:tt) => {
Rc::new(stringify!($string).to_string())
};
}