diff --git a/src/mem/basic.rs b/src/mem/basic.rs index 1a616de..1db4857 100644 --- a/src/mem/basic.rs +++ b/src/mem/basic.rs @@ -21,23 +21,12 @@ impl Gc for BasicGc { self.objects.push(owned); } - fn mark(&mut self, alive: &[DynRef]) { - for obj in alive.iter() { - obj.borrow().mark(); - } - // TODO : where should interned strings be marked? + fn mark(&mut self, _alive: &[DynRef]) { + todo!() } fn sweep(&mut self) { - // sweep - self.objects.retain(|cell| { - let obj = cell.borrow(); - !obj.is_marked() - }); - // unmark all objects - self.objects - .iter_mut() - .for_each(|cell| cell.borrow().unmark()); + todo!() } } diff --git a/src/mem/gc.rs b/src/mem/gc.rs index 866e09e..4ba5e59 100644 --- a/src/mem/gc.rs +++ b/src/mem/gc.rs @@ -1,4 +1,4 @@ -use crate::{mem::ptr::ObjCell, obj::prelude::*}; +use crate::{mem::ptr::ObjCell, obj::prelude::*, visit::{Accept, Visit},}; pub trait Gc { fn alloc(&mut self, obj: O) -> ObjRef; @@ -9,3 +9,12 @@ pub trait Gc { fn sweep(&mut self); } + +impl Visit for O + where O: Obj + Accept +{ + type Out = (); + fn visit(&mut self, obj: &O) -> Self::Out { + obj.accept(self) + } +} diff --git a/src/mem/ptr.rs b/src/mem/ptr.rs index aa25436..2441c2c 100644 --- a/src/mem/ptr.rs +++ b/src/mem/ptr.rs @@ -1,4 +1,4 @@ -use crate::obj::Obj; +use crate::{obj::Obj, visit::{DynAccept, Accept, Visit}}; use std::{ any, cell::RefCell, @@ -30,13 +30,6 @@ where } } -impl AsRef> for ObjRef { - fn as_ref(&self) -> &ObjCell { - // safe because pointer should point at live data assuming GC is working appropriately - unsafe { &*self.as_ptr() } - } -} - impl ObjRef where O: Obj, @@ -47,6 +40,13 @@ where } } +impl AsRef> for ObjRef { + fn as_ref(&self) -> &ObjCell { + // safe because pointer should point at live data assuming GC is working appropriately + unsafe { &*self.as_ptr() } + } +} + impl Deref for ObjRef where O: Obj + ?Sized, @@ -94,6 +94,14 @@ impl Debug for ObjRef { } } +impl DynAccept for ObjRef + where O: Obj + ?Sized + DynAccept +{ + fn accept(&self, visitor: &mut impl Visit) { + todo!() + } +} + // // Comparison impls // diff --git a/src/obj/attrs.rs b/src/obj/attrs.rs index 68950b9..8825910 100644 --- a/src/obj/attrs.rs +++ b/src/obj/attrs.rs @@ -1,6 +1,7 @@ use crate::{ mem::ptr::{DynRef, ObjCell}, obj::prelude::*, + visit::Visit, }; use std::{ cell::Cell, @@ -60,48 +61,17 @@ impl Obj for 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 } } -#[test] -fn test_attrs_new() { - use crate::mem::BasicGc; +//impl_accept!(Attrs); - let mut gc = BasicGc::default(); +impl Visit for G { + type Out = (); - let attrs_ref = Attrs::new(&mut gc, Default::default()); - - { - let mut attrs = attrs_ref.borrow_mut(); - let sym = Sym::new(0); - 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 - ),); + fn visit(&mut self, _attrs: &Attrs) -> Self::Out { + todo!() } } diff --git a/src/obj/dict.rs b/src/obj/dict.rs index 74e8178..ecb6052 100644 --- a/src/obj/dict.rs +++ b/src/obj/dict.rs @@ -1,4 +1,4 @@ -use crate::obj::prelude::*; +use crate::{obj::prelude::*, visit::Visit}; use std::{any::Any, cell::Cell}; pub type DictRef = ObjRef; @@ -24,31 +24,20 @@ impl Obj for Dict { self.attrs } - fn is_marked(&self) -> bool { - self.marked.get() - } - - fn mark(&self) { - if self.is_marked() { - return; - } - self.marked.set(true); - // TODO: dict - self.attrs.borrow().mark(); - todo!() - } - - fn unmark(&self) { - if !self.is_marked() { - return; - } - self.marked.set(false); - // TODO: dict - self.attrs.borrow().unmark(); - todo!() - } - fn as_any(&self) -> &dyn Any { self } } + +//impl_accept!(Dict); + +impl Visit for G + where G: Gc + Visit, +{ + type Out = (); + + fn visit(&mut self, dict: &Dict) -> Self::Out { + let attrs_ref: &Attrs = &dict.attrs.borrow(); + self.visit(attrs_ref); + } +} diff --git a/src/obj/fun.rs b/src/obj/fun.rs index 274b667..3ebd120 100644 --- a/src/obj/fun.rs +++ b/src/obj/fun.rs @@ -24,15 +24,6 @@ impl Obj for NativeFun { self.attrs } - fn is_marked(&self) -> bool { - // native functions are always available - true - } - - fn mark(&self) {} - - fn unmark(&self) {} - fn as_any(&self) -> &dyn std::any::Any { self } @@ -63,26 +54,6 @@ impl Obj for Fun { self.attrs } - fn is_marked(&self) -> bool { - self.marked.get() - } - - fn mark(&self) { - if self.is_marked() { - return; - } - self.marked.set(true); - self.attrs.borrow().mark(); - } - - fn unmark(&self) { - if !self.is_marked() { - return; - } - self.marked.set(false); - self.attrs.borrow().unmark(); - } - fn as_any(&self) -> &dyn Any { self } diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 65b5ca0..1b018a4 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -50,10 +50,5 @@ use std::any::Any; pub trait Obj { fn attrs(&self) -> ObjRef; - - fn is_marked(&self) -> bool; - fn mark(&self); - fn unmark(&self); - fn as_any(&self) -> &dyn Any; } diff --git a/src/obj/str.rs b/src/obj/str.rs index 9b0979d..c4b2ff5 100644 --- a/src/obj/str.rs +++ b/src/obj/str.rs @@ -1,4 +1,4 @@ -use crate::obj::prelude::*; +use crate::{obj::prelude::*, visit::{DynAccept, Visit}}; use derivative::Derivative; use std::{any::Any, cell::Cell}; @@ -35,27 +35,25 @@ impl Obj for Str { self.attrs } - fn is_marked(&self) -> bool { - self.marked.get() - } - - fn mark(&self) { - if self.is_marked() { - return; - } - self.marked.set(true); - self.attrs.borrow().mark(); - } - - fn unmark(&self) { - if !self.is_marked() { - return; - } - self.marked.set(false); - todo!() - } - fn as_any(&self) -> &dyn Any { self } } + +//impl_accept!(Str); + +impl DynAccept for O + where O: Obj + ?Sized +{ + fn accept(&self, visitor: &mut impl Visit) { + visitor.visit(self) + } +} + +impl Visit for G { + type Out = (); + + fn visit(&mut self, _s: &Str) -> Self::Out { + todo!() + } +} diff --git a/src/syn/ast.rs b/src/syn/ast.rs index 5468f14..8c55d18 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -169,3 +169,39 @@ impl Spanned for BaseExpr { self.span } } + +//////////////////////////////////////////////////////////////////////////////// +// Acceptor (visitor) impls +//////////////////////////////////////////////////////////////////////////////// + +impl_accept!(Stmt); +impl_default_accept!(Stmt : AssignStmt, Expr => + fn default_accept(&self, visitor: &mut V) -> Out { + match self { + Stmt::Assign(a) => visitor.visit(a), + Stmt::Expr(e) => visitor.visit(e), + } + } +); +impl_accept!(AssignStmt); +impl_accept!(Expr); + +impl_default_accept!(Expr: BinExpr, UnExpr, FunCallExpr, IndexExpr, FunExpr, BaseExpr => + fn default_accept(&self, visitor: &mut V) -> Out { + match self { + Expr::Bin(b) => visitor.visit(b.as_ref()), + Expr::Un(u) => visitor.visit(u.as_ref()), + Expr::FunCall(f) => visitor.visit(f.as_ref()), + Expr::Index(i) => visitor.visit(i.as_ref()), + Expr::Fun(f) => visitor.visit(f.as_ref()), + Expr::Base(b) => visitor.visit(b), + } + } +); + +impl_accept!(BinExpr); +impl_accept!(UnExpr); +impl_accept!(FunCallExpr); +impl_accept!(IndexExpr); +impl_accept!(FunExpr); +impl_accept!(BaseExpr); diff --git a/src/visit.rs b/src/visit.rs index a25fe51..68cdd90 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -1,14 +1,14 @@ -use crate::syn::ast::prelude::*; - -pub trait Visit { +pub trait Visit { type Out; fn visit(&mut self, acceptor: &A) -> Self::Out; } pub trait Accept { - fn accept>(&self, visitor: &mut V) -> V::Out - where - Self: Sized; + fn accept>(&self, visitor: &mut V) -> V::Out; +} + +pub trait DynAccept { + fn accept(&self, visitor: &mut impl Visit); } pub trait DefaultAccept>: Accept + Sized { @@ -18,7 +18,7 @@ pub trait DefaultAccept>: Accept + Sized { #[macro_export] macro_rules! default_visitor { ($default:ident for $visitor:ty where Out = $out:ty) => { - impl crate::visit::Visit<$default> for $visitor { + impl $crate::visit::Visit<$default> for $visitor { type Out = $out; fn visit(&mut self, acceptor: &$default) -> Self::Out { acceptor.default_accept(self) @@ -30,61 +30,31 @@ macro_rules! default_visitor { #[macro_export] macro_rules! empty_visitor { ($default:ident for $visitor:ty) => { - impl crate::visit::Visit<$default> for $visitor { + impl $crate::visit::Visit<$default> for $visitor { type Out = (); fn visit(&mut self, _: &$default) -> Self::Out {} } }; } +#[macro_export] macro_rules! impl_accept { - ($what:ident) => { - impl crate::visit::Accept for $what { - fn accept>(&self, visitor: &mut V) -> V::Out { + ($what:ty) => { + impl $crate::visit::Accept for $what { + fn accept>(&self, visitor: &mut V) -> V::Out { visitor.visit(self) } } }; } +#[macro_export] macro_rules! impl_default_accept { ($what:ident : $($requires:ident),+ => $($tail:tt)+) => { - impl DefaultAccept for $what - where V: Visit $(+ Visit<$requires, Out=Out>)+ + impl $crate::visit::DefaultAccept for $what + where V: $crate::visit::Visit $(+ $crate::visit::Visit<$requires, Out=Out>)+ { $($tail)+ } }; } - -impl_accept!(Stmt); -impl_default_accept!(Stmt : AssignStmt, Expr => - fn default_accept(&self, visitor: &mut V) -> Out { - match self { - Stmt::Assign(a) => visitor.visit(a), - Stmt::Expr(e) => visitor.visit(e), - } - } -); -impl_accept!(AssignStmt); -impl_accept!(Expr); - -impl_default_accept!(Expr: BinExpr, UnExpr, FunCallExpr, IndexExpr, FunExpr, BaseExpr => - fn default_accept(&self, visitor: &mut V) -> Out { - match self { - Expr::Bin(b) => visitor.visit(b.as_ref()), - Expr::Un(u) => visitor.visit(u.as_ref()), - Expr::FunCall(f) => visitor.visit(f.as_ref()), - Expr::Index(i) => visitor.visit(i.as_ref()), - Expr::Fun(f) => visitor.visit(f.as_ref()), - Expr::Base(b) => visitor.visit(b), - } - } -); - -impl_accept!(BinExpr); -impl_accept!(UnExpr); -impl_accept!(FunCallExpr); -impl_accept!(IndexExpr); -impl_accept!(FunExpr); -impl_accept!(BaseExpr);