mica_language/value/
closures.rs

1use std::cell::UnsafeCell;
2use std::marker::PhantomPinned;
3use std::pin::Pin;
4use std::rc::Rc;
5use std::{fmt, mem, ptr};
6
7use crate::bytecode::Opr24;
8
9use super::RawValue;
10
11/// An upvalue captured by a closure.
12pub struct Upvalue {
13   /// A writable pointer to the variable captured by this upvalue.
14   pub(crate) ptr: UnsafeCell<ptr::NonNull<RawValue>>,
15   /// Storage for a closed upvalue.
16   closed: UnsafeCell<RawValue>,
17
18   _pinned: PhantomPinned,
19}
20
21impl fmt::Debug for Upvalue {
22   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23      f.debug_struct("Upvalue")
24         .field("ptr", unsafe { self.ptr.get().as_ref() }.unwrap())
25         .field("closed", unsafe { self.closed.get().as_ref() }.unwrap())
26         .finish_non_exhaustive()
27   }
28}
29
30impl Upvalue {
31   /// Creates a new upvalue pointing to a live variable.
32   pub(crate) fn new(var: ptr::NonNull<RawValue>) -> Pin<Rc<Upvalue>> {
33      Rc::pin(Upvalue {
34         ptr: UnsafeCell::new(var),
35         closed: UnsafeCell::new(RawValue::from(())),
36         _pinned: PhantomPinned,
37      })
38   }
39
40   /// Closes an upvalue by `mem::take`ing the value behind the `ptr` into the `closed` field, and
41   /// updating the `ptr` field to point to the `closed` field's contents.
42   ///
43   /// # Safety
44   /// The caller must ensure there are no mutable references to the variable at the time of
45   /// calling this.
46   pub(crate) unsafe fn close(&self) {
47      let ptr = &mut *self.ptr.get();
48      let closed = &mut *self.closed.get();
49      let value = mem::take(ptr.as_mut());
50      *closed = value;
51      *ptr = ptr::NonNull::new(closed).unwrap();
52   }
53
54   /// Returns the value pointed to by this upvalue.
55   ///
56   /// # Safety
57   /// The caller must ensure there are no mutable references to the source variable at the time
58   /// of calling this.
59   pub(crate) unsafe fn get(&self) -> RawValue {
60      *(*self.ptr.get()).as_ptr()
61   }
62
63   /// Writes to the variable pointed to by this upvalue.
64   ///
65   /// # Safety
66   /// The caller must ensure there are no mutable references to the source variable at the time
67   /// of calling this.
68   pub(crate) unsafe fn set(&self, value: RawValue) {
69      *(*self.ptr.get()).as_ptr() = value;
70   }
71}
72
73/// The runtime representation of a function.
74#[derive(Debug)]
75#[repr(align(8))]
76pub struct Closure {
77   pub function_id: Opr24,
78   pub captures: Vec<Pin<Rc<Upvalue>>>,
79}