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}