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

@@ -8,6 +8,7 @@ use crate::{
}; };
use std::{collections::HashMap, ptr::NonNull}; use std::{collections::HashMap, ptr::NonNull};
#[derive(Default)]
pub struct BasicGc { pub struct BasicGc {
objects: Vec<Box<ObjCell<dyn Obj>>>, objects: Vec<Box<ObjCell<dyn Obj>>>,
strs: HashMap<String, ObjRef<Str>>, strs: HashMap<String, ObjRef<Str>>,
@@ -69,3 +70,33 @@ impl Intern for BasicGc {
.or_insert_with(|| len) .or_insert_with(|| len)
} }
} }
// TODO object cloning
// implementing `clone` is difficult without an ObjCtx, since Attrs has a pointer to itself. This
// pointer would need to be updated.
//
// This will probably require a custom `ObjClone` trait to achieve the desired behavior with a ctx
// object
/*
#[test]
fn test_gc_clone() {
use crate::{obj::{attrs::AttrsBuilder, ctx::DefaultGc, Attrs, ObjCtx}};
let mut ctx = ObjCtx::new(DefaultGc::default());
let empty_attrs = Attrs::new(&mut ctx, Default::default());
let empty_sym = ctx.gc_mut().add_sym("empty");
let attrs_source = AttrsBuilder::new(&mut ctx)
.attr_sym(empty_sym, empty_attrs.as_dyn())
.finish();
let attrs_clone = ctx.gc_mut().cloned(attrs_source.borrow());
assert!(!std::ptr::eq(attrs_source.as_ptr(), attrs_clone.as_ptr()));
let empty1 = attrs_source.borrow().get(empty_sym).unwrap();
}
*/

View File

@@ -5,18 +5,14 @@ use crate::{
intern::Intern, intern::Intern,
} }
}; };
use std::ptr::NonNull;
pub trait Gc: Intern { pub trait Gc: Intern {
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O>; fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O>;
fn add_obj<O: Obj + 'static>(&mut self, owned: Box<ObjCell<O>>); fn add_obj<O: Obj + 'static>(&mut self, owned: Box<ObjCell<O>>);
fn mark(&mut self, alive: &[DynRef]) { fn mark(&mut self, alive: &[DynRef]);
for obj in alive.iter() {
obj.borrow_mut().mark();
}
}
fn sweep(&mut self); fn sweep(&mut self);
} }

View File

@@ -4,19 +4,21 @@ use crate::{
}; };
use std::{ use std::{
cell::Cell, cell::Cell,
collections::BTreeMap,
mem::MaybeUninit, mem::MaybeUninit,
ptr::{self, NonNull}, ptr::{self, NonNull},
}; };
#[derive(Clone)] pub type AttrsMap = BTreeMap<Sym, DynRef>;
pub struct Attrs { pub struct Attrs {
attrs: Vec<(Sym, DynRef)>, attrs: AttrsMap,
marked: Cell<bool>, marked: Cell<bool>,
this: ObjRef<Attrs>, this: ObjRef<Attrs>,
} }
impl 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 obj: Box<ObjCell<Attrs>> = unsafe {
let mut obj: Box<MaybeUninit<ObjCell<Attrs>>> = Box::new_uninit(); let mut obj: Box<MaybeUninit<ObjCell<Attrs>>> = Box::new_uninit();
// maybe UB? taking away the uninit right before it's initialized may be bad // maybe UB? taking away the uninit right before it's initialized may be bad
@@ -31,19 +33,27 @@ impl Attrs {
obj.assume_init() obj.assume_init()
}; };
let attrs = { let obj_ref = {
let obj_ref: &Attrs = &obj.borrow(); let obj_ref: &Attrs = &obj.borrow();
assert!( assert!(
ptr::eq(&*obj as *const _, obj_ref.this.as_ptr()), ptr::eq(&*obj as *const _, obj_ref.this.as_ptr()),
"Attr 'this' member does not point to itself" "Attr 'this' member does not point to itself"
); );
obj_ref.clone() obj_ref.this
}; };
// Add the object to the allocator pool // Add the object to the allocator pool
ctx.gc_mut().add_obj(obj); 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] #[test]
fn test_attrs_new() { fn test_attrs_new() {
use crate::mem::BasicGc; use crate::mem::BasicGc;
let mut ctx = ObjCtx::new(BasicGc::default()); 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
),
);
}
} }

View File

@@ -1,4 +1,8 @@
use crate::mem::{gc::Gc, BasicGc}; use crate::{
mem::{gc::Gc, ptr::DynRef, BasicGc},
obj::Sym,
};
use std::collections::BTreeMap;
pub type DefaultGc = BasicGc; pub type DefaultGc = BasicGc;
@@ -7,6 +11,7 @@ where
G: Gc, G: Gc,
{ {
gc: G, gc: G,
globals: BTreeMap<Sym, DynRef>,
} }
impl<G> ObjCtx<G> impl<G> ObjCtx<G>
@@ -14,13 +19,22 @@ where
G: Gc, G: Gc,
{ {
pub fn new(gc: G) -> Self { pub fn new(gc: G) -> Self {
ObjCtx { gc } ObjCtx { gc, globals: Default::default() }
} }
pub fn gc(&self) -> &G { pub fn gc(&self) -> &G {
&self.gc &self.gc
} }
pub fn gc_mut(&mut self) -> &mut G { pub fn gc_mut(&mut self) -> &mut G {
&mut self.gc &mut self.gc
} }
pub fn globals(&self) -> &BTreeMap<Sym, DynRef> {
&self.globals
}
pub fn globals_mut(&mut self) -> &mut BTreeMap<Sym, DynRef> {
&mut self.globals
}
} }

View File

@@ -1,6 +1,6 @@
use crate::obj::prelude::*; use crate::obj::{attrs::AttrsBuilder, prelude::*};
use derivative::Derivative; use derivative::Derivative;
use std::{any::Any, cell::Cell}; use std::{any::Any, cell::Cell, collections::BTreeMap};
pub type StrRef = ObjRef<Str>; pub type StrRef = ObjRef<Str>;
@@ -18,14 +18,17 @@ pub struct Str {
impl Str { impl Str {
pub fn new(ctx: &mut ObjCtx, contents: String) -> Self { pub fn new(ctx: &mut ObjCtx, contents: String) -> Self {
todo!()
/*
Str { Str {
attrs: Default::default(), attrs: Self::type_attrs(ctx),
contents, contents,
marked: Cell::new(false), marked: Cell::new(false),
} }
*/ }
fn type_attrs(ctx: &mut ObjCtx) -> ObjRef<Attrs> {
// TODO need global namespace
// TODO need upcast from dyn to static
todo!()
} }
pub fn contents(&self) -> &String { pub fn contents(&self) -> &String {

View File

@@ -1,9 +1,9 @@
use crate::obj::prelude::*; use crate::obj::{attrs::AttrsBuilder, prelude::*};
use std::cell::Cell; use std::cell::Cell;
pub struct Ty { pub struct Ty {
marked: Cell<bool>, marked: Cell<bool>,
this: ObjRef<Ty>, attrs: ObjRef<Attrs>,
} }
impl Ty { impl Ty {