2020-05-14 17:10:53 -04:00
|
|
|
use crate::{
|
|
|
|
|
mem::ptr::{DynRef, ObjCell},
|
|
|
|
|
obj::prelude::*,
|
|
|
|
|
};
|
|
|
|
|
use std::{
|
|
|
|
|
cell::Cell,
|
2020-05-15 11:33:53 -04:00
|
|
|
collections::BTreeMap,
|
2020-05-14 17:10:53 -04:00
|
|
|
mem::MaybeUninit,
|
|
|
|
|
ptr::{self, NonNull},
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-15 11:33:53 -04:00
|
|
|
pub type AttrsMap = BTreeMap<Sym, DynRef>;
|
|
|
|
|
|
2020-05-14 17:10:53 -04:00
|
|
|
pub struct Attrs {
|
2020-05-15 11:33:53 -04:00
|
|
|
attrs: AttrsMap,
|
2020-05-14 17:10:53 -04:00
|
|
|
marked: Cell<bool>,
|
|
|
|
|
this: ObjRef<Attrs>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Attrs {
|
2020-05-15 11:33:53 -04:00
|
|
|
pub fn new(ctx: &mut ObjCtx, attrs: BTreeMap<Sym, DynRef>) -> ObjRef<Self> {
|
2020-05-14 17:10:53 -04:00
|
|
|
let obj: Box<ObjCell<Attrs>> = unsafe {
|
|
|
|
|
let mut obj: Box<MaybeUninit<ObjCell<Attrs>>> = Box::new_uninit();
|
|
|
|
|
// maybe UB? taking away the uninit right before it's initialized may be bad
|
|
|
|
|
let this = &*obj as *const _ as *const ObjCell<Attrs>;
|
|
|
|
|
|
|
|
|
|
obj.as_mut_ptr().write(ObjCell::new(Attrs {
|
|
|
|
|
attrs: Default::default(),
|
|
|
|
|
marked: Cell::new(false),
|
|
|
|
|
this: ObjRef::new(NonNull::new(this as *mut _).unwrap()),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
obj.assume_init()
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-15 11:33:53 -04:00
|
|
|
let obj_ref = {
|
2020-05-14 17:10:53 -04:00
|
|
|
let obj_ref: &Attrs = &obj.borrow();
|
|
|
|
|
assert!(
|
|
|
|
|
ptr::eq(&*obj as *const _, obj_ref.this.as_ptr()),
|
|
|
|
|
"Attr 'this' member does not point to itself"
|
|
|
|
|
);
|
2020-05-15 11:33:53 -04:00
|
|
|
obj_ref.this
|
2020-05-14 17:10:53 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Add the object to the allocator pool
|
|
|
|
|
ctx.gc_mut().add_obj(obj);
|
2020-05-15 11:33:53 -04:00
|
|
|
obj_ref
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn insert(&mut self, sym: Sym, value: DynRef) -> Option<DynRef> {
|
|
|
|
|
self.attrs.insert(sym, value)
|
|
|
|
|
}
|
2020-05-14 17:10:53 -04:00
|
|
|
|
2020-05-15 11:33:53 -04:00
|
|
|
pub fn get(&self, sym: Sym) -> Option<DynRef> {
|
|
|
|
|
dbg!(&self.attrs);
|
|
|
|
|
self.attrs.get(&dbg!(sym)).copied()
|
2020-05-14 17:10:53 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Obj for Attrs {
|
|
|
|
|
fn attrs(&self) -> ObjRef<Attrs> {
|
|
|
|
|
self.this
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_marked(&self) -> bool {
|
|
|
|
|
self.marked.get()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mark(&self) {
|
|
|
|
|
if self.is_marked() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
self.marked.set(true);
|
|
|
|
|
self.attrs.iter().for_each(|(_, v)| v.borrow().mark());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn unmark(&self) {
|
|
|
|
|
if !self.is_marked() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
self.marked.set(false);
|
|
|
|
|
self.attrs.iter().for_each(|(_, v)| v.borrow().unmark());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-15 11:33:53 -04:00
|
|
|
pub struct AttrsBuilder<'ctx> {
|
|
|
|
|
ctx: &'ctx mut ObjCtx,
|
|
|
|
|
attrs: AttrsMap,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'ctx> AttrsBuilder<'ctx> {
|
|
|
|
|
pub fn new(ctx: &'ctx mut ObjCtx) -> Self {
|
|
|
|
|
Self::with_base(ctx, Default::default())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_base(ctx: &'ctx mut ObjCtx, attrs: AttrsMap) -> Self {
|
|
|
|
|
AttrsBuilder {
|
|
|
|
|
attrs,
|
|
|
|
|
ctx,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn attr(mut self, symbol_name: &str, value: DynRef) -> Self {
|
|
|
|
|
let sym = self.ctx.gc_mut().add_sym(symbol_name);
|
|
|
|
|
self.attr_sym(sym, value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn attr_sym(mut self, sym: Sym, value: DynRef) -> Self {
|
|
|
|
|
self.attrs.insert(sym, value);
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn finish(self) -> ObjRef<Attrs> {
|
|
|
|
|
let Self { ctx, attrs } = self;
|
|
|
|
|
Attrs::new(ctx, attrs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-14 17:10:53 -04:00
|
|
|
#[test]
|
|
|
|
|
fn test_attrs_new() {
|
2020-05-14 17:17:14 -04:00
|
|
|
use crate::mem::BasicGc;
|
|
|
|
|
|
|
|
|
|
let mut ctx = ObjCtx::new(BasicGc::default());
|
|
|
|
|
|
2020-05-15 11:33:53 -04:00
|
|
|
let attrs_ref = Attrs::new(&mut ctx, Default::default());
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut attrs = attrs_ref.borrow_mut();
|
|
|
|
|
let sym = ctx.gc_mut().add_sym("symbol");
|
|
|
|
|
attrs.insert(sym, attrs_ref.as_dyn());
|
|
|
|
|
|
|
|
|
|
assert!(
|
|
|
|
|
ptr::eq(
|
|
|
|
|
dbg!(attrs.get(sym).unwrap().as_ptr()),
|
|
|
|
|
dbg!(attrs_ref.as_dyn().as_ptr())
|
|
|
|
|
// ^ as_dyn() is important here - this will cause the test to fail
|
|
|
|
|
// otherwise
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
2020-05-14 17:10:53 -04:00
|
|
|
}
|