mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Implement Jumping
This commit is contained in:
parent
04480663e8
commit
dc7437a8c1
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user