Update how visitors work, add NameId type

* Visitors are now defined on a per-type level, allowing for greater
  flexibility in combining and re-using behavior
* NameId is used for namespaces, which are used to index locally scoped
  variables. Syms are used for free namespaces, specifically in objects.
  All NameIDs are symbols, while not all symbols are NameIDs.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-05-20 14:41:12 -04:00
parent 3ce7384f15
commit 32591f5e29
15 changed files with 306 additions and 206 deletions

View File

@@ -1,21 +1,23 @@
pub mod op;
pub mod frame;
pub mod op;
use crate::{
obj::prelude::*,
mem::gc::Gc,
vm::{
op::Op,
frame::Frame,
}
obj::prelude::*,
vm::{frame::Frame, op::Op},
};
use std::rc::Rc;
/*
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.insert(
intern.intern_sym("Unit"),
Attrs::new(gc, Default::default()),
);
ns
}
*/
pub struct State<I: Intern, G: Gc> {
intern: I,
@@ -25,9 +27,14 @@ pub struct State<I: Intern, G: Gc> {
}
impl<I: Intern, G: Gc> State<I, G> {
pub fn new(mut intern: I, mut gc: G) -> Self {
let root_ns = root_ns(&mut intern, &mut gc);
State { intern, gc, root_ns, frames: Default::default(), }
pub fn new(intern: I, gc: G, root_ns: Ns) -> Self {
//let root_ns = root_ns(&mut intern, &mut gc);
State {
intern,
gc,
root_ns,
frames: Default::default(),
}
}
pub fn frames(&self) -> &Vec<Frame> {
@@ -39,25 +46,19 @@ impl<I: Intern, G: Gc> State<I, G> {
}
pub fn frame(&self) -> &Frame {
self.frames
.last()
.unwrap()
self.frames.last().unwrap()
}
pub fn frame_mut(&mut self) -> &mut Frame {
self.frames
.last_mut()
.unwrap()
self.frames.last_mut().unwrap()
}
pub fn push_stack(&mut self, value: DynRef) {
self.frame_mut()
.push(value);
self.frame_mut().push(value);
}
pub fn pop_stack(&mut self) -> Option<DynRef> {
self.frame_mut()
.pop()
self.frame_mut().pop()
}
pub fn ip(&self) -> usize {
@@ -68,12 +69,12 @@ impl<I: Intern, G: Gc> State<I, G> {
self.frame_mut().set_ip(ip);
}
pub fn get_local(&self, sym: Sym) -> Option<DynRef> {
self.frame().get_local(sym)
pub fn get_local(&self, name: NameId) -> Option<DynRef> {
self.frame().get_local(name)
}
pub fn set_local(&mut self, sym: Sym, obj_ref: DynRef) -> Option<DynRef> {
self.frame_mut().set_local(sym, obj_ref)
pub fn set_local(&mut self, name: NameId, obj_ref: DynRef) -> Option<DynRef> {
self.frame_mut().set_local(name, obj_ref)
}
pub fn ops(&self) -> &Rc<Vec<Op>> {
@@ -97,40 +98,36 @@ impl<I: Intern, G: Gc> State<I, G> {
pub fn step(&mut self) {
let mut next_ip = self.ip() + 1;
match self.ops()[self.ip()] {
Op::Push(sym) => {
Op::Push(name) => {
// TODO - local not found
let obj_ref = self.get_local(sym)
.expect("TODO - local not found");
let obj_ref = self.get_local(name).expect("TODO - local not found");
self.push_stack(obj_ref);
}
Op::Pop(sym) => {
Op::Pop(name) => {
// stack should not underflow
let obj_ref = self.pop_stack()
.expect("misaligned stack for pop");
if let Some(sym) = sym {
self.set_local(sym, obj_ref);
let obj_ref = self.pop_stack().expect("misaligned stack for pop");
if let Some(name) = name {
self.set_local(name, obj_ref);
}
}
Op::GetAttr(sym) => {
let top = self.pop_stack()
.expect("misaligned stack for getattrs");
let top = self.pop_stack().expect("misaligned stack for getattrs");
let obj_ref = {
let top_ref = top.borrow();
let attrs = top_ref.attrs();
let attrs_ref = attrs.borrow();
// TODO - local not found
attrs_ref.get(sym)
.expect("TODO - local not found")
attrs_ref.get(sym).expect("TODO - local not found")
};
self.push_stack(obj_ref);
}
Op::Call(argc) => {
let fun = self.pop_stack()
let fun = self
.pop_stack()
.expect("misaligned stack for function call");
let mut argv = Vec::with_capacity(argc);
for _ in 0 .. argc {
let arg = self.pop_stack()
.expect("misaligned stack for argv");
for _ in 0..argc {
let arg = self.pop_stack().expect("misaligned stack for argv");
argv.push(arg);
}
// reverse since arguments are pushed in order of being passed
@@ -147,7 +144,6 @@ impl<I: Intern, G: Gc> State<I, G> {
} else {
todo!("TODO - not a function");
}
}
}
self.set_ip(next_ip);