1
1
/*
2
2
* Builtin set type with a sequence of unique items.
3
3
*/
4
- use super :: pytype:: PyTypeRef ;
4
+ use super :: { pytype:: PyTypeRef , PyDictRef } ;
5
5
use crate :: common:: hash:: PyHash ;
6
6
use crate :: common:: rc:: PyRc ;
7
7
use crate :: dictdatatype;
8
- use crate :: function:: { Args , OptionalArg } ;
8
+ use crate :: function:: { Args , FuncArgs , OptionalArg } ;
9
9
use crate :: slots:: { Comparable , Hashable , Iterable , PyComparisonOp , PyIter , Unhashable } ;
10
10
use crate :: vm:: { ReprGuard , VirtualMachine } ;
11
11
use crate :: {
@@ -113,7 +113,7 @@ impl PySetInner {
113
113
} else {
114
114
( self , other)
115
115
} ;
116
- for key in subset. content . keys ( ) {
116
+ for key in subset. elements ( ) {
117
117
if !superset. contains ( & key, vm) ? {
118
118
return Ok ( false ) ;
119
119
}
@@ -155,7 +155,7 @@ impl PySetInner {
155
155
// We want to remove duplicates in other
156
156
let other_set = Self :: new ( other, vm) ?;
157
157
158
- for item in other_set. content . keys ( ) {
158
+ for item in other_set. elements ( ) {
159
159
new_inner. content . delete_or_insert ( vm, & item, ( ) ) ?
160
160
}
161
161
@@ -193,14 +193,14 @@ impl PySetInner {
193
193
194
194
PySetIterator {
195
195
dict : PyRc :: clone ( & self . content ) ,
196
- elements : self . content . keys ( ) ,
196
+ elements : self . elements ( ) ,
197
197
size_info : AtomicCell :: new ( set_size) ,
198
198
}
199
199
}
200
200
201
201
fn repr ( & self , vm : & VirtualMachine ) -> PyResult < String > {
202
202
let mut str_parts = Vec :: with_capacity ( self . content . len ( ) ) ;
203
- for key in self . content . keys ( ) {
203
+ for key in self . elements ( ) {
204
204
let part = vm. to_repr ( & key) ?;
205
205
str_parts. push ( part. as_str ( ) . to_owned ( ) ) ;
206
206
}
@@ -224,6 +224,10 @@ impl PySetInner {
224
224
self . content . clear ( )
225
225
}
226
226
227
+ fn elements ( & self ) -> Vec < PyObjectRef > {
228
+ self . content . keys ( )
229
+ }
230
+
227
231
fn pop ( & self , vm : & VirtualMachine ) -> PyResult {
228
232
// TODO: should be pop_front, but that requires rearranging every index
229
233
if let Some ( ( key, _) ) = self . content . pop_back ( ) {
@@ -275,15 +279,15 @@ impl PySetInner {
275
279
for iterable in others {
276
280
// We want to remove duplicates in iterable
277
281
let iterable_set = Self :: new ( iterable, vm) ?;
278
- for item in iterable_set. content . keys ( ) {
282
+ for item in iterable_set. elements ( ) {
279
283
self . content . delete_or_insert ( vm, & item, ( ) ) ?;
280
284
}
281
285
}
282
286
Ok ( ( ) )
283
287
}
284
288
285
289
fn hash ( & self , vm : & VirtualMachine ) -> PyResult < PyHash > {
286
- crate :: utils:: hash_iter_unordered ( self . content . keys ( ) . iter ( ) , vm)
290
+ crate :: utils:: hash_iter_unordered ( self . elements ( ) . iter ( ) , vm)
287
291
}
288
292
289
293
// Run operation, on failure, if item is a set/set subclass, convert it
@@ -331,6 +335,21 @@ fn extract_set(obj: &PyObjectRef) -> Option<&PySetInner> {
331
335
} )
332
336
}
333
337
338
+ fn reduce_set (
339
+ zelf : & PyObjectRef ,
340
+ vm : & VirtualMachine ,
341
+ ) -> PyResult < ( PyTypeRef , PyObjectRef , Option < PyDictRef > ) > {
342
+ Ok ( (
343
+ zelf. clone_class ( ) ,
344
+ vm. ctx . new_tuple ( vec ! [ vm. ctx. new_list(
345
+ extract_set( zelf)
346
+ . unwrap_or( & PySetInner :: default ( ) )
347
+ . elements( ) ,
348
+ ) ] ) ,
349
+ zelf. dict ( ) ,
350
+ ) )
351
+ }
352
+
334
353
macro_rules! multi_args_set {
335
354
( $vm: expr, $others: expr, $zelf: expr, $op: tt) => { {
336
355
let mut res = $zelf. inner. copy( ) ;
@@ -344,11 +363,7 @@ macro_rules! multi_args_set {
344
363
#[ pyimpl( with( Hashable , Comparable , Iterable ) , flags( BASETYPE ) ) ]
345
364
impl PySet {
346
365
#[ pyslot]
347
- fn tp_new (
348
- cls : PyTypeRef ,
349
- _iterable : OptionalArg < PyIterable > ,
350
- vm : & VirtualMachine ,
351
- ) -> PyResult < PyRef < Self > > {
366
+ fn tp_new ( cls : PyTypeRef , _args : FuncArgs , vm : & VirtualMachine ) -> PyResult < PyRef < Self > > {
352
367
PySet :: default ( ) . into_ref_with_type ( vm, cls)
353
368
}
354
369
@@ -543,6 +558,14 @@ impl PySet {
543
558
. symmetric_difference_update ( iterable. iterable , vm) ?;
544
559
Ok ( zelf. as_object ( ) . clone ( ) )
545
560
}
561
+
562
+ #[ pymethod( magic) ]
563
+ fn reduce (
564
+ zelf : PyRef < Self > ,
565
+ vm : & VirtualMachine ,
566
+ ) -> PyResult < ( PyTypeRef , PyObjectRef , Option < PyDictRef > ) > {
567
+ reduce_set ( & zelf. into_object ( ) , vm)
568
+ }
546
569
}
547
570
548
571
impl Comparable for PySet {
@@ -719,6 +742,14 @@ impl PyFrozenSet {
719
742
} ;
720
743
Ok ( vm. ctx . new_str ( s) )
721
744
}
745
+
746
+ #[ pymethod( magic) ]
747
+ fn reduce (
748
+ zelf : PyRef < Self > ,
749
+ vm : & VirtualMachine ,
750
+ ) -> PyResult < ( PyTypeRef , PyObjectRef , Option < PyDictRef > ) > {
751
+ reduce_set ( & zelf. into_object ( ) , vm)
752
+ }
722
753
}
723
754
724
755
impl Hashable for PyFrozenSet {
0 commit comments