From dc7437a8c1e223e90b232a2d8790b9a26fab8066 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Sun, 30 Jun 2019 22:21:28 -0500 Subject: [PATCH] DEV: Implement Jumping --- src/build/opcode/mod.rs | 37 ++++++++++++++++++++++++++++++------- src/build/opcode/test.rs | 38 +++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index c6c5b5f..36005dc 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -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, + // TODO(jwall): We may want to preserve order on these. symbols: BTreeMap, 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(()) } diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index eaabbcb..309a8c9 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -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); + } +}