about summary refs log tree commit diff
path: root/tvix/eval/src/value
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/value')
-rw-r--r--tvix/eval/src/value/list.rs10
-rw-r--r--tvix/eval/src/value/mod.rs15
2 files changed, 24 insertions, 1 deletions
diff --git a/tvix/eval/src/value/list.rs b/tvix/eval/src/value/list.rs
index 8ea3db7aecf3..236a654ad88d 100644
--- a/tvix/eval/src/value/list.rs
+++ b/tvix/eval/src/value/list.rs
@@ -1,4 +1,6 @@
 //! This module implements Nix lists.
+use std::ops::Deref;
+
 use crate::errors::ErrorKind;
 use crate::vm::VM;
 
@@ -125,3 +127,11 @@ impl<'a> IntoIterator for &'a NixList {
         self.0.iter()
     }
 }
+
+impl Deref for NixList {
+    type Target = Vec<Value>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs
index 355540402d42..c590495b5344 100644
--- a/tvix/eval/src/value/mod.rs
+++ b/tvix/eval/src/value/mod.rs
@@ -351,12 +351,25 @@ impl Value {
     }
 
     /// Compare `self` against other using (fallible) Nix ordering semantics.
-    pub fn nix_cmp(&self, other: &Self) -> Result<Option<Ordering>, ErrorKind> {
+    pub fn nix_cmp(&self, other: &Self, vm: &mut VM) -> 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)),
+            (Value::List(l1), Value::List(l2)) => {
+                for i in 0.. {
+                    if i == l2.len() {
+                        return Ok(Some(Ordering::Greater));
+                    } else if i == l1.len() {
+                        return Ok(Some(Ordering::Less));
+                    } else if !l1[i].nix_eq(&l2[i], vm)? {
+                        return l1[i].force(vm)?.nix_cmp(&*l2[i].force(vm)?, vm);
+                    }
+                }
+
+                unreachable!()
+            }
 
             // different types
             (Value::Integer(i1), Value::Float(f2)) => Ok((*i1 as f64).partial_cmp(f2)),