Changes all around - objects and GC
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![feature(new_uninit)]
|
#![feature(unsize, coerce_unsized, new_uninit)]
|
||||||
|
|
||||||
mod compile;
|
mod compile;
|
||||||
mod syn;
|
mod syn;
|
||||||
|
|||||||
@@ -2,17 +2,15 @@ use crate::{
|
|||||||
mem::{
|
mem::{
|
||||||
gc::Gc,
|
gc::Gc,
|
||||||
intern::Intern,
|
intern::Intern,
|
||||||
ptr::{DynRef, ObjCell, ObjRef},
|
ptr::ObjCell,
|
||||||
},
|
},
|
||||||
obj::{ctx::ObjCtx, Obj, Str, Sym},
|
obj::prelude::*,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, ptr::NonNull};
|
use std::{collections::HashMap, ptr::NonNull};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[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>>,
|
|
||||||
syms: HashMap<String, Sym>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gc for BasicGc {
|
impl Gc for BasicGc {
|
||||||
@@ -23,7 +21,7 @@ impl Gc for BasicGc {
|
|||||||
ObjRef::new(NonNull::new(obj_ptr).unwrap())
|
ObjRef::new(NonNull::new(obj_ptr).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_obj<O: Obj + 'static>(&mut self, owned: Box<ObjCell<O>>) {
|
fn add_obj(&mut self, owned: Box<ObjCell<dyn Obj>>) {
|
||||||
self.objects.push(owned);
|
self.objects.push(owned);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,24 +45,23 @@ impl Gc for BasicGc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Intern for BasicGc {
|
pub struct BasicIntern {
|
||||||
fn get_str(&self, s: &str) -> Option<ObjRef<Str>> {
|
strs: HashMap<String, ObjRef<Str>>,
|
||||||
self.strs.get(s).copied()
|
syms: HashMap<String, Sym>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Intern for BasicIntern {
|
||||||
|
fn intern_str<G: Gc>(&mut self, gc: &mut G, s: &str) -> StrRef {
|
||||||
|
if let Some(obj_ref) = self.strs.get(s) {
|
||||||
|
*obj_ref
|
||||||
|
} else {
|
||||||
|
todo!("TODO(obj) intern strings - need attrs somehow")
|
||||||
|
//let s = Str::new(&mut ctx, s.to_string());
|
||||||
|
//ctx.gc_mut().alloc(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_str(&mut self, ctx: &mut ObjCtx, s: &str) -> ObjRef<Str> {
|
fn intern_sym(&mut self, s: &str) -> Sym {
|
||||||
*self.strs.entry(s.to_string())
|
|
||||||
.or_insert_with(|| {
|
|
||||||
let s = Str::new(ctx, s.to_string());
|
|
||||||
ctx.gc_mut().alloc(s)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_sym(&self, s: &str) -> Option<Sym> {
|
|
||||||
self.syms.get(s).copied()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_sym(&mut self, s: &str) -> Sym {
|
|
||||||
let len = self.syms.len();
|
let len = self.syms.len();
|
||||||
*self.syms.entry(s.to_string())
|
*self.syms.entry(s.to_string())
|
||||||
.or_insert_with(|| len)
|
.or_insert_with(|| len)
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ use crate::{
|
|||||||
obj::prelude::*,
|
obj::prelude::*,
|
||||||
mem::{
|
mem::{
|
||||||
ptr::ObjCell,
|
ptr::ObjCell,
|
||||||
intern::Intern,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait Gc: Intern {
|
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>;
|
||||||
|
|
||||||
fn add_obj<O: Obj + 'static>(&mut self, owned: Box<ObjCell<O>>);
|
fn add_obj(&mut self, owned: Box<ObjCell<dyn Obj>>);
|
||||||
|
|
||||||
fn mark(&mut self, alive: &[DynRef]);
|
fn mark(&mut self, alive: &[DynRef]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
use crate::{
|
use crate::obj::prelude::*;
|
||||||
mem::ptr::ObjRef,
|
|
||||||
obj::{
|
|
||||||
ctx::ObjCtx,
|
|
||||||
Str, Sym,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait Intern {
|
pub trait Intern {
|
||||||
fn get_str(&self, s: &str) -> Option<ObjRef<Str>>;
|
fn intern_str<G: Gc>(&mut self, gc: &mut G, s: &str) -> StrRef;
|
||||||
fn add_str(&mut self, ctx: &mut ObjCtx, s: &str) -> ObjRef<Str>;
|
|
||||||
|
|
||||||
fn get_sym(&self, s: &str) -> Option<Sym>;
|
fn intern_sym(&mut self, s: &str) -> Sym;
|
||||||
fn add_sym(&mut self, s: &str) -> Sym;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
mod basic;
|
pub mod basic;
|
||||||
pub mod intern;
|
|
||||||
pub mod gc;
|
pub mod gc;
|
||||||
|
pub mod intern;
|
||||||
pub mod ptr;
|
pub mod ptr;
|
||||||
|
|
||||||
pub use self::basic::BasicGc;
|
pub use basic::BasicGc;
|
||||||
|
|
||||||
/*
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::mem::{
|
pub use crate::mem::{
|
||||||
alloc::Alloc,
|
BasicGc,
|
||||||
gc::Gc,
|
gc::Gc,
|
||||||
ptr::*
|
intern::Intern,
|
||||||
}
|
ptr::{DynRef, ObjRef},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::obj::Obj;
|
use crate::obj::Obj;
|
||||||
use std::{
|
use std::{
|
||||||
any::{self, Any},
|
any,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
ops::Deref,
|
marker::Unsize,
|
||||||
|
ops::{CoerceUnsized, Deref},
|
||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,6 +125,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, U> CoerceUnsized<ObjRef<U>> for ObjRef<T>
|
||||||
|
where T: Obj + Unsize<U> + ?Sized,
|
||||||
|
U: Obj + ?Sized
|
||||||
|
{}
|
||||||
|
|
||||||
|
impl<T, U> CoerceUnsized<ObjCell<U>> for ObjCell<T>
|
||||||
|
where T: CoerceUnsized<U> + Obj,
|
||||||
|
U: Obj
|
||||||
|
{}
|
||||||
|
|
||||||
//
|
//
|
||||||
// ObjCell
|
// ObjCell
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -4,28 +4,27 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
collections::BTreeMap,
|
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
ptr::{self, NonNull},
|
ptr::{self, NonNull},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type AttrsMap = BTreeMap<Sym, DynRef>;
|
pub type AttrsRef = ObjRef<Attrs>;
|
||||||
|
|
||||||
pub struct Attrs {
|
pub struct Attrs {
|
||||||
attrs: AttrsMap,
|
attrs: Ns,
|
||||||
marked: Cell<bool>,
|
marked: Cell<bool>,
|
||||||
this: ObjRef<Attrs>,
|
this: ObjRef<Attrs>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attrs {
|
impl Attrs {
|
||||||
pub fn new(ctx: &mut ObjCtx, attrs: BTreeMap<Sym, DynRef>) -> ObjRef<Self> {
|
pub fn new<G: Gc>(gc: &mut G, attrs: Ns) -> 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
|
||||||
let this = &*obj as *const _ as *const ObjCell<Attrs>;
|
let this = &*obj as *const _ as *const ObjCell<Attrs>;
|
||||||
|
|
||||||
obj.as_mut_ptr().write(ObjCell::new(Attrs {
|
obj.as_mut_ptr().write(ObjCell::new(Attrs {
|
||||||
attrs: Default::default(),
|
attrs,
|
||||||
marked: Cell::new(false),
|
marked: Cell::new(false),
|
||||||
this: ObjRef::new(NonNull::new(this as *mut _).unwrap()),
|
this: ObjRef::new(NonNull::new(this as *mut _).unwrap()),
|
||||||
}));
|
}));
|
||||||
@@ -43,7 +42,7 @@ impl Attrs {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add the object to the allocator pool
|
// Add the object to the allocator pool
|
||||||
ctx.gc_mut().add_obj(obj);
|
gc.add_obj(obj);
|
||||||
obj_ref
|
obj_ref
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,25 +86,25 @@ impl Obj for Attrs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AttrsBuilder<'ctx> {
|
pub struct AttrsBuilder<'i, I: Intern> {
|
||||||
ctx: &'ctx mut ObjCtx,
|
intern: &'i mut I,
|
||||||
attrs: AttrsMap,
|
attrs: Ns,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> AttrsBuilder<'ctx> {
|
impl<'i, I: Intern> AttrsBuilder<'i, I> {
|
||||||
pub fn new(ctx: &'ctx mut ObjCtx) -> Self {
|
pub fn new(intern: &'i mut I) -> Self {
|
||||||
Self::with_base(ctx, Default::default())
|
Self::with_base(intern, Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_base(ctx: &'ctx mut ObjCtx, attrs: AttrsMap) -> Self {
|
pub fn with_base(intern: &'i mut I, attrs: Ns) -> Self {
|
||||||
AttrsBuilder {
|
AttrsBuilder {
|
||||||
attrs,
|
attrs,
|
||||||
ctx,
|
intern,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attr(self, symbol_name: &str, value: DynRef) -> Self {
|
pub fn attr(self, symbol_name: &str, value: DynRef) -> Self {
|
||||||
let sym = self.ctx.gc_mut().add_sym(symbol_name);
|
let sym = self.intern.intern_sym(symbol_name);
|
||||||
self.attr_sym(sym, value)
|
self.attr_sym(sym, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +113,9 @@ impl<'ctx> AttrsBuilder<'ctx> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(self) -> ObjRef<Attrs> {
|
pub fn finish<G: Gc>(self, gc: &mut G) -> ObjRef<Attrs> {
|
||||||
let Self { ctx, attrs } = self;
|
let Self { intern: _, attrs } = self;
|
||||||
Attrs::new(ctx, attrs)
|
Attrs::new(gc, attrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,13 +123,13 @@ impl<'ctx> AttrsBuilder<'ctx> {
|
|||||||
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 gc = BasicGc::default();
|
||||||
|
|
||||||
let attrs_ref = Attrs::new(&mut ctx, Default::default());
|
let attrs_ref = Attrs::new(&mut gc, Default::default());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut attrs = attrs_ref.borrow_mut();
|
let mut attrs = attrs_ref.borrow_mut();
|
||||||
let sym = ctx.gc_mut().add_sym("symbol");
|
let sym = gc.add_sym("symbol");
|
||||||
attrs.insert(sym, attrs_ref.as_dyn());
|
attrs.insert(sym, attrs_ref.as_dyn());
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -1,40 +1,31 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
mem::{gc::Gc, ptr::DynRef, BasicGc},
|
mem::{gc::Gc, BasicGc},
|
||||||
obj::Sym,
|
obj::prelude::*,
|
||||||
};
|
};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
pub type DefaultGc = BasicGc;
|
pub type DefaultGc = BasicGc;
|
||||||
|
|
||||||
pub struct ObjCtx<G = DefaultGc>
|
pub struct ObjCtx<'g, 'n, G>
|
||||||
where
|
where
|
||||||
G: Gc,
|
G: Gc + 'g,
|
||||||
{
|
{
|
||||||
gc: G,
|
gc: &'g mut G,
|
||||||
globals: BTreeMap<Sym, DynRef>,
|
ns: &'n mut Ns,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G> ObjCtx<G>
|
impl<'g, 'n, G> ObjCtx<'g, 'n, G>
|
||||||
where
|
where
|
||||||
G: Gc,
|
G: Gc + 'g,
|
||||||
{
|
{
|
||||||
pub fn new(gc: G) -> Self {
|
pub fn new(gc: &'g mut G, ns: &'n mut Ns) -> Self {
|
||||||
ObjCtx { gc, globals: Default::default() }
|
ObjCtx { gc, ns }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gc(&self) -> &G {
|
pub fn gc_mut(&'g mut self) -> &'g mut G {
|
||||||
&self.gc
|
self.gc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gc_mut(&mut self) -> &mut G {
|
pub fn ns_mut(&'n mut self) -> &'n mut Ns {
|
||||||
&mut self.gc
|
self.ns
|
||||||
}
|
|
||||||
|
|
||||||
pub fn globals(&self) -> &BTreeMap<Sym, DynRef> {
|
|
||||||
&self.globals
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn globals_mut(&mut self) -> &mut BTreeMap<Sym, DynRef> {
|
|
||||||
&mut self.globals
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,19 +10,12 @@ pub struct Dict {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Dict {
|
impl Dict {
|
||||||
// TODO : base types need to be interned. This should probably be stored in a root namespace.
|
pub fn new(attrs: AttrsRef) -> Self {
|
||||||
// * How to get the root namespace?
|
|
||||||
// * ObjCtx object that holds allocator, gc, root namespace, etc..?
|
|
||||||
// * How to create initial types?
|
|
||||||
pub fn new(ctx: &mut ObjCtx) -> Self {
|
|
||||||
todo!()
|
|
||||||
/*
|
|
||||||
Dict {
|
Dict {
|
||||||
dict: Default::default(),
|
dict: Default::default(),
|
||||||
attrs: Attrs::new(ctx),
|
attrs,
|
||||||
marked: Cell::new(false),
|
marked: Cell::new(false),
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ use std::{any::Any, cell::Cell, rc::Rc};
|
|||||||
pub type NativeFunPtr = fn(argv: Vec<DynRef>);
|
pub type NativeFunPtr = fn(argv: Vec<DynRef>);
|
||||||
|
|
||||||
pub struct NativeFun {
|
pub struct NativeFun {
|
||||||
attrs: ObjRef<Attrs>,
|
attrs: AttrsRef,
|
||||||
fn_ptr: NativeFunPtr,
|
fn_ptr: NativeFunPtr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NativeFun {
|
impl NativeFun {
|
||||||
pub fn new(ctx: &mut ObjCtx, name: StrRef, fn_ptr: NativeFunPtr) -> Self {
|
pub fn new(attrs: AttrsRef, name: StrRef, fn_ptr: NativeFunPtr) -> Self {
|
||||||
let attrs = Attrs::new(ctx, Default::default());
|
// TODO : clone attrs, add name
|
||||||
NativeFun {
|
NativeFun {
|
||||||
attrs,
|
attrs,
|
||||||
fn_ptr,
|
fn_ptr,
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ pub mod dict;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod fun;
|
pub mod fun;
|
||||||
//pub mod num;
|
//pub mod num;
|
||||||
|
pub mod ns {
|
||||||
|
use crate::{mem::ptr::DynRef, obj::Sym};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
/// A namespace
|
||||||
|
pub type Ns = BTreeMap<Sym, DynRef>;
|
||||||
|
}
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod sym {
|
pub mod sym {
|
||||||
pub type Sym = usize;
|
pub type Sym = usize;
|
||||||
@@ -12,22 +19,21 @@ pub mod sym {
|
|||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
obj::{
|
|
||||||
Attrs, Dict, DictRef, Fun, NativeFun, Str, StrRef, Sym, ObjCtx, Obj,
|
|
||||||
},
|
|
||||||
mem::{
|
mem::{
|
||||||
ptr::{ObjRef, DynRef},
|
|
||||||
intern::Intern,
|
|
||||||
gc::Gc,
|
gc::Gc,
|
||||||
}
|
intern::Intern,
|
||||||
|
ptr::{DynRef, ObjRef},
|
||||||
|
},
|
||||||
|
obj::{Attrs, AttrsRef, Dict, DictRef, Fun, NativeFun, Ns, Obj, ObjCtx, Str, StrRef, Sym},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
attrs::Attrs,
|
attrs::{Attrs, AttrsBuilder, AttrsRef},
|
||||||
ctx::ObjCtx,
|
ctx::ObjCtx,
|
||||||
dict::{Dict, DictRef},
|
dict::{Dict, DictRef},
|
||||||
fun::{NativeFun, Fun},
|
fun::{Fun, NativeFun},
|
||||||
|
ns::Ns,
|
||||||
str::{Str, StrRef},
|
str::{Str, StrRef},
|
||||||
sym::Sym,
|
sym::Sym,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub type StrRef = ObjRef<Str>;
|
|||||||
#[derivative(PartialEq, PartialOrd, Ord, Eq)]
|
#[derivative(PartialEq, PartialOrd, Ord, Eq)]
|
||||||
pub struct Str {
|
pub struct Str {
|
||||||
#[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
|
#[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
|
||||||
attrs: ObjRef<Attrs>,
|
attrs: AttrsRef,
|
||||||
|
|
||||||
contents: String,
|
contents: String,
|
||||||
|
|
||||||
@@ -17,20 +17,14 @@ pub struct Str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Str {
|
impl Str {
|
||||||
pub fn new(ctx: &mut ObjCtx, contents: String) -> Self {
|
pub fn new<G: Gc>(attrs: AttrsRef, contents: String) -> Self {
|
||||||
Str {
|
Str {
|
||||||
attrs: Self::type_attrs(ctx),
|
attrs,
|
||||||
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 {
|
||||||
&self.contents
|
&self.contents
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
use crate::obj::prelude::*;
|
use crate::{
|
||||||
use std::collections::BTreeMap;
|
obj::prelude::*,
|
||||||
|
vm::op::Op,
|
||||||
|
};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
stack: Vec<DynRef>,
|
stack: Vec<DynRef>,
|
||||||
ip: usize,
|
ip: usize,
|
||||||
return_value: Option<DynRef>,
|
return_value: Option<DynRef>,
|
||||||
locals: BTreeMap<Sym, DynRef>,
|
locals: Ns,
|
||||||
|
ops: Rc<Vec<Op>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn new() -> Self {
|
pub fn new(ops: Rc<Vec<Op>>) -> Self {
|
||||||
Default::default()
|
Frame {
|
||||||
|
stack: Default::default(),
|
||||||
|
ip: 0,
|
||||||
|
return_value: None,
|
||||||
|
locals: Default::default(),
|
||||||
|
ops,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, obj_ref: DynRef) {
|
pub fn push(&mut self, obj_ref: DynRef) {
|
||||||
@@ -45,5 +54,9 @@ impl Frame {
|
|||||||
pub fn set_local(&mut self, sym: Sym, obj_ref: DynRef) -> Option<DynRef> {
|
pub fn set_local(&mut self, sym: Sym, obj_ref: DynRef) -> Option<DynRef> {
|
||||||
self.locals.insert(sym, obj_ref)
|
self.locals.insert(sym, obj_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ops(&self) -> &Rc<Vec<Op>> {
|
||||||
|
&self.ops
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
106
src/vm/mod.rs
106
src/vm/mod.rs
@@ -3,6 +3,7 @@ pub mod frame;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::prelude::*,
|
obj::prelude::*,
|
||||||
|
mem::gc::Gc,
|
||||||
vm::{
|
vm::{
|
||||||
op::Op,
|
op::Op,
|
||||||
frame::Frame,
|
frame::Frame,
|
||||||
@@ -10,61 +11,95 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct State {
|
fn root_ns<I: Intern, G: Gc>(intern: &mut I, gc: &mut G) -> Ns {
|
||||||
|
let mut ns: Ns = Default::default();
|
||||||
|
ns.insert(intern.intern_sym("Unit"), Attrs::new(gc, Default::default()));
|
||||||
|
ns
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct State<I: Intern, G: Gc> {
|
||||||
|
intern: I,
|
||||||
|
gc: G,
|
||||||
|
root_ns: Ns,
|
||||||
frames: Vec<Frame>,
|
frames: Vec<Frame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl<I: Intern, G: Gc> State<I, G> {
|
||||||
pub fn new() -> Self {
|
pub fn new(mut intern: I, mut gc: G) -> Self {
|
||||||
State { frames: Default::default(), }
|
let root_ns = root_ns(&mut intern, &mut gc);
|
||||||
|
State { intern, gc, root_ns, frames: Default::default(), }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame(&self) -> &Frame {
|
pub fn frames(&self) -> &Vec<Frame> {
|
||||||
|
&self.frames
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn frames_mut(&mut self) -> &mut Vec<Frame> {
|
||||||
|
&mut self.frames
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn frame(&self) -> &Frame {
|
||||||
self.frames
|
self.frames
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_mut(&mut self) -> &mut Frame {
|
pub fn frame_mut(&mut self) -> &mut Frame {
|
||||||
self.frames
|
self.frames
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_stack(&mut self, value: DynRef) {
|
pub fn push_stack(&mut self, value: DynRef) {
|
||||||
self.frame_mut()
|
self.frame_mut()
|
||||||
.push(value);
|
.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_stack(&mut self) -> Option<DynRef> {
|
pub fn pop_stack(&mut self) -> Option<DynRef> {
|
||||||
self.frame_mut()
|
self.frame_mut()
|
||||||
.pop()
|
.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ip(&self) -> usize {
|
pub fn ip(&self) -> usize {
|
||||||
self.frame().ip()
|
self.frame().ip()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_ip(&mut self, ip: usize) {
|
pub fn set_ip(&mut self, ip: usize) {
|
||||||
self.frame_mut().set_ip(ip);
|
self.frame_mut().set_ip(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_local(&self, sym: Sym) -> Option<DynRef> {
|
pub fn get_local(&self, sym: Sym) -> Option<DynRef> {
|
||||||
self.frame().get_local(sym)
|
self.frame().get_local(sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_local(&mut self, sym: Sym, obj_ref: DynRef) -> Option<DynRef> {
|
pub fn set_local(&mut self, sym: Sym, obj_ref: DynRef) -> Option<DynRef> {
|
||||||
self.frame_mut().set_local(sym, obj_ref)
|
self.frame_mut().set_local(sym, obj_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, ops: Rc<Vec<Op>>) {
|
pub fn ops(&self) -> &Rc<Vec<Op>> {
|
||||||
self.frames.push(Default::default());
|
self.frame().ops()
|
||||||
while self.ip() < ops.len() {
|
}
|
||||||
|
|
||||||
|
pub fn resume(&mut self) {
|
||||||
|
while !self.frames().is_empty() {
|
||||||
|
self.resume_fun();
|
||||||
|
let _frame = self.frames_mut().pop().unwrap();
|
||||||
|
// Push return value?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resume_fun(&mut self) {
|
||||||
|
while self.ip() < self.ops().len() {
|
||||||
|
self.step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(&mut self) {
|
||||||
let mut next_ip = self.ip() + 1;
|
let mut next_ip = self.ip() + 1;
|
||||||
match &ops[self.ip()] {
|
match self.ops()[self.ip()] {
|
||||||
Op::Push(sym) => {
|
Op::Push(sym) => {
|
||||||
// TODO - local not found
|
// TODO - local not found
|
||||||
let obj_ref = self.get_local(*sym)
|
let obj_ref = self.get_local(sym)
|
||||||
.expect("TODO - local not found");
|
.expect("TODO - local not found");
|
||||||
self.push_stack(obj_ref);
|
self.push_stack(obj_ref);
|
||||||
}
|
}
|
||||||
@@ -72,7 +107,7 @@ impl State {
|
|||||||
// stack should not underflow
|
// stack should not underflow
|
||||||
let obj_ref = self.pop_stack()
|
let obj_ref = self.pop_stack()
|
||||||
.expect("misaligned stack for pop");
|
.expect("misaligned stack for pop");
|
||||||
if let Some(sym) = *sym {
|
if let Some(sym) = sym {
|
||||||
self.set_local(sym, obj_ref);
|
self.set_local(sym, obj_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +119,7 @@ impl State {
|
|||||||
let attrs = top_ref.attrs();
|
let attrs = top_ref.attrs();
|
||||||
let attrs_ref = attrs.borrow();
|
let attrs_ref = attrs.borrow();
|
||||||
// TODO - local not found
|
// TODO - local not found
|
||||||
attrs_ref.get(*sym)
|
attrs_ref.get(sym)
|
||||||
.expect("TODO - local not found")
|
.expect("TODO - local not found")
|
||||||
};
|
};
|
||||||
self.push_stack(obj_ref);
|
self.push_stack(obj_ref);
|
||||||
@@ -92,8 +127,8 @@ impl State {
|
|||||||
Op::Call(argc) => {
|
Op::Call(argc) => {
|
||||||
let fun = self.pop_stack()
|
let fun = self.pop_stack()
|
||||||
.expect("misaligned stack for function call");
|
.expect("misaligned stack for function call");
|
||||||
let mut argv = Vec::with_capacity(*argc);
|
let mut argv = Vec::with_capacity(argc);
|
||||||
for i in 0 .. *argc {
|
for _ in 0 .. argc {
|
||||||
let arg = self.pop_stack()
|
let arg = self.pop_stack()
|
||||||
.expect("misaligned stack for argv");
|
.expect("misaligned stack for argv");
|
||||||
argv.push(arg);
|
argv.push(arg);
|
||||||
@@ -101,31 +136,20 @@ impl State {
|
|||||||
// reverse since arguments are pushed in order of being passed
|
// reverse since arguments are pushed in order of being passed
|
||||||
argv.reverse();
|
argv.reverse();
|
||||||
|
|
||||||
// call function
|
|
||||||
// TODO - call the function indirectly?
|
|
||||||
//
|
|
||||||
// problem: downcast_ref returns a reference bound by the lifetime of the
|
|
||||||
// function (because of the ref cell). This keeps the fun object borrowed,
|
|
||||||
// which means any attempts to modify the function while it is running will
|
|
||||||
// cause the VM to panic.
|
|
||||||
//
|
|
||||||
// possible solution:
|
|
||||||
// pop the function object, and then determine which function to call on the
|
|
||||||
// object (possibly after downcasting?)
|
|
||||||
//
|
|
||||||
// TODO
|
// TODO
|
||||||
// Figure out a way to either call a native function with NativeFun::call, or
|
// move ops pointer to the stack frame
|
||||||
// call a user function with Fun::code()
|
if let Some(_fun) = fun.borrow().as_any().downcast_ref::<Fun>() {
|
||||||
if let Some(fun) = fun.borrow().as_any().downcast_ref::<Fun>() {
|
self.set_ip(next_ip);
|
||||||
} else if let Some(fun) = fun.borrow().as_any().downcast_ref::<NativeFun>() {
|
next_ip = 0;
|
||||||
|
todo!("New stack frame");
|
||||||
|
} else if let Some(_fun) = fun.borrow().as_any().downcast_ref::<NativeFun>() {
|
||||||
|
todo!();
|
||||||
} else {
|
} else {
|
||||||
todo!("TODO - not a function")
|
todo!("TODO - not a function");
|
||||||
}
|
}
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.set_ip(next_ip);
|
self.set_ip(next_ip);
|
||||||
}
|
}
|
||||||
self.frames.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::obj::Sym;
|
|||||||
// * ops deal with symbols directly
|
// * ops deal with symbols directly
|
||||||
// * stack values are either obj references or symbols
|
// * stack values are either obj references or symbols
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub enum Op {
|
pub enum Op {
|
||||||
/// Push a value from a symbol
|
/// Push a value from a symbol
|
||||||
Push(Sym),
|
Push(Sym),
|
||||||
|
|||||||
Reference in New Issue
Block a user