DEV: Equality Ops

This commit is contained in:
Jeremy Wall 2019-06-30 22:51:47 -05:00
parent dc7437a8c1
commit 7de2e1c349
2 changed files with 171 additions and 12 deletions

View File

@ -26,6 +26,8 @@ pub enum Primitive {
Empty,
}
use Primitive::{Bool, Empty, Float, Int, Str};
#[derive(Debug, PartialEq, Clone)]
pub enum Composite {
List(Vec<Value>),
@ -45,6 +47,7 @@ pub enum Value {
// Program Pointer
T(usize),
}
use Value::{C, P, S, T};
#[derive(Debug, PartialEq, Clone)]
pub enum Op {
@ -56,6 +59,12 @@ pub enum Op {
Sub,
Div,
Mul,
// Comparison Ops
Equal,
Gt,
Lt,
GtEq,
LtEq,
// Primitive Types ops
Val(Primitive),
// A bareword for use in bindings or lookups
@ -68,7 +77,6 @@ pub enum Op {
// Operations
Cp,
// Control Flow
Select,
Bang,
Jump(usize),
Noop,
@ -116,6 +124,11 @@ impl VM {
Op::Mul => self.op_mul()?,
Op::Div => self.op_div()?,
Op::Bind => self.op_bind()?,
Op::Equal => self.op_equal()?,
Op::Gt => self.op_gt()?,
Op::Lt => self.op_lt()?,
Op::GtEq => self.op_gteq()?,
Op::LtEq => self.op_lteq()?,
// Add a Composite list value to the stack
Op::InitList => self.composite_push(List(Vec::new()))?,
// Add a composite tuple value to the stack
@ -123,7 +136,6 @@ impl VM {
Op::Field => self.op_field()?,
Op::Element => self.op_element()?,
Op::Cp => self.op_copy()?,
Op::Select => self.op_select()?,
Op::Bang => return Err(Error {}),
Op::InitThunk(jp) => self.op_thunk(idx, *jp)?,
Op::Noop => {
@ -148,13 +160,70 @@ impl VM {
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()?;
fn op_equal(&mut self) -> Result<(), Error> {
let left = self.pop()?;
let right = self.pop()?;
self.push(Value::P(Bool(left == right)))?;
Ok(())
}
fn op_gt(&mut self) -> Result<(), Error> {
let left = self.pop()?;
let right = self.pop()?;
match (left, right) {
(P(Int(i)), P(Int(ii))) => {
self.push(Value::P(Bool(i > ii)))?;
}
(P(Float(f)), P(Float(ff))) => {
self.push(Value::P(Bool(f > ff)))?;
}
_ => return Err(Error {}),
}
Ok(())
}
fn op_lt(&mut self) -> Result<(), Error> {
let left = self.pop()?;
let right = self.pop()?;
match (left, right) {
(P(Int(i)), P(Int(ii))) => {
self.push(Value::P(Bool(i < ii)))?;
}
(P(Float(f)), P(Float(ff))) => {
self.push(Value::P(Bool(f < ff)))?;
}
_ => return Err(Error {}),
}
Ok(())
}
fn op_lteq(&mut self) -> Result<(), Error> {
let left = self.pop()?;
let right = self.pop()?;
match (left, right) {
(P(Int(i)), P(Int(ii))) => {
self.push(Value::P(Bool(i <= ii)))?;
}
(P(Float(f)), P(Float(ff))) => {
self.push(Value::P(Bool(f <= ff)))?;
}
_ => return Err(Error {}),
}
Ok(())
}
fn op_gteq(&mut self) -> Result<(), Error> {
let left = self.pop()?;
let right = self.pop()?;
match (left, right) {
(P(Int(i)), P(Int(ii))) => {
self.push(Value::P(Bool(i >= ii)))?;
}
(P(Float(f)), P(Float(ff))) => {
self.push(Value::P(Bool(f >= ff)))?;
}
_ => return Err(Error {}),
}
Ok(())
}

View File

@ -14,10 +14,10 @@
use super::Composite::{List, Tuple};
use super::Op::{
Add, Bind, Cp, Div, Element, Field, InitList, InitThunk, InitTuple, Jump, Mul, Noop, Sub, Sym,
Val,
Add, Bind, Cp, Div, Element, Equal, Field, InitList, InitThunk, InitTuple, Jump, JumpIfTrue,
Mul, Noop, Sub, Sym, Val,
};
use super::Primitive::{Float, Int, Str};
use super::Primitive::{Bool, Float, Int, Str};
use super::Value::{C, P, T};
use super::VM;
@ -199,3 +199,93 @@ fn test_jump_ops() {
assert_eq!(vm.pop().unwrap(), case.1);
}
}
#[test]
fn test_equality_ops() {
let mut cases = vec![
(
vec![
Val(Str("foo".to_owned())),
Val(Str("foo".to_owned())),
Equal,
],
P(Bool(true)),
),
(
vec![
Val(Str("bar".to_owned())),
Val(Str("foo".to_owned())),
Equal,
],
P(Bool(false)),
),
(vec![Val(Int(1)), Val(Int(1)), Equal], P(Bool(true))),
(vec![Val(Int(1)), Val(Int(2)), Equal], P(Bool(false))),
(vec![Val(Bool(true)), Val(Bool(true)), Equal], P(Bool(true))),
(
vec![Val(Bool(false)), Val(Bool(false)), Equal],
P(Bool(true)),
),
(
vec![Val(Bool(true)), Val(Bool(false)), Equal],
P(Bool(false)),
),
(
vec![
InitTuple,
Val(Str("foo".to_owned())),
Val(Int(1)),
Field,
InitTuple,
Val(Str("foo".to_owned())),
Val(Int(1)),
Field,
Equal,
],
P(Bool(true)),
),
(
vec![
InitTuple,
Val(Str("foo".to_owned())),
Val(Int(1)),
Field,
InitTuple,
Val(Str("bar".to_owned())),
Val(Int(1)),
Field,
Equal,
],
P(Bool(false)),
),
(
vec![
InitList,
Val(Str("foo".to_owned())),
Element,
InitList,
Val(Str("foo".to_owned())),
Element,
Equal,
],
P(Bool(true)),
),
(
vec![
InitList,
Val(Str("foo".to_owned())),
Element,
InitList,
Val(Str("bar".to_owned())),
Element,
Equal,
],
P(Bool(false)),
),
];
for case in cases.drain(0..) {
let mut vm = VM::new(case.0);
vm.run().unwrap();
assert_eq!(vm.pop().unwrap(), case.1);
}
}