scout-interpreter 0.5.2

A web crawling programming language
Documentation
use crate::Object;
use futures::future::BoxFuture;
use futures::lock::Mutex;
use futures::FutureExt;
use scout_parser::ast::Identifier;
use std::borrow::Borrow;
use std::collections::HashMap;
use std::sync::{Arc, Weak};

pub type EnvPointer = Arc<Mutex<Env>>;

#[derive(Debug, Default)]
pub struct Env {
    store: HashMap<String, Arc<Object>>,
    outer: Mutex<Weak<Mutex<Env>>>,
}

impl Env {
    pub async fn add_outer(&mut self, env: EnvPointer) {
        *self.outer.get_mut() = Arc::downgrade(&env);
    }

    pub fn get<'a>(&'a self, id: &'a Identifier) -> BoxFuture<'a, Option<Arc<Object>>> {
        async move {
            match self.outer.borrow().lock().await.upgrade() {
                None => self.store.get(&id.name).cloned(),
                Some(env) => {
                    if let Some(obj) = self.store.get(&id.name) {
                        Some(obj.clone())
                    } else {
                        env.lock().await.get(id).await
                    }
                }
            }
        }
        .boxed()
    }

    pub fn set<'a>(&'a mut self, id: &'a Identifier, obj: Arc<Object>) -> BoxFuture<'a, ()> {
        async move {
            match self.outer.lock().await.upgrade() {
                None => {
                    self.store.insert(id.name.clone(), obj);
                }
                Some(env) => {
                    if env.lock().await.get(id).await.is_some() {
                        env.lock().await.set(id, obj).await;
                    } else {
                        self.store.insert(id.name.clone(), obj);
                    }
                }
            }
        }
        .boxed()
    }
}