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::{
|
use crate::{
|
||||||
compile::{ctx::Ctx, error::*, ir},
|
compile::{ctx::Ctx, error::*, ir},
|
||||||
syn::{ast::*, op::BinOp, span::*},
|
syn::ast::*,
|
||||||
visit::*,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// basic block
|
// basic block
|
||||||
@@ -9,8 +8,39 @@ pub enum Block {
|
|||||||
Body(ir::Body),
|
Body(ir::Body),
|
||||||
Blocks(Vec<Block>),
|
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
|
// TranslateAst
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -25,27 +55,40 @@ impl<'c, 't> TranslateAst<'c, 't> {
|
|||||||
TranslateAst { ctx, text }
|
TranslateAst { ctx, text }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn translate(&mut self, _ast: &Vec<Stmt>) -> Result<Block> {
|
pub fn translate(&mut self, ast: &Vec<Stmt>) -> Result<ir::Body> {
|
||||||
todo!()
|
let mut body = Vec::new();
|
||||||
}
|
for stmt in ast.iter() {
|
||||||
|
body.push(stmt.to_ir(self.ctx)?);
|
||||||
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() }),
|
|
||||||
}
|
}
|
||||||
|
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<'_, '_> {
|
impl Visit<Stmt> for TranslateAst<'_, '_> {
|
||||||
type Out = Result<ir::Stmt>;
|
type Out = Result<ir::Stmt>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![feature(unsize, coerce_unsized, new_uninit)]
|
#![feature(unsize, coerce_unsized, new_uninit, box_into_pin)]
|
||||||
|
|
||||||
#[macro_use] mod visit;
|
#[macro_use] mod visit;
|
||||||
mod compile;
|
mod compile;
|
||||||
|
|||||||
@@ -2,31 +2,20 @@ use crate::{
|
|||||||
mem::{gc::Gc, ptr::ObjCell},
|
mem::{gc::Gc, ptr::ObjCell},
|
||||||
obj::prelude::*,
|
obj::prelude::*,
|
||||||
};
|
};
|
||||||
use std::ptr::NonNull;
|
use std::pin::Pin;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BasicGc {
|
pub struct BasicGc {
|
||||||
objects: Vec<Box<ObjCell<dyn Obj>>>,
|
objects: Vec<Pin<Box<ObjCell<dyn Obj>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gc for BasicGc {
|
impl Gc for BasicGc {
|
||||||
fn alloc<O: Obj + 'static>(&mut self, obj: O) -> ObjRef<O> {
|
fn add_obj(&mut self, owned: Pin<Box<ObjCell<dyn Obj>>>) {
|
||||||
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>>) {
|
|
||||||
self.objects.push(owned);
|
self.objects.push(owned);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark(&mut self, _alive: &[DynRef]) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sweep(&mut self) {
|
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 {
|
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);
|
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 crate::obj::Obj;
|
||||||
use std::{
|
use std::{
|
||||||
any,
|
any,
|
||||||
cell::RefCell,
|
cell::{Cell, RefCell},
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
marker::Unsize,
|
marker::Unsize,
|
||||||
ops::{CoerceUnsized, Deref},
|
ops::{CoerceUnsized, Deref},
|
||||||
@@ -51,7 +51,7 @@ impl<O> Deref for ObjRef<O>
|
|||||||
where
|
where
|
||||||
O: Obj + ?Sized,
|
O: Obj + ?Sized,
|
||||||
{
|
{
|
||||||
type Target = RefCell<O>;
|
type Target = ObjCell<O>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
// Safe, so long as there are no dangling pointers from the GC
|
// Safe, so long as there are no dangling pointers from the GC
|
||||||
@@ -140,22 +140,34 @@ where
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// ObjCell
|
// ObjCell
|
||||||
//
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ObjCell<O: Obj + ?Sized> {
|
pub struct ObjCell<O: Obj + ?Sized> {
|
||||||
|
marked: Cell<bool>,
|
||||||
cell: RefCell<O>,
|
cell: RefCell<O>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<O: Obj> ObjCell<O> {
|
impl<O: Obj> ObjCell<O> {
|
||||||
pub fn new(obj: O) -> Self {
|
pub fn new(obj: O) -> Self {
|
||||||
ObjCell {
|
ObjCell {
|
||||||
|
marked: Cell::new(false),
|
||||||
cell: RefCell::new(obj),
|
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> {
|
impl<O: Obj + ?Sized> Deref for ObjCell<O> {
|
||||||
type Target = RefCell<O>;
|
type Target = RefCell<O>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
mem::ptr::{DynRef, ObjCell},
|
mem::ptr::{DynRef, ObjCell},
|
||||||
obj::prelude::*,
|
obj::prelude::*,
|
||||||
visit::Visit,
|
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
@@ -42,10 +41,14 @@ impl Attrs {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add the object to the allocator pool
|
// Add the object to the allocator pool
|
||||||
gc.add_obj(obj);
|
gc.add_obj(Box::into_pin(obj));
|
||||||
obj_ref
|
obj_ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inner(&self) -> &Ss {
|
||||||
|
&self.attrs
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, sym: Sym, value: DynRef) -> Option<DynRef> {
|
pub fn insert(&mut self, sym: Sym, value: DynRef) -> Option<DynRef> {
|
||||||
self.attrs.insert(sym, value)
|
self.attrs.insert(sym, value)
|
||||||
}
|
}
|
||||||
@@ -64,17 +67,8 @@ impl Obj for Attrs {
|
|||||||
fn as_any(&self) -> &dyn std::any::Any {
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
fn accept(&self, visitor: &mut dyn VisitObj) {
|
||||||
impl_accept!(Attrs);
|
visitor.visit_attrs(self);
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
use crate::{obj::prelude::*, visit::Visit};
|
use crate::obj::prelude::*;
|
||||||
use std::{any::Any, cell::Cell};
|
use std::any::Any;
|
||||||
|
|
||||||
pub type DictRef = ObjRef<Dict>;
|
pub type DictRef = ObjRef<Dict>;
|
||||||
|
|
||||||
pub struct Dict {
|
pub struct Dict {
|
||||||
dict: Vec<(DynRef, DynRef)>,
|
dict: Vec<(DynRef, DynRef)>,
|
||||||
attrs: ObjRef<Attrs>,
|
attrs: ObjRef<Attrs>,
|
||||||
marked: Cell<bool>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dict {
|
impl Dict {
|
||||||
@@ -14,9 +13,16 @@ impl Dict {
|
|||||||
Dict {
|
Dict {
|
||||||
dict: Default::default(),
|
dict: Default::default(),
|
||||||
attrs,
|
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 {
|
impl Obj for Dict {
|
||||||
@@ -27,4 +33,8 @@ impl Obj for Dict {
|
|||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
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 {
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn accept(&self, _: &mut dyn VisitObj) {
|
||||||
|
todo!("visit NativeFun");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Fun {
|
pub struct Fun {
|
||||||
@@ -57,4 +61,8 @@ impl Obj for Fun {
|
|||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn accept(&self, _: &mut dyn VisitObj) {
|
||||||
|
todo!("visit Fun");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ pub mod ns {
|
|||||||
}
|
}
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod sym;
|
pub mod sym;
|
||||||
|
pub mod visit;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
@@ -30,7 +31,7 @@ pub mod prelude {
|
|||||||
},
|
},
|
||||||
obj::{
|
obj::{
|
||||||
Attrs, AttrsRef, Dict, DictRef, Fun, NameId, NativeFun, Ns, Obj, ObjCtx, Ss, Str,
|
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},
|
ns::{Ns, Ss},
|
||||||
str::{Str, StrRef},
|
str::{Str, StrRef},
|
||||||
sym::Sym,
|
sym::Sym,
|
||||||
|
visit::VisitObj,
|
||||||
};
|
};
|
||||||
use crate::mem::ptr::ObjRef;
|
use crate::mem::ptr::ObjRef;
|
||||||
use crate::visit::*;
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
pub trait Obj {
|
pub trait Obj {
|
||||||
fn attrs(&self) -> ObjRef<Attrs>;
|
fn attrs(&self) -> ObjRef<Attrs>;
|
||||||
fn as_any(&self) -> &dyn Any;
|
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 derivative::Derivative;
|
||||||
use std::{any::Any, cell::Cell};
|
use std::any::Any;
|
||||||
|
|
||||||
pub type StrRef = ObjRef<Str>;
|
pub type StrRef = ObjRef<Str>;
|
||||||
|
|
||||||
@@ -11,18 +11,11 @@ pub struct Str {
|
|||||||
attrs: AttrsRef,
|
attrs: AttrsRef,
|
||||||
|
|
||||||
contents: String,
|
contents: String,
|
||||||
|
|
||||||
#[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
|
|
||||||
marked: Cell<bool>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Str {
|
impl Str {
|
||||||
pub fn new<G: Gc>(attrs: AttrsRef, contents: String) -> Self {
|
pub fn new<G: Gc>(attrs: AttrsRef, contents: String) -> Self {
|
||||||
Str {
|
Str { attrs, contents }
|
||||||
attrs,
|
|
||||||
contents,
|
|
||||||
marked: Cell::new(false),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contents(&self) -> &String {
|
pub fn contents(&self) -> &String {
|
||||||
@@ -38,4 +31,8 @@ impl Obj for Str {
|
|||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
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