Skip to main content

sim_lib_binding/
cell.rs

1//! Shared mutable cells for closed-over lexical bindings.
2
3use std::sync::{Arc, Mutex};
4
5use sim_kernel::{Error, Result, Symbol, Value};
6
7/// A reference-shared mutable binding slot captured from a lexical scope.
8///
9/// Cloned cells point at the same slot, so writes through one handle are visible
10/// through every other handle for the same lexical binding. Closure languages use
11/// this shape for boxed upvalues and closed-over mutable locals.
12#[derive(Clone, Debug)]
13pub struct BindingCell {
14    name: Symbol,
15    slot: Arc<Mutex<Option<Value>>>,
16}
17
18impl BindingCell {
19    pub(crate) fn from_slot(name: Symbol, slot: Arc<Mutex<Option<Value>>>) -> Self {
20        Self { name, slot }
21    }
22
23    /// Returns the binding name associated with this cell.
24    pub fn name(&self) -> &Symbol {
25        &self.name
26    }
27
28    /// Reads the cell's current value.
29    ///
30    /// Errors if the captured slot is still uninitialized.
31    pub fn get(&self) -> Result<Value> {
32        self.slot
33            .lock()
34            .map_err(|_| Error::Eval(format!("binding cell {} lock is poisoned", self.name)))?
35            .clone()
36            .ok_or_else(|| Error::Eval(format!("binding cell {} is not initialized", self.name)))
37    }
38
39    /// Replaces the cell's current value.
40    pub fn set(&self, value: Value) -> Result<()> {
41        *self
42            .slot
43            .lock()
44            .map_err(|_| Error::Eval(format!("binding cell {} lock is poisoned", self.name)))? =
45            Some(value);
46        Ok(())
47    }
48}