FIX: Rc instead of borrows because the lifetimes get unweildy.

This commit is contained in:
Jeremy Wall 2019-07-11 16:48:08 -05:00
parent 3cb73e9543
commit a50eb46c5e
3 changed files with 85 additions and 71 deletions

View File

@ -14,6 +14,8 @@
pub mod pointer; pub mod pointer;
pub mod scope; pub mod scope;
use std::rc::Rc;
use pointer::OpPointer; use pointer::OpPointer;
use scope::Stack; use scope::Stack;
@ -30,43 +32,41 @@ pub enum Primitive {
use Primitive::{Bool, Float, Int, Str}; use Primitive::{Bool, Float, Int, Str};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Composite<'a> { pub enum Composite {
List(Vec<Value<'a>>), List(Vec<Value>),
Tuple(Vec<(String, Value<'a>)>), Tuple(Vec<(String, Value)>),
} }
use Composite::{List, Tuple}; use Composite::{List, Tuple};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Func<'a> { pub struct Func {
// TODO(jwall): Embed the OpsPointer? ptr: OpPointer,
ptr: OpPointer<'a>,
bindings: Vec<String>, bindings: Vec<String>,
snapshot: Stack, snapshot: Stack,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Module<'a> { pub struct Module {
// TODO(jwall): Embed the OpsPointer? ptr: OpPointer,
ptr: OpPointer<'a>,
result_ptr: Option<usize>, result_ptr: Option<usize>,
flds: Vec<(String, Value<'a>)>, flds: Vec<(String, Value)>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Value<'a> { pub enum Value {
// Binding names. // Binding names.
S(String), S(String),
// Primitive Types // Primitive Types
P(Primitive), P(Primitive),
// Composite Types. // Composite Types.
C(Composite<'a>), C(Composite),
// Program Pointer // Program Pointer
T(usize), T(usize),
// Function // Function
F(Func<'a>), F(Func),
// Module // Module
M(Module<'a>), M(Module),
} }
use Value::{C, F, M, P, S, T}; use Value::{C, F, M, P, S, T};
@ -130,18 +130,18 @@ pub enum Op {
#[derive(Debug)] #[derive(Debug)]
pub struct Error {} pub struct Error {}
pub struct VM<'a> { pub struct VM {
stack: Vec<Value<'a>>, stack: Vec<Value>,
symbols: Stack, symbols: Stack,
ops: OpPointer<'a>, ops: OpPointer,
} }
impl<'a> VM<'a> { impl<'a> VM {
pub fn new(ops: &'a Vec<Op>) -> Self { pub fn new(ops: Rc<Vec<Op>>) -> Self {
Self::with_pointer(OpPointer::new(ops)) Self::with_pointer(OpPointer::new(ops))
} }
pub fn with_pointer(ops: OpPointer<'a>) -> Self { pub fn with_pointer(ops: OpPointer) -> Self {
Self { Self {
stack: Vec::new(), stack: Vec::new(),
symbols: Stack::new(), symbols: Stack::new(),
@ -157,10 +157,15 @@ impl<'a> VM<'a> {
} }
} }
pub fn run(&'a mut self) -> Result<(), Error> { pub fn run(&mut self) -> Result<(), Error> {
while self.ops.next().is_some() { loop {
let idx = self.ops.ptr.unwrap(); let op = if let Some(op) = dbg!(self.ops.next()) {
match dbg!(self.ops.op()).unwrap() { op.clone()
} else {
break;
};
let idx = self.ops.idx()?;
match op {
Op::Val(p) => self.push(dbg!(P(p.clone())))?, Op::Val(p) => self.push(dbg!(P(p.clone())))?,
Op::Sym(s) => self.push(S(s.clone()))?, Op::Sym(s) => self.push(S(s.clone()))?,
Op::DeRef(s) => self.op_deref(s.clone())?, Op::DeRef(s) => self.op_deref(s.clone())?,
@ -183,16 +188,16 @@ impl<'a> VM<'a> {
Op::Cp => self.op_copy()?, Op::Cp => self.op_copy()?,
//TODO(jwall): Should this take a user provided message? //TODO(jwall): Should this take a user provided message?
Op::Bang => return dbg!(Err(Error {})), Op::Bang => return dbg!(Err(Error {})),
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?, Op::InitThunk(jp) => self.op_thunk(idx, jp)?,
Op::Noop => { Op::Noop => {
// Do nothing // Do nothing
} }
Op::Jump(jp) => self.op_jump(*jp)?, Op::Jump(jp) => self.op_jump(jp)?,
Op::JumpIfTrue(jp) => self.op_jump_if_true(*jp)?, Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?,
Op::JumpIfFalse(jp) => self.op_jump_if_false(*jp)?, Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?,
Op::SelectJump(jp) => self.op_select_jump(*jp)?, Op::SelectJump(jp) => self.op_select_jump(jp)?,
Op::Module(mptr) => self.op_module(idx, *mptr)?, Op::Module(mptr) => self.op_module(idx, mptr)?,
Op::Func(jptr) => self.op_func(idx, *jptr)?, Op::Func(jptr) => self.op_func(idx, jptr)?,
Op::FCall => self.op_fcall()?, Op::FCall => self.op_fcall()?,
Op::Return => return Ok(()), Op::Return => return Ok(()),
Op::Pop => { Op::Pop => {
@ -203,12 +208,12 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_deref(&'a mut self, name: String) -> Result<(), Error> { fn op_deref(&mut self, name: String) -> Result<(), Error> {
let val = dbg!(self.get_binding(&name)?.clone()); let val = dbg!(self.get_binding(&name)?.clone());
self.push(val) self.push(val)
} }
fn op_jump(&'a mut self, jp: i32) -> Result<(), Error> { fn op_jump(&mut self, jp: i32) -> Result<(), Error> {
self.ops.jump( self.ops.jump(
self.ops self.ops
.ptr .ptr
@ -218,7 +223,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_jump_if_true(&'a mut self, jp: i32) -> Result<(), Error> { fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> {
if let P(Bool(cond)) = self.pop()? { if let P(Bool(cond)) = self.pop()? {
if cond { if cond {
self.op_jump(jp)?; self.op_jump(jp)?;
@ -227,7 +232,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_jump_if_false(&'a mut self, jp: i32) -> Result<(), Error> { fn op_jump_if_false(&mut self, jp: i32) -> Result<(), Error> {
if let P(Bool(cond)) = self.pop()? { if let P(Bool(cond)) = self.pop()? {
if !cond { if !cond {
self.op_jump(jp)?; self.op_jump(jp)?;
@ -275,7 +280,7 @@ impl<'a> VM<'a> {
self.ops.jump(dbg!(jptr)) self.ops.jump(dbg!(jptr))
} }
fn op_func(&'a mut self, idx: usize, jptr: usize) -> Result<(), Error> { fn op_func(&mut self, idx: usize, jptr: usize) -> Result<(), Error> {
// get arity from stack // get arity from stack
let mut scope_snapshot = self.symbols.snapshot(); let mut scope_snapshot = self.symbols.snapshot();
scope_snapshot.push(); scope_snapshot.push();
@ -306,7 +311,7 @@ impl<'a> VM<'a> {
self.ops.jump(jptr) self.ops.jump(jptr)
} }
fn op_fcall(&'a mut self) -> Result<(), Error> { fn op_fcall(&mut self) -> Result<(), Error> {
let f = self.pop()?; let f = self.pop()?;
if let F(Func { if let F(Func {
ptr, ptr,
@ -330,19 +335,19 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_thunk(&'a mut self, idx: usize, jp: i32) -> Result<(), Error> { fn op_thunk(&mut self, idx: usize, jp: i32) -> Result<(), Error> {
self.push(dbg!(T(idx)))?; self.push(dbg!(T(idx)))?;
self.op_jump(jp) self.op_jump(jp)
} }
fn op_equal(&'a mut self) -> Result<(), Error> { fn op_equal(&mut self) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
self.push(P(Bool(left == right)))?; self.push(P(Bool(left == right)))?;
Ok(()) Ok(())
} }
fn op_gt(&'a mut self) -> Result<(), Error> { fn op_gt(&mut self) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left, right) { match (left, right) {
@ -357,7 +362,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_lt(&'a mut self) -> Result<(), Error> { fn op_lt(&mut self) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left, right) { match (left, right) {
@ -372,7 +377,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_lteq(&'a mut self) -> Result<(), Error> { fn op_lteq(&mut self) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left, right) { match (left, right) {
@ -387,7 +392,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_gteq(&'a mut self) -> Result<(), Error> { fn op_gteq(&mut self) -> Result<(), Error> {
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
match (left, right) { match (left, right) {
@ -402,7 +407,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_add(&'a mut self) -> Result<(), Error> { fn op_add(&mut self) -> Result<(), Error> {
// Adds the previous two items in the stack. // Adds the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
@ -411,7 +416,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_sub(&'a mut self) -> Result<(), Error> { fn op_sub(&mut self) -> Result<(), Error> {
// Subtracts the previous two items in the stack. // Subtracts the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
@ -420,7 +425,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_mul(&'a mut self) -> Result<(), Error> { fn op_mul(&mut self) -> Result<(), Error> {
// Multiplies the previous two items in the stack. // Multiplies the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
@ -429,7 +434,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_div(&'a mut self) -> Result<(), Error> { fn op_div(&mut self) -> Result<(), Error> {
// Divides the previous two items in the stack. // Divides the previous two items in the stack.
let left = self.pop()?; let left = self.pop()?;
let right = self.pop()?; let right = self.pop()?;
@ -438,7 +443,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_bind(&'a mut self) -> Result<(), Error> { fn op_bind(&mut self) -> Result<(), Error> {
// pop val off stack. // pop val off stack.
let val = dbg!(self.pop())?; let val = dbg!(self.pop())?;
// pop name off stack. // pop name off stack.
@ -451,7 +456,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_field(&'a mut self) -> Result<(), Error> { fn op_field(&mut self) -> Result<(), Error> {
// Add a Composite field value to a tuple on the stack // Add a Composite field value to a tuple on the stack
// get value from stack // get value from stack
let val = self.pop()?; let val = self.pop()?;
@ -474,7 +479,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_element(&'a mut self) -> Result<(), Error> { fn op_element(&mut self) -> Result<(), Error> {
// get element from stack. // get element from stack.
let val = self.pop()?; let val = self.pop()?;
// get next value. It should be a Composite list. // get next value. It should be a Composite list.
@ -490,7 +495,7 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn op_copy(&'a mut self) -> Result<(), Error> { fn op_copy(&mut self) -> Result<(), Error> {
// TODO Use Cow pointers for this? // TODO Use Cow pointers for this?
// get next value. It should be a Module. // get next value. It should be a Module.
let tgt = self.pop()?; let tgt = self.pop()?;
@ -546,10 +551,10 @@ impl<'a> VM<'a> {
} }
fn merge_field_into_tuple( fn merge_field_into_tuple(
&'a self, &self,
src_fields: &'a mut Vec<(String, Value<'a>)>, src_fields: &'a mut Vec<(String, Value)>,
name: String, name: String,
value: Value<'a>, value: Value,
) -> Result<(), Error> { ) -> Result<(), Error> {
for fld in src_fields.iter_mut() { for fld in src_fields.iter_mut() {
if fld.0 == name { if fld.0 == name {
@ -561,12 +566,12 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
fn push(&'a mut self, p: Value<'a>) -> Result<(), Error> { fn push(&mut self, p: Value) -> Result<(), Error> {
self.stack.push(p); self.stack.push(p);
Ok(()) Ok(())
} }
fn binding_push(&'a mut self, name: String, val: Value) -> Result<(), Error> { fn binding_push(&mut self, name: String, val: Value) -> Result<(), Error> {
if self.symbols.is_bound(&name) { if self.symbols.is_bound(&name) {
return Err(Error {}); return Err(Error {});
} }
@ -574,21 +579,21 @@ impl<'a> VM<'a> {
Ok(()) Ok(())
} }
pub fn get_binding(&'a mut self, name: &str) -> Result<&'a Value, Error> { pub fn get_binding(&'a self, name: &str) -> Result<&Value, Error> {
match self.symbols.get(name) { match self.symbols.get(name) {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(Error {}), None => Err(Error {}),
} }
} }
fn pop(&'a mut self) -> Result<Value, Error> { fn pop(&mut self) -> Result<Value, Error> {
match self.stack.pop() { match self.stack.pop() {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(Error {}), None => Err(Error {}),
} }
} }
fn mul(&'a self, left: Value, right: Value) -> Result<Primitive, Error> { fn mul(&self, left: Value, right: Value) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), P(Int(ii))) => Int(i * ii), (P(Int(i)), P(Int(ii))) => Int(i * ii),
(P(Float(f)), P(Float(ff))) => Float(f * ff), (P(Float(f)), P(Float(ff))) => Float(f * ff),
@ -596,7 +601,7 @@ impl<'a> VM<'a> {
}) })
} }
fn div(&'a self, left: Value, right: Value) -> Result<Primitive, Error> { fn div(&self, left: Value, right: Value) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), P(Int(ii))) => Int(i / ii), (P(Int(i)), P(Int(ii))) => Int(i / ii),
(P(Float(f)), P(Float(ff))) => Float(f / ff), (P(Float(f)), P(Float(ff))) => Float(f / ff),
@ -604,7 +609,7 @@ impl<'a> VM<'a> {
}) })
} }
fn sub(&'a self, left: Value, right: Value) -> Result<Primitive, Error> { fn sub(&self, left: Value, right: Value) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), Value::P(Int(ii))) => Int(i - ii), (P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
(P(Float(f)), Value::P(Float(ff))) => Float(f - ff), (P(Float(f)), Value::P(Float(ff))) => Float(f - ff),
@ -612,7 +617,7 @@ impl<'a> VM<'a> {
}) })
} }
fn add(&'a self, left: Value, right: Value) -> Result<Primitive, Error> { fn add(&self, left: Value, right: Value) -> Result<Primitive, Error> {
Ok(match (left, right) { Ok(match (left, right) {
(P(Int(i)), Value::P(Int(ii))) => Int(i + ii), (P(Int(i)), Value::P(Int(ii))) => Int(i + ii),
(P(Float(f)), Value::P(Float(ff))) => Float(f + ff), (P(Float(f)), Value::P(Float(ff))) => Float(f + ff),

View File

@ -11,17 +11,18 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::rc::Rc;
use super::{Error, Op}; use super::{Error, Op};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct OpPointer<'a> { pub struct OpPointer {
pub ops: &'a Vec<Op>, pub ops: Rc<Vec<Op>>,
pub ptr: Option<usize>, pub ptr: Option<usize>,
} }
impl<'a> OpPointer<'a> { impl OpPointer {
pub fn new(ops: &'a Vec<Op>) -> Self { pub fn new(ops: Rc<Vec<Op>>) -> Self {
// If we load an empty program what happens? // If we load an empty program what happens?
Self { Self {
ops: ops, ops: ops,
@ -29,7 +30,7 @@ impl<'a> OpPointer<'a> {
} }
} }
pub fn next(&mut self) -> Option<usize> { pub fn next(&mut self) -> Option<&Op> {
if let Some(i) = self.ptr { if let Some(i) = self.ptr {
let nxt = i + 1; let nxt = i + 1;
if nxt < self.ops.len() { if nxt < self.ops.len() {
@ -40,7 +41,7 @@ impl<'a> OpPointer<'a> {
} else if self.ops.len() != 0 { } else if self.ops.len() != 0 {
self.ptr = Some(0); self.ptr = Some(0);
} }
self.ptr self.op()
} }
pub fn jump(&mut self, ptr: usize) -> Result<(), Error> { pub fn jump(&mut self, ptr: usize) -> Result<(), Error> {
@ -58,9 +59,16 @@ impl<'a> OpPointer<'a> {
None None
} }
pub fn idx(&self) -> Result<usize, Error> {
match self.ptr {
Some(ptr) => Ok(ptr),
None => dbg!(Err(Error {})),
}
}
pub fn snapshot(&self) -> Self { pub fn snapshot(&self) -> Self {
Self { Self {
ops: self.ops, ops: self.ops.clone(),
ptr: None, ptr: None,
} }
} }

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::rc::Rc;
use super::scope::Stack; use super::scope::Stack;
use super::Composite::{List, Tuple}; use super::Composite::{List, Tuple};
@ -26,7 +27,7 @@ use super::VM;
macro_rules! assert_cases { macro_rules! assert_cases {
(__impl__ $cases:expr) => { (__impl__ $cases:expr) => {
for case in $cases.drain(0..) { for case in $cases.drain(0..) {
let mut vm = VM::new(&case.0); let mut vm = VM::new(Rc::new(case.0));
vm.run().unwrap(); vm.run().unwrap();
assert_eq!(dbg!(vm.pop()).unwrap(), case.1); assert_eq!(dbg!(vm.pop()).unwrap(), case.1);
} }
@ -87,7 +88,7 @@ fn test_bind_op() {
)]; )];
for case in cases.drain(0..) { for case in cases.drain(0..) {
let mut vm = VM::new(&case.0); let mut vm = VM::new(Rc::new(case.0));
vm.run().unwrap(); vm.run().unwrap();
let (name, result) = case.1; let (name, result) = case.1;
let v = vm.get_binding(name).unwrap(); let v = vm.get_binding(name).unwrap();