about summary refs log tree commit diff
path: root/tvix/eval/src/value/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tvix/eval/src/value/mod.rs21
1 files changed, 21 insertions, 0 deletions
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs
index 14b1a5c612..82be292819 100644
--- a/tvix/eval/src/value/mod.rs
+++ b/tvix/eval/src/value/mod.rs
@@ -1,5 +1,6 @@
 //! This module implements the backing representation of runtime
 //! values in the Nix language.
+use std::cmp::Ordering;
 use std::ops::Deref;
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -348,6 +349,26 @@ impl Value {
         }
     }
 
+    /// Compare `self` against other using (fallible) Nix ordering semantics.
+    pub fn nix_cmp(&self, other: &Self) -> Result<Option<Ordering>, ErrorKind> {
+        match (self, other) {
+            // same types
+            (Value::Integer(i1), Value::Integer(i2)) => Ok(i1.partial_cmp(i2)),
+            (Value::Float(f1), Value::Float(f2)) => Ok(f1.partial_cmp(f2)),
+            (Value::String(s1), Value::String(s2)) => Ok(s1.partial_cmp(s2)),
+
+            // different types
+            (Value::Integer(i1), Value::Float(f2)) => Ok((*i1 as f64).partial_cmp(f2)),
+            (Value::Float(f1), Value::Integer(i2)) => Ok(f1.partial_cmp(&(*i2 as f64))),
+
+            // unsupported types
+            (lhs, rhs) => Err(ErrorKind::Incomparable {
+                lhs: lhs.type_of(),
+                rhs: rhs.type_of(),
+            }),
+        }
+    }
+
     /// Ensure `self` is forced if it is a thunk, and return a reference to the resulting value.
     pub(crate) fn force(&self, vm: &mut VM) -> Result<ForceResult, ErrorKind> {
         match self {