mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Implement lexicographic array comparison (#2827)
This commit is contained in:
parent
3960f8f7d9
commit
0ebce56b36
@ -551,6 +551,7 @@ pub fn compare(lhs: &Value, rhs: &Value) -> StrResult<Ordering> {
|
|||||||
|
|
||||||
(Duration(a), Duration(b)) => a.cmp(b),
|
(Duration(a), Duration(b)) => a.cmp(b),
|
||||||
(Datetime(a), Datetime(b)) => try_cmp_datetimes(a, 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),
|
_ => 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()))
|
.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.
|
/// Test whether one value is "in" another one.
|
||||||
pub fn in_(lhs: Value, rhs: Value) -> StrResult<Value> {
|
pub fn in_(lhs: Value, rhs: Value) -> StrResult<Value> {
|
||||||
if let Some(b) = contains(&lhs, &rhs) {
|
if let Some(b) = contains(&lhs, &rhs) {
|
||||||
|
@ -37,6 +37,14 @@
|
|||||||
// Error: 3-22 cannot compare 2.2 with NaN
|
// Error: 3-22 cannot compare 2.2 with NaN
|
||||||
#(2.2 <= float("nan"))
|
#(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
|
// Error: 3-12 cannot divide by zero
|
||||||
#(1.2 / 0.0)
|
#(1.2 / 0.0)
|
||||||
|
@ -206,6 +206,18 @@
|
|||||||
#test(50% < 40% + 0pt, false)
|
#test(50% < 40% + 0pt, false)
|
||||||
#test(40% + 0pt < 50% + 0pt, true)
|
#test(40% + 0pt < 50% + 0pt, true)
|
||||||
#test(1em < 2em, 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.
|
// Test assignment operators.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user