1use std::sync::{Arc, Mutex};
4
5use sim_kernel::{Error, Result, Symbol, Value};
6
7#[derive(Clone, Debug)]
13pub struct BindingCell {
14 name: Symbol,
15 slot: Arc<Mutex<BindingCellState>>,
16}
17
18#[derive(Clone, Debug)]
20pub enum BindingCellState {
21 Uninitialized,
23 Initialized(Value),
25 Deleted,
27 Immutable(Value),
29 LiveAlias(BindingCell),
31}
32
33impl BindingCell {
34 pub(crate) fn from_slot(name: Symbol, slot: Arc<Mutex<BindingCellState>>) -> Self {
35 Self { name, slot }
36 }
37
38 pub fn uninitialized(name: Symbol) -> Self {
40 Self::from_slot(name, Arc::new(Mutex::new(BindingCellState::Uninitialized)))
41 }
42
43 pub fn initialized(name: Symbol, value: Value) -> Self {
45 Self::from_slot(
46 name,
47 Arc::new(Mutex::new(BindingCellState::Initialized(value))),
48 )
49 }
50
51 pub fn immutable(name: Symbol, value: Value) -> Self {
53 Self::from_slot(
54 name,
55 Arc::new(Mutex::new(BindingCellState::Immutable(value))),
56 )
57 }
58
59 pub fn live_alias(name: Symbol, target: BindingCell) -> Self {
61 Self::from_slot(
62 name,
63 Arc::new(Mutex::new(BindingCellState::LiveAlias(target))),
64 )
65 }
66
67 pub fn name(&self) -> &Symbol {
69 &self.name
70 }
71
72 pub fn get(&self) -> Result<Value> {
76 let state = self
77 .slot
78 .lock()
79 .map_err(|_| Error::Eval(format!("binding cell {} lock is poisoned", self.name)))?
80 .clone();
81 match state {
82 BindingCellState::Initialized(value) | BindingCellState::Immutable(value) => Ok(value),
83 BindingCellState::LiveAlias(target) => target.get(),
84 BindingCellState::Uninitialized => Err(Error::Eval(format!(
85 "binding cell {} is not initialized",
86 self.name
87 ))),
88 BindingCellState::Deleted => Err(Error::Eval(format!(
89 "binding cell {} is deleted",
90 self.name
91 ))),
92 }
93 }
94
95 pub fn set(&self, value: Value) -> Result<()> {
97 let mut state = self
98 .slot
99 .lock()
100 .map_err(|_| Error::Eval(format!("binding cell {} lock is poisoned", self.name)))?;
101 match &mut *state {
102 BindingCellState::LiveAlias(target) => target.set(value),
103 BindingCellState::Immutable(_) => Err(Error::Eval(format!(
104 "binding cell {} is immutable",
105 self.name
106 ))),
107 BindingCellState::Deleted => Err(Error::Eval(format!(
108 "binding cell {} is deleted",
109 self.name
110 ))),
111 BindingCellState::Uninitialized | BindingCellState::Initialized(_) => {
112 *state = BindingCellState::Initialized(value);
113 Ok(())
114 }
115 }
116 }
117
118 pub fn delete(&self) -> Result<()> {
120 let mut state = self
121 .slot
122 .lock()
123 .map_err(|_| Error::Eval(format!("binding cell {} lock is poisoned", self.name)))?;
124 if matches!(*state, BindingCellState::Immutable(_)) {
125 return Err(Error::Eval(format!(
126 "binding cell {} is immutable",
127 self.name
128 )));
129 }
130 *state = BindingCellState::Deleted;
131 Ok(())
132 }
133
134 pub fn state(&self) -> Result<BindingCellState> {
136 self.slot
137 .lock()
138 .map_err(|_| Error::Eval(format!("binding cell {} lock is poisoned", self.name)))
139 .map(|state| state.clone())
140 }
141}