intuicio_core/
context.rs

1use intuicio_data::data_stack::{DataStack, DataStackMode, DataStackRegisterAccess};
2use std::{any::Any, collections::HashMap};
3
4pub struct Context {
5    stack: DataStack,
6    registers: DataStack,
7    registers_barriers: Vec<usize>,
8    custom: HashMap<String, Box<dyn Any + Send + Sync>>,
9}
10
11impl Context {
12    pub fn new(stack_capacity: usize, registers_capacity: usize) -> Self {
13        Self {
14            stack: DataStack::new(stack_capacity, DataStackMode::Values),
15            registers: DataStack::new(registers_capacity, DataStackMode::Registers),
16            registers_barriers: vec![],
17            custom: Default::default(),
18        }
19    }
20
21    pub fn fork(&self) -> Self {
22        Self::new(self.stack.size(), self.registers.size())
23    }
24
25    pub fn stack_capacity(&self) -> usize {
26        self.stack.size()
27    }
28
29    pub fn registers_capacity(&self) -> usize {
30        self.registers.size()
31    }
32
33    pub fn stack(&mut self) -> &mut DataStack {
34        &mut self.stack
35    }
36
37    pub fn registers(&mut self) -> &mut DataStack {
38        &mut self.registers
39    }
40
41    pub fn stack_and_registers(&mut self) -> (&mut DataStack, &mut DataStack) {
42        (&mut self.stack, &mut self.registers)
43    }
44
45    pub fn store_registers(&mut self) {
46        self.registers_barriers
47            .push(self.registers.registers_count());
48    }
49
50    pub fn restore_registers(&mut self) {
51        if let Some(count) = self.registers_barriers.pop() {
52            while self.registers.registers_count() > count {
53                self.registers.drop_register();
54            }
55        }
56    }
57
58    pub fn registers_barriers(&self) -> &[usize] {
59        &self.registers_barriers
60    }
61
62    pub fn absolute_register_index(&self, index: usize) -> usize {
63        self.registers_barriers
64            .last()
65            .map(|count| index + count)
66            .unwrap_or(index)
67    }
68
69    pub fn access_register(&mut self, index: usize) -> Option<DataStackRegisterAccess> {
70        let index = self.absolute_register_index(index);
71        self.registers.access_register(index)
72    }
73
74    pub fn custom<T: Send + Sync + 'static>(&self, name: &str) -> Option<&T> {
75        self.custom.get(name)?.downcast_ref::<T>()
76    }
77
78    pub fn custom_mut<T: Send + Sync + 'static>(&mut self, name: &str) -> Option<&mut T> {
79        self.custom.get_mut(name)?.downcast_mut::<T>()
80    }
81
82    pub fn set_custom<T: Send + Sync + 'static>(&mut self, name: impl ToString, data: T) {
83        self.custom.insert(name.to_string(), Box::new(data));
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn test_async() {
93        fn is_async<T: Send + Sync>() {}
94
95        is_async::<Context>();
96    }
97}