use crate::value::Value;
use crate::VMError;
use std::ops::Div;
impl<'vm> Div for Value<'vm> {
type Output = Value<'vm>;
fn div(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Value::Error(v), _) => Value::Error(v),
(_, Value::Error(v)) => Value::Error(v),
(Value::None, _) => Value::None,
(lhs, Value::None) => Value::Error(VMError::RuntimeError(format!(
"Cannot divide {} by 0/none",
lhs
))),
(Value::Bool(a), Value::Bool(b)) => Value::Bool(a | b),
(Value::Bool(a), b) => Value::Bool(a | b.to_bool()),
(b, Value::Bool(a)) => Value::Bool(a | b.to_bool()),
(Value::Number(a), Value::Number(b)) => {
if b.is_zero() {
return Value::Error(VMError::RuntimeError(format!(
"Cannot divide {} by 0/none",
a
)));
}
match a / b {
Ok(n) => Value::Number(n),
Err(e) => Value::Error(e),
}
}
(Value::String(a), Value::String(b)) => {
let result = a.split(b.as_str());
Value::List(result.map(|s| Value::String(s.to_string())).collect())
}
(Value::String(a), b) => {
let b = b.to_string();
let result = a.split(b.as_str());
Value::List(result.map(|s| Value::String(s.to_string())).collect())
}
_ => todo!(),
}
}
}
#[cfg(test)]
mod tests {
use crate::define_value_tests;
use crate::number::Number;
use crate::value::Value;
use crate::VMError::RuntimeError;
define_value_tests! {
/ {
test_none_div_none => (Value::None, Value::None, Value::None);
test_none_bool_false_div_none => (Value::Bool(false), Value::None, Value::Error(RuntimeError("Cannot divide false by 0/none".to_string())));
test_bool_true_div_none => (Value::Bool(true), Value::None, Value::Error(RuntimeError("Cannot divide true by 0/none".to_string())));
test_none_bool_true_div_true => (Value::None, Value::Bool(true), Value::None);
test_false_bool_true_div_true => (Value::Bool(false), Value::Bool(true), Value::Bool(true));
test_false_0_div_true => (Value::Bool(false), Value::Number(Number::UInt(0)), Value::Bool(false));
test_true_0_div_true => (Value::Bool(true), Value::Number(Number::UInt(0)), Value::Number(Number::UInt(1)));
}
}
}