Skip to content

Commit 9b78e9f

Browse files
authored
Merge pull request #1452 from HyeockJinKim/issue1450
Fix sequence comparison
2 parents 311b53d + e812024 commit 9b78e9f

4 files changed

Lines changed: 138 additions & 61 deletions

File tree

tests/snippets/list.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,42 @@ def bad_iter_assign():
488488
assert x == [0, 1, 2, 3, 4, 5]
489489
x = list(range(10))
490490
del x[-5:-1:-1]
491+
492+
# list gt, ge, lt, le
493+
assert_raises(TypeError, lambda: [0, []] < [0, 0])
494+
assert_raises(TypeError, lambda: [0, []] <= [0, 0])
495+
assert_raises(TypeError, lambda: [0, []] > [0, 0])
496+
assert_raises(TypeError, lambda: [0, []] >= [0, 0])
497+
498+
assert_raises(TypeError, lambda: [0, 0] < [0, []])
499+
assert_raises(TypeError, lambda: [0, 0] <= [0, []])
500+
assert_raises(TypeError, lambda: [0, 0] > [0, []])
501+
assert_raises(TypeError, lambda: [0, 0] >= [0, []])
502+
503+
assert [0, 0] < [1, -1]
504+
assert [0, 0] < [0, 0, 1]
505+
assert [0, 0] < [0, 0, -1]
506+
assert [0, 0] <= [0, 0, -1]
507+
assert not [0, 0, 0, 0] <= [0, -1]
508+
509+
assert [0, 0] > [-1, 1]
510+
assert [0, 0] >= [-1, 1]
511+
assert [0, 0, 0] >= [-1, 1]
512+
513+
assert [0, 0] <= [0, 1]
514+
assert [0, 0] <= [0, 0]
515+
assert [0, 0] <= [0, 0]
516+
assert not [0, 0] > [0, 0]
517+
assert not [0, 0] < [0, 0]
518+
519+
assert not [float('nan'), float('nan')] <= [float('nan'), 1]
520+
assert not [float('nan'), float('nan')] <= [float('nan'), float('nan')]
521+
assert not [float('nan'), float('nan')] >= [float('nan'), float('nan')]
522+
assert not [float('nan'), float('nan')] < [float('nan'), float('nan')]
523+
assert not [float('nan'), float('nan')] > [float('nan'), float('nan')]
524+
525+
assert [float('inf'), float('inf')] >= [float('inf'), 1]
526+
assert [float('inf'), float('inf')] <= [float('inf'), float('inf')]
527+
assert [float('inf'), float('inf')] >= [float('inf'), float('inf')]
528+
assert not [float('inf'), float('inf')] < [float('inf'), float('inf')]
529+
assert not [float('inf'), float('inf')] > [float('inf'), float('inf')]

tests/snippets/tuple.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from testutils import assert_raises
2+
13
assert (1,2) == (1,2)
24

35
x = (1,2)
@@ -47,3 +49,42 @@ def __eq__(self, x):
4749
a = ()
4850
b = ()
4951
assert a is b
52+
53+
# tuple gt, ge, lt, le
54+
assert_raises(TypeError, lambda: (0, ()) < (0, 0))
55+
assert_raises(TypeError, lambda: (0, ()) <= (0, 0))
56+
assert_raises(TypeError, lambda: (0, ()) > (0, 0))
57+
assert_raises(TypeError, lambda: (0, ()) >= (0, 0))
58+
59+
assert_raises(TypeError, lambda: (0, 0) < (0, ()))
60+
assert_raises(TypeError, lambda: (0, 0) <= (0, ()))
61+
assert_raises(TypeError, lambda: (0, 0) > (0, ()))
62+
assert_raises(TypeError, lambda: (0, 0) >= (0, ()))
63+
64+
assert (0, 0) < (1, -1)
65+
assert (0, 0) < (0, 0, 1)
66+
assert (0, 0) < (0, 0, -1)
67+
assert (0, 0) <= (0, 0, -1)
68+
assert not (0, 0, 0, 0) <= (0, -1)
69+
70+
assert (0, 0) > (-1, 1)
71+
assert (0, 0) >= (-1, 1)
72+
assert (0, 0, 0) >= (-1, 1)
73+
74+
assert (0, 0) <= (0, 1)
75+
assert (0, 0) <= (0, 0)
76+
assert (0, 0) <= (0, 0)
77+
assert not (0, 0) > (0, 0)
78+
assert not (0, 0) < (0, 0)
79+
80+
assert not (float('nan'), float('nan')) <= (float('nan'), 1)
81+
assert not (float('nan'), float('nan')) <= (float('nan'), float('nan'))
82+
assert not (float('nan'), float('nan')) >= (float('nan'), float('nan'))
83+
assert not (float('nan'), float('nan')) < (float('nan'), float('nan'))
84+
assert not (float('nan'), float('nan')) > (float('nan'), float('nan'))
85+
86+
assert (float('inf'), float('inf')) >= (float('inf'), 1)
87+
assert (float('inf'), float('inf')) <= (float('inf'), float('inf'))
88+
assert (float('inf'), float('inf')) >= (float('inf'), float('inf'))
89+
assert not (float('inf'), float('inf')) < (float('inf'), float('inf'))
90+
assert not (float('inf'), float('inf')) > (float('inf'), float('inf'))

vm/src/obj/objsequence.rs

Lines changed: 46 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -307,38 +307,18 @@ pub fn seq_lt(
307307
zelf: &dyn SimpleSeq,
308308
other: &dyn SimpleSeq,
309309
) -> Result<bool, PyObjectRef> {
310-
if zelf.len() == other.len() {
311-
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
312-
let lt = vm._lt(a.clone(), b.clone())?;
313-
let value = objbool::boolval(vm, lt)?;
314-
if !value {
315-
return Ok(false);
316-
}
317-
}
318-
Ok(true)
319-
} else {
320-
// This case is more complicated because it can still return true if
321-
// `zelf` is the head of `other` e.g. [1,2,3] < [1,2,3,4] should return true
322-
let mut head = true; // true if `zelf` is the head of `other`
323-
324-
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
325-
let lt = vm._lt(a.clone(), b.clone())?;
326-
let eq = vm._eq(a.clone(), b.clone())?;
327-
let lt_value = objbool::boolval(vm, lt)?;
328-
let eq_value = objbool::boolval(vm, eq)?;
329-
330-
if !lt_value && !eq_value {
331-
return Ok(false);
332-
} else if !eq_value {
333-
head = false;
334-
}
310+
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
311+
if vm.bool_lt(a.clone(), b.clone())? {
312+
return Ok(true);
313+
} else if !vm.bool_eq(a.clone(), b.clone())? {
314+
return Ok(false);
335315
}
316+
}
336317

337-
if head {
338-
Ok(zelf.len() < other.len())
339-
} else {
340-
Ok(true)
341-
}
318+
if zelf.len() == other.len() {
319+
Ok(false)
320+
} else {
321+
Ok(zelf.len() < other.len())
342322
}
343323
}
344324

@@ -347,37 +327,18 @@ pub fn seq_gt(
347327
zelf: &dyn SimpleSeq,
348328
other: &dyn SimpleSeq,
349329
) -> Result<bool, PyObjectRef> {
350-
if zelf.len() == other.len() {
351-
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
352-
let gt = vm._gt(a.clone(), b.clone())?;
353-
let value = objbool::boolval(vm, gt)?;
354-
if !value {
355-
return Ok(false);
356-
}
357-
}
358-
Ok(true)
359-
} else {
360-
let mut head = true; // true if `other` is the head of `zelf`
361-
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
362-
// This case is more complicated because it can still return true if
363-
// `other` is the head of `zelf` e.g. [1,2,3,4] > [1,2,3] should return true
364-
let gt = vm._gt(a.clone(), b.clone())?;
365-
let eq = vm._eq(a.clone(), b.clone())?;
366-
let gt_value = objbool::boolval(vm, gt)?;
367-
let eq_value = objbool::boolval(vm, eq)?;
368-
369-
if !gt_value && !eq_value {
370-
return Ok(false);
371-
} else if !eq_value {
372-
head = false;
373-
}
330+
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
331+
if vm.bool_gt(a.clone(), b.clone())? {
332+
return Ok(true);
333+
} else if !vm.bool_eq(a.clone(), b.clone())? {
334+
return Ok(false);
374335
}
336+
}
375337

376-
if head {
377-
Ok(zelf.len() > other.len())
378-
} else {
379-
Ok(true)
380-
}
338+
if zelf.len() == other.len() {
339+
Ok(false)
340+
} else {
341+
Ok(zelf.len() > other.len())
381342
}
382343
}
383344

@@ -386,15 +347,39 @@ pub fn seq_ge(
386347
zelf: &dyn SimpleSeq,
387348
other: &dyn SimpleSeq,
388349
) -> Result<bool, PyObjectRef> {
389-
Ok(seq_gt(vm, zelf, other)? || seq_equal(vm, zelf, other)?)
350+
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
351+
if vm.bool_gt(a.clone(), b.clone())? {
352+
return Ok(true);
353+
} else if !vm.bool_eq(a.clone(), b.clone())? {
354+
return Ok(false);
355+
}
356+
}
357+
358+
if zelf.len() == other.len() {
359+
Ok(true)
360+
} else {
361+
Ok(zelf.len() > other.len())
362+
}
390363
}
391364

392365
pub fn seq_le(
393366
vm: &VirtualMachine,
394367
zelf: &dyn SimpleSeq,
395368
other: &dyn SimpleSeq,
396369
) -> Result<bool, PyObjectRef> {
397-
Ok(seq_lt(vm, zelf, other)? || seq_equal(vm, zelf, other)?)
370+
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
371+
if vm.bool_lt(a.clone(), b.clone())? {
372+
return Ok(true);
373+
} else if !vm.bool_eq(a.clone(), b.clone())? {
374+
return Ok(false);
375+
}
376+
}
377+
378+
if zelf.len() == other.len() {
379+
Ok(true)
380+
} else {
381+
Ok(zelf.len() < other.len())
382+
}
398383
}
399384

400385
pub struct SeqMul<'a> {

vm/src/vm.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,18 @@ impl VirtualMachine {
12481248
let value = objbool::boolval(self, eq)?;
12491249
Ok(value)
12501250
}
1251+
1252+
pub fn bool_lt(&self, a: PyObjectRef, b: PyObjectRef) -> PyResult<bool> {
1253+
let lt = self._lt(a.clone(), b.clone())?;
1254+
let value = objbool::boolval(self, lt)?;
1255+
Ok(value)
1256+
}
1257+
1258+
pub fn bool_gt(&self, a: PyObjectRef, b: PyObjectRef) -> PyResult<bool> {
1259+
let gt = self._gt(a.clone(), b.clone())?;
1260+
let value = objbool::boolval(self, gt)?;
1261+
Ok(value)
1262+
}
12511263
}
12521264

12531265
impl Default for VirtualMachine {

0 commit comments

Comments
 (0)