Clean up value methods
This commit is contained in:
parent
f08c7c6f1f
commit
e2df823566
@ -114,63 +114,92 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
use ConcreteValue::*;
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
use Value::*;
|
||||||
|
|
||||||
|
let sum = match (self, other) {
|
||||||
|
(Concrete(Byte(left)), Concrete(Byte(right))) => {
|
||||||
|
Value::byte(left.saturating_add(*right))
|
||||||
|
}
|
||||||
|
(Concrete(Float(left)), Concrete(Float(right))) => Value::float(left + right),
|
||||||
|
(Concrete(Integer(left)), Concrete(Integer(right))) => {
|
||||||
|
Value::integer(left.saturating_add(*right))
|
||||||
|
}
|
||||||
|
(Concrete(String(left)), Concrete(String(right))) => {
|
||||||
|
Value::string(format!("{}{}", left, right))
|
||||||
|
}
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let sum = left
|
|
||||||
.add(right)
|
|
||||||
.ok_or_else(|| ValueError::CannotAdd(self.clone(), other.clone()))?;
|
|
||||||
|
|
||||||
Ok(Value::Concrete(sum))
|
Ok(sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
use ConcreteValue::*;
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
use Value::*;
|
||||||
|
|
||||||
|
let different = match (self, other) {
|
||||||
|
(Concrete(Byte(left)), Concrete(Byte(right))) => {
|
||||||
|
Value::byte(left.saturating_sub(*right))
|
||||||
|
}
|
||||||
|
(Concrete(Float(left)), Concrete(Float(right))) => Value::float(left - right),
|
||||||
|
(Concrete(Integer(left)), Concrete(Integer(right))) => {
|
||||||
|
Value::integer(left.saturating_sub(*right))
|
||||||
|
}
|
||||||
_ => return Err(ValueError::CannotSubtract(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotSubtract(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let difference = left
|
|
||||||
.subtract(right)
|
|
||||||
.ok_or_else(|| ValueError::CannotSubtract(self.clone(), other.clone()))?;
|
|
||||||
|
|
||||||
Ok(Value::Concrete(difference))
|
Ok(different)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
use ConcreteValue::*;
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
use Value::*;
|
||||||
_ => return Err(ValueError::CannotMultiply(self.clone(), other.clone())),
|
|
||||||
};
|
|
||||||
let product = left
|
|
||||||
.multiply(right)
|
|
||||||
.ok_or_else(|| ValueError::CannotMultiply(self.clone(), other.clone()))?;
|
|
||||||
|
|
||||||
Ok(Value::Concrete(product))
|
let product = match (self, other) {
|
||||||
|
(Concrete(Byte(left)), Concrete(Byte(right))) => {
|
||||||
|
Value::byte(left.saturating_mul(*right))
|
||||||
|
}
|
||||||
|
(Concrete(Float(left)), Concrete(Float(right))) => Value::float(left * right),
|
||||||
|
(Concrete(Integer(left)), Concrete(Integer(right))) => {
|
||||||
|
Value::integer(left.saturating_mul(*right))
|
||||||
|
}
|
||||||
|
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(product)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
use ConcreteValue::*;
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
use Value::*;
|
||||||
|
|
||||||
|
let product = match (self, other) {
|
||||||
|
(Concrete(Byte(left)), Concrete(Byte(right))) => {
|
||||||
|
Value::byte(left.saturating_div(*right))
|
||||||
|
}
|
||||||
|
(Concrete(Float(left)), Concrete(Float(right))) => Value::float(left / right),
|
||||||
|
(Concrete(Integer(left)), Concrete(Integer(right))) => {
|
||||||
|
Value::integer(left.saturating_div(*right))
|
||||||
|
}
|
||||||
_ => return Err(ValueError::CannotDivide(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotDivide(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let quotient = left
|
|
||||||
.divide(right)
|
|
||||||
.ok_or_else(|| ValueError::CannotDivide(self.clone(), other.clone()))?;
|
|
||||||
|
|
||||||
Ok(Value::Concrete(quotient))
|
Ok(product)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
let (left, right) = match (self, other) {
|
use ConcreteValue::*;
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
use Value::*;
|
||||||
|
|
||||||
|
let product = match (self, other) {
|
||||||
|
(Concrete(Byte(left)), Concrete(Byte(right))) => Value::byte(left % right),
|
||||||
|
(Concrete(Float(left)), Concrete(Float(right))) => Value::float(left % right),
|
||||||
|
(Concrete(Integer(left)), Concrete(Integer(right))) => Value::integer(left % right),
|
||||||
_ => return Err(ValueError::CannotModulo(self.clone(), other.clone())),
|
_ => return Err(ValueError::CannotModulo(self.clone(), other.clone())),
|
||||||
};
|
};
|
||||||
let remainder = left
|
|
||||||
.modulo(right)
|
|
||||||
.ok_or_else(|| ValueError::CannotModulo(self.clone(), other.clone()))?;
|
|
||||||
|
|
||||||
Ok(Value::Concrete(remainder))
|
Ok(product)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> {
|
pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
@ -200,46 +229,31 @@ impl Value {
|
|||||||
Ok(Value::boolean(left == right))
|
Ok(Value::boolean(left == right))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn not_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
|
||||||
let (left, right) = match (self, other) {
|
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
|
||||||
_ => return Err(ValueError::CannotCompare(self.clone(), other.clone())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Value::boolean(left != right))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn negate(&self) -> Result<Value, ValueError> {
|
pub fn negate(&self) -> Result<Value, ValueError> {
|
||||||
let data = match self {
|
use ConcreteValue::*;
|
||||||
Value::Concrete(data) => data,
|
use Value::*;
|
||||||
|
|
||||||
|
let negated = match self {
|
||||||
|
Concrete(Integer(integer)) => Value::integer(-integer),
|
||||||
|
Concrete(Float(float)) => Value::float(-float),
|
||||||
_ => return Err(ValueError::CannotNot(self.clone())),
|
_ => return Err(ValueError::CannotNot(self.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
data.negate()
|
Ok(negated)
|
||||||
.ok_or_else(|| ValueError::CannotNot(self.clone()))
|
|
||||||
.map(Value::Concrete)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn not(&self) -> Result<Value, ValueError> {
|
pub fn not(&self) -> Result<Value, ValueError> {
|
||||||
let data = match self {
|
use ConcreteValue::*;
|
||||||
Value::Concrete(data) => data,
|
use Value::*;
|
||||||
|
|
||||||
|
let not = match self {
|
||||||
|
Concrete(Boolean(boolean)) => Value::boolean(!boolean),
|
||||||
|
Concrete(Byte(byte)) => Value::byte(!byte),
|
||||||
|
Concrete(Integer(integer)) => Value::integer(!integer),
|
||||||
_ => return Err(ValueError::CannotNot(self.clone())),
|
_ => return Err(ValueError::CannotNot(self.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
data.not()
|
Ok(not)
|
||||||
.ok_or_else(|| ValueError::CannotNot(self.clone()))
|
|
||||||
.map(Value::Concrete)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn and(&self, other: &Value) -> Result<Value, ValueError> {
|
|
||||||
let (left, right) = match (self, other) {
|
|
||||||
(Value::Concrete(left), Value::Concrete(right)) => (left, right),
|
|
||||||
_ => return Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
|
||||||
};
|
|
||||||
|
|
||||||
left.and(right)
|
|
||||||
.ok_or_else(|| ValueError::CannotAnd(self.clone(), other.clone()))
|
|
||||||
.map(Value::Concrete)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_concrete(self, vm: &mut Vm, position: Span) -> Result<Value, VmError> {
|
pub fn to_concrete(self, vm: &mut Vm, position: Span) -> Result<Value, VmError> {
|
||||||
@ -375,179 +389,6 @@ impl ConcreteValue {
|
|||||||
| ConcreteValue::Byte(_)
|
| ConcreteValue::Byte(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Byte(left), ConcreteValue::Byte(right)) => {
|
|
||||||
Some(ConcreteValue::Byte(left.saturating_add(*right)))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Float(left + right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Integer(left.saturating_add(*right)))
|
|
||||||
}
|
|
||||||
(ConcreteValue::String(left), ConcreteValue::String(right)) => {
|
|
||||||
Some(ConcreteValue::String(format!("{}{}", left, right)))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn subtract(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Byte(left), ConcreteValue::Byte(right)) => {
|
|
||||||
Some(ConcreteValue::Byte(left.saturating_sub(*right)))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Float(left - right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Integer(left.saturating_sub(*right)))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn multiply(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Byte(left), ConcreteValue::Byte(right)) => {
|
|
||||||
Some(ConcreteValue::Byte(left.saturating_mul(*right)))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Float(left * right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Integer(left.saturating_mul(*right)))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn divide(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Byte(left), ConcreteValue::Byte(right)) => {
|
|
||||||
Some(ConcreteValue::Byte(left.saturating_div(*right)))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Float(left / right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Integer(left.saturating_div(*right)))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulo(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Float(left % right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Integer(left % right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_than(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left < right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left < right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn less_than_or_equal(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left <= right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left <= right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn greater_than(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left > right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left > right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn greater_than_or_equal(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Float(left), ConcreteValue::Float(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left >= right))
|
|
||||||
}
|
|
||||||
(ConcreteValue::Integer(left), ConcreteValue::Integer(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(left >= right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn and(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Boolean(left), ConcreteValue::Boolean(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(*left && *right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn or(&self, other: &ConcreteValue) -> Option<ConcreteValue> {
|
|
||||||
match (self, other) {
|
|
||||||
(ConcreteValue::Boolean(left), ConcreteValue::Boolean(right)) => {
|
|
||||||
Some(ConcreteValue::Boolean(*left || *right))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_even(&self) -> Option<ConcreteValue> {
|
|
||||||
match self {
|
|
||||||
ConcreteValue::Integer(integer) => Some(ConcreteValue::Boolean(integer % 2 == 0)),
|
|
||||||
ConcreteValue::Float(float) => Some(ConcreteValue::Boolean(float % 2.0 == 0.0)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_odd(&self) -> Option<ConcreteValue> {
|
|
||||||
match self {
|
|
||||||
ConcreteValue::Integer(integer) => Some(ConcreteValue::Boolean(integer % 2 != 0)),
|
|
||||||
ConcreteValue::Float(float) => Some(ConcreteValue::Boolean(float % 2.0 != 0.0)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn negate(&self) -> Option<ConcreteValue> {
|
|
||||||
match self {
|
|
||||||
ConcreteValue::Byte(value) => Some(ConcreteValue::Byte(!value)),
|
|
||||||
ConcreteValue::Float(value) => Some(ConcreteValue::Float(-value)),
|
|
||||||
ConcreteValue::Integer(value) => Some(ConcreteValue::Integer(-value)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn not(&self) -> Option<ConcreteValue> {
|
|
||||||
match self {
|
|
||||||
ConcreteValue::Boolean(value) => Some(ConcreteValue::Boolean(!value)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ConcreteValue {
|
impl Display for ConcreteValue {
|
||||||
|
Loading…
Reference in New Issue
Block a user