Add AttrsBuidler, change Attrs struct around some

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-05-15 11:33:53 -04:00
parent f3680f29ad
commit a60471f526
6 changed files with 127 additions and 25 deletions

View File

@@ -4,19 +4,21 @@ use crate::{
};
use std::{
cell::Cell,
collections::BTreeMap,
mem::MaybeUninit,
ptr::{self, NonNull},
};
#[derive(Clone)]
pub type AttrsMap = BTreeMap<Sym, DynRef>;
pub struct Attrs {
attrs: Vec<(Sym, DynRef)>,
attrs: AttrsMap,
marked: Cell<bool>,
this: ObjRef<Attrs>,
}
impl Attrs {
pub fn new(ctx: &mut ObjCtx) -> Self {
pub fn new(ctx: &mut ObjCtx, attrs: BTreeMap<Sym, DynRef>) -> ObjRef<Self> {
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
@@ -31,19 +33,27 @@ impl Attrs {
obj.assume_init()
};
let attrs = {
let obj_ref = {
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"
);
obj_ref.clone()
obj_ref.this
};
// Add the object to the allocator pool
ctx.gc_mut().add_obj(obj);
obj_ref
}
attrs
pub fn insert(&mut self, sym: Sym, value: DynRef) -> Option<DynRef> {
self.attrs.insert(sym, value)
}
pub fn get(&self, sym: Sym) -> Option<DynRef> {
dbg!(&self.attrs);
self.attrs.get(&dbg!(sym)).copied()
}
}
@@ -77,11 +87,59 @@ impl Obj for Attrs {
}
}
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)
}
}
#[test]
fn test_attrs_new() {
use crate::mem::BasicGc;
let mut ctx = ObjCtx::new(BasicGc::default());
let attrs = Attrs::new(&mut ctx);
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
),
);
}
}