Skip to content

Instantly share code, notes, and snippets.

@nviennot
Last active August 1, 2020 16:40
Show Gist options
  • Save nviennot/0aca77cbc27256ddd18c187d9c520c9f to your computer and use it in GitHub Desktop.
Save nviennot/0aca77cbc27256ddd18c187d9c520c9f to your computer and use it in GitHub Desktop.
sym.rs
use std::collections::HashMap;
type Value = i32;
struct SymbolTable {
// We wish to own the parent SymbolTable, but we need a level of indirection
// with box, otherwise it would create an unallocatable recursive structure.
parent: Option<Box<SymbolTable>>,
values: HashMap<String, Value>,
}
impl SymbolTable {
pub fn default() -> SymbolTable {
SymbolTable {values: HashMap::default(), parent: None }
}
pub fn child(parent: SymbolTable) -> SymbolTable {
SymbolTable {values: HashMap::default(), parent: Some(Box::new(parent)) }
}
pub fn get_parent(&self) -> Option<&SymbolTable> {
// as_ref() is needed to avoid consuming the option
// the &** deref dance gets a reference of the boxed value
self.parent.as_ref().map(|p| &**p)
}
fn get_on_parent(&self, symbol: &str) -> Option<&Value> {
self.parent.as_ref().map(|p| p.get(symbol)).flatten()
}
pub fn get(&self, symbol: &str) -> Option<&Value> {
self.values.get(symbol).or_else(|| self.get_on_parent(symbol))
}
pub fn put(&mut self, symbol: String, value: Value) {
// XXX This has bad complexity: O(n!)
if self.get_on_parent(&symbol).is_some() {
self.parent.as_mut().unwrap().put(symbol, value);
} else {
self.values.insert(symbol, value);
}
}
}
fn main() {
let mut parent = SymbolTable::default();
parent.put("x".into(), 10);
let mut child = SymbolTable::child(parent);
child.put("x".into(), 20);
child.get_parent().unwrap().get("x");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment