DEV: Implement Jumping

This commit is contained in:
Jeremy Wall 2019-06-30 22:21:28 -05:00
parent 04480663e8
commit dc7437a8c1
2 changed files with 57 additions and 18 deletions

View File

@ -62,13 +62,18 @@ pub enum Op {
Sym(String),
// Complex Type ops
InitTuple,
FIELD,
Field,
InitList,
Element,
// Operations
Cp,
// record
InitThunk,
// Control Flow
Select,
Bang,
Jump(usize),
Noop,
// Pending Computation
InitThunk(usize),
Return,
// - Call
// Runtime hooks
@ -86,6 +91,7 @@ pub struct Error {}
pub struct VM {
stack: Vec<Value>,
// TODO(jwall): We may want to preserve order on these.
symbols: BTreeMap<String, Value>,
ops: OpPointer,
}
@ -114,13 +120,19 @@ impl VM {
Op::InitList => self.composite_push(List(Vec::new()))?,
// Add a composite tuple value to the stack
Op::InitTuple => self.composite_push(Tuple(Vec::new()))?,
Op::FIELD => self.op_field()?,
Op::Field => self.op_field()?,
Op::Element => self.op_element()?,
Op::Cp => self.op_copy()?,
Op::InitThunk => self.op_thunk(idx)?,
Op::Select => self.op_select()?,
Op::Bang => return Err(Error {}),
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?,
Op::Noop => {
// Do nothing
}
Op::Return => {
// TODO(jwall): This means we return back to the start of the frame.
}
Op::Jump(jp) => self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(*jp))?,
Op::Pop => {
self.pop()?;
}
@ -129,9 +141,20 @@ impl VM {
Ok(())
}
fn op_thunk(&mut self, idx: usize) -> Result<(), Error> {
// TODO(jwall): Record the position in the op codes.
fn op_thunk(&mut self, idx: usize, jp: usize) -> Result<(), Error> {
self.push(Value::T(idx))?;
self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(jp))?;
// TODO(jwall): Skip over the rest until we reach the return?
Ok(())
}
fn op_select(&mut self) -> Result<(), Error> {
// first get our compare value from the stack
let search_field = self.pop()?;
// next get our default value from the stack
let default_field = self.pop()?;
// finally get our fields from the stack
let fields = self.pop()?;
Ok(())
}

View File

@ -13,9 +13,12 @@
// limitations under the License.
use super::Composite::{List, Tuple};
use super::Op::{Add, Bind, Cp, Div, Element, InitList, InitTuple, Mul, Sub, Sym, Val, FIELD};
use super::Op::{
Add, Bind, Cp, Div, Element, Field, InitList, InitThunk, InitTuple, Jump, Mul, Noop, Sub, Sym,
Val,
};
use super::Primitive::{Float, Int, Str};
use super::Value::{C, P};
use super::Value::{C, P, T};
use super::VM;
#[test]
@ -118,7 +121,7 @@ fn test_tuple_ops() {
let mut cases = vec![
(vec![InitTuple], C(Tuple(Vec::new()))),
(
vec![InitTuple, Val(Str("foo".to_owned())), Val(Int(1)), FIELD],
vec![InitTuple, Val(Str("foo".to_owned())), Val(Int(1)), Field],
C(Tuple(vec![("foo".to_owned(), P(Int(1)))])),
),
(
@ -126,10 +129,10 @@ fn test_tuple_ops() {
InitTuple,
Sym("bar".to_owned()),
Val(Str("quux".to_owned())),
FIELD,
Field,
Val(Str("foo".to_owned())),
Val(Int(1)),
FIELD,
Field,
],
C(Tuple(vec![
("bar".to_owned(), P(Str("quux".to_owned()))),
@ -141,14 +144,14 @@ fn test_tuple_ops() {
InitTuple,
Sym("bar".to_owned()),
Val(Str("quux".to_owned())),
FIELD,
Field,
Val(Str("foo".to_owned())),
Val(Int(1)),
FIELD,
Field,
Cp,
Val(Str("foo".to_owned())),
Val(Int(2)),
FIELD,
Field,
],
C(Tuple(vec![
("bar".to_owned(), P(Str("quux".to_owned()))),
@ -162,14 +165,14 @@ fn test_tuple_ops() {
Val(Str("ux".to_owned())),
Val(Str("qu".to_owned())),
Add,
FIELD,
Field,
Val(Str("foo".to_owned())),
Val(Int(1)),
FIELD,
Field,
Cp,
Val(Str("foo".to_owned())),
Val(Int(2)),
FIELD,
Field,
],
C(Tuple(vec![
("bar".to_owned(), P(Str("quux".to_owned()))),
@ -183,3 +186,16 @@ fn test_tuple_ops() {
assert_eq!(vm.pop().unwrap(), case.1);
}
}
#[test]
fn test_jump_ops() {
let mut cases = vec![
(vec![InitThunk(1), Val(Int(1)), Noop], T(0)),
(vec![Jump(1), Val(Int(1)), Noop, Val(Int(1))], P(Int(1))),
];
for case in cases.drain(0..) {
let mut vm = VM::new(case.0);
vm.run().unwrap();
assert_eq!(vm.pop().unwrap(), case.1);
}
}