@@ -892,11 +892,11 @@ impl KotoVm {
892892 value,
893893 index,
894894 } => self . run_index ( register, value, index) ?,
895- SetIndex {
895+ IndexMut {
896896 register,
897897 index,
898898 value,
899- } => self . run_set_index ( register, index, value) ?,
899+ } => self . run_index_mut ( register, index, value) ?,
900900 MapInsert {
901901 register,
902902 key,
@@ -2221,7 +2221,7 @@ impl KotoVm {
22212221 import_result
22222222 }
22232223
2224- fn run_set_index (
2224+ fn run_index_mut (
22252225 & mut self ,
22262226 indexable_register : u8 ,
22272227 index_register : u8 ,
@@ -2230,8 +2230,8 @@ impl KotoVm {
22302230 use KValue :: * ;
22312231
22322232 let indexable = self . clone_register ( indexable_register) ;
2233- let index_value = self . clone_register ( index_register) ;
2234- let value = self . clone_register ( value_register) ;
2233+ let index_value = self . get_register ( index_register) ;
2234+ let value = self . get_register ( value_register) ;
22352235
22362236 match indexable {
22372237 List ( list) => {
@@ -2240,24 +2240,50 @@ impl KotoVm {
22402240 match index_value {
22412241 Number ( index) => {
22422242 let u_index = usize:: from ( index) ;
2243- if index >= 0.0 && u_index < list_len {
2244- list_data[ u_index] = value;
2243+ if * index >= 0.0 && u_index < list_len {
2244+ list_data[ u_index] = value. clone ( ) ;
22452245 } else {
2246- return runtime_error ! ( "Index ' {index}' not in List " ) ;
2246+ return runtime_error ! ( "Invalid index ( {index}) " ) ;
22472247 }
22482248 }
22492249 Range ( range) => {
22502250 for i in range. indices ( list_len) {
22512251 list_data[ i] = value. clone ( ) ;
22522252 }
22532253 }
2254- unexpected => return unexpected_type ( "index " , & unexpected) ,
2254+ unexpected => return unexpected_type ( "Number or Range " , unexpected) ,
22552255 }
2256+ Ok ( ( ) )
22562257 }
2257- unexpected => return unexpected_type ( "a mutable indexable value" , & unexpected) ,
2258- } ;
2259-
2260- Ok ( ( ) )
2258+ Map ( map) => match index_value {
2259+ Number ( index) => {
2260+ let mut map_data = map. data_mut ( ) ;
2261+ let map_len = map_data. len ( ) ;
2262+ let u_index = usize:: from ( index) ;
2263+ if * index >= 0.0 && u_index < map_len {
2264+ match value {
2265+ Tuple ( new_entry) if new_entry. len ( ) == 2 => {
2266+ let key = ValueKey :: try_from ( new_entry[ 0 ] . clone ( ) ) ?;
2267+ // There's no API on IndexMap for replacing an entry,
2268+ // so use swap_remove_index to remove the old entry,
2269+ // then insert the new entry at the end of the map,
2270+ // followed by swap_indices to swap the new entry back into position.
2271+ map_data. swap_remove_index ( u_index) ;
2272+ map_data. insert ( key, new_entry[ 1 ] . clone ( ) ) ;
2273+ map_data. swap_indices ( u_index, map_len - 1 ) ;
2274+ Ok ( ( ) )
2275+ }
2276+ unexpected => unexpected_type ( "Tuple with 2 elements" , unexpected) ,
2277+ }
2278+ } else {
2279+ runtime_error ! ( "Invalid index ({index})" )
2280+ }
2281+ }
2282+ unexpected => unexpected_type ( "Number" , unexpected) ,
2283+ } ,
2284+ Object ( o) => o. try_borrow_mut ( ) ?. index_mut ( index_value, value) ,
2285+ unexpected => unexpected_type ( "a mutable indexable value" , & unexpected) ,
2286+ }
22612287 }
22622288
22632289 fn validate_index ( & self , n : KNumber , size : Option < usize > ) -> Result < usize > {
0 commit comments