chore: add Float

This commit is contained in:
Shunsuke Shibayama 2024-09-04 14:13:24 +09:00
parent 4bc596af00
commit de92e295dc
6 changed files with 159 additions and 153 deletions

View file

@ -91,7 +91,7 @@ impl Context {
EPSILON,
Visibility::BUILTIN_PUBLIC,
None,
ValueObj::Float(2.220446049250313e-16),
ValueObj::from(2.220446049250313e-16),
);
complex.register_builtin_py_impl(
REAL,

View file

@ -639,7 +639,7 @@ fn _list_sum(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
sum += *n as f64;
}
ValueObj::Float(n) => {
sum += *n;
sum += **n;
}
ValueObj::Inf => {
return Ok(ValueObj::Inf);
@ -657,7 +657,7 @@ fn _list_sum(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
} else if sum.round() == sum {
Ok(ValueObj::Int(sum as i32))
} else {
Ok(ValueObj::Float(sum))
Ok(ValueObj::from(sum))
}
}
_ => Err(format!("Cannot sum {arr}")),
@ -689,7 +689,7 @@ fn _list_prod(lis: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
prod *= *n as f64;
}
ValueObj::Float(n) => {
prod *= *n;
prod *= **n;
}
ValueObj::Inf => {
return Ok(ValueObj::Inf);
@ -707,7 +707,7 @@ fn _list_prod(lis: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
} else if prod.round() == prod {
Ok(ValueObj::Int(prod as i32))
} else {
Ok(ValueObj::Float(prod))
Ok(ValueObj::from(prod))
}
}
_ => Err(format!("Cannot prod {lis}")),
@ -1144,7 +1144,7 @@ pub(crate) fn abs_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
ValueObj::Nat(n) => Ok(ValueObj::Nat(n).into()),
ValueObj::Int(n) => Ok(ValueObj::Nat(n.unsigned_abs() as u64).into()),
ValueObj::Bool(b) => Ok(ValueObj::Nat(b as u64).into()),
ValueObj::Float(n) => Ok(ValueObj::Float(n.abs()).into()),
ValueObj::Float(n) => Ok(ValueObj::from(n.abs()).into()),
ValueObj::Inf => Ok(ValueObj::Inf.into()),
ValueObj::NegInf => Ok(ValueObj::Inf.into()),
_ => Err(type_mismatch("Num", num, "num")),
@ -1490,7 +1490,7 @@ pub(crate) fn succ_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<
ValueObj::Bool(b) => ValueObj::Nat(*b as u64 + 1),
ValueObj::Nat(n) => ValueObj::Nat(n + 1),
ValueObj::Int(n) => ValueObj::Int(n + 1),
ValueObj::Float(n) => ValueObj::Float(n + f64::EPSILON),
ValueObj::Float(n) => ValueObj::from(**n + f64::EPSILON),
v @ (ValueObj::Inf | ValueObj::NegInf) => v.clone(),
_ => {
return Err(type_mismatch("Number", val, "Value"));
@ -1507,7 +1507,7 @@ pub(crate) fn pred_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<
ValueObj::Bool(b) => ValueObj::Nat((*b as u64).saturating_sub(1)),
ValueObj::Nat(n) => ValueObj::Nat(n.saturating_sub(1)),
ValueObj::Int(n) => ValueObj::Int(n - 1),
ValueObj::Float(n) => ValueObj::Float(n - f64::EPSILON),
ValueObj::Float(n) => ValueObj::from(**n - f64::EPSILON),
v @ (ValueObj::Inf | ValueObj::NegInf) => v.clone(),
_ => {
return Err(type_mismatch("Number", val, "Value"));

View file

@ -171,7 +171,7 @@ impl Deserializer {
}
DataTypePrefix::BinFloat => {
let bytes = Self::consume::<8>(v);
Ok(ValueObj::Float(f64::from_le_bytes(bytes)))
Ok(ValueObj::from(f64::from_le_bytes(bytes)))
}
DataTypePrefix::ShortAscii | DataTypePrefix::ShortAsciiInterned => {
let len = v.remove(0);

View file

@ -7,7 +7,7 @@ use std::sync::atomic::AtomicUsize;
use erg_common::consts::DEBUG_MODE;
use erg_common::shared::Forkable;
use erg_common::traits::{LimitedDisplay, StructuralEq};
use erg_common::{addr, Str};
use erg_common::Str;
use erg_common::{addr_eq, log};
use super::typaram::TyParam;
@ -579,9 +579,7 @@ impl Hash for Free<TyParam> {
if let Some(lev) = self.level() {
lev.hash(state);
}
if self.is_recursive() {
addr!(self).hash(state);
} else if let Some(t) = self.get_type() {
if let Some(t) = self.get_type() {
t.hash(state);
} else if self.is_linked() {
self.crack().hash(state);
@ -768,6 +766,7 @@ impl Free<Type> {
Type::FreeVar(self.clone()).is_recursive()
}
/// interior-mut
fn _do_avoiding_recursion<O, F: FnOnce() -> O>(&self, placeholder: Option<&Type>, f: F) -> O {
let placeholder = placeholder.unwrap_or(&Type::Failure);
let is_recursive = self.is_recursive();
@ -781,10 +780,12 @@ impl Free<Type> {
res
}
/// interior-mut
pub fn do_avoiding_recursion<O, F: FnOnce() -> O>(&self, f: F) -> O {
self._do_avoiding_recursion(None, f)
}
/// interior-mut
pub fn do_avoiding_recursion_with<O, F: FnOnce() -> O>(&self, placeholder: &Type, f: F) -> O {
self._do_avoiding_recursion(Some(placeholder), f)
}

View file

@ -1451,6 +1451,7 @@ impl PartialEq for Type {
| (Self::NotImplementedType, Self::NotImplementedType)
| (Self::Ellipsis, Self::Ellipsis)
| (Self::Never, Self::Never) => true,
(Self::Failure, Self::Failure) | (Self::Uninited, Self::Uninited) => true,
(Self::Mono(l), Self::Mono(r)) => l == r,
(Self::Ref(l), Self::Ref(r)) => l == r,
(
@ -1474,7 +1475,7 @@ impl PartialEq for Type {
return_t: rr,
},
) => {
lps.len() != rps.len()
lps.len() == rps.len()
&& lps.iter().zip(rps.iter()).all(|(l, r)| l == r)
&& (lr == rr)
}
@ -1482,10 +1483,8 @@ impl PartialEq for Type {
(Self::NamedTuple(lhs), Self::NamedTuple(rhs)) => lhs == rhs,
(Self::Refinement(l), Self::Refinement(r)) => l == r,
(Self::Quantified(l), Self::Quantified(r)) => l == r,
// REVIEW: should use the same way as `structural_eq`?
(Self::And(ll, lr), Self::And(rl, rr)) | (Self::Or(ll, lr), Self::Or(rl, rr)) => {
(ll == rl && lr == rr) || (ll == rr && lr == rl)
}
(Self::And(_, _), Self::And(_, _)) => self.ands() == other.ands(),
(Self::Or(_, _), Self::Or(_, _)) => self.ors() == other.ors(),
(Self::Not(l), Self::Not(r)) => l == r,
(
Self::Poly {
@ -1521,7 +1520,6 @@ impl PartialEq for Type {
(Self::FreeVar(fv), other) if fv.is_linked() => &*fv.crack() == other,
(_self, Self::FreeVar(fv)) if fv.is_linked() => _self == &*fv.crack(),
(Self::FreeVar(l), Self::FreeVar(r)) => l == r,
(Self::Failure, Self::Failure) | (Self::Uninited, Self::Uninited) => true,
// NoneType == {None}
(Self::NoneType, Self::Refinement(refine))
| (Self::Refinement(refine), Self::NoneType) => {
@ -2134,10 +2132,11 @@ impl StructuralEq for Type {
return_t: return_t2,
},
) => {
param_ts
.iter()
.zip(param_ts2.iter())
.all(|(t, t2)| t.structural_eq(t2))
param_ts.len() == param_ts2.len()
&& param_ts
.iter()
.zip(param_ts2.iter())
.all(|(t, t2)| t.structural_eq(t2))
&& return_t.structural_eq(return_t2)
}
(Self::Quantified(quant), Self::Quantified(quant2)) => quant.structural_eq(quant2),

View file

@ -4,7 +4,7 @@
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Neg;
use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Sub};
use std::sync::Arc;
use erg_common::consts::DEBUG_MODE;
@ -571,13 +571,81 @@ impl TypeObj {
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct Float(f64);
impl fmt::Display for Float {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl Eq for Float {}
#[allow(clippy::derive_ord_xor_partial_ord)]
impl Ord for Float {
fn cmp(&self, other: &Self) -> Ordering {
self.0.partial_cmp(&other.0).unwrap()
}
}
// HACK:
impl Hash for Float {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.to_bits().hash(state);
}
}
impl Deref for Float {
type Target = f64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Neg for Float {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl Add for Float {
type Output = Self;
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl Sub for Float {
type Output = Self;
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
impl Mul for Float {
type Output = Self;
fn mul(self, other: Self) -> Self {
Self(self.0 * other.0)
}
}
impl Div for Float {
type Output = Self;
fn div(self, other: Self) -> Self {
Self(self.0 / other.0)
}
}
impl Rem for Float {
type Output = Self;
fn rem(self, other: Self) -> Self {
Self(self.0 % other.0)
}
}
/// 値オブジェクト
/// コンパイル時評価ができ、シリアライズも可能(Typeなどはシリアライズ不可)
#[derive(Clone, PartialEq, Default)]
#[derive(Clone, PartialEq, Default, Hash)]
pub enum ValueObj {
Int(i32),
Nat(u64),
Float(f64),
Float(Float),
Str(Str),
Bool(bool),
List(ArcArray<ValueObj>),
@ -919,60 +987,6 @@ impl Neg for ValueObj {
}
}
// FIXME:
impl Hash for ValueObj {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Self::Int(i) => i.hash(state),
Self::Nat(n) => n.hash(state),
// TODO:
Self::Float(f) => f.to_bits().hash(state),
Self::Str(s) => s.hash(state),
Self::Bool(b) => b.hash(state),
Self::List(lis) => lis.hash(state),
Self::UnsizedList(elem) => {
"UnsizedArray".hash(state);
elem.hash(state)
}
Self::Dict(dict) => dict.hash(state),
Self::Tuple(tup) => tup.hash(state),
Self::Set(st) => st.hash(state),
Self::Code(code) => code.hash(state),
Self::Record(rec) => rec.hash(state),
Self::DataClass { name, fields } => {
name.hash(state);
fields.hash(state);
}
Self::Subr(subr) => subr.hash(state),
Self::Type(t) => t.hash(state),
Self::None => {
"literal".hash(state);
"None".hash(state)
}
Self::Ellipsis => {
"literal".hash(state);
"Ellipsis".hash(state)
}
Self::NotImplemented => {
"literal".hash(state);
"NotImplemented".hash(state)
}
Self::NegInf => {
"literal".hash(state);
"NegInf".hash(state)
}
Self::Inf => {
"literal".hash(state);
"Inf".hash(state)
}
Self::Failure => {
"literal".hash(state);
"illegal".hash(state)
}
}
}
}
impl HasLevel for ValueObj {
fn level(&self) -> Option<usize> {
match self {
@ -1057,7 +1071,7 @@ impl From<usize> for ValueObj {
impl From<f64> for ValueObj {
fn from(item: f64) -> Self {
ValueObj::Float(item)
ValueObj::Float(Float(item))
}
}
@ -1111,7 +1125,7 @@ impl TryFrom<&ValueObj> for f64 {
match val {
ValueObj::Int(i) => Ok(*i as f64),
ValueObj::Nat(n) => Ok(*n as f64),
ValueObj::Float(f) => Ok(*f),
ValueObj::Float(f) => Ok(**f),
ValueObj::Inf => Ok(f64::INFINITY),
ValueObj::NegInf => Ok(f64::NEG_INFINITY),
ValueObj::Bool(b) => Ok(if *b { 1.0 } else { 0.0 }),
@ -1126,7 +1140,7 @@ impl TryFrom<&ValueObj> for usize {
match val {
ValueObj::Int(i) => usize::try_from(*i).map_err(|_| ()),
ValueObj::Nat(n) => usize::try_from(*n).map_err(|_| ()),
ValueObj::Float(f) => Ok(*f as usize),
ValueObj::Float(f) => Ok(**f as usize),
ValueObj::Bool(b) => Ok(if *b { 1 } else { 0 }),
_ => Err(()),
}
@ -1319,17 +1333,9 @@ impl ValueObj {
_ => content.parse::<u64>().ok().map(Self::Nat),
}
}
Type::Float => content
.replace('_', "")
.parse::<f64>()
.ok()
.map(Self::Float),
Type::Float => content.replace('_', "").parse::<f64>().ok().map(Self::from),
// TODO:
Type::Ratio => content
.replace('_', "")
.parse::<f64>()
.ok()
.map(Self::Float),
Type::Ratio => content.replace('_', "").parse::<f64>().ok().map(Self::from),
Type::Str => {
if &content[..] == "\"\"" {
Some(Self::Str(Str::from("")))
@ -1463,7 +1469,7 @@ impl ValueObj {
Self::Int(i) => Some(*i),
Self::Nat(n) => i32::try_from(*n).ok(),
Self::Bool(b) => Some(if *b { 1 } else { 0 }),
Self::Float(f) if f.round() == *f => Some(*f as i32),
Self::Float(f) if f.round() == **f => Some(**f as i32),
_ => None,
}
}
@ -1473,7 +1479,7 @@ impl ValueObj {
Self::Int(i) => Some(*i as f64),
Self::Nat(n) => Some(*n as f64),
Self::Bool(b) => Some(if *b { 1.0 } else { 0.0 }),
Self::Float(f) => Some(*f),
Self::Float(f) => Some(**f),
_ => None,
}
}
@ -1543,10 +1549,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::Float(l + r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l + r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::Int(l as i32 + r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::Float(l - r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::Float(l as f64 - r)),
(Self::Nat(l), Self::Float(r)) => Some(Self::Float(l as f64 - r)),
(Self::Float(l), Self::Int(r)) => Some(Self::Float(l - r as f64)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l - r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 - *r)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 - *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l - r as f64)),
(Self::Str(l), Self::Str(r)) => Some(Self::Str(Str::from(format!("{l}{r}")))),
(Self::List(l), Self::List(r)) => {
let lis = Arc::from([l, r].concat());
@ -1567,10 +1573,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::Float(l - r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l - r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from(l as i32 - r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l - r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 - r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l - r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 - r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l - r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 - *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l - r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 - *r)),
(inf @ (Self::Inf | Self::NegInf), other)
| (other, inf @ (Self::Inf | Self::NegInf))
if other != Self::Inf && other != Self::NegInf =>
@ -1588,10 +1594,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::Float(l * r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::Int(l * r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::Int(l as i32 * r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l * r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 * r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l * r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 * r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l * r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 * *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l * r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 * *r)),
(Self::Str(l), Self::Nat(r)) => Some(Self::Str(Str::from(l.repeat(r as usize)))),
(inf @ (Self::Inf | Self::NegInf), _) | (_, inf @ (Self::Inf | Self::NegInf)) => {
Some(inf)
@ -1602,15 +1608,15 @@ impl ValueObj {
pub fn try_div(self, other: Self) -> Option<Self> {
match (self, other) {
(Self::Int(l), Self::Int(r)) => Some(Self::Float(l as f64 / r as f64)),
(Self::Nat(l), Self::Nat(r)) => Some(Self::Float(l as f64 / r as f64)),
(Self::Int(l), Self::Int(r)) => Some(Self::from(l as f64 / r as f64)),
(Self::Nat(l), Self::Nat(r)) => Some(Self::from(l as f64 / r as f64)),
(Self::Float(l), Self::Float(r)) => Some(Self::Float(l / r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::Float(l as f64 / r as f64)),
(Self::Nat(l), Self::Int(r)) => Some(Self::Float(l as f64 / r as f64)),
(Self::Float(l), Self::Nat(r)) => Some(Self::Float(l / r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 / r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l / r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 / r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l as f64 / r as f64)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from(l as f64 / r as f64)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l / r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 / *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l / r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 / *r)),
// TODO: x/±Inf = 0
_ => None,
}
@ -1620,13 +1626,13 @@ impl ValueObj {
match (self, other) {
(Self::Int(l), Self::Int(r)) => Some(Self::Int(l / r)),
(Self::Nat(l), Self::Nat(r)) => Some(Self::Nat(l / r)),
(Self::Float(l), Self::Float(r)) => Some(Self::Float((l / r).floor())),
(Self::Float(l), Self::Float(r)) => Some(Self::from((l / r).floor())),
(Self::Int(l), Self::Nat(r)) => Some(Self::Int(l / r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::Int(l as i32 / r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::Float((l / r as f64).floor())),
(Self::Nat(l), Self::Float(r)) => Some(Self::Float((l as f64 / r).floor())),
(Self::Float(l), Self::Int(r)) => Some(Self::Float((l / r as f64).floor())),
(Self::Int(l), Self::Float(r)) => Some(Self::Float((l as f64 / r).floor())),
(Self::Float(l), Self::Nat(r)) => Some(Self::from((*l / r as f64).floor())),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64 / *r).floor())),
(Self::Float(l), Self::Int(r)) => Some(Self::from((*l / r as f64).floor())),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64 / *r).floor())),
// TODO: x//±Inf = 0
_ => None,
}
@ -1636,13 +1642,13 @@ impl ValueObj {
match (self, other) {
(Self::Int(l), Self::Int(r)) => Some(Self::Int(l.pow(r.try_into().ok()?))),
(Self::Nat(l), Self::Nat(r)) => Some(Self::Nat(l.pow(r.try_into().ok()?))),
(Self::Float(l), Self::Float(r)) => Some(Self::Float(l.powf(r))),
(Self::Float(l), Self::Float(r)) => Some(Self::from(l.powf(*r))),
(Self::Int(l), Self::Nat(r)) => Some(Self::Int(l.pow(r.try_into().ok()?))),
(Self::Nat(l), Self::Int(r)) => Some(Self::Nat(l.pow(r.try_into().ok()?))),
(Self::Float(l), Self::Nat(r)) => Some(Self::Float(l.powf(r as f64))),
(Self::Nat(l), Self::Float(r)) => Some(Self::Float((l as f64).powf(r))),
(Self::Float(l), Self::Int(r)) => Some(Self::Float(l.powi(r))),
(Self::Int(l), Self::Float(r)) => Some(Self::Float((l as f64).powf(r))),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l.powf(r as f64))),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64).powf(*r))),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l.powi(r))),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64).powf(*r))),
_ => None,
}
}
@ -1654,10 +1660,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::Float(l % r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::Int(l % r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::Int(l as i32 % r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::Float(l % r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::Float(l as f64 % r)),
(Self::Float(l), Self::Int(r)) => Some(Self::Float(l % r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::Float(l as f64 % r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l % r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 % *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l % r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 % *r)),
_ => None,
}
}
@ -1669,10 +1675,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::from(l > r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l > r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from(l as i32 > r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l > r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 > r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l > r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 > r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l > r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 > *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l > r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 > *r)),
(Self::Inf, Self::Inf) | (Self::NegInf, Self::NegInf) => Some(Self::Bool(false)),
(Self::Inf, Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_))
| (Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_), Self::NegInf) => {
@ -1693,10 +1699,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::from(l >= r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l >= r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from(l as i32 >= r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l >= r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 >= r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l >= r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 >= r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l >= r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 >= *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l >= r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 >= *r)),
(Self::Inf, Self::Inf) | (Self::NegInf, Self::NegInf) => Some(Self::Bool(true)),
(Self::Inf, Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_))
| (Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_), Self::NegInf) => {
@ -1717,10 +1723,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::from(l < r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l < r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from((l as i32) < r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l < r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64) < r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l < r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64) < r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l < r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64) < *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l < r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64) < *r)),
(Self::Inf, Self::Inf) | (Self::NegInf, Self::NegInf) => Some(Self::Bool(false)),
(Self::Inf, Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_))
| (Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_), Self::NegInf) => {
@ -1741,10 +1747,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::from(l <= r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l <= r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from((l as i32) <= r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l <= r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64) <= r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l <= r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64) <= r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l <= r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64) <= *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l <= r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64) <= *r)),
(Self::Inf, Self::Inf) | (Self::NegInf, Self::NegInf) => Some(Self::Bool(true)),
(Self::Inf, Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_))
| (Self::Nat(_) | Self::Int(_) | Self::Float(_) | Self::Bool(_), Self::NegInf) => {
@ -1765,10 +1771,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::from(l == r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l == r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from(l as i32 == r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l == r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 == r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l == r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 == r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l == r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 == *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l == r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 == *r)),
(Self::Str(l), Self::Str(r)) => Some(Self::from(l == r)),
(Self::Bool(l), Self::Bool(r)) => Some(Self::from(l == r)),
(Self::Type(l), Self::Type(r)) => Some(Self::from(l == r)),
@ -1785,10 +1791,10 @@ impl ValueObj {
(Self::Float(l), Self::Float(r)) => Some(Self::from(l != r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l != r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from(l as i32 != r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l != r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 != r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l != r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 != r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(*l != r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from(l as f64 != *r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(*l != r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 != *r)),
(Self::Str(l), Self::Str(r)) => Some(Self::from(l != r)),
(Self::Bool(l), Self::Bool(r)) => Some(Self::from(l != r)),
(Self::Type(l), Self::Type(r)) => Some(Self::from(l != r)),