@@ -11,9 +11,11 @@ use super::objstr;
1111use super :: objtype;
1212use num_bigint:: ToBigInt ;
1313use num_traits:: ToPrimitive ;
14+ use std:: cell:: { Ref , RefMut } ;
15+ use std:: ops:: { Deref , DerefMut } ;
1416
1517// set_item:
16- pub fn set_item (
18+ fn set_item (
1719vm : & mut VirtualMachine ,
1820l : & mut Vec < PyObjectRef > ,
1921idx : PyObjectRef ,
@@ -32,12 +34,26 @@ pub fn set_item(
3234}
3335}
3436
35- pub fn get_elements ( obj : & PyObjectRef ) ->Vec < PyObjectRef > {
36- if let PyObjectKind :: List { elements} =& obj. borrow ( ) . kind {
37- elements. to_vec ( )
38- } else {
39- panic ! ( "Cannot extract list elements from non-list" ) ;
40- }
37+ pub fn get_elements < ' a > ( obj : & ' a PyObjectRef ) ->impl Deref < Target =Vec < PyObjectRef > > +' a {
38+ Ref :: map ( obj. borrow ( ) , |x|{
39+ if let PyObjectKind :: List { ref elements} = x. kind {
40+ elements
41+ } else {
42+ panic ! ( "Cannot extract list elements from non-list" ) ;
43+ }
44+ } )
45+ }
46+
47+ pub fn get_mut_elements < ' a > ( obj : & ' a PyObjectRef ) ->impl DerefMut < Target =Vec < PyObjectRef > > +' a {
48+ RefMut :: map ( obj. borrow_mut ( ) , |x|{
49+ if let PyObjectKind :: List { ref mut elements} = x. kind {
50+ elements
51+ } else {
52+ panic ! ( "Cannot extract list elements from non-list" ) ;
53+ // TODO: raise proper error?
54+ // Err(vm.new_type_error("list.append is called with no list".to_string()))
55+ }
56+ } )
4157}
4258
4359fn list_new ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
@@ -76,7 +92,7 @@ fn list_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7692let result =if objtype:: isinstance ( other, & vm. ctx . list_type ( ) ) {
7793let zelf =get_elements ( zelf) ;
7894let other =get_elements ( other) ;
79- seq_equal ( vm, zelf, other) ?
95+ seq_equal ( vm, & zelf, & other) ?
8096} else {
8197false
8298} ;
@@ -105,7 +121,7 @@ fn list_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
105121
106122let elements =get_elements ( o) ;
107123let mut str_parts =vec ! [ ] ;
108- for elemin elements{
124+ for elemin elements. iter ( ) {
109125let s = vm. to_repr ( elem) ?;
110126 str_parts. push ( objstr:: get_value ( & s) ) ;
111127}
@@ -121,25 +137,17 @@ pub fn list_append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
121137 args,
122138 required =[ ( list, Some ( vm. ctx. list_type( ) ) ) , ( x, None ) ]
123139) ;
124- let mut list_obj = list. borrow_mut ( ) ;
125- if let PyObjectKind :: List { ref mut elements} = list_obj. kind {
126- elements. push ( x. clone ( ) ) ;
127- Ok ( vm. get_none ( ) )
128- } else {
129- Err ( vm. new_type_error ( "list.append is called with no list" . to_string ( ) ) )
130- }
140+ let mut elements =get_mut_elements ( list) ;
141+ elements. push ( x. clone ( ) ) ;
142+ Ok ( vm. get_none ( ) )
131143}
132144
133145fn list_clear ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
134146trace ! ( "list.clear called with: {:?}" , args) ;
135147arg_check ! ( vm, args, required =[ ( list, Some ( vm. ctx. list_type( ) ) ) ] ) ;
136- let mut list_obj = list. borrow_mut ( ) ;
137- if let PyObjectKind :: List { ref mut elements} = list_obj. kind {
138- elements. clear ( ) ;
139- Ok ( vm. get_none ( ) )
140- } else {
141- Err ( vm. new_type_error ( "list.clear is called with no list" . to_string ( ) ) )
142- }
148+ let mut elements =get_mut_elements ( list) ;
149+ elements. clear ( ) ;
150+ Ok ( vm. get_none ( ) )
143151}
144152
145153pub fn list_extend ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
@@ -149,13 +157,9 @@ pub fn list_extend(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
149157 required =[ ( list, Some ( vm. ctx. list_type( ) ) ) , ( x, None ) ]
150158) ;
151159let mut new_elements = vm. extract_elements ( x) ?;
152- let mut list_obj = list. borrow_mut ( ) ;
153- if let PyObjectKind :: List { ref mut elements} = list_obj. kind {
154- elements. append ( & mut new_elements) ;
155- Ok ( vm. get_none ( ) )
156- } else {
157- Err ( vm. new_type_error ( "list.extend is called with no list" . to_string ( ) ) )
158- }
160+ let mut elements =get_mut_elements ( list) ;
161+ elements. append ( & mut new_elements) ;
162+ Ok ( vm. get_none ( ) )
159163}
160164
161165fn list_len ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
@@ -168,13 +172,9 @@ fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
168172fn list_reverse ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
169173trace ! ( "list.reverse called with: {:?}" , args) ;
170174arg_check ! ( vm, args, required =[ ( list, Some ( vm. ctx. list_type( ) ) ) ] ) ;
171- let mut list_obj = list. borrow_mut ( ) ;
172- if let PyObjectKind :: List { ref mut elements} = list_obj. kind {
173- elements. reverse ( ) ;
174- Ok ( vm. get_none ( ) )
175- } else {
176- Err ( vm. new_type_error ( "list.reverse is called with no list" . to_string ( ) ) )
177- }
175+ let mut elements =get_mut_elements ( list) ;
176+ elements. reverse ( ) ;
177+ Ok ( vm. get_none ( ) )
178178}
179179
180180fn list_contains ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
@@ -208,12 +208,23 @@ fn list_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
208208get_item ( vm, list, & get_elements ( list) , needle. clone ( ) )
209209}
210210
211+ fn list_setitem ( vm : & mut VirtualMachine , args : PyFuncArgs ) ->PyResult {
212+ arg_check ! (
213+ vm,
214+ args,
215+ required =[ ( list, Some ( vm. ctx. list_type( ) ) ) , ( key, None ) , ( value, None ) ]
216+ ) ;
217+ let mut elements =get_mut_elements ( list) ;
218+ set_item ( vm, & mut elements, key. clone ( ) , value. clone ( ) )
219+ }
220+
211221pub fn init ( context : & PyContext ) {
212222let ref list_type = context. list_type ;
213223 list_type. set_attr ( "__add__" , context. new_rustfunc ( list_add) ) ;
214224 list_type. set_attr ( "__contains__" , context. new_rustfunc ( list_contains) ) ;
215225 list_type. set_attr ( "__eq__" , context. new_rustfunc ( list_eq) ) ;
216226 list_type. set_attr ( "__getitem__" , context. new_rustfunc ( list_getitem) ) ;
227+ list_type. set_attr ( "__setitem__" , context. new_rustfunc ( list_setitem) ) ;
217228 list_type. set_attr ( "__len__" , context. new_rustfunc ( list_len) ) ;
218229 list_type. set_attr ( "__new__" , context. new_rustfunc ( list_new) ) ;
219230 list_type. set_attr ( "__repr__" , context. new_rustfunc ( list_repr) ) ;