mini-lang 0.1.2

A minimal, experimental language for lazy evaluation.
Documentation
use crate::{MiniError, MiniResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NameSpace<T>(Vec<Option<T>>, Vec<usize>);

impl<T> NameSpace<T> {
    pub fn new() -> Self {
        Self(Vec::new(), vec![0])
    }

    fn get_pos(&self, depth: usize, id: usize) -> MiniResult<usize> {
        let offset = self.1.get(depth).copied().ok_or("Use of undefined depth")?;
        let pos = offset + id;
        let next_offset = self
            .1
            .get(depth + 1)
            .copied()
            .unwrap_or_else(|| self.0.len());
        if pos >= next_offset {
            return Err(MiniError::from("Illegal id"));
        }
        Ok(pos)
    }

    fn get_last_offset(&self) -> usize {
        self.1.last().copied().unwrap_or_default()
    }

    pub fn chunk(&mut self) -> usize {
        self.1.push(self.0.len());
        self.1.len() - 1
    }

    pub fn back(&mut self) {
        let offset = self.1.pop().unwrap_or_default();
        for _ in 0..(self.0.len() - offset) {
            self.0.pop();
        }
    }

    pub fn register(&mut self, item: T) -> usize {
        self.0.push(Some(item));
        self.0.len() - self.get_last_offset() - 1
    }

    pub fn get(&self, depth: usize, id: usize) -> MiniResult<&T> {
        let pos = self.get_pos(depth, id)?;
        Ok(self.0[pos].as_ref().ok_or("The value is borrowed.")?)
    }

    pub fn borrow(&mut self, depth: usize, id: usize) -> MiniResult<T> {
        let pos = self.get_pos(depth, id)?;
        let res = std::mem::replace(&mut self.0[pos], None);
        Ok(res.ok_or("The value is borrowed.")?)
    }

    pub fn ret(&mut self, depth: usize, id: usize, item: T) -> MiniResult<()> {
        let pos = self.get_pos(depth, id)?;
        if self.0[pos].is_some() {
            return Err(MiniError::from("Illegal id"));
        }
        self.0[pos] = Some(item);
        Ok(())
    }
}