1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use roussillon_type_system::value::concept::ValueCell;
use roussillon_type_system::value::reference::Reference;

use crate::region::{Allocator, Dereference, Region};

#[derive(Clone, Debug)]
pub struct StackReference {
    level: usize,
    reference: Reference,
}

impl StackReference {
    pub fn reference(&self) -> &Reference {
        &self.reference
    }
}

#[derive(Default, Debug)]
pub struct Stack {
    raw: Vec<Region>,
}

impl Stack {
    pub fn new() -> Self { Stack { raw: Vec::new() } }

    pub fn push(&mut self, region: Region) {
        self.raw.push(region)
    }

    pub fn pop(&mut self) -> Option<Region> {
        self.raw.pop()
    }
}

impl Allocator<StackReference> for Stack {
    fn allocate(&mut self, cell: ValueCell) -> StackReference {
        let mut current = self.pop().unwrap();
        let level = self.raw.len();
        let reference = current.allocate(cell);
        StackReference { level, reference }
    }
}

impl Dereference<StackReference> for Stack {
    fn dereference(&self, reference: StackReference) -> Option<ValueCell> {
        if reference.level >= self.raw.len() {
            None
        } else {
            self.raw[reference.level].dereference(reference.reference)
        }
    }

    fn validate(&self, reference: &StackReference) -> bool {
        reference.level < self.raw.len()
    }
}