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}