@@ -3,18 +3,21 @@ use std::fmt;
3
3
use crossbeam_utils:: atomic:: AtomicCell ;
4
4
5
5
use super :: objiter;
6
+ use super :: objset:: PySet ;
6
7
use super :: objstr;
7
8
use super :: objtype:: { self , PyClassRef } ;
8
9
use crate :: dictdatatype:: { self , DictKey } ;
9
10
use crate :: exceptions:: PyBaseExceptionRef ;
10
11
use crate :: function:: { KwArgs , OptionalArg , PyFuncArgs } ;
11
12
use crate :: pyobject:: {
12
- BorrowValue , IdProtocol , IntoPyObject , ItemProtocol , PyAttributes , PyClassImpl , PyContext ,
13
- PyIterable , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject , TypeProtocol ,
13
+ BorrowValue , IdProtocol , IntoPyObject , ItemProtocol , PyArithmaticValue , PyAttributes ,
14
+ PyClassImpl , PyComparisonValue , PyContext , PyIterable , PyObjectRef , PyRef , PyResult , PyValue ,
15
+ TryFromObject , TypeProtocol ,
14
16
} ;
15
17
use crate :: vm:: { ReprGuard , VirtualMachine } ;
16
18
17
19
use std:: mem:: size_of;
20
+ use PyArithmaticValue :: { Implemented , NotImplemented } ;
18
21
19
22
pub type DictContentType = dictdatatype:: Dict ;
20
23
@@ -146,46 +149,65 @@ impl PyDict {
146
149
!self . entries . is_empty ( )
147
150
}
148
151
149
- fn inner_eq ( zelf : PyRef < Self > , other : & PyDict , vm : & VirtualMachine ) -> PyResult < bool > {
150
- if other. entries . len ( ) != zelf. entries . len ( ) {
151
- return Ok ( false ) ;
152
+ fn inner_cmp (
153
+ zelf : PyRef < Self > ,
154
+ other : PyDictRef ,
155
+ size_func : fn ( usize , usize ) -> bool ,
156
+ item : bool ,
157
+ vm : & VirtualMachine ,
158
+ ) -> PyResult < PyComparisonValue > {
159
+ if size_func ( zelf. len ( ) , other. len ( ) ) {
160
+ return Ok ( Implemented ( false ) ) ;
152
161
}
153
- for ( k, v1) in zelf {
154
- match other. entries . get ( vm, & k) ? {
162
+ let ( zelf, other) = if zelf. len ( ) < other. len ( ) {
163
+ ( other, zelf)
164
+ } else {
165
+ ( zelf, other)
166
+ } ;
167
+ for ( k, v1) in other {
168
+ match zelf. get_item_option ( k, vm) ? {
155
169
Some ( v2) => {
156
170
if v1. is ( & v2) {
157
171
continue ;
158
172
}
159
- if !vm. bool_eq ( v1, v2) ? {
160
- return Ok ( false ) ;
173
+ if item && !vm. bool_eq ( v1, v2) ? {
174
+ return Ok ( Implemented ( false ) ) ;
161
175
}
162
176
}
163
177
None => {
164
- return Ok ( false ) ;
178
+ return Ok ( Implemented ( false ) ) ;
165
179
}
166
180
}
167
181
}
168
- Ok ( true )
182
+ Ok ( Implemented ( true ) )
169
183
}
170
184
171
185
#[ pymethod( magic) ]
172
- fn eq ( zelf : PyRef < Self > , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
173
- if let Some ( other) = other. payload :: < PyDict > ( ) {
174
- let eq = Self :: inner_eq ( zelf, other, vm) ?;
175
- Ok ( vm. ctx . new_bool ( eq) )
186
+ fn eq (
187
+ zelf : PyRef < Self > ,
188
+ other : PyObjectRef ,
189
+ vm : & VirtualMachine ,
190
+ ) -> PyResult < PyComparisonValue > {
191
+ if let Ok ( other) = other. downcast :: < PyDict > ( ) {
192
+ Self :: inner_cmp (
193
+ zelf,
194
+ other,
195
+ |zelf : usize , other : usize | -> bool { zelf != other } ,
196
+ true ,
197
+ vm,
198
+ )
176
199
} else {
177
- Ok ( vm . ctx . not_implemented ( ) )
200
+ Ok ( NotImplemented )
178
201
}
179
202
}
180
203
181
204
#[ pymethod( magic) ]
182
- fn ne ( zelf : PyRef < Self > , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
183
- if let Some ( other) = other. payload :: < PyDict > ( ) {
184
- let neq = !Self :: inner_eq ( zelf, other, vm) ?;
185
- Ok ( vm. ctx . new_bool ( neq) )
186
- } else {
187
- Ok ( vm. ctx . not_implemented ( ) )
188
- }
205
+ fn ne (
206
+ zelf : PyRef < Self > ,
207
+ other : PyObjectRef ,
208
+ vm : & VirtualMachine ,
209
+ ) -> PyResult < PyComparisonValue > {
210
+ Ok ( Self :: eq ( zelf, other, vm) ?. map ( |v| !v) )
189
211
}
190
212
191
213
#[ pymethod( magic) ]
@@ -611,6 +633,111 @@ macro_rules! dict_iterator {
611
633
fn reversed( & self ) -> $reverse_iter_name {
612
634
$reverse_iter_name:: new( self . dict. clone( ) )
613
635
}
636
+
637
+ fn cmp(
638
+ zelf: PyRef <Self >,
639
+ other: PyObjectRef ,
640
+ size_func: fn ( usize , usize ) -> bool ,
641
+ vm: & VirtualMachine ,
642
+ ) -> PyResult <PyComparisonValue > {
643
+ match_class!( match other {
644
+ dictview @ Self => {
645
+ PyDict :: inner_cmp(
646
+ zelf. dict. clone( ) ,
647
+ dictview. dict. clone( ) ,
648
+ size_func,
649
+ !zelf. class( ) . is( & vm. ctx. types. dict_keys_type) ,
650
+ vm,
651
+ )
652
+ }
653
+ _set @ PySet => {
654
+ // TODO: Implement comparison for set
655
+ Ok ( NotImplemented )
656
+ }
657
+ _ => {
658
+ Ok ( NotImplemented )
659
+ }
660
+ } )
661
+ }
662
+
663
+ #[ pymethod( name = "__eq__" ) ]
664
+ fn eq(
665
+ zelf: PyRef <Self >,
666
+ other: PyObjectRef ,
667
+ vm: & VirtualMachine ,
668
+ ) -> PyResult <PyComparisonValue > {
669
+ Self :: cmp(
670
+ zelf,
671
+ other,
672
+ |zelf: usize , other: usize | -> bool { zelf != other } ,
673
+ vm,
674
+ )
675
+ }
676
+
677
+ #[ pymethod( name = "__ne__" ) ]
678
+ fn ne(
679
+ zelf: PyRef <Self >,
680
+ other: PyObjectRef ,
681
+ vm: & VirtualMachine ,
682
+ ) -> PyResult <PyComparisonValue > {
683
+ Ok ( Self :: eq( zelf, other, vm) ?. map( |v| !v) )
684
+ }
685
+
686
+ #[ pymethod( name = "__lt__" ) ]
687
+ fn lt(
688
+ zelf: PyRef <Self >,
689
+ other: PyObjectRef ,
690
+ vm: & VirtualMachine ,
691
+ ) -> PyResult <PyComparisonValue > {
692
+ Self :: cmp(
693
+ zelf,
694
+ other,
695
+ |zelf: usize , other: usize | -> bool { zelf >= other } ,
696
+ vm,
697
+ )
698
+ }
699
+
700
+ #[ pymethod( name = "__le__" ) ]
701
+ fn le(
702
+ zelf: PyRef <Self >,
703
+ other: PyObjectRef ,
704
+ vm: & VirtualMachine ,
705
+ ) -> PyResult <PyComparisonValue > {
706
+ Self :: cmp(
707
+ zelf,
708
+ other,
709
+ |zelf: usize , other: usize | -> bool { zelf > other } ,
710
+ vm,
711
+ )
712
+ }
713
+
714
+ #[ pymethod( name = "__gt__" ) ]
715
+ fn gt(
716
+ zelf: PyRef <Self >,
717
+ other: PyObjectRef ,
718
+ vm: & VirtualMachine ,
719
+ ) -> PyResult <PyComparisonValue > {
720
+ Self :: cmp(
721
+ zelf,
722
+ other,
723
+ |zelf: usize , other: usize | -> bool { zelf <= other } ,
724
+ vm,
725
+ )
726
+ }
727
+
728
+ #[ pymethod( name = "__ge__" ) ]
729
+ fn ge(
730
+ zelf: PyRef <Self >,
731
+ other: PyObjectRef ,
732
+ vm: & VirtualMachine ,
733
+ ) -> PyResult <PyComparisonValue > {
734
+ Self :: cmp(
735
+ zelf,
736
+ other,
737
+ |zelf: usize , other: usize | -> bool { zelf < other } ,
738
+ vm,
739
+ )
740
+ }
614
741
}
615
742
616
743
impl PyValue for $name {
0 commit comments