Skip to main content

scheme_rs/
value.rs

1//! Scheme values.
2//!
3//! Scheme values are dynamic and can contain essentially any value, similar to
4//! an [`Arc<dyn Any>`](std::any::Any). Any type that has a valid scheme
5//! representation (see [scheme types](#scheme-types) for more information) can
6//! be converted easily to a Scheme `Value`. Converting a Rust primitive or
7//! standard library type can be done simply with the `From` trait:
8//!
9//! ```
10//! # use scheme_rs::value::Value;
11//! let value = Value::from(3.1415926f64);
12//! ```
13//!
14//! Converting a Value back to a concrete rust type can be done via the
15//! [`TryFrom`] trait or by obtaining an enum through the
16//! [`unpack`](Value::unpack) or [`unpacked_ref`](Value::unpacked_ref)
17//! functions:
18//!
19//! ```
20//! # use scheme_rs::value::{Value, UnpackedValue};
21//! # let value = Value::from(3.1415926f64);
22//! let float: f64 = value.clone().try_into().unwrap();
23//! let float: f64 = match value.unpack() {
24//!     UnpackedValue::Number(num) => num.try_into().unwrap(),
25//!     _ => unreachable!(),
26//! };
27//! ```
28//!
29//! It is generally preferrable to use `try_into` as opposed to `unpack` since
30//! `UnpackedValue` is an enumeration that is subject to change.
31//!
32//! Alternatively, the [`cast_to_scheme_type`](Value::cast_to_scheme_type)
33//! method can be used to obtain an Option from a reference for more ergonomic
34//! casting. There is also the [`try_to_scheme_type`](Value::try_to_scheme_type)
35//! function that is similarly more ergonomic:
36//!
37//! ```
38//! # use scheme_rs::value::{Value, UnpackedValue};
39//! let value = Value::from(3);
40//! let float = value.cast_to_scheme_type::<f64>().unwrap();
41//! let int = value.cast_to_scheme_type::<i64>().unwrap();
42//! ```
43//!
44//! ## Converting to and from arbitrary Rust types
45//!
46//! Besides primitives and standard library types, scheme-rs supports converting
47//! arbitrary Rust types (such as structs and enums) to `Values` by representing
48//! them as [`Records`](Record). To do this, the type must implement the
49//! [`SchemeCompatible`] trait (see [`records`](scheme_rs::records) for more
50//! information).
51//!
52//! `Value` provides three convenience methods to facilitate these conversions:
53//! - [`from_rust_type`](Value::from_rust_type): convert a `SchemeCompatible`
54//!   type to a record type, and then to a `Value`.
55//! - [`try_to_rust_type`](Value::try_to_rust_type): attempt to convert the
56//!   value to a `Gc<T>` where `T: SchemeCompatible` providing a detailed error
57//!   on failure.
58//! - [`cast_to_rust_type`](Value::cast_to_rust_type): attempt to convert the
59//!   value to a `Gc<T>` where `T: SchemeCompatible`, returning `None` on
60//!   failure.
61//!
62//! ## Scheme types
63//!
64//! Scheme values can inhabit at most one of any of the following types:
65//! - **Undefined**: Variables with this value throw an error upon being read.
66//! - **Null**: Can only be one possible value which is itself. Conceptually the
67//!   same as the [`()`](https://doc.rust-lang.org/std/primitive.unit.html) type.
68//! - **Pair**: A [collection of two Values](Pair). Conceptually similar to a
69//!   Rust [two-tuple](https://doc.rust-lang.org/std/primitive.tuple.html).
70//! - **Boolean**: Can either be `true` or `false`.
71//! - **Character**: A unicode code point. Same thing as a [`char`](std::char).
72//! - **Number**: A numerical value on the numerical tower. Represented by a
73//!   [`Arc<Number>`](crate::num::Number).
74//! - **String**: An array of [`chars`](std::char).
75//! - **Symbol**: A [`Symbol`].
76//! - **Vector**: A [`Vector`].
77//! - **Byte-vector**: A [`ByteVector`].
78//! - **Syntax**: A [`Syntax`].
79//! - **Procedure**: A [`Procedure`].
80//! - **Record**: A [`Record`], which can possibly be a [`SchemeCompatible`].
81//! - **Record Type Descriptor**: A [descriptor of a record's type](RecordTypeDescriptor).
82//! - **Hashtable**: A [`HashTable`].
83//! - **Port**: A value that can handle [input/output](scheme_rs::ports::Port)
84//!   from the outside world.
85//! - **Cell**: A mutable reference to another Value. This type is completely
86//!   transparent and impossible to observe.
87
88use indexmap::{IndexMap, IndexSet};
89use malachite::Integer;
90use parking_lot::RwLock;
91
92use crate::{
93    exceptions::Exception,
94    gc::{Gc, GcInner, Trace},
95    hashtables::{HashTable, HashTableInner},
96    lists::{self, Pair, PairInner},
97    num::{ComplexNumber, Number, NumberInner, SimpleNumber},
98    ports::{Port, PortInner},
99    proc::{Procedure, ProcedureInner},
100    records::{Record, RecordInner, RecordTypeDescriptor, SchemeCompatible},
101    registry::bridge,
102    strings::{WideString, WideStringInner},
103    symbols::Symbol,
104    syntax::{Identifier, Syntax},
105    vectors::{self, ByteVector, Vector, VectorInner},
106};
107use std::{
108    collections::HashMap,
109    convert::Infallible,
110    fmt,
111    hash::{Hash, Hasher},
112    marker::PhantomData,
113    mem::ManuallyDrop,
114    ops::Deref,
115    ptr::null,
116    sync::Arc,
117};
118
119const ALIGNMENT: usize = 16;
120const TAG_BITS: usize = ALIGNMENT.ilog2() as usize;
121pub(crate) const TAG: usize = 0b1111;
122pub(crate) const NULL_VALUE: usize = Tag::Pair as usize;
123pub(crate) const TRUE_VALUE: usize = Tag::Boolean as usize | 1 << TAG_BITS;
124pub(crate) const FALSE_VALUE: usize = Tag::Boolean as usize;
125
126/// A Scheme value. See [the module documentation](scheme_rs::value) for more
127/// information.
128#[repr(transparent)]
129pub struct Value(*const ());
130
131impl Value {
132    /// Create a new `Value` from an `UnpackedValue`.
133    ///
134    /// This is generally discouraged as it's cumbersome; try using `From`
135    /// instead.
136    pub fn new(v: UnpackedValue) -> Self {
137        v.into_value()
138    }
139
140    /// #f is false, everything else is true
141    pub fn is_true(&self) -> bool {
142        self.0 as usize != FALSE_VALUE
143    }
144
145    pub fn is_null(&self) -> bool {
146        self.0 as usize == Tag::Pair as usize
147    }
148
149    pub fn is_undefined(&self) -> bool {
150        self.type_of() == ValueType::Undefined
151    }
152
153    /// Creates a new Value from a raw u64.
154    ///
155    /// # Safety
156    /// Calling this function is undefined behavior if the raw u64 was not obtained
157    /// via [into_raw](Value::into_raw)
158    pub unsafe fn from_raw(raw: *const ()) -> Self {
159        Self(raw)
160    }
161
162    /// Creates a new Value from a raw u64, incrementing the reference count.
163    ///
164    /// # Safety
165    /// Calling this function is undefined behavior if the raw u64 was not obtained
166    /// via [into_raw](Value::into_raw)
167    pub unsafe fn from_raw_inc_rc(raw: *const ()) -> Self {
168        let tag = Tag::from(raw as usize & TAG);
169        let untagged = raw.map_addr(|raw| raw & !TAG);
170        unsafe {
171            match tag {
172                Tag::Number => Arc::increment_strong_count(untagged as *const NumberInner),
173                Tag::String => Arc::increment_strong_count(untagged as *const WideStringInner),
174                Tag::Vector => {
175                    Gc::increment_reference_count(untagged as *mut GcInner<VectorInner<Value>>)
176                }
177                Tag::ByteVector => Arc::increment_strong_count(untagged as *const VectorInner<u8>),
178                Tag::Syntax => Gc::increment_reference_count(untagged as *mut GcInner<Syntax>),
179                Tag::Procedure => {
180                    Gc::increment_reference_count(untagged as *mut GcInner<ProcedureInner>)
181                }
182                Tag::Record => Gc::increment_reference_count(untagged as *mut GcInner<RecordInner>),
183                Tag::RecordTypeDescriptor => {
184                    Arc::increment_strong_count(untagged as *const RecordTypeDescriptor)
185                }
186                Tag::Pair => {
187                    if !untagged.is_null() {
188                        Gc::increment_reference_count(untagged as *mut GcInner<PairInner>)
189                    }
190                }
191                Tag::Port => Arc::increment_strong_count(untagged as *const PortInner),
192                Tag::HashTable => {
193                    Gc::increment_reference_count(untagged as *mut GcInner<HashTableInner>)
194                }
195                Tag::Cell => {
196                    Gc::increment_reference_count(untagged as *mut GcInner<Value>);
197                }
198                Tag::Undefined | Tag::Symbol | Tag::Boolean | Tag::Character => (),
199            }
200        }
201        Self(raw)
202    }
203
204    /// Creates a raw u64 from a Value. Does not decrement the reference count.
205    /// Calling this function without turning the raw value into a Value via
206    /// [from_raw](Value::from_raw) is equivalent to calling mem::forget on the
207    /// value.
208    pub fn into_raw(val: Self) -> *const () {
209        ManuallyDrop::new(val).0
210    }
211
212    /// Creates a raw u64 from the Value. Does not decrement the reference count.
213    pub fn as_raw(this: &Self) -> *const () {
214        this.0
215    }
216
217    fn from_ptr_and_tag<T: Send + Sync>(ptr: *const T, tag: Tag) -> Self {
218        Self(ptr.map_addr(|raw| raw | tag as usize) as *const ())
219    }
220
221    fn from_mut_ptr_and_tag<T: Send + Sync>(ptr: *mut T, tag: Tag) -> Self {
222        Self(ptr.map_addr(|raw| raw | tag as usize) as *const ())
223    }
224
225    pub fn undefined() -> Self {
226        Self(null::<()>().map_addr(|raw| raw | Tag::Undefined as usize))
227    }
228
229    pub fn null() -> Self {
230        Self(null::<()>().map_addr(|raw| raw | Tag::Pair as usize))
231    }
232
233    /// Convert a [`Syntax`] into its corresponding datum representation.
234    pub fn datum_from_syntax(syntax: &Syntax) -> Self {
235        match syntax {
236            Syntax::Wrapped { value, .. } => value.clone(),
237            Syntax::List { list, .. } => {
238                let mut curr = Self::datum_from_syntax(list.last().unwrap());
239                for item in list[..list.len() - 1].iter().rev() {
240                    curr = Self::from(Pair::immutable(Self::datum_from_syntax(item), curr));
241                }
242                curr
243            }
244            Syntax::Vector { vector, .. } => Self::from(
245                vector
246                    .iter()
247                    .map(Self::datum_from_syntax)
248                    .collect::<Vec<_>>(),
249            ),
250            Syntax::Identifier { ident, .. } => Self::new(UnpackedValue::Symbol(ident.sym)),
251        }
252    }
253
254    pub fn type_of(&self) -> ValueType {
255        self.unpacked_ref().type_of()
256    }
257
258    pub fn type_name(&self) -> &'static str {
259        self.unpacked_ref().type_name()
260    }
261
262    /// Attempt to cast the value into a Scheme primitive type.
263    pub fn cast_to_scheme_type<T>(&self) -> Option<T>
264    where
265        for<'a> &'a Self: Into<Option<T>>,
266    {
267        self.into()
268    }
269
270    /// Attempt to cast the value into a Scheme primitive type and return a
271    /// descriptive error on failure.
272    pub fn try_to_scheme_type<T>(&self) -> Result<T, Exception>
273    where
274        T: for<'a> TryFrom<&'a Self, Error = Exception>,
275    {
276        self.try_into()
277    }
278
279    /// Attempt to cast the value into a Rust type that implements
280    /// [`SchemeCompatible`].
281    pub fn cast_to_rust_type<T: SchemeCompatible>(&self) -> Option<Gc<T>> {
282        let UnpackedValue::Record(record) = self.clone().unpack() else {
283            return None;
284        };
285        record.cast::<T>()
286    }
287
288    /// Attempt to cast the value into a Rust type and return a descriptive
289    /// error on failure.
290    pub fn try_to_rust_type<T: SchemeCompatible>(&self) -> Result<Gc<T>, Exception> {
291        let type_name = T::rtd().name.to_str();
292        let this = self.clone().unpack();
293        let record = match this {
294            UnpackedValue::Record(record) => record,
295            e => return Err(Exception::type_error(&type_name, e.type_name())),
296        };
297
298        record
299            .cast::<T>()
300            .ok_or_else(|| Exception::type_error(&type_name, &record.rtd().name.to_str()))
301    }
302
303    /// Automatically convert a `SchemeCompatible` type to a `Record` and then
304    /// into a `Value`.
305    pub fn from_rust_type<T: SchemeCompatible>(t: T) -> Self {
306        Self::from(Record::from_rust_type(t))
307    }
308
309    /// Unpack the value into an enum representation.
310    pub fn unpack(self) -> UnpackedValue {
311        let raw = ManuallyDrop::new(self).0;
312        let tag = Tag::from(raw as usize & TAG);
313        let untagged = raw.map_addr(|raw| raw & !TAG);
314        match tag {
315            Tag::Undefined => UnpackedValue::Undefined,
316            Tag::Boolean => {
317                let untagged = untagged as usize >> TAG_BITS;
318                UnpackedValue::Boolean(untagged != 0)
319            }
320            Tag::Character => {
321                let untagged = (untagged as usize >> TAG_BITS) as u32;
322                UnpackedValue::Character(char::from_u32(untagged).unwrap())
323            }
324            Tag::Number => {
325                let number = unsafe { Arc::from_raw(untagged as *const NumberInner) };
326                UnpackedValue::Number(Number(number))
327            }
328            Tag::String => {
329                let str = unsafe { Arc::from_raw(untagged as *const WideStringInner) };
330                UnpackedValue::String(WideString(str))
331            }
332            Tag::Symbol => {
333                let untagged = (untagged as usize >> TAG_BITS) as u32;
334                UnpackedValue::Symbol(Symbol(untagged))
335            }
336            Tag::Vector => {
337                let vec = unsafe { Gc::from_raw(untagged as *mut GcInner<VectorInner<Self>>) };
338                UnpackedValue::Vector(Vector(vec))
339            }
340            Tag::ByteVector => {
341                let bvec = unsafe { Arc::from_raw(untagged as *const VectorInner<u8>) };
342                UnpackedValue::ByteVector(ByteVector(bvec))
343            }
344            Tag::Syntax => {
345                let syn = unsafe { Gc::from_raw(untagged as *mut GcInner<Syntax>) };
346                UnpackedValue::Syntax(syn)
347            }
348            Tag::Procedure => {
349                let clos = unsafe { Gc::from_raw(untagged as *mut GcInner<ProcedureInner>) };
350                UnpackedValue::Procedure(Procedure(clos))
351            }
352            Tag::Record => {
353                let rec = unsafe { Gc::from_raw(untagged as *mut GcInner<RecordInner>) };
354                UnpackedValue::Record(Record(rec))
355            }
356            Tag::RecordTypeDescriptor => {
357                let rt = unsafe { Arc::from_raw(untagged as *const RecordTypeDescriptor) };
358                UnpackedValue::RecordTypeDescriptor(rt)
359            }
360            Tag::Pair => {
361                if untagged.is_null() {
362                    UnpackedValue::Null
363                } else {
364                    let pair = unsafe { Gc::from_raw(untagged as *mut GcInner<PairInner>) };
365                    UnpackedValue::Pair(Pair(pair))
366                }
367            }
368            Tag::Port => {
369                let port_inner = unsafe { Arc::from_raw(untagged as *const PortInner) };
370                UnpackedValue::Port(Port(port_inner))
371            }
372            Tag::HashTable => {
373                let ht = unsafe { Gc::from_raw(untagged as *mut GcInner<HashTableInner>) };
374                UnpackedValue::HashTable(HashTable(ht))
375            }
376            Tag::Cell => {
377                let cell = unsafe { Gc::from_raw(untagged as *mut GcInner<RwLock<Value>>) };
378                UnpackedValue::Cell(Cell(cell))
379            }
380        }
381    }
382
383    pub fn unpacked_ref(&self) -> UnpackedValueRef<'_> {
384        let unpacked = ManuallyDrop::new(Value(self.0).unpack());
385        UnpackedValueRef {
386            unpacked,
387            marker: PhantomData,
388        }
389    }
390
391    /// The eq? predicate as defined by the R6RS specification.
392    #[allow(clippy::should_implement_trait)]
393    pub fn eq(&self, rhs: &Self) -> bool {
394        let obj1 = self.unpacked_ref();
395        let obj2 = rhs.unpacked_ref();
396        obj1.eq(&obj2)
397    }
398
399    /// The eqv? predicate as defined by the R6RS specification.
400    pub fn eqv(&self, rhs: &Self) -> bool {
401        let obj1 = self.unpacked_ref();
402        let obj2 = rhs.unpacked_ref();
403        obj1.eqv(&obj2)
404    }
405
406    /// The equal? predicate as defined by the R6RS specification.
407    pub fn equal(&self, rhs: &Self) -> bool {
408        equal(self, rhs)
409    }
410
411    /// Performs a hash suitable for use with eq? as an equivalance function
412    pub fn eq_hash<H: Hasher>(&self, state: &mut H) {
413        let unpacked = self.unpacked_ref();
414        std::mem::discriminant(&*unpacked).hash(state);
415        match &*unpacked {
416            UnpackedValue::Undefined => (),
417            UnpackedValue::Null => (),
418            UnpackedValue::Boolean(b) => b.hash(state),
419            UnpackedValue::Character(c) => c.hash(state),
420            UnpackedValue::Number(n) => Arc::as_ptr(&n.0).hash(state),
421            UnpackedValue::String(s) => Arc::as_ptr(&s.0).hash(state),
422            UnpackedValue::Symbol(s) => s.hash(state),
423            UnpackedValue::ByteVector(v) => Arc::as_ptr(&v.0).hash(state),
424            UnpackedValue::Syntax(s) => Gc::as_ptr(s).hash(state),
425            UnpackedValue::Procedure(c) => Gc::as_ptr(&c.0).hash(state),
426            UnpackedValue::Record(r) => Gc::as_ptr(&r.0).hash(state),
427            UnpackedValue::RecordTypeDescriptor(rt) => Arc::as_ptr(rt).hash(state),
428            UnpackedValue::Pair(p) => Gc::as_ptr(&p.0).hash(state),
429            UnpackedValue::Vector(v) => Gc::as_ptr(&v.0).hash(state),
430            UnpackedValue::Port(p) => Arc::as_ptr(&p.0).hash(state),
431            UnpackedValue::HashTable(ht) => Gc::as_ptr(&ht.0).hash(state),
432            UnpackedValue::Cell(c) => c.0.read().eqv_hash(state),
433        }
434    }
435
436    /// Performs a hash suitable for use with eqv? as an equivalance function
437    pub fn eqv_hash<H: Hasher>(&self, state: &mut H) {
438        let unpacked = self.unpacked_ref();
439        std::mem::discriminant(&*unpacked).hash(state);
440        match &*unpacked {
441            UnpackedValue::Undefined => (),
442            UnpackedValue::Null => (),
443            UnpackedValue::Boolean(b) => b.hash(state),
444            UnpackedValue::Character(c) => c.hash(state),
445            UnpackedValue::Number(n) => n.hash(state),
446            UnpackedValue::String(s) => Arc::as_ptr(&s.0).hash(state),
447            UnpackedValue::Symbol(s) => s.hash(state),
448            UnpackedValue::ByteVector(v) => Arc::as_ptr(&v.0).hash(state),
449            UnpackedValue::Syntax(s) => Gc::as_ptr(s).hash(state),
450            UnpackedValue::Procedure(c) => Gc::as_ptr(&c.0).hash(state),
451            UnpackedValue::Record(r) => Gc::as_ptr(&r.0).hash(state),
452            UnpackedValue::RecordTypeDescriptor(rt) => Arc::as_ptr(rt).hash(state),
453            UnpackedValue::Pair(p) => Gc::as_ptr(&p.0).hash(state),
454            UnpackedValue::Vector(v) => Gc::as_ptr(&v.0).hash(state),
455            UnpackedValue::Port(p) => Arc::as_ptr(&p.0).hash(state),
456            UnpackedValue::HashTable(ht) => Gc::as_ptr(&ht.0).hash(state),
457            UnpackedValue::Cell(c) => c.0.read().eqv_hash(state),
458        }
459    }
460
461    /// Performs a hash suitable for use with equal? as an equivalance function
462    pub fn equal_hash<H: Hasher>(&self, recursive: &mut IndexSet<Value>, state: &mut H) {
463        let unpacked = self.unpacked_ref();
464        std::mem::discriminant(&*unpacked).hash(state);
465
466        // I think this is fine, because types that would be recursive will
467        // write out at least two values here where we're only writing out one.
468        if let Some(index) = recursive.get_index_of(self) {
469            state.write_usize(index);
470            return;
471        }
472
473        match &*unpacked {
474            UnpackedValue::Undefined => (),
475            UnpackedValue::Null => (),
476            UnpackedValue::Boolean(b) => b.hash(state),
477            UnpackedValue::Character(c) => c.hash(state),
478            UnpackedValue::Number(n) => n.hash(state),
479            UnpackedValue::String(s) => s.hash(state),
480            UnpackedValue::Symbol(s) => s.hash(state),
481            UnpackedValue::ByteVector(v) => v.hash(state),
482            UnpackedValue::Syntax(s) => Gc::as_ptr(s).hash(state),
483            UnpackedValue::Procedure(c) => Gc::as_ptr(&c.0).hash(state),
484            UnpackedValue::Record(r) => Gc::as_ptr(&r.0).hash(state),
485            UnpackedValue::RecordTypeDescriptor(rt) => Arc::as_ptr(rt).hash(state),
486            UnpackedValue::Pair(p) => {
487                recursive.insert(self.clone());
488                let (car, cdr) = p.clone().into();
489                car.equal_hash(recursive, state);
490                cdr.equal_hash(recursive, state);
491            }
492            UnpackedValue::Vector(v) => {
493                recursive.insert(self.clone());
494                let v_read = v.0.vec.read();
495                state.write_usize(v_read.len());
496                for val in v_read.iter() {
497                    val.equal_hash(recursive, state);
498                }
499            }
500            UnpackedValue::Port(p) => Arc::as_ptr(&p.0).hash(state),
501            UnpackedValue::HashTable(ht) => Gc::as_ptr(&ht.0).hash(state),
502            UnpackedValue::Cell(c) => c.0.read().eqv_hash(state),
503        }
504    }
505}
506
507impl Clone for Value {
508    fn clone(&self) -> Self {
509        unsafe { Self::from_raw_inc_rc(self.0) }
510    }
511}
512
513impl Drop for Value {
514    fn drop(&mut self) {
515        // FIXME: This is a pretty dumb way to do this, do it manually!
516        unsafe { ManuallyDrop::drop(&mut ManuallyDrop::new(Self(self.0).unpack())) }
517    }
518}
519
520/// Default Hash implementation for Value is [Value::eqv_hash]. This produces
521/// reasonable hash maps.
522impl Hash for Value {
523    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
524        self.eqv_hash(state)
525    }
526}
527
528/// Default PartialEq implementation for Value is [Value::eqv]. This allows us
529/// to implement [Eq].
530impl PartialEq for Value {
531    fn eq(&self, rhs: &Value) -> bool {
532        self.eqv(rhs)
533    }
534}
535
536/// Eq can be implemented reasonably for Value since (eqv? +nan.0 +nan.0) is
537/// true
538impl Eq for Value {}
539
540unsafe impl Send for Value {}
541unsafe impl Sync for Value {}
542
543impl fmt::Display for Value {
544    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545        let mut circular_values = IndexSet::default();
546        determine_circularity(self, &mut IndexSet::default(), &mut circular_values);
547        let mut circular_values = circular_values.into_iter().map(|k| (k, false)).collect();
548        write_value(self, display_value, &mut circular_values, f)
549    }
550}
551
552impl fmt::Debug for Value {
553    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554        let mut circular_values = IndexSet::default();
555        determine_circularity(self, &mut IndexSet::default(), &mut circular_values);
556        let mut circular_values = circular_values.into_iter().map(|k| (k, false)).collect();
557        write_value(self, debug_value, &mut circular_values, f)
558    }
559}
560
561unsafe impl Trace for Value {
562    unsafe fn visit_children(&self, visitor: &mut dyn FnMut(crate::gc::OpaqueGcPtr)) {
563        unsafe {
564            self.unpacked_ref().visit_children(visitor);
565        }
566    }
567
568    unsafe fn finalize(&mut self) {
569        unsafe { ManuallyDrop::new(Self(self.0).unpack()).finalize() }
570    }
571}
572
573/// A Cell is a value that is mutable, essentially a variable.
574#[derive(Clone, Trace)]
575pub struct Cell(pub(crate) Gc<RwLock<Value>>);
576
577impl Cell {
578    pub fn new(val: Value) -> Self {
579        Self(Gc::new(RwLock::new(val)))
580    }
581
582    pub fn get(&self) -> Value {
583        self.0.read().clone()
584    }
585
586    pub fn set(&self, new_val: Value) {
587        *self.0.write() = new_val;
588    }
589}
590
591/// A reference to an [`UnpackedValue`]. Allows for unpacking a `Value` without
592/// cloning/modifying the reference count.
593pub struct UnpackedValueRef<'a> {
594    unpacked: ManuallyDrop<UnpackedValue>,
595    marker: PhantomData<&'a UnpackedValue>,
596}
597
598impl Deref for UnpackedValueRef<'_> {
599    type Target = UnpackedValue;
600
601    fn deref(&self) -> &Self::Target {
602        &self.unpacked
603    }
604}
605
606impl AsRef<UnpackedValue> for UnpackedValueRef<'_> {
607    fn as_ref(&self) -> &UnpackedValue {
608        &self.unpacked
609    }
610}
611
612impl<T> From<Option<T>> for Value
613where
614    Value: From<T>,
615    Value: From<bool>,
616{
617    // Probably not the best way to do this, but whatever
618    fn from(value: Option<T>) -> Self {
619        match value {
620            Some(t) => Self::from(t),
621            None => Self::from(false),
622        }
623    }
624}
625
626/*
627impl From<ast::Literal> for Value {
628    fn from(lit: ast::Literal) -> Self {
629        Value::new(lit.into())
630    }
631}
632*/
633
634impl From<Exception> for Value {
635    fn from(value: Exception) -> Self {
636        value.0
637    }
638}
639
640#[repr(u64)]
641#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
642pub(crate) enum Tag {
643    Undefined = 0,
644    Pair = 1,
645    Boolean = 2,
646    Character = 3,
647    Number = 4,
648    String = 5,
649    Symbol = 6,
650    Vector = 7,
651    ByteVector = 8,
652    Syntax = 9,
653    Procedure = 10,
654    Record = 11,
655    RecordTypeDescriptor = 12,
656    HashTable = 13,
657    Port = 14,
658    Cell = 15,
659}
660
661// TODO: Make TryFrom with error
662impl From<usize> for Tag {
663    fn from(tag: usize) -> Self {
664        match tag {
665            0 => Self::Undefined,
666            1 => Self::Pair,
667            2 => Self::Boolean,
668            3 => Self::Character,
669            4 => Self::Number,
670            5 => Self::String,
671            6 => Self::Symbol,
672            7 => Self::Vector,
673            8 => Self::ByteVector,
674            9 => Self::Syntax,
675            10 => Self::Procedure,
676            11 => Self::Record,
677            12 => Self::RecordTypeDescriptor,
678            13 => Self::HashTable,
679            14 => Self::Port,
680            15 => Self::Cell,
681            tag => panic!("Invalid tag: {tag}"),
682        }
683    }
684}
685
686/// Different possible types that a Value can inhabit.
687#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
688pub enum ValueType {
689    Undefined,
690    Null,
691    Pair,
692    Boolean,
693    Character,
694    Number,
695    String,
696    Symbol,
697    Vector,
698    ByteVector,
699    Syntax,
700    Procedure,
701    Record,
702    RecordTypeDescriptor,
703    HashTable,
704    Port,
705}
706
707/// The external, unpacked, enumeration representation of a scheme value.
708///
709/// Values that are not potentially cyclical, such as syntax objects and byte
710/// vectors use Arcs as they are much less expensive than Gc types.
711#[non_exhaustive]
712#[derive(Trace, Clone)]
713pub enum UnpackedValue {
714    Undefined,
715    Null,
716    Boolean(bool),
717    Character(char),
718    Number(Number),
719    String(WideString),
720    Symbol(Symbol),
721    Vector(Vector),
722    ByteVector(ByteVector),
723    Syntax(Gc<Syntax>),
724    Procedure(Procedure),
725    Record(Record),
726    RecordTypeDescriptor(Arc<RecordTypeDescriptor>),
727    Pair(Pair),
728    Port(Port),
729    HashTable(HashTable),
730    Cell(Cell),
731}
732
733impl UnpackedValue {
734    pub fn into_value(self) -> Value {
735        match self {
736            Self::Undefined => Value::undefined(),
737            Self::Null => Value::null(),
738            Self::Boolean(b) => {
739                Value::from_ptr_and_tag(((b as usize) << TAG_BITS) as *const (), Tag::Boolean)
740            }
741            Self::Character(c) => {
742                Value::from_ptr_and_tag(((c as usize) << TAG_BITS) as *const (), Tag::Character)
743            }
744            Self::Number(num) => {
745                let untagged = Arc::into_raw(num.0);
746                Value::from_ptr_and_tag(untagged, Tag::Number)
747            }
748            Self::String(str) => {
749                let untagged = Arc::into_raw(str.0);
750                Value::from_ptr_and_tag(untagged, Tag::String)
751            }
752            Self::Symbol(sym) => {
753                Value::from_ptr_and_tag(((sym.0 as usize) << TAG_BITS) as *const (), Tag::Symbol)
754            }
755            Self::Vector(vec) => {
756                let untagged = Gc::into_raw(vec.0);
757                Value::from_mut_ptr_and_tag(untagged, Tag::Vector)
758            }
759            Self::ByteVector(b_vec) => {
760                let untagged = Arc::into_raw(b_vec.0);
761                Value::from_ptr_and_tag(untagged, Tag::ByteVector)
762            }
763            Self::Syntax(syn) => {
764                let untagged = Gc::into_raw(syn);
765                Value::from_mut_ptr_and_tag(untagged, Tag::Syntax)
766            }
767            Self::Procedure(clos) => {
768                let untagged = Gc::into_raw(clos.0);
769                Value::from_mut_ptr_and_tag(untagged, Tag::Procedure)
770            }
771            Self::Record(rec) => {
772                let untagged = Gc::into_raw(rec.0);
773                Value::from_mut_ptr_and_tag(untagged, Tag::Record)
774            }
775            Self::RecordTypeDescriptor(rt) => {
776                let untagged = Arc::into_raw(rt);
777                Value::from_ptr_and_tag(untagged, Tag::RecordTypeDescriptor)
778            }
779            Self::Pair(pair) => {
780                let untagged = Gc::into_raw(pair.0);
781                Value::from_mut_ptr_and_tag(untagged, Tag::Pair)
782            }
783            Self::Port(port) => {
784                let untagged = Arc::into_raw(port.0);
785                Value::from_ptr_and_tag(untagged, Tag::Port)
786            }
787            Self::HashTable(ht) => {
788                let untagged = Gc::into_raw(ht.0);
789                Value::from_ptr_and_tag(untagged, Tag::HashTable)
790            }
791            Self::Cell(cell) => {
792                let untagged = Gc::into_raw(cell.0);
793                Value::from_mut_ptr_and_tag(untagged, Tag::Cell)
794            }
795        }
796    }
797
798    #[allow(clippy::should_implement_trait)]
799    pub fn eq(&self, rhs: &Self) -> bool {
800        match (self, rhs) {
801            (Self::Boolean(a), Self::Boolean(b)) => a == b,
802            (Self::Symbol(a), Self::Symbol(b)) => a == b,
803            (Self::Number(a), Self::Number(b)) => Arc::ptr_eq(&a.0, &b.0),
804            (Self::Character(a), Self::Character(b)) => a == b,
805            (Self::Null, Self::Null) => true,
806            (Self::String(a), Self::String(b)) => Arc::ptr_eq(&a.0, &b.0),
807            (Self::Pair(a), Self::Pair(b)) => Gc::ptr_eq(&a.0, &b.0),
808            (Self::Vector(a), Self::Vector(b)) => Gc::ptr_eq(&a.0, &b.0),
809            (Self::ByteVector(a), Self::ByteVector(b)) => Arc::ptr_eq(&a.0, &b.0),
810            (Self::Procedure(a), Self::Procedure(b)) => Gc::ptr_eq(&a.0, &b.0),
811            (Self::Syntax(a), Self::Syntax(b)) => Gc::ptr_eq(a, b),
812            (Self::Record(a), Self::Record(b)) => Gc::ptr_eq(&a.0, &b.0),
813            (Self::RecordTypeDescriptor(a), Self::RecordTypeDescriptor(b)) => Arc::ptr_eq(a, b),
814            (Self::Port(a), Self::Port(b)) => Arc::ptr_eq(&a.0, &b.0),
815            (Self::HashTable(a), Self::HashTable(b)) => Gc::ptr_eq(&a.0, &b.0),
816            (Self::Cell(a), b) => a.0.read().unpacked_ref().eq(b),
817            (a, Self::Cell(b)) => a.eq(&b.0.read().unpacked_ref()),
818            _ => false,
819        }
820    }
821
822    pub fn eqv(&self, rhs: &Self) -> bool {
823        match (self, rhs) {
824            // Undefined is equivalent to undefined since it is impossible to
825            // read
826            (Self::Undefined, Self::Undefined) => true,
827            // boolean=?
828            (Self::Boolean(a), Self::Boolean(b)) => a == b,
829            // symbol=?
830            (Self::Symbol(a), Self::Symbol(b)) => a == b,
831            (Self::Number(a), Self::Number(b)) => a.eqv(b),
832            // char=?
833            (Self::Character(a), Self::Character(b)) => a == b,
834            // Both obj1 and obj2 are the empty list
835            (Self::Null, Self::Null) => true,
836            // Everything else is pointer equivalence
837            (Self::String(a), Self::String(b)) => Arc::ptr_eq(&a.0, &b.0),
838            (Self::Pair(a), Self::Pair(b)) => Gc::ptr_eq(&a.0, &b.0),
839            (Self::Vector(a), Self::Vector(b)) => Gc::ptr_eq(&a.0, &b.0),
840            (Self::ByteVector(a), Self::ByteVector(b)) => Arc::ptr_eq(&a.0, &b.0),
841            (Self::Procedure(a), Self::Procedure(b)) => Gc::ptr_eq(&a.0, &b.0),
842            (Self::Syntax(a), Self::Syntax(b)) => Gc::ptr_eq(a, b),
843            (Self::Record(a), Self::Record(b)) => Gc::ptr_eq(&a.0, &b.0),
844            (Self::RecordTypeDescriptor(a), Self::RecordTypeDescriptor(b)) => Arc::ptr_eq(a, b),
845            (Self::Port(a), Self::Port(b)) => Arc::ptr_eq(&a.0, &b.0),
846            (Self::HashTable(a), Self::HashTable(b)) => Gc::ptr_eq(&a.0, &b.0),
847            (Self::Cell(a), b) => a.0.read().unpacked_ref().eqv(b),
848            (a, Self::Cell(b)) => a.eqv(&b.0.read().unpacked_ref()),
849            _ => false,
850        }
851    }
852
853    pub fn type_name(&self) -> &'static str {
854        match self {
855            Self::Undefined => "undefined",
856            Self::Boolean(_) => "bool",
857            Self::Number(_) => "number",
858            Self::Character(_) => "character",
859            Self::String(_) => "string",
860            Self::Symbol(_) => "symbol",
861            Self::Pair(_) | Self::Null => "pair",
862            Self::Vector(_) => "vector",
863            Self::ByteVector(_) => "byte vector",
864            Self::Syntax(_) => "syntax",
865            Self::Procedure(_) => "procedure",
866            Self::Record(_) => "record",
867            Self::RecordTypeDescriptor(_) => "rtd",
868            Self::Port(_) => "port",
869            Self::HashTable(_) => "hashtable",
870            Self::Cell(cell) => cell.0.read().type_name(),
871        }
872    }
873
874    pub fn type_of(&self) -> ValueType {
875        match self {
876            Self::Undefined => ValueType::Undefined,
877            Self::Null => ValueType::Null,
878            Self::Boolean(_) => ValueType::Boolean,
879            Self::Number(_) => ValueType::Number,
880            Self::Character(_) => ValueType::Character,
881            Self::String(_) => ValueType::String,
882            Self::Symbol(_) => ValueType::Symbol,
883            Self::Pair(_) => ValueType::Pair,
884            Self::Vector(_) => ValueType::Vector,
885            Self::ByteVector(_) => ValueType::ByteVector,
886            Self::Syntax(_) => ValueType::Syntax,
887            Self::Procedure(_) => ValueType::Procedure,
888            Self::Record(_) => ValueType::Record,
889            Self::RecordTypeDescriptor(_) => ValueType::RecordTypeDescriptor,
890            Self::Port(_) => ValueType::Port,
891            Self::HashTable(_) => ValueType::HashTable,
892            Self::Cell(cell) => cell.0.read().type_of(),
893        }
894    }
895}
896
897/// Determine if two objects are equal in an extremely granular sense.
898///
899/// This implementation is a Rust translation of Efficient Dondestructive
900/// Equality Checking for Trees and Graphs by Michael D. Adams and R. Kent
901/// Dybvig.
902pub fn equal(obj1: &Value, obj2: &Value) -> bool {
903    interleave(&mut HashMap::default(), obj1, obj2, K0)
904}
905
906const K0: i64 = 400;
907const KB: i64 = -40;
908
909fn interleave(ht: &mut HashMap<Value, Value>, obj1: &Value, obj2: &Value, k: i64) -> bool {
910    e(ht, obj1, obj2, k).is_some()
911}
912
913fn e(ht: &mut HashMap<Value, Value>, obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
914    match k {
915        KB => fast(ht, obj1, obj2, rand::random_range(0..(K0 * 2))),
916        k if k <= 0 => slow(ht, obj1, obj2, k),
917        k => fast(ht, obj1, obj2, k),
918    }
919}
920
921fn fast(ht: &mut HashMap<Value, Value>, obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
922    let k = k - 1;
923    if obj1.eqv(obj2) {
924        return Some(k);
925    }
926    match (obj1.type_of(), obj2.type_of()) {
927        (ValueType::Pair, ValueType::Pair) => pair_eq(ht, obj1, obj2, k),
928        (ValueType::Vector, ValueType::Vector) => vector_eq(ht, obj1, obj2, k),
929        (ValueType::ByteVector, ValueType::ByteVector) => bytevector_eq(obj1, obj2, k),
930        (ValueType::String, ValueType::String) => string_eq(obj1, obj2, k),
931        _ => None,
932    }
933}
934
935fn slow(ht: &mut HashMap<Value, Value>, obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
936    if obj1.eqv(obj2) {
937        return Some(k);
938    }
939    match (obj1.type_of(), obj2.type_of()) {
940        (ValueType::Pair, ValueType::Pair) => {
941            if union_find(ht, obj1, obj2) {
942                return Some(0);
943            }
944            pair_eq(ht, obj1, obj2, k)
945        }
946        (ValueType::Vector, ValueType::Vector) => {
947            if union_find(ht, obj1, obj2) {
948                return Some(0);
949            }
950            vector_eq(ht, obj1, obj2, k)
951        }
952        (ValueType::ByteVector, ValueType::ByteVector) => bytevector_eq(obj1, obj2, k),
953        (ValueType::String, ValueType::String) => string_eq(obj1, obj2, k),
954        _ => None,
955    }
956}
957
958fn pair_eq(ht: &mut HashMap<Value, Value>, obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
959    let obj1: Pair = obj1.clone().try_into().unwrap();
960    let obj2: Pair = obj2.clone().try_into().unwrap();
961    let (car_x, cdr_x) = obj1.into();
962    let (car_y, cdr_y) = obj2.into();
963    e(ht, &car_x, &car_y, k - 1).and_then(|k| e(ht, &cdr_x, &cdr_y, k))
964}
965
966fn vector_eq(ht: &mut HashMap<Value, Value>, obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
967    let vobj1: Vector = obj1.clone().try_into().unwrap();
968    let vobj2: Vector = obj2.clone().try_into().unwrap();
969    let vobj1 = vobj1.0.vec.read();
970    let vobj2 = vobj2.0.vec.read();
971    if vobj1.len() != vobj2.len() {
972        return None;
973    }
974    let mut k = k - 1;
975    for (x, y) in vobj1.iter().zip(vobj2.iter()) {
976        k = e(ht, x, y, k)?;
977    }
978    Some(k)
979}
980
981fn bytevector_eq(obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
982    let obj1: ByteVector = obj1.clone().try_into().unwrap();
983    let obj2: ByteVector = obj2.clone().try_into().unwrap();
984    (*obj1.0.vec.read() == *obj2.0.vec.read()).then_some(k)
985}
986
987fn string_eq(obj1: &Value, obj2: &Value, k: i64) -> Option<i64> {
988    let obj1: WideString = obj1.clone().try_into().unwrap();
989    let obj2: WideString = obj2.clone().try_into().unwrap();
990    (obj1 == obj2).then_some(k)
991}
992
993fn union_find(ht: &mut HashMap<Value, Value>, x: &Value, y: &Value) -> bool {
994    let bx = ht.get(x).cloned();
995    let by = ht.get(y).cloned();
996    match (bx, by) {
997        (None, None) => {
998            let b = boxv(Value::from(Number::from(1)));
999            ht.insert(x.clone(), b.clone());
1000            ht.insert(y.clone(), b);
1001        }
1002        (None, Some(by)) => {
1003            let ry = find(by);
1004            ht.insert(x.clone(), ry);
1005        }
1006        (Some(bx), None) => {
1007            let rx = find(bx);
1008            ht.insert(y.clone(), rx);
1009        }
1010        (Some(bx), Some(by)) => {
1011            let rx = find(bx);
1012            let ry = find(by);
1013            if rx.eqv(&ry) {
1014                return true;
1015            }
1016            let nx = unbox_to_num(&rx);
1017            let ny = unbox_to_num(&ry);
1018            if nx > ny {
1019                set_box(&ry, rx.clone());
1020                set_box(&rx, nx + ny);
1021            } else {
1022                set_box(&rx, ry.clone());
1023                set_box(&ry, nx + ny);
1024            }
1025        }
1026    }
1027    false
1028}
1029
1030fn find(mut b: Value) -> Value {
1031    let mut n = unbox(&b);
1032    if is_box(&n) {
1033        loop {
1034            let nn = unbox(&n);
1035            if !is_box(&nn) {
1036                return n;
1037            }
1038            set_box(&b, nn.clone());
1039            b = n;
1040            n = nn;
1041        }
1042    } else {
1043        b
1044    }
1045}
1046
1047fn boxv(v: Value) -> Value {
1048    Value::from(Pair::mutable(v.clone(), Value::null()))
1049}
1050
1051fn unbox(v: &Value) -> Value {
1052    let pair: Pair = v.clone().try_into().unwrap();
1053    pair.car()
1054}
1055
1056fn unbox_to_num(v: &Value) -> Number {
1057    let pair: Pair = v.clone().try_into().unwrap();
1058    pair.car().try_into().unwrap()
1059}
1060
1061fn is_box(v: &Value) -> bool {
1062    v.type_of() == ValueType::Pair
1063}
1064
1065fn set_box(b: &Value, val: impl Into<Value>) {
1066    let pair: Pair = b.clone().try_into().unwrap();
1067    pair.set_car(val.into()).unwrap();
1068}
1069
1070macro_rules! impl_try_from_value_for {
1071    ($ty:ty, $variant:ident, $type_name:literal) => {
1072        impl From<$ty> for UnpackedValue {
1073            fn from(v: $ty) -> Self {
1074                Self::$variant(v)
1075            }
1076        }
1077
1078        impl From<$ty> for Value {
1079            fn from(v: $ty) -> Self {
1080                UnpackedValue::from(v).into_value()
1081            }
1082        }
1083
1084        impl From<UnpackedValue> for Option<$ty> {
1085            fn from(v: UnpackedValue) -> Self {
1086                match v {
1087                    UnpackedValue::$variant(v) => Some(v),
1088                    _ => None,
1089                }
1090            }
1091        }
1092
1093        impl From<Value> for Option<$ty> {
1094            fn from(v: Value) -> Self {
1095                v.unpack().into()
1096            }
1097        }
1098
1099        impl From<&'_ Value> for Option<$ty> {
1100            fn from(v: &Value) -> Self {
1101                v.clone().unpack().into()
1102            }
1103        }
1104
1105        impl TryFrom<UnpackedValue> for $ty {
1106            type Error = Exception;
1107
1108            fn try_from(v: UnpackedValue) -> Result<Self, Self::Error> {
1109                match v {
1110                    UnpackedValue::$variant(v) => Ok(v),
1111                    UnpackedValue::Cell(cell) => cell.0.read().clone().try_into(),
1112                    e => Err(Exception::type_error($type_name, e.type_name())),
1113                }
1114            }
1115        }
1116
1117        impl TryFrom<Value> for $ty {
1118            type Error = Exception;
1119
1120            fn try_from(v: Value) -> Result<Self, Self::Error> {
1121                v.unpack().try_into()
1122            }
1123        }
1124
1125        impl TryFrom<&Value> for $ty {
1126            type Error = Exception;
1127
1128            fn try_from(v: &Value) -> Result<Self, Self::Error> {
1129                v.clone().unpack().try_into()
1130            }
1131        }
1132    };
1133}
1134
1135impl From<Infallible> for Value {
1136    fn from(value: Infallible) -> Self {
1137        match value {}
1138    }
1139}
1140
1141impl From<()> for UnpackedValue {
1142    fn from((): ()) -> Self {
1143        Self::Null
1144    }
1145}
1146
1147impl From<()> for Value {
1148    fn from((): ()) -> Self {
1149        UnpackedValue::Null.into_value()
1150    }
1151}
1152
1153impl TryFrom<UnpackedValue> for () {
1154    type Error = Exception;
1155
1156    fn try_from(value: UnpackedValue) -> Result<Self, Self::Error> {
1157        match value {
1158            UnpackedValue::Null => Ok(()),
1159            e => Err(Exception::type_error("null", e.type_name())),
1160        }
1161    }
1162}
1163
1164impl TryFrom<Value> for () {
1165    type Error = Exception;
1166
1167    fn try_from(value: Value) -> Result<Self, Self::Error> {
1168        value.unpack().try_into()
1169    }
1170}
1171
1172impl From<Cell> for UnpackedValue {
1173    fn from(cell: Cell) -> Self {
1174        Self::Cell(cell)
1175    }
1176}
1177
1178impl From<Cell> for Value {
1179    fn from(cell: Cell) -> Self {
1180        UnpackedValue::from(cell).into_value()
1181    }
1182}
1183
1184impl TryFrom<UnpackedValue> for Cell {
1185    type Error = Exception;
1186
1187    fn try_from(v: UnpackedValue) -> Result<Self, Self::Error> {
1188        match v {
1189            UnpackedValue::Cell(cell) => Ok(cell.clone()),
1190            e => Err(Exception::type_error("cell", e.type_name())),
1191        }
1192    }
1193}
1194
1195impl TryFrom<Value> for Cell {
1196    type Error = Exception;
1197
1198    fn try_from(v: Value) -> Result<Self, Self::Error> {
1199        v.unpack().try_into()
1200    }
1201}
1202
1203impl TryFrom<&Value> for Cell {
1204    type Error = Exception;
1205
1206    fn try_from(v: &Value) -> Result<Self, Self::Error> {
1207        v.clone().unpack().try_into()
1208    }
1209}
1210
1211impl From<Value> for bool {
1212    fn from(value: Value) -> Self {
1213        value.is_true()
1214    }
1215}
1216
1217impl From<bool> for UnpackedValue {
1218    fn from(value: bool) -> Self {
1219        Self::Boolean(value)
1220    }
1221}
1222
1223impl From<bool> for Value {
1224    fn from(value: bool) -> Self {
1225        UnpackedValue::from(value).into_value()
1226    }
1227}
1228
1229// impl_try_from_value_for!(bool, Boolean, "bool");
1230
1231impl_try_from_value_for!(char, Character, "char");
1232impl_try_from_value_for!(Number, Number, "number");
1233impl_try_from_value_for!(WideString, String, "string");
1234impl_try_from_value_for!(Symbol, Symbol, "symbol");
1235impl_try_from_value_for!(Vector, Vector, "vector");
1236impl_try_from_value_for!(ByteVector, ByteVector, "byte-vector");
1237impl_try_from_value_for!(Gc<Syntax>, Syntax, "syntax");
1238impl_try_from_value_for!(Procedure, Procedure, "procedure");
1239impl_try_from_value_for!(Pair, Pair, "pair");
1240impl_try_from_value_for!(Record, Record, "record");
1241impl_try_from_value_for!(Port, Port, "port");
1242impl_try_from_value_for!(HashTable, HashTable, "hashtable");
1243impl_try_from_value_for!(Arc<RecordTypeDescriptor>, RecordTypeDescriptor, "rt");
1244
1245macro_rules! impl_from_wrapped_for {
1246    ($ty:ty, $variant:ident, $wrapper:expr_2021) => {
1247        impl From<$ty> for UnpackedValue {
1248            fn from(v: $ty) -> Self {
1249                Self::$variant(($wrapper)(v))
1250            }
1251        }
1252
1253        impl From<$ty> for Value {
1254            fn from(v: $ty) -> Self {
1255                UnpackedValue::from(v).into_value()
1256            }
1257        }
1258    };
1259}
1260
1261impl_from_wrapped_for!(String, String, WideString::immutable);
1262impl_from_wrapped_for!(Vec<Value>, Vector, Vector::immutable);
1263impl_from_wrapped_for!(Vec<u8>, ByteVector, ByteVector::immutable);
1264impl_from_wrapped_for!(Syntax, Syntax, Gc::new);
1265impl_from_wrapped_for!((Value, Value), Pair, |(car, cdr)| Pair::immutable(car, cdr));
1266
1267impl From<UnpackedValue> for Option<(Value, Value)> {
1268    fn from(val: UnpackedValue) -> Self {
1269        match val {
1270            UnpackedValue::Pair(pair) => Some(pair.into()),
1271            _ => None,
1272        }
1273    }
1274}
1275
1276impl TryFrom<UnpackedValue> for (Value, Value) {
1277    type Error = Exception;
1278
1279    fn try_from(val: UnpackedValue) -> Result<Self, Self::Error> {
1280        match val {
1281            UnpackedValue::Pair(pair) => Ok(pair.into()),
1282            e => Err(Exception::type_error("pair", e.type_name())),
1283        }
1284    }
1285}
1286
1287macro_rules! impl_num_conversion {
1288    ($ty:ty) => {
1289        // TODO: Can we reverse these?
1290        impl TryFrom<&Value> for $ty {
1291            type Error = Exception;
1292
1293            fn try_from(value: &Value) -> Result<$ty, Self::Error> {
1294                match &*value.unpacked_ref() {
1295                    UnpackedValue::Number(num) => num.try_into(),
1296                    e => Err(Exception::type_error("number", e.type_name())),
1297                }
1298            }
1299        }
1300
1301        impl TryFrom<Value> for $ty {
1302            type Error = Exception;
1303
1304            fn try_from(value: Value) -> Result<$ty, Self::Error> {
1305                (&value).try_into()
1306            }
1307        }
1308
1309        impl From<&Value> for Option<$ty> {
1310            fn from(value: &Value) -> Self {
1311                match &*value.unpacked_ref() {
1312                    UnpackedValue::Number(num) => num.into(),
1313                    _ => None,
1314                }
1315            }
1316        }
1317
1318        impl From<Value> for Option<$ty> {
1319            fn from(value: Value) -> Self {
1320                match value.unpack() {
1321                    UnpackedValue::Number(num) => num.into(),
1322                    _ => None,
1323                }
1324            }
1325        }
1326
1327        impl From<$ty> for Value {
1328            fn from(n: $ty) -> Self {
1329                Self::from(Number::from(n))
1330            }
1331        }
1332    };
1333}
1334
1335impl_num_conversion!(u8);
1336impl_num_conversion!(u16);
1337impl_num_conversion!(u32);
1338impl_num_conversion!(u64);
1339impl_num_conversion!(u128);
1340impl_num_conversion!(usize);
1341impl_num_conversion!(i8);
1342impl_num_conversion!(i16);
1343impl_num_conversion!(i32);
1344impl_num_conversion!(i64);
1345impl_num_conversion!(i128);
1346impl_num_conversion!(isize);
1347impl_num_conversion!(f64);
1348impl_num_conversion!(Integer);
1349impl_num_conversion!(SimpleNumber);
1350impl_num_conversion!(ComplexNumber);
1351
1352impl From<&Value> for Option<Identifier> {
1353    fn from(value: &Value) -> Self {
1354        match &*value.unpacked_ref() {
1355            UnpackedValue::Syntax(syn) => match syn.as_ref() {
1356                Syntax::Identifier { ident, .. } => Some(ident.clone()),
1357                _ => None,
1358            },
1359            _ => None,
1360        }
1361    }
1362}
1363
1364impl TryFrom<&Value> for Identifier {
1365    type Error = Exception;
1366
1367    fn try_from(value: &Value) -> Result<Self, Self::Error> {
1368        match Option::<Identifier>::from(value) {
1369            Some(ident) => Ok(ident),
1370            None => Err(Exception::type_error("identifier", value.type_name())),
1371        }
1372    }
1373}
1374
1375impl From<Value> for Option<(Value, Value)> {
1376    fn from(value: Value) -> Self {
1377        value.unpack().into()
1378    }
1379}
1380
1381impl From<&Value> for Option<(Value, Value)> {
1382    fn from(value: &Value) -> Self {
1383        value.clone().unpack().into()
1384    }
1385}
1386
1387impl TryFrom<Value> for (Value, Value) {
1388    type Error = Exception;
1389
1390    fn try_from(val: Value) -> Result<Self, Self::Error> {
1391        Self::try_from(val.unpack())
1392    }
1393}
1394
1395impl TryFrom<&Value> for (Value, Value) {
1396    type Error = Exception;
1397
1398    fn try_from(val: &Value) -> Result<Self, Self::Error> {
1399        Self::try_from(val.clone().unpack())
1400    }
1401}
1402
1403impl TryFrom<Value> for String {
1404    type Error = Exception;
1405
1406    fn try_from(value: Value) -> Result<Self, Self::Error> {
1407        let string: WideString = value.try_into()?;
1408        Ok(string.into())
1409    }
1410}
1411
1412/// Trait for converting vecs of values into arrays
1413pub trait ExpectN<T> {
1414    fn expect_n<const N: usize>(self) -> Result<[T; N], Exception>;
1415}
1416
1417impl<T> ExpectN<T> for Vec<Value>
1418where
1419    Value: TryInto<T>,
1420    Exception: From<<Value as TryInto<T>>::Error>,
1421{
1422    fn expect_n<const N: usize>(self) -> Result<[T; N], Exception> {
1423        if self.len() != N {
1424            return Err(Exception::error("wrong number of values"));
1425        }
1426        // Safety: we've already determined that self is the correct size, so we
1427        // can safely use unwrap_unchecked
1428        Ok(unsafe {
1429            self.into_iter()
1430                .map(Value::try_into)
1431                .collect::<Result<Vec<_>, _>>()?
1432                .try_into()
1433                .unwrap_unchecked()
1434        })
1435    }
1436}
1437
1438/// Trait for converting vecs of values into one type
1439pub trait Expect1<T> {
1440    fn expect1(self) -> Result<T, Exception>;
1441}
1442
1443impl<T> Expect1<T> for Vec<Value>
1444where
1445    Value: TryInto<T>,
1446    Exception: From<<Value as TryInto<T>>::Error>,
1447{
1448    fn expect1(self) -> Result<T, Exception> {
1449        let [val] = self
1450            .try_into()
1451            .map_err(|_| Exception::error("wrong number of values"))?;
1452        val.try_into().map_err(Exception::from)
1453    }
1454}
1455
1456/// Determines which children of the given list are circular, i.e. have children
1457/// that refer to back to them. This is just a depth-first search.
1458fn determine_circularity(
1459    curr: &Value,
1460    visited: &mut IndexSet<Value>,
1461    circular: &mut IndexSet<Value>,
1462) {
1463    if visited.contains(curr) {
1464        circular.insert(curr.clone());
1465        return;
1466    }
1467
1468    visited.insert(curr.clone());
1469
1470    match curr.clone().unpack() {
1471        UnpackedValue::Pair(pair) => {
1472            let (car, cdr) = pair.into();
1473            determine_circularity(&car, visited, circular);
1474            determine_circularity(&cdr, visited, circular);
1475        }
1476        UnpackedValue::Vector(vec) => {
1477            let vec_read = vec.0.vec.read();
1478            for item in vec_read.iter() {
1479                determine_circularity(item, visited, circular);
1480            }
1481        }
1482        _ => (),
1483    }
1484
1485    visited.swap_remove(curr);
1486}
1487
1488pub(crate) fn write_value(
1489    val: &Value,
1490    fmt: fn(&Value, &mut IndexMap<Value, bool>, &mut fmt::Formatter<'_>) -> fmt::Result,
1491    circular_values: &mut IndexMap<Value, bool>,
1492    f: &mut fmt::Formatter<'_>,
1493) -> fmt::Result {
1494    if let Some((idx, _, seen)) = circular_values.get_full_mut(val) {
1495        if *seen {
1496            write!(f, "#{idx}#")?;
1497            return Ok(());
1498        } else {
1499            write!(f, "#{idx}=")?;
1500            *seen = true;
1501        }
1502    }
1503
1504    fmt(val, circular_values, f)
1505}
1506
1507fn display_value(
1508    val: &Value,
1509    circular_values: &mut IndexMap<Value, bool>,
1510    f: &mut fmt::Formatter<'_>,
1511) -> fmt::Result {
1512    match val.clone().unpack() {
1513        UnpackedValue::Undefined => write!(f, "<undefined>"),
1514        UnpackedValue::Null => write!(f, "()"),
1515        UnpackedValue::Boolean(true) => write!(f, "#t"),
1516        UnpackedValue::Boolean(false) => write!(f, "#f"),
1517        UnpackedValue::Number(number) => write!(f, "{number}"),
1518        UnpackedValue::Character(c) => write!(f, "#\\{c}"),
1519        UnpackedValue::String(string) => write!(f, "{string}"),
1520        UnpackedValue::Symbol(symbol) => write!(f, "{symbol}"),
1521        UnpackedValue::Pair(pair) => {
1522            let (car, cdr) = pair.into();
1523            lists::write_list(&car, &cdr, display_value, circular_values, f)
1524        }
1525        UnpackedValue::Vector(v) => vectors::write_vec(&v, display_value, circular_values, f),
1526        UnpackedValue::ByteVector(v) => vectors::write_bytevec(&v, f),
1527        UnpackedValue::Procedure(_) => write!(f, "<procedure>"),
1528        UnpackedValue::Record(record) => write!(f, "{record:?}"),
1529        UnpackedValue::Syntax(syntax) => write!(f, "#<syntax {syntax:#?}>"),
1530        UnpackedValue::RecordTypeDescriptor(rtd) => write!(f, "{rtd:?}"),
1531        UnpackedValue::Port(_) => write!(f, "<port>"),
1532        UnpackedValue::HashTable(hashtable) => write!(f, "{hashtable:?}"),
1533        UnpackedValue::Cell(cell) => display_value(&cell.0.read(), circular_values, f),
1534    }
1535}
1536
1537fn debug_value(
1538    val: &Value,
1539    circular_values: &mut IndexMap<Value, bool>,
1540    f: &mut fmt::Formatter<'_>,
1541) -> fmt::Result {
1542    match val.clone().unpack() {
1543        UnpackedValue::Undefined => write!(f, "<undefined>"),
1544        UnpackedValue::Null => write!(f, "()"),
1545        UnpackedValue::Boolean(true) => write!(f, "#t"),
1546        UnpackedValue::Boolean(false) => write!(f, "#f"),
1547        UnpackedValue::Number(number) => write!(f, "{number}"),
1548        UnpackedValue::Character(c) => write!(f, "#\\{c}"),
1549        UnpackedValue::String(string) => write!(f, "{string:?}"),
1550        UnpackedValue::Symbol(symbol) => write!(f, "{symbol}"),
1551        UnpackedValue::Pair(pair) => {
1552            let (car, cdr) = pair.into();
1553            lists::write_list(&car, &cdr, debug_value, circular_values, f)
1554        }
1555        UnpackedValue::Vector(v) => vectors::write_vec(&v, debug_value, circular_values, f),
1556        UnpackedValue::ByteVector(v) => vectors::write_bytevec(&v, f),
1557        UnpackedValue::Syntax(syntax) => {
1558            let span = syntax.span();
1559            write!(f, "#<syntax:{span} {syntax:#?}>")
1560        }
1561        UnpackedValue::Procedure(proc) => write!(f, "#<procedure {proc:?}>"),
1562        UnpackedValue::Record(record) => write!(f, "{record:#?}"),
1563        UnpackedValue::RecordTypeDescriptor(rtd) => write!(f, "{rtd:?}"),
1564        UnpackedValue::Port(_) => write!(f, "<port>"),
1565        UnpackedValue::HashTable(hashtable) => write!(f, "{hashtable:?}"),
1566        UnpackedValue::Cell(cell) => debug_value(&cell.0.read(), circular_values, f),
1567    }
1568}
1569#[bridge(name = "not", lib = "(rnrs base builtins (6))")]
1570pub fn not(a: &Value) -> Result<Vec<Value>, Exception> {
1571    Ok(vec![Value::from(a.0 as usize == Tag::Boolean as usize)])
1572}
1573
1574#[bridge(name = "eqv?", lib = "(rnrs base builtins (6))")]
1575pub fn eqv(a: &Value, b: &Value) -> Result<Vec<Value>, Exception> {
1576    Ok(vec![Value::from(a.eqv(b))])
1577}
1578
1579#[bridge(name = "eq?", lib = "(rnrs base builtins (6))")]
1580pub fn eq(a: &Value, b: &Value) -> Result<Vec<Value>, Exception> {
1581    Ok(vec![Value::from(a.eqv(b))])
1582}
1583
1584#[bridge(name = "equal?", lib = "(rnrs base builtins (6))")]
1585pub fn equal_pred(a: &Value, b: &Value) -> Result<Vec<Value>, Exception> {
1586    Ok(vec![Value::from(a.equal(b))])
1587}
1588
1589#[bridge(name = "boolean?", lib = "(rnrs base builtins (6))")]
1590pub fn boolean_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1591    Ok(vec![Value::from(arg.type_of() == ValueType::Boolean)])
1592}
1593
1594#[bridge(name = "boolean=?", lib = "(rnrs base builtins (6))")]
1595pub fn boolean_eq_pred(a: &Value, args: &[Value]) -> Result<Vec<Value>, Exception> {
1596    let res = if a.type_of() == ValueType::Boolean {
1597        args.iter().all(|arg| arg == a)
1598    } else {
1599        false
1600    };
1601    Ok(vec![Value::from(res)])
1602}
1603
1604#[bridge(name = "symbol?", lib = "(rnrs base builtins (6))")]
1605pub fn symbol_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1606    Ok(vec![Value::from(arg.type_of() == ValueType::Symbol)])
1607}
1608
1609#[bridge(name = "char?", lib = "(rnrs base builtins (6))")]
1610pub fn char_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1611    Ok(vec![Value::from(arg.type_of() == ValueType::Character)])
1612}
1613
1614#[bridge(name = "vector?", lib = "(rnrs base builtins (6))")]
1615pub fn vector_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1616    Ok(vec![Value::from(arg.type_of() == ValueType::Vector)])
1617}
1618
1619#[bridge(name = "null?", lib = "(rnrs base builtins (6))")]
1620pub fn null_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1621    Ok(vec![Value::from(arg.type_of() == ValueType::Null)])
1622}
1623
1624#[bridge(name = "pair?", lib = "(rnrs base builtins (6))")]
1625pub fn pair_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1626    Ok(vec![Value::from(matches!(
1627        *arg.unpacked_ref(),
1628        UnpackedValue::Pair(_)
1629    ))])
1630}
1631
1632#[bridge(name = "procedure?", lib = "(rnrs base builtins (6))")]
1633pub fn procedure_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
1634    Ok(vec![Value::from(arg.type_of() == ValueType::Procedure)])
1635}