@@ -30,7 +30,7 @@ impl<'a> VM<'a> {
3030 OpCode :: CallType => self . call_type ( ) ,
3131 OpCode :: CallChr => self . call_chr ( ) ,
3232 OpCode :: CallOrd => self . call_ord ( ) ,
33- OpCode :: CallSorted => self . call_sorted ( ) ,
33+ OpCode :: CallSorted => self . call_sorted ( false ) ,
3434 OpCode :: CallList => self . call_list ( chunk, slots) ,
3535 OpCode :: CallTuple => self . call_tuple ( chunk, slots) ,
3636 OpCode :: CallEnumerate => self . call_enumerate ( ) ,
@@ -241,6 +241,23 @@ impl<'a> VM<'a> {
241241 if let HeapObj :: BoundMethod ( recv, id) = self . heap . get ( callee) {
242242 let recv = * recv;
243243 let id = * id;
244+ if id. name ( ) == "sort" && !kw_flat. is_empty ( ) {
245+ if !positional. is_empty ( ) {
246+ return Err ( cold_type ( "list.sort() takes no positional arguments" ) ) ;
247+ }
248+ let mut sort_key: Option < Val > = None ;
249+ let mut sort_reverse = false ;
250+ for pair in kw_flat. chunks ( 2 ) {
251+ let ( name_v, val_v) = ( pair[ 0 ] , pair[ 1 ] ) ;
252+ let is_key = name_v. is_heap ( ) && matches ! ( self . heap. get( name_v) , HeapObj :: Str ( s) if s == "key" ) ;
253+ let is_reverse = name_v. is_heap ( ) && matches ! ( self . heap. get( name_v) , HeapObj :: Str ( s) if s == "reverse" ) ;
254+ if is_key { sort_key = Some ( val_v) ; }
255+ else if is_reverse { sort_reverse = self . truthy ( val_v) ; }
256+ else { return Err ( cold_type ( "list.sort() got unexpected keyword argument" ) ) ; }
257+ }
258+ self . call_list_sort_keyed ( recv, sort_key, sort_reverse, chunk, slots) ?;
259+ return Ok ( true ) ;
260+ }
244261 self . exec_bound_method ( recv, id, positional, kw_flat) ?;
245262 return Ok ( true ) ;
246263 }
@@ -594,20 +611,19 @@ impl<'a> VM<'a> {
594611 pub ( crate ) fn dispatch_native ( & mut self , id : super :: super :: types:: NativeFnId , positional : & [ Val ] , kw : & [ Val ] , chunk : & SSAChunk , slots : & mut [ Val ] ) -> Result < ( ) , VmErr > {
595612 use super :: super :: types:: NativeFnId :: * ;
596613
597- // `sorted()` is the only builtin taking kwargs (`key=fn` ); extract it before the no-kw guard.
614+ // `sorted()` is the only builtin taking kwargs (`key=`, `reverse=` ); extract them before the no-kw guard.
598615 let mut sort_key: Option < Val > = None ;
616+ let mut sort_reverse = false ;
599617 let leftover_storage: Vec < Val > ;
600618 let kw_remaining: & [ Val ] = if id == Sorted {
601619 let mut leftover: Vec < Val > = Vec :: new ( ) ;
602620 for chunk_pair in kw. chunks ( 2 ) {
603621 let ( name_v, val_v) = ( chunk_pair[ 0 ] , chunk_pair[ 1 ] ) ;
604622 let is_key = name_v. is_heap ( ) && matches ! ( self . heap. get( name_v) , HeapObj :: Str ( s) if s == "key" ) ;
605- if is_key {
606- sort_key = Some ( val_v) ;
607- } else {
608- leftover. push ( name_v) ;
609- leftover. push ( val_v) ;
610- }
623+ let is_reverse = name_v. is_heap ( ) && matches ! ( self . heap. get( name_v) , HeapObj :: Str ( s) if s == "reverse" ) ;
624+ if is_key { sort_key = Some ( val_v) ; }
625+ else if is_reverse { sort_reverse = self . truthy ( val_v) ; }
626+ else { leftover. push ( name_v) ; leftover. push ( val_v) ; }
611627 }
612628 leftover_storage = leftover;
613629 & leftover_storage
@@ -679,7 +695,7 @@ impl<'a> VM<'a> {
679695 Type => self . call_type ( ) ,
680696 Chr => self . call_chr ( ) ,
681697 Ord => self . call_ord ( ) ,
682- Sorted => self . call_sorted_with_key ( sort_key, chunk, slots) ,
698+ Sorted => self . call_sorted_with_key ( sort_key, sort_reverse , chunk, slots) ,
683699 Enumerate => self . call_enumerate ( ) ,
684700 List => self . call_list ( chunk, slots) ,
685701 Tuple => self . call_tuple ( chunk, slots) ,
0 commit comments