use std::{
any::TypeId,
ops::{Deref, DerefMut},
rc::Rc,
};
use gc_arena::{Collect, Gc};
use lasso::{Rodeo, Spur};
use magus_vals::PrimitiveData;
pub struct PrimitiveBox {
inner_type: TypeId,
inner: Box<dyn PrimitiveData>,
}
impl std::fmt::Debug for PrimitiveBox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(datum) = self.as_datum() {
_ = datum;
todo!()
} else {
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
}
}
#[derive(Debug, Collect, Clone)]
#[collect(no_drop)]
#[allow(missing_docs)]
pub enum Primitive<'gc> {
List(Gc<'gc, ConsCell<'gc>>),
Vector(Vec<Gc<'gc, Primitive<'gc>>>),
Bytevector(Vec<u8>),
Integer(i64),
Float(f64),
String(Rc<str>),
Symbol(SymbolId),
Bool(bool),
Data(Gc<'gc, PrimitiveBox>),
}
impl<'gc> Primitive<'gc> {
pub fn copy_to_arena<'a>(
&self,
arena: &'a typed_arena::Arena<Primitive<'a>>,
) -> &'a mut FreePrimitive<'a> {
_ = arena;
todo!()
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum FreePrimitive<'a> {
List(FreeConsCell<'a>),
Vector(Vec<FreePrimitive<'a>>),
Bytevector(Vec<u8>),
Integer(i64),
Float(f64),
String(Rc<str>),
Symbol(Rc<str>),
Bool(bool),
Data(Rc<PrimitiveBox>),
}
#[derive(Debug, Clone)]
pub struct FreeConsCell<'a> {
pub car: Option<&'a FreePrimitive<'a>>,
pub cdr: Option<&'a FreePrimitive<'a>>,
}
#[derive(Debug, Collect, Clone)]
#[collect(no_drop)]
pub struct ConsCell<'gc> {
car: Option<Gc<'gc, Primitive<'gc>>>,
cdr: Option<Gc<'gc, Primitive<'gc>>>,
}
impl Default for ConsCell<'_> {
fn default() -> Self {
Self {
car: None,
cdr: None,
}
}
}
impl<'gc> ConsCell<'gc> {
pub fn is_empty_list(&self) -> bool {
self.car.is_none() && self.cdr.is_none()
}
pub fn is_list(&self) -> bool {
self.cdr
.as_ref()
.is_some_and(|cdr| matches!(cdr.as_ref(), Primitive::List(_)))
|| self.cdr.is_none()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Collect)]
#[collect(require_static)]
pub struct SymbolId(Spur);
#[derive(Default)]
pub struct SymbolTable(Rodeo);
impl SymbolTable {
pub fn id<S: AsRef<str>>(&self, source: S) -> Option<SymbolId> {
self.0.get(source).map(SymbolId)
}
pub fn id_mut<S: AsRef<str>>(&mut self, source: S) -> SymbolId {
SymbolId(self.0.get_or_intern(source))
}
pub fn symbol(&self, id: SymbolId) -> Option<&str> {
self.0.try_resolve(&id.0)
}
}