//! Internal data structures for running the code
use std::ops::{Deref, DerefMut};
use gc_arena::{Collect, Gc};
use magus_vals::PrimitiveData;
/// A Box for [`PrimitiveData`]
pub struct PrimitiveBox {
inner: Box<dyn PrimitiveData>,
}
impl std::fmt::Debug for PrimitiveBox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"#<{}>",
self.inner
.as_debug()
.map(|d| format!("{:?}", d))
.unwrap_or_else(|| format!("primitive {}", self.inner.type_name()))
)
}
}
impl Deref for PrimitiveBox {
type Target = dyn PrimitiveData;
fn deref(&self) -> &Self::Target {
&*self.inner
}
}
impl DerefMut for PrimitiveBox {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.inner
}
}
/// The Value that a VM/interpreter can manipulate
#[derive(Debug, Collect, Clone)]
#[collect(no_drop)]
pub enum Primitive<'gc> {
List(Gc<'gc, ListCons<'gc>>),
Vector(Vec<Gc<'gc, Primitive<'gc>>>),
Bytevector(Vec<u8>),
// TODO allow exact operations on numbers
// For now, it's just integer = exact, and float = inexact
Integer(i64),
Float(f64),
Data(Gc<'gc, PrimitiveBox>),
}
#[derive(Debug, Collect, Clone)]
#[collect(no_drop)]
pub enum ListCons<'gc> {
/// The empty list
Null,
Leaf(Primitive<'gc>),
Cons(Gc<'gc, ListCons<'gc>>, Gc<'gc, ListCons<'gc>>),
}