@@ -3,9 +3,9 @@ use std::collections::HashMap;
3
3
use std:: fmt;
4
4
use std:: ops:: { Deref , DerefMut } ;
5
5
6
- use crate :: function:: { OptionalArg , PyFuncArgs } ;
6
+ use crate :: function:: { KwArgs , OptionalArg } ;
7
7
use crate :: pyobject:: {
8
- PyAttributes , PyContext , PyIteratorValue , PyObjectRef , PyRef , PyResult , PyValue , TypeProtocol ,
8
+ DictProtocol , PyAttributes , PyContext , PyIteratorValue , PyObjectRef , PyRef , PyResult , PyValue ,
9
9
} ;
10
10
use crate :: vm:: { ReprGuard , VirtualMachine } ;
11
11
@@ -124,57 +124,48 @@ pub fn py_dict_to_attributes(dict: &PyObjectRef) -> PyAttributes {
124
124
attrs
125
125
}
126
126
127
- pub fn attributes_to_py_dict ( vm : & VirtualMachine , attributes : PyAttributes ) -> PyResult {
128
- let dict = vm. ctx . new_dict ( ) ;
129
- for ( key, value) in attributes {
130
- let key = vm. ctx . new_str ( key) ;
131
- set_item ( & dict, vm, & key, & value) ;
132
- }
133
- Ok ( dict)
134
- }
135
-
136
127
// Python dict methods:
137
- fn dict_new ( vm : & VirtualMachine , args : PyFuncArgs ) -> PyResult {
138
- arg_check ! (
139
- vm,
140
- args,
141
- required = [ ( _ty, Some ( vm. ctx. type_type( ) ) ) ] ,
142
- optional = [ ( dict_obj, None ) ]
143
- ) ;
144
- let dict = vm. ctx . new_dict ( ) ;
145
- if let Some ( dict_obj) = dict_obj {
146
- if objtype:: isinstance ( & dict_obj, & vm. ctx . dict_type ( ) ) {
147
- for ( needle, value) in get_key_value_pairs ( & dict_obj) {
148
- set_item ( & dict, vm, & needle, & value) ;
149
- }
150
- } else {
151
- let iter = objiter:: get_iter ( vm, dict_obj) ?;
152
- loop {
153
- fn err ( vm : & VirtualMachine ) -> PyObjectRef {
154
- vm. new_type_error ( "Iterator must have exactly two elements" . to_string ( ) )
128
+ impl PyDictRef {
129
+ fn new (
130
+ _class : PyClassRef , // TODO Support subclasses of int.
131
+ dict_obj : OptionalArg < PyObjectRef > ,
132
+ kwargs : KwArgs ,
133
+ vm : & VirtualMachine ,
134
+ ) -> PyResult < PyDictRef > {
135
+ let dict = vm. ctx . new_dict ( ) ;
136
+ if let OptionalArg :: Present ( dict_obj) = dict_obj {
137
+ if objtype:: isinstance ( & dict_obj, & vm. ctx . dict_type ( ) ) {
138
+ for ( needle, value) in get_key_value_pairs ( & dict_obj) {
139
+ set_item ( dict. as_object ( ) , vm, & needle, & value) ;
155
140
}
156
- let element = match objiter:: get_next_object ( vm, & iter) ? {
157
- Some ( obj) => obj,
158
- None => break ,
159
- } ;
160
- let elem_iter = objiter:: get_iter ( vm, & element) ?;
161
- let needle = objiter:: get_next_object ( vm, & elem_iter) ?. ok_or_else ( || err ( vm) ) ?;
162
- let value = objiter:: get_next_object ( vm, & elem_iter) ?. ok_or_else ( || err ( vm) ) ?;
163
- if objiter:: get_next_object ( vm, & elem_iter) ?. is_some ( ) {
164
- return Err ( err ( vm) ) ;
141
+ } else {
142
+ let iter = objiter:: get_iter ( vm, & dict_obj) ?;
143
+ loop {
144
+ fn err ( vm : & VirtualMachine ) -> PyObjectRef {
145
+ vm. new_type_error ( "Iterator must have exactly two elements" . to_string ( ) )
146
+ }
147
+ let element = match objiter:: get_next_object ( vm, & iter) ? {
148
+ Some ( obj) => obj,
149
+ None => break ,
150
+ } ;
151
+ let elem_iter = objiter:: get_iter ( vm, & element) ?;
152
+ let needle =
153
+ objiter:: get_next_object ( vm, & elem_iter) ?. ok_or_else ( || err ( vm) ) ?;
154
+ let value = objiter:: get_next_object ( vm, & elem_iter) ?. ok_or_else ( || err ( vm) ) ?;
155
+ if objiter:: get_next_object ( vm, & elem_iter) ?. is_some ( ) {
156
+ return Err ( err ( vm) ) ;
157
+ }
158
+ set_item ( dict. as_object ( ) , vm, & needle, & value) ;
165
159
}
166
- set_item ( & dict, vm, & needle, & value) ;
167
160
}
168
161
}
162
+ for ( needle, value) in kwargs. into_iter ( ) {
163
+ let py_needle = vm. new_str ( needle) ;
164
+ set_item ( & dict. as_object ( ) , vm, & py_needle, & value) ;
165
+ }
166
+ Ok ( dict)
169
167
}
170
- for ( needle, value) in args. kwargs {
171
- let py_needle = vm. new_str ( needle) ;
172
- set_item ( & dict, vm, & py_needle, & value) ;
173
- }
174
- Ok ( dict)
175
- }
176
168
177
- impl PyDictRef {
178
169
fn bool ( self , _vm : & VirtualMachine ) -> bool {
179
170
!self . entries . borrow ( ) . is_empty ( )
180
171
}
@@ -302,6 +293,31 @@ impl PyDictRef {
302
293
}
303
294
}
304
295
296
+ impl DictProtocol for PyDictRef {
297
+ fn contains_key ( & self , k : & str ) -> bool {
298
+ content_contains_key_str ( & self . entries . borrow ( ) , k)
299
+ }
300
+
301
+ fn get_item ( & self , k : & str ) -> Option < PyObjectRef > {
302
+ content_get_key_str ( & self . entries . borrow ( ) , k)
303
+ }
304
+
305
+ fn get_key_value_pairs ( & self ) -> Vec < ( PyObjectRef , PyObjectRef ) > {
306
+ get_key_value_pairs ( self . as_object ( ) )
307
+ }
308
+
309
+ // Item set/get:
310
+ fn set_item ( & self , ctx : & PyContext , key : & str , v : PyObjectRef ) {
311
+ let key = ctx. new_str ( key. to_string ( ) ) ;
312
+ set_item_in_content ( & mut self . entries . borrow_mut ( ) , & key, & v) ;
313
+ }
314
+
315
+ fn del_item ( & self , key : & str ) {
316
+ let mut elements = get_mut_elements ( self . as_object ( ) ) ;
317
+ elements. remove ( key) . unwrap ( ) ;
318
+ }
319
+ }
320
+
305
321
pub fn init ( context : & PyContext ) {
306
322
extend_class ! ( context, & context. dict_type, {
307
323
"__bool__" => context. new_rustfunc( PyDictRef :: bool ) ,
@@ -310,7 +326,7 @@ pub fn init(context: &PyContext) {
310
326
"__delitem__" => context. new_rustfunc( PyDictRef :: delitem) ,
311
327
"__getitem__" => context. new_rustfunc( PyDictRef :: getitem) ,
312
328
"__iter__" => context. new_rustfunc( PyDictRef :: iter) ,
313
- "__new__" => context. new_rustfunc( dict_new ) ,
329
+ "__new__" => context. new_rustfunc( PyDictRef :: new ) ,
314
330
"__repr__" => context. new_rustfunc( PyDictRef :: repr) ,
315
331
"__setitem__" => context. new_rustfunc( PyDictRef :: setitem) ,
316
332
"clear" => context. new_rustfunc( PyDictRef :: clear) ,
0 commit comments