dark_vm/utils/store.rs
1//! The Store struct is a basic wrapper around a HashMap.
2//! It is useful for maintaining variables and available functions.
3
4use crate::{
5 errors::{error::Error, error_kind::ErrorKind},
6 values::value::Value,
7};
8use std::{collections::HashMap, rc::Rc, cell::RefCell};
9
10#[derive(Debug, PartialEq)]
11pub struct Store {
12 parent_store: Option<Rc<RefCell<Store>>>,
13 store: HashMap<String, Rc<Value>>,
14}
15
16impl Store {
17 /// Creates a new Store.
18 ///
19 /// # Arguments
20 /// `parent_store` - The parent of this store. This maintains all of the variables defined in a higher scope.
21 pub fn new(parent_store: Option<Rc<RefCell<Store>>>) -> Store {
22 Store {
23 parent_store,
24 store: HashMap::new(),
25 }
26 }
27
28 /// This function defines a new variable. The variable will be bound to the scope containing this store.
29 /// This function will override any existing value of a previously defined value.
30 ///
31 /// # Arguments
32 /// `name` - The name of the variable.
33 /// `value` - The value of the variable.
34 pub fn define(&mut self, name: &str, value: Rc<Value>) {
35 self.store.insert(name.to_owned(), value);
36 }
37
38 /// This function gets the value of a variable. If the variable does not exist, then an error is reported.
39 ///
40 /// # Arguments
41 /// `name` - The name of the variable.
42 /// `pos` - The position where this operation was called.
43 pub fn get(&self, name: &str, pos: usize) -> Result<Rc<Value>, Error> {
44 let var = self.store.get(name);
45 if let Some(variable) = var {
46 Ok(variable.clone())
47 } else if let Some(parent) = &self.parent_store {
48 parent.borrow().get(name, pos)
49 } else {
50 Err(Error::new(ErrorKind::UndefinedVariable, pos))
51 }
52 }
53}