Add VisitObj and Obj::accept(&self, ..) method
- VisitObj is for visiting object instances and dyn objects (and thus dynamically dispatching accept) - Obj::accept method is used for dispatching to the specific visitor method - GcMark ZST added for visiting/marking living objects Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
compile::{ctx::Ctx, error::*, ir},
|
||||
syn::{ast::*, op::BinOp, span::*},
|
||||
visit::*,
|
||||
syn::ast::*,
|
||||
};
|
||||
|
||||
// basic block
|
||||
@@ -9,8 +8,39 @@ pub enum Block {
|
||||
Body(ir::Body),
|
||||
Blocks(Vec<Block>),
|
||||
}
|
||||
|
||||
/*
|
||||
* Current problem:
|
||||
* Visiting a TranslateAst would generally return the IR directly per-function. However, returning
|
||||
* a different value type per Acceptor would make it impossible to have &dyn Acceptor refs, which
|
||||
* is needed for visitor-based GC.
|
||||
*
|
||||
* Ideas:
|
||||
* - Remove Visit::Out return value, and instead expect that the acceptor implementation to report
|
||||
* anything new to its visitor. Visitors/acceptors that require returning an error should use
|
||||
* TryVisit and TryAccept.
|
||||
* - Doesn't play nicely with something that might want to return something else.
|
||||
* - TranslateAst doesn't necessarily need to be a Visitor, except for the context
|
||||
* - Can we just fake it with TryFrom?
|
||||
* impl TryFrom<(&'_ mut Ctx, ast::Stmt)> for ir::Stmt { ... }
|
||||
*
|
||||
*/
|
||||
|
||||
trait ToIr<I> {
|
||||
fn to_ir(&self, ctx: &mut Ctx) -> Result<I>;
|
||||
}
|
||||
|
||||
trait FromAst<A>: Sized {
|
||||
fn from_ast(other: &A, ctx: &mut Ctx) -> Result<Self>;
|
||||
}
|
||||
|
||||
impl<I, A> FromAst<A> for I
|
||||
where A: ToIr<I>
|
||||
{
|
||||
fn from_ast(other: &A, ctx: &mut Ctx) -> Result<Self> {
|
||||
other.to_ir(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TranslateAst
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -25,27 +55,40 @@ impl<'c, 't> TranslateAst<'c, 't> {
|
||||
TranslateAst { ctx, text }
|
||||
}
|
||||
|
||||
pub fn translate(&mut self, _ast: &Vec<Stmt>) -> Result<Block> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn visit_lhs_expr(&mut self, expr: &Expr) -> Result<ir::Lhs> {
|
||||
match expr {
|
||||
Expr::Bin(b) if b.op == BinOp::Dot => todo!(),
|
||||
Expr::Base(BaseExpr {
|
||||
kind: BaseExprKind::Ident,
|
||||
..
|
||||
}) => {
|
||||
let _name = expr.text_at(self.text);
|
||||
//let name_id = self.ctx.
|
||||
todo!()
|
||||
//Ok(ir::Lhs::Name(
|
||||
}
|
||||
_ => Err(Error::InvalidLhs { span: expr.span() }),
|
||||
pub fn translate(&mut self, ast: &Vec<Stmt>) -> Result<ir::Body> {
|
||||
let mut body = Vec::new();
|
||||
for stmt in ast.iter() {
|
||||
body.push(stmt.to_ir(self.ctx)?);
|
||||
}
|
||||
Ok(body)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIr<ir::Stmt> for Stmt {
|
||||
fn to_ir(&self, _ctx: &mut Ctx) -> Result<ir::Stmt> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIr<ir::Stmt> for AssignStmt {
|
||||
fn to_ir(&self, _ctx: &mut Ctx) -> Result<ir::Stmt> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIr<ir::Expr> for Expr {
|
||||
fn to_ir(&self, _ctx: &mut Ctx) -> Result<ir::Expr> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToIr<ir::Lhs> for Expr {
|
||||
fn to_ir(&self, _ctx: &mut Ctx) -> Result<ir::Lhs> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl Visit<Stmt> for TranslateAst<'_, '_> {
|
||||
type Out = Result<ir::Stmt>;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
#![feature(unsize, coerce_unsized, new_uninit)]
|
||||
#![feature(unsize, coerce_unsized, new_uninit, box_into_pin)]
|
||||
|
||||
#[macro_use] mod visit;
|
||||
mod compile;
|
||||
|
||||
@@ -2,31 +2,20 @@ use crate::{
|
||||
mem::{gc::Gc, ptr::ObjCell},
|
||||
obj::prelude::*,
|
||||
};
|
||||
use std::ptr::NonNull;
|
||||
use std::pin::Pin;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct BasicGc {
|
||||
objects: Vec<Box<ObjCell<dyn Obj>>>,
|
||||
objects: Vec<Pin<Box<ObjCell<dyn Obj>>>>,
|
||||
}
|
||||
|
||||
impl Gc for BasicGc {
|
||||
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O> {
|
||||
let obj_cell = Box::new(ObjCell::new(obj));
|
||||
let obj_ptr = &*obj_cell as *const _ as *mut _;
|
||||
self.objects.push(obj_cell);
|
||||
ObjRef::new(NonNull::new(obj_ptr).unwrap())
|
||||
}
|
||||
|
||||
fn add_obj(&mut self, owned: Box<ObjCell<dyn Obj>>) {
|
||||
fn add_obj(&mut self, owned: Pin<Box<ObjCell<dyn Obj>>>) {
|
||||
self.objects.push(owned);
|
||||
}
|
||||
|
||||
fn mark(&mut self, _alive: &[DynRef]) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn sweep(&mut self) {
|
||||
todo!()
|
||||
self.objects.retain(|cell| cell.is_marked())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,56 @@
|
||||
use crate::{mem::ptr::ObjCell, obj::prelude::*, visit::{Accept, Visit},};
|
||||
use crate::{mem::ptr::ObjCell, obj::prelude::*};
|
||||
use std::pin::Pin;
|
||||
|
||||
pub trait Gc {
|
||||
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O>;
|
||||
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O> {
|
||||
let obj_cell = Box::pin(ObjCell::new(obj));
|
||||
let obj_ptr = &*obj_cell as *const _ as *mut _;
|
||||
self.add_obj(obj_cell);
|
||||
ObjRef::new(std::ptr::NonNull::new(obj_ptr).unwrap())
|
||||
}
|
||||
|
||||
fn add_obj(&mut self, owned: Box<ObjCell<dyn Obj>>);
|
||||
fn add_obj(&mut self, owned: Pin<Box<ObjCell<dyn Obj>>>);
|
||||
|
||||
fn mark(&mut self, alive: &[DynRef]);
|
||||
fn mark(&mut self, alive: &[DynRef]) {
|
||||
alive.iter()
|
||||
.copied()
|
||||
.for_each(|obj| GcMark.visit(obj));
|
||||
}
|
||||
|
||||
fn sweep(&mut self);
|
||||
}
|
||||
|
||||
pub struct GcMark;
|
||||
|
||||
impl VisitObj for GcMark {
|
||||
fn visit(&mut self, obj: DynRef) {
|
||||
if obj.is_marked() {
|
||||
return;
|
||||
}
|
||||
obj.set_marked(true);
|
||||
obj.borrow().accept(self)
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, attrs: &Attrs) {
|
||||
attrs.inner()
|
||||
.values()
|
||||
.copied()
|
||||
.for_each(|obj| {
|
||||
self.visit(obj);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_dict(&mut self, d: &Dict) {
|
||||
d.dict()
|
||||
.iter()
|
||||
.for_each(|(k, v)| {
|
||||
self.visit(*k);
|
||||
self.visit(*v);
|
||||
});
|
||||
self.visit(d.attrs());
|
||||
}
|
||||
|
||||
fn visit_str(&mut self, s: &Str) {
|
||||
self.visit(s.attrs())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::obj::Obj;
|
||||
use std::{
|
||||
any,
|
||||
cell::RefCell,
|
||||
cell::{Cell, RefCell},
|
||||
fmt::{self, Debug, Formatter},
|
||||
marker::Unsize,
|
||||
ops::{CoerceUnsized, Deref},
|
||||
@@ -51,7 +51,7 @@ impl<O> Deref for ObjRef<O>
|
||||
where
|
||||
O: Obj + ?Sized,
|
||||
{
|
||||
type Target = RefCell<O>;
|
||||
type Target = ObjCell<O>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// Safe, so long as there are no dangling pointers from the GC
|
||||
@@ -140,22 +140,34 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ObjCell
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ObjCell<O: Obj + ?Sized> {
|
||||
marked: Cell<bool>,
|
||||
cell: RefCell<O>,
|
||||
}
|
||||
|
||||
impl<O: Obj> ObjCell<O> {
|
||||
pub fn new(obj: O) -> Self {
|
||||
ObjCell {
|
||||
marked: Cell::new(false),
|
||||
cell: RefCell::new(obj),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Obj + ?Sized> ObjCell<O> {
|
||||
pub fn is_marked(&self) -> bool {
|
||||
self.marked.get()
|
||||
}
|
||||
|
||||
pub fn set_marked(&self, marked: bool) {
|
||||
self.marked.set(marked);
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Obj + ?Sized> Deref for ObjCell<O> {
|
||||
type Target = RefCell<O>;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
mem::ptr::{DynRef, ObjCell},
|
||||
obj::prelude::*,
|
||||
visit::Visit,
|
||||
};
|
||||
use std::{
|
||||
cell::Cell,
|
||||
@@ -42,10 +41,14 @@ impl Attrs {
|
||||
};
|
||||
|
||||
// Add the object to the allocator pool
|
||||
gc.add_obj(obj);
|
||||
gc.add_obj(Box::into_pin(obj));
|
||||
obj_ref
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Ss {
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, sym: Sym, value: DynRef) -> Option<DynRef> {
|
||||
self.attrs.insert(sym, value)
|
||||
}
|
||||
@@ -64,17 +67,8 @@ impl Obj for Attrs {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl_accept!(Attrs);
|
||||
|
||||
impl<G: Gc> Visit<Attrs> for G {
|
||||
type Out = ();
|
||||
|
||||
fn visit(&mut self, attrs: &Attrs) -> Self::Out {
|
||||
attrs.attrs.values()
|
||||
.for_each(|obj| obj.accept(self));
|
||||
fn accept(&self, visitor: &mut dyn VisitObj) {
|
||||
visitor.visit_attrs(self);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use crate::{obj::prelude::*, visit::Visit};
|
||||
use std::{any::Any, cell::Cell};
|
||||
use crate::obj::prelude::*;
|
||||
use std::any::Any;
|
||||
|
||||
pub type DictRef = ObjRef<Dict>;
|
||||
|
||||
pub struct Dict {
|
||||
dict: Vec<(DynRef, DynRef)>,
|
||||
attrs: ObjRef<Attrs>,
|
||||
marked: Cell<bool>,
|
||||
}
|
||||
|
||||
impl Dict {
|
||||
@@ -14,9 +13,16 @@ impl Dict {
|
||||
Dict {
|
||||
dict: Default::default(),
|
||||
attrs,
|
||||
marked: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dict(&self) -> &Vec<(DynRef, DynRef)> {
|
||||
&self.dict
|
||||
}
|
||||
|
||||
pub fn dict_mut(&mut self) -> &mut Vec<(DynRef, DynRef)> {
|
||||
&mut self.dict
|
||||
}
|
||||
}
|
||||
|
||||
impl Obj for Dict {
|
||||
@@ -27,4 +33,8 @@ impl Obj for Dict {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn accept(&self, visitor: &mut dyn VisitObj) {
|
||||
visitor.visit_dict(self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ impl Obj for NativeFun {
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn accept(&self, _: &mut dyn VisitObj) {
|
||||
todo!("visit NativeFun");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Fun {
|
||||
@@ -57,4 +61,8 @@ impl Obj for Fun {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn accept(&self, _: &mut dyn VisitObj) {
|
||||
todo!("visit Fun");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ pub mod ns {
|
||||
}
|
||||
pub mod str;
|
||||
pub mod sym;
|
||||
pub mod visit;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{
|
||||
@@ -30,7 +31,7 @@ pub mod prelude {
|
||||
},
|
||||
obj::{
|
||||
Attrs, AttrsRef, Dict, DictRef, Fun, NameId, NativeFun, Ns, Obj, ObjCtx, Ss, Str,
|
||||
StrRef, Sym,
|
||||
StrRef, Sym, VisitObj,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -44,13 +45,14 @@ pub use self::{
|
||||
ns::{Ns, Ss},
|
||||
str::{Str, StrRef},
|
||||
sym::Sym,
|
||||
visit::VisitObj,
|
||||
};
|
||||
use crate::mem::ptr::ObjRef;
|
||||
use crate::visit::*;
|
||||
use std::any::Any;
|
||||
|
||||
pub trait Obj {
|
||||
fn attrs(&self) -> ObjRef<Attrs>;
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
fn accept(&self, visitor: &mut dyn VisitObj);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{obj::prelude::*, visit::Visit};
|
||||
use crate::obj::prelude::*;
|
||||
use derivative::Derivative;
|
||||
use std::{any::Any, cell::Cell};
|
||||
use std::any::Any;
|
||||
|
||||
pub type StrRef = ObjRef<Str>;
|
||||
|
||||
@@ -11,18 +11,11 @@ pub struct Str {
|
||||
attrs: AttrsRef,
|
||||
|
||||
contents: String,
|
||||
|
||||
#[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
|
||||
marked: Cell<bool>,
|
||||
}
|
||||
|
||||
impl Str {
|
||||
pub fn new<G: Gc>(attrs: AttrsRef, contents: String) -> Self {
|
||||
Str {
|
||||
attrs,
|
||||
contents,
|
||||
marked: Cell::new(false),
|
||||
}
|
||||
Str { attrs, contents }
|
||||
}
|
||||
|
||||
pub fn contents(&self) -> &String {
|
||||
@@ -38,4 +31,8 @@ impl Obj for Str {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn accept(&self, visitor: &mut dyn VisitObj) {
|
||||
visitor.visit_str(self);
|
||||
}
|
||||
}
|
||||
|
||||
14
src/obj/visit.rs
Normal file
14
src/obj/visit.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use crate::obj::prelude::*;
|
||||
|
||||
pub trait VisitObj {
|
||||
fn visit(&mut self, obj: DynRef) where Self: Sized {
|
||||
obj.borrow().accept(self)
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, attrs: &Attrs);
|
||||
|
||||
fn visit_str(&mut self, s: &Str);
|
||||
|
||||
fn visit_dict(&mut self, d: &Dict);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user