mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Unit test verifying we can implement a select expression.
* Also unify our jumps as relative jumps
This commit is contained in:
parent
aac263be2c
commit
996d8821d7
@ -99,15 +99,17 @@ pub enum Op {
|
|||||||
Cp,
|
Cp,
|
||||||
// Control Flow
|
// Control Flow
|
||||||
Bang,
|
Bang,
|
||||||
Jump(usize),
|
Jump(i32),
|
||||||
JumpIfTrue(usize),
|
JumpIfTrue(i32),
|
||||||
JumpIfFalse(usize),
|
JumpIfFalse(i32),
|
||||||
|
JumpIfNotEqual(i32),
|
||||||
// FIXME(jwall): Short circuiting operations
|
// FIXME(jwall): Short circuiting operations
|
||||||
// - And(usize)
|
// - And(usize)
|
||||||
// - Or(usize)
|
// - Or(usize)
|
||||||
// Spacer operation, Does nothing.
|
// Spacer operation, Does nothing.
|
||||||
Noop,
|
Noop,
|
||||||
// Pending Computation
|
// Pending Computation
|
||||||
|
// TODO(jwall): This is unnecessary. Remove it.
|
||||||
InitThunk(usize),
|
InitThunk(usize),
|
||||||
Module(usize),
|
Module(usize),
|
||||||
Func(usize),
|
Func(usize),
|
||||||
@ -153,8 +155,8 @@ impl<'a> VM<'a> {
|
|||||||
pub fn run(&mut self) -> Result<(), Error> {
|
pub fn run(&mut self) -> Result<(), Error> {
|
||||||
while self.ops.next().is_some() {
|
while self.ops.next().is_some() {
|
||||||
let idx = self.ops.ptr.unwrap();
|
let idx = self.ops.ptr.unwrap();
|
||||||
match self.ops.op().unwrap() {
|
match dbg!(self.ops.op()).unwrap() {
|
||||||
Op::Val(p) => self.push(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())?,
|
||||||
Op::Add => self.op_add()?,
|
Op::Add => self.op_add()?,
|
||||||
@ -174,15 +176,17 @@ impl<'a> VM<'a> {
|
|||||||
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()?,
|
||||||
//TODO(jwall): Should this whould take a user provided message?
|
//TODO(jwall): Should this take a user provided message?
|
||||||
Op::Bang => return Err(Error {}),
|
Op::Bang => return dbg!(Err(Error {})),
|
||||||
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?,
|
// TODO(jwall): Remove this
|
||||||
|
Op::InitThunk(jp) => self.op_thunk(idx, *jp as i32)?,
|
||||||
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::JumpIfNotEqual(jp) => self.op_jump_if_not_equal(*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()?,
|
||||||
@ -200,12 +204,17 @@ impl<'a> VM<'a> {
|
|||||||
self.push(val)
|
self.push(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_jump(&mut self, jp: usize) -> Result<(), Error> {
|
fn op_jump(&mut self, jp: i32) -> Result<(), Error> {
|
||||||
self.ops.jump(self.ops.ptr.map(|v| v + jp).unwrap_or(jp))?;
|
self.ops.jump(
|
||||||
|
self.ops
|
||||||
|
.ptr
|
||||||
|
.map(|v| (v as i32 + jp) as usize)
|
||||||
|
.unwrap_or(jp as usize),
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_jump_if_true(&mut self, jp: usize) -> 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)?;
|
||||||
@ -214,7 +223,7 @@ impl<'a> VM<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_jump_if_false(&mut self, jp: usize) -> 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)?;
|
||||||
@ -223,6 +232,21 @@ impl<'a> VM<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn op_jump_if_not_equal(&mut self, jp: i32) -> Result<(), Error> {
|
||||||
|
// pop field value off
|
||||||
|
let field_name = dbg!(self.pop())?;
|
||||||
|
// pop search value off
|
||||||
|
let search = dbg!(self.pop())?;
|
||||||
|
// compare them.
|
||||||
|
if dbg!(field_name != search) {
|
||||||
|
self.op_jump(dbg!(jp))?;
|
||||||
|
self.push(dbg!(search))?;
|
||||||
|
}
|
||||||
|
dbg!(self.ops.ptr.unwrap());
|
||||||
|
// if they aren't equal then push search value back on and jump
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn op_module(&mut self, idx: usize, jptr: usize) -> Result<(), Error> {
|
fn op_module(&mut self, idx: usize, jptr: usize) -> Result<(), Error> {
|
||||||
let (result_ptr, flds) = match self.pop()? {
|
let (result_ptr, flds) = match self.pop()? {
|
||||||
C(Tuple(flds)) => (None, flds),
|
C(Tuple(flds)) => (None, flds),
|
||||||
@ -300,7 +324,7 @@ impl<'a> VM<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_thunk(&mut self, idx: usize, jp: usize) -> 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)
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
use super::scope::Stack;
|
use super::scope::Stack;
|
||||||
use super::Composite::{List, Tuple};
|
use super::Composite::{List, Tuple};
|
||||||
use super::Op::{
|
use super::Op::{
|
||||||
Add, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, InitList, InitThunk, InitTuple,
|
Add, Bang, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, InitList, InitThunk,
|
||||||
Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Return, Sub, Sym, Val,
|
InitTuple, Jump, JumpIfFalse, JumpIfNotEqual, JumpIfTrue, Module, Mul, Noop, Return, Sub, Sym,
|
||||||
|
Val,
|
||||||
};
|
};
|
||||||
use super::Primitive::{Bool, Float, Int, Str};
|
use super::Primitive::{Bool, Float, Int, Str};
|
||||||
use super::Value::{C, P, T};
|
use super::Value::{C, P, T};
|
||||||
@ -27,7 +28,7 @@ macro_rules! assert_cases {
|
|||||||
for case in $cases.drain(0..) {
|
for case in $cases.drain(0..) {
|
||||||
let mut vm = VM::new(&case.0);
|
let mut vm = VM::new(&case.0);
|
||||||
vm.run().unwrap();
|
vm.run().unwrap();
|
||||||
assert_eq!(vm.pop().unwrap(), case.1);
|
assert_eq!(dbg!(vm.pop()).unwrap(), case.1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -186,7 +187,6 @@ fn test_tuple_ops() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_jump_ops() {
|
fn test_jump_ops() {
|
||||||
assert_cases!(
|
assert_cases!(
|
||||||
vec![InitThunk(1), Val(Int(1)), Noop] => T(0),
|
|
||||||
vec![Jump(1), Val(Int(1)), Noop, Val(Int(1))] => P(Int(1)),
|
vec![Jump(1), Val(Int(1)), Noop, Val(Int(1))] => P(Int(1)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -400,6 +400,24 @@ fn test_module_call() {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_select_short_circuit() {
|
||||||
|
assert_cases![
|
||||||
|
vec![
|
||||||
|
Sym("field".to_owned()), // 0 // search field
|
||||||
|
Sym("not_field".to_owned()), // 1 // first field to compare
|
||||||
|
JumpIfNotEqual(2), // 2
|
||||||
|
Val(Str("not our value".to_owned())), // 3
|
||||||
|
Jump(4), // 4
|
||||||
|
Sym("field".to_owned()), // 5 // second field to compare
|
||||||
|
JumpIfNotEqual(2), // 6
|
||||||
|
Val(Int(1)), // 7
|
||||||
|
Jump(1), // 8
|
||||||
|
Bang, // 9
|
||||||
|
] => P(Int(1)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scope_stacks() {
|
fn test_scope_stacks() {
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user