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), Sym(String),
// Complex Type ops // Complex Type ops
InitTuple, InitTuple,
FIELD, Field,
InitList, InitList,
Element, Element,
// Operations // Operations
Cp, Cp,
// record // Control Flow
InitThunk, Select,
Bang,
Jump(usize),
Noop,
// Pending Computation
InitThunk(usize),
Return, Return,
// - Call // - Call
// Runtime hooks // Runtime hooks
@ -86,6 +91,7 @@ pub struct Error {}
pub struct VM { pub struct VM {
stack: Vec<Value>, stack: Vec<Value>,
// TODO(jwall): We may want to preserve order on these.
symbols: BTreeMap<String, Value>, symbols: BTreeMap<String, Value>,
ops: OpPointer, ops: OpPointer,
} }
@ -114,13 +120,19 @@ impl VM {
Op::InitList => self.composite_push(List(Vec::new()))?, Op::InitList => self.composite_push(List(Vec::new()))?,
// Add a composite tuple value to the stack // Add a composite tuple value to the stack
Op::InitTuple => self.composite_push(Tuple(Vec::new()))?, Op::InitTuple => self.composite_push(Tuple(Vec::new()))?,
Op::FIELD => self.op_field()?, Op::Field => self.op_field()?,
Op::Element => self.op_element()?, Op::Element => self.op_element()?,
Op::Cp => self.op_copy()?, 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 => { Op::Return => {
// TODO(jwall): This means we return back to the start of the frame. // 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 => { Op::Pop => {
self.pop()?; self.pop()?;
} }
@ -129,9 +141,20 @@ impl VM {
Ok(()) Ok(())
} }
fn op_thunk(&mut self, idx: usize) -> Result<(), Error> { fn op_thunk(&mut self, idx: usize, jp: usize) -> Result<(), Error> {
// TODO(jwall): Record the position in the op codes.
self.push(Value::T(idx))?; 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(()) Ok(())
} }

View File

@ -13,9 +13,12 @@
// limitations under the License. // limitations under the License.
use super::Composite::{List, Tuple}; 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::Primitive::{Float, Int, Str};
use super::Value::{C, P}; use super::Value::{C, P, T};
use super::VM; use super::VM;
#[test] #[test]
@ -118,7 +121,7 @@ fn test_tuple_ops() {
let mut cases = vec![ let mut cases = vec![
(vec![InitTuple], C(Tuple(Vec::new()))), (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)))])), C(Tuple(vec![("foo".to_owned(), P(Int(1)))])),
), ),
( (
@ -126,10 +129,10 @@ fn test_tuple_ops() {
InitTuple, InitTuple,
Sym("bar".to_owned()), Sym("bar".to_owned()),
Val(Str("quux".to_owned())), Val(Str("quux".to_owned())),
FIELD, Field,
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Val(Int(1)), Val(Int(1)),
FIELD, Field,
], ],
C(Tuple(vec![ C(Tuple(vec![
("bar".to_owned(), P(Str("quux".to_owned()))), ("bar".to_owned(), P(Str("quux".to_owned()))),
@ -141,14 +144,14 @@ fn test_tuple_ops() {
InitTuple, InitTuple,
Sym("bar".to_owned()), Sym("bar".to_owned()),
Val(Str("quux".to_owned())), Val(Str("quux".to_owned())),
FIELD, Field,
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Val(Int(1)), Val(Int(1)),
FIELD, Field,
Cp, Cp,
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Val(Int(2)), Val(Int(2)),
FIELD, Field,
], ],
C(Tuple(vec![ C(Tuple(vec![
("bar".to_owned(), P(Str("quux".to_owned()))), ("bar".to_owned(), P(Str("quux".to_owned()))),
@ -162,14 +165,14 @@ fn test_tuple_ops() {
Val(Str("ux".to_owned())), Val(Str("ux".to_owned())),
Val(Str("qu".to_owned())), Val(Str("qu".to_owned())),
Add, Add,
FIELD, Field,
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Val(Int(1)), Val(Int(1)),
FIELD, Field,
Cp, Cp,
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
Val(Int(2)), Val(Int(2)),
FIELD, Field,
], ],
C(Tuple(vec![ C(Tuple(vec![
("bar".to_owned(), P(Str("quux".to_owned()))), ("bar".to_owned(), P(Str("quux".to_owned()))),
@ -183,3 +186,16 @@ fn test_tuple_ops() {
assert_eq!(vm.pop().unwrap(), case.1); 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);
}
}