use cervine::Cow;
use super::*;
pub fn add(vm: &mut VM, (lhs, rhs): (RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut().write(lhs + rhs);
Ok(())
}
pub fn clamp(vm: &mut VM, (value, a, b): (RantyValue, RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut().write(util::clamp(value, a, b));
Ok(())
}
pub fn mul(vm: &mut VM, (lhs, rhs): (RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut().write(lhs * rhs);
Ok(())
}
pub fn mul_add(
vm: &mut VM,
(lhs, mhs, rhs): (RantyValue, RantyValue, RantyValue),
) -> RantyStdResult {
vm.cur_frame_mut().write(lhs * mhs + rhs);
Ok(())
}
pub fn sub(vm: &mut VM, (lhs, rhs): (RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut().write(lhs - rhs);
Ok(())
}
pub fn div(vm: &mut VM, (lhs, rhs): (RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut().write((lhs / rhs).into_runtime_result()?);
Ok(())
}
pub fn mod_(vm: &mut VM, (lhs, rhs): (RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut().write((lhs % rhs).into_runtime_result()?);
Ok(())
}
pub fn neg(vm: &mut VM, val: RantyValue) -> RantyStdResult {
vm.cur_frame_mut().write(-val);
Ok(())
}
pub fn recip(vm: &mut VM, val: RantyValue) -> RantyStdResult {
vm.cur_frame_mut()
.write((RantyValue::Float(1.0) / val).into_runtime_result()?);
Ok(())
}
pub fn floor(vm: &mut VM, val: RantyValue) -> RantyStdResult {
let val_result = match val {
RantyValue::Float(f) => RantyValue::Float(f.floor()),
RantyValue::Int(i) => RantyValue::Int(i),
other => runtime_error!(
RuntimeErrorType::ArgumentError,
"cannot use floor function on '{}' value"
),
};
vm.cur_frame_mut().write(val_result);
Ok(())
}
pub fn ceil(vm: &mut VM, val: RantyValue) -> RantyStdResult {
let val_result = match val {
RantyValue::Float(f) => RantyValue::Float(f.ceil()),
RantyValue::Int(i) => RantyValue::Int(i),
other => runtime_error!(
RuntimeErrorType::ArgumentError,
"cannot use ceil function on '{}' value"
),
};
vm.cur_frame_mut().write(val_result);
Ok(())
}
pub fn frac(vm: &mut VM, val: RantyValue) -> RantyStdResult {
let val_result = match val {
RantyValue::Float(f) => RantyValue::Float(f.fract()),
other => runtime_error!(
RuntimeErrorType::ArgumentError,
"cannot use frac function on '{}' value"
),
};
vm.cur_frame_mut().write(val_result);
Ok(())
}
pub fn abs(vm: &mut VM, num: RantyValue) -> RantyStdResult {
vm.cur_frame_mut().write(num.abs().into_runtime_result()?);
Ok(())
}
pub fn pow(vm: &mut VM, (lhs, rhs): (RantyValue, RantyValue)) -> RantyStdResult {
vm.cur_frame_mut()
.write(lhs.pow(rhs).into_runtime_result()?);
Ok(())
}
pub fn sin(vm: &mut VM, x: f64) -> RantyStdResult {
vm.cur_frame_mut().write(x.sin());
Ok(())
}
pub fn asin(vm: &mut VM, x: f64) -> RantyStdResult {
vm.cur_frame_mut().write(x.asin());
Ok(())
}
pub fn cos(vm: &mut VM, x: f64) -> RantyStdResult {
vm.cur_frame_mut().write(x.cos());
Ok(())
}
pub fn acos(vm: &mut VM, x: f64) -> RantyStdResult {
vm.cur_frame_mut().write(x.acos());
Ok(())
}
pub fn tan(vm: &mut VM, x: f64) -> RantyStdResult {
vm.cur_frame_mut().write(x.tan());
Ok(())
}
pub fn atan(vm: &mut VM, x: f64) -> RantyStdResult {
vm.cur_frame_mut().write(x.atan());
Ok(())
}
pub fn atan2(vm: &mut VM, (y, x): (f64, f64)) -> RantyStdResult {
vm.cur_frame_mut().write(y.atan2(x));
Ok(())
}
pub fn sqrt(vm: &mut VM, num: RantyNumber) -> RantyStdResult {
let result = match num {
RantyNumber::Int(i) => (i as f64).sqrt(),
RantyNumber::Float(f) => f.sqrt(),
};
vm.cur_frame_mut().write(result);
Ok(())
}
pub fn min(vm: &mut VM, values: RequiredVarArgs<RantyValue>) -> RantyStdResult {
if values.is_empty() {
return Ok(());
}
let iter = values.iter();
let mut min = None;
for val in iter {
let flat_val = match val {
RantyValue::List(list_ref) => Some(Cow::Owned(
util::min_ranty_value(list_ref.borrow().iter())
.cloned()
.unwrap_or_default(),
)),
RantyValue::Tuple(tuple_ref) => Some(Cow::Owned(
util::min_ranty_value(tuple_ref.iter())
.cloned()
.unwrap_or_default(),
)),
other => Some(Cow::Borrowed(other)),
};
if min.is_none() || flat_val < min {
min = flat_val;
}
}
vm.cur_frame_mut().write(match min.unwrap() {
Cow::Owned(val) => val,
Cow::Borrowed(val) => val.clone(),
});
Ok(())
}
pub fn max(vm: &mut VM, values: RequiredVarArgs<RantyValue>) -> RantyStdResult {
if values.is_empty() {
return Ok(());
}
let iter = values.iter();
let mut max = None;
for val in iter {
let flat_val = match val {
RantyValue::List(list_ref) => Some(Cow::Owned(
util::max_ranty_value(list_ref.borrow().iter())
.cloned()
.unwrap_or_default(),
)),
RantyValue::Tuple(tuple_ref) => Some(Cow::Owned(
util::max_ranty_value(tuple_ref.iter())
.cloned()
.unwrap_or_default(),
)),
other => Some(Cow::Borrowed(other)),
};
if max.is_none() || flat_val >= max {
max = flat_val;
}
}
vm.cur_frame_mut().write(match max.unwrap() {
Cow::Owned(val) => val,
Cow::Borrowed(val) => val.clone(),
});
Ok(())
}