summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst/src/eval/ops.rs21
-rw-r--r--tests/typ/compiler/ops-invalid.typ8
-rw-r--r--tests/typ/compiler/ops.typ12
3 files changed, 41 insertions, 0 deletions
diff --git a/crates/typst/src/eval/ops.rs b/crates/typst/src/eval/ops.rs
index cb830614..8e8b6d29 100644
--- a/crates/typst/src/eval/ops.rs
+++ b/crates/typst/src/eval/ops.rs
@@ -551,6 +551,7 @@ pub fn compare(lhs: &Value, rhs: &Value) -> StrResult<Ordering> {
(Duration(a), Duration(b)) => a.cmp(b),
(Datetime(a), Datetime(b)) => try_cmp_datetimes(a, b)?,
+ (Array(a), Array(b)) => try_cmp_arrays(a.as_slice(), b.as_slice())?,
_ => mismatch!("cannot compare {} and {}", lhs, rhs),
})
@@ -568,6 +569,26 @@ fn try_cmp_datetimes(a: &Datetime, b: &Datetime) -> StrResult<Ordering> {
.ok_or_else(|| eco_format!("cannot compare {} and {}", a.kind(), b.kind()))
}
+/// Try to compare arrays of values lexicographically.
+fn try_cmp_arrays(a: &[Value], b: &[Value]) -> StrResult<Ordering> {
+ a.iter()
+ .zip(b.iter())
+ .find_map(|(first, second)| {
+ match compare(first, second) {
+ // Keep searching for a pair of elements that isn't equal.
+ Ok(Ordering::Equal) => None,
+ // Found a pair which either is not equal or not comparable, so
+ // we stop searching.
+ result => Some(result),
+ }
+ })
+ .unwrap_or_else(|| {
+ // The two arrays are equal up to the shortest array's extent,
+ // so compare their lengths instead.
+ Ok(a.len().cmp(&b.len()))
+ })
+}
+
/// Test whether one value is "in" another one.
pub fn in_(lhs: Value, rhs: Value) -> StrResult<Value> {
if let Some(b) = contains(&lhs, &rhs) {
diff --git a/tests/typ/compiler/ops-invalid.typ b/tests/typ/compiler/ops-invalid.typ
index de8e6234..64e3a878 100644
--- a/tests/typ/compiler/ops-invalid.typ
+++ b/tests/typ/compiler/ops-invalid.typ
@@ -38,6 +38,14 @@
#(2.2 <= float("nan"))
---
+// Error: 3-26 cannot compare integer and string
+#((0, 1, 3) > (0, 1, "a"))
+
+---
+// Error: 3-42 cannot compare 3.5 with NaN
+#((0, "a", 3.5) <= (0, "a", float("nan")))
+
+---
// Error: 3-12 cannot divide by zero
#(1.2 / 0.0)
diff --git a/tests/typ/compiler/ops.typ b/tests/typ/compiler/ops.typ
index 89ed3e5f..64736228 100644
--- a/tests/typ/compiler/ops.typ
+++ b/tests/typ/compiler/ops.typ
@@ -206,6 +206,18 @@
#test(50% < 40% + 0pt, false)
#test(40% + 0pt < 50% + 0pt, true)
#test(1em < 2em, true)
+#test((0, 1, 2, 4) < (0, 1, 2, 5), true)
+#test((0, 1, 2, 4) < (0, 1, 2, 3), false)
+#test((0, 1, 2, 3.3) > (0, 1, 2, 4), false)
+#test((0, 1, 2) < (0, 1, 2, 3), true)
+#test((0, 1, "b") > (0, 1, "a", 3), true)
+#test((0, 1.1, 3) >= (0, 1.1, 3), true)
+#test((0, 1, datetime(day: 1, month: 12, year: 2023)) <= (0, 1, datetime(day: 1, month: 12, year: 2023), 3), true)
+#test(("a", 23, 40, "b") > ("a", 23, 40), true)
+#test(() <= (), true)
+#test(() >= (), true)
+#test(() <= (1,), true)
+#test((1,) <= (), false)
---
// Test assignment operators.