From 5bd0e723c13b8a41bfba442bd8ef5351e31099e6 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Sun, 23 Oct 2022 13:24:05 -0400 Subject: refactor(tvix/eval): Implement value comparison with a method Rather than implementing all of the interesting semantics of value comparison with a macro bound to the VM, implement the bulk of the logic with a method on Value itself that returns an Ordering, and then use the macro to implement the comparison against that Ordering. This has no functional change, but paves the way to implementing lexicographic comparison of list values, which is supported in the latest version of upstream nix. Change-Id: I8af1a020b41577021af5939f5edc160c407d4a9e Reviewed-on: https://cl.tvl.fyi/c/depot/+/7069 Autosubmit: grfn Tested-by: BuildkiteCI Reviewed-by: tazjin --- tvix/eval/src/vm.rs | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'tvix/eval/src/vm.rs') diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 08c913ed2d6d..6a5c56dc03bf 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -2,7 +2,7 @@ //! Tvix bytecode. use serde_json::json; -use std::{ops::DerefMut, path::PathBuf, rc::Rc}; +use std::{cmp::Ordering, ops::DerefMut, path::PathBuf, rc::Rc}; use crate::{ chunk::Chunk, @@ -123,31 +123,26 @@ macro_rules! cmp_op { ( $self:ident, $op:tt ) => {{ let b = $self.pop(); let a = $self.pop(); - let result = fallible!($self, cmp_op!(&a, &b, $op)); + let ordering = fallible!($self, a.nix_cmp(&b)); + let result = Value::Bool(cmp_op!(@order $op ordering)); $self.push(result); }}; - ( $a:expr, $b:expr, $op:tt ) => { - // Comparable (in terms of ordering) values are numbers and - // strings. Numbers need to be coerced similarly to arithmetic - // ops if mixed types are encountered. - match ($a, $b) { - // same types - (Value::Integer(i1), Value::Integer(i2)) => Ok(Value::Bool(i1 $op i2)), - (Value::Float(f1), Value::Float(f2)) => Ok(Value::Bool(f1 $op f2)), - (Value::String(s1), Value::String(s2)) => Ok(Value::Bool(s1 $op s2)), - - // different types - (Value::Integer(i1), Value::Float(f2)) => Ok(Value::Bool((*i1 as f64) $op *f2)), - (Value::Float(f1), Value::Integer(i2)) => Ok(Value::Bool(*f1 $op (*i2 as f64))), - - // unsupported types - (lhs, rhs) => Err(ErrorKind::Incomparable { - lhs: lhs.type_of(), - rhs: rhs.type_of(), - }), - } - } + (@order < $ordering:expr) => { + $ordering == Some(Ordering::Less) + }; + + (@order > $ordering:expr) => { + $ordering == Some(Ordering::Greater) + }; + + (@order <= $ordering:expr) => { + !matches!($ordering, None | Some(Ordering::Greater)) + }; + + (@order >= $ordering:expr) => { + !matches!($ordering, None | Some(Ordering::Less)) + }; } impl<'o> VM<'o> { -- cgit 1.4.1