Add AttrsBuidler, change Attrs struct around some
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -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();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
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;
|
||||||
|
|
||||||
pub struct ObjCtx<G=DefaultGc>
|
pub struct ObjCtx<G = DefaultGc>
|
||||||
where
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user