66
77package py
88
9+ import (
10+ "sort"
11+ )
12+
913var ListType = ObjectType .NewType ("list" , "list() -> new empty list\n list(iterable) -> new list initialized from iterable's items" , ListNew , nil )
1014
1115// FIXME lists are mutable so this should probably be struct { Tuple } then can use the sub methods on Tuple
@@ -14,6 +18,7 @@ type List struct {
1418}
1519
1620func init () {
21+ // FIXME: all methods should be callable using list.method([], *args, **kwargs) or [].method(*args, **kwargs)
1722 ListType .Dict ["append" ] = MustNewMethod ("append" , func (self Object , args Tuple ) (Object , error ) {
1823 listSelf := self .(* List )
1924 if len (args ) != 1 {
@@ -34,6 +39,36 @@ func init() {
3439 return NoneType {}, nil
3540 }, 0 , "extend([item])" )
3641
42+ ListType .Dict ["sort" ] = MustNewMethod ("sort" , func (self Object , args Tuple , kwargs StringDict ) (Object , error ) {
43+ const funcName = "sort"
44+ var l * List
45+ if self == None {
46+ // method called using `list.sort([], **kwargs)`
47+ var o Object
48+ err := UnpackTuple (args , nil , funcName , 1 , 1 , & o )
49+ if err != nil {
50+ return nil , err
51+ }
52+ var ok bool
53+ l , ok = o .(* List )
54+ if ! ok {
55+ return nil , ExceptionNewf (TypeError , "descriptor 'sort' requires a 'list' object but received a '%s'" , o .Type ())
56+ }
57+ } else {
58+ // method called using `[].sort(**kargs)`
59+ err := UnpackTuple (args , nil , funcName , 0 , 0 )
60+ if err != nil {
61+ return nil , err
62+ }
63+ l = self .(* List )
64+ }
65+ err := SortInPlace (l , kwargs , funcName )
66+ if err != nil {
67+ return nil , err
68+ }
69+ return NoneType {}, nil
70+ }, 0 , "sort(key=None, reverse=False)" )
71+
3772}
3873
3974// Type of this List object
@@ -331,3 +366,122 @@ func (a *List) M__ne__(other Object) (Object, error) {
331366 }
332367 return False , nil
333368}
369+
370+ type sortable struct {
371+ l * List
372+ keyFunc Object
373+ reverse bool
374+ firstErr error
375+ }
376+
377+ type ptrSortable struct {
378+ s * sortable
379+ }
380+
381+ func (s ptrSortable ) Len () int {
382+ return s .s .l .Len ()
383+ }
384+
385+ func (s ptrSortable ) Swap (i , j int ) {
386+ itemI , err := s .s .l .M__getitem__ (Int (i ))
387+ if err != nil {
388+ if s .s .firstErr == nil {
389+ s .s .firstErr = err
390+ }
391+ return
392+ }
393+ itemJ , err := s .s .l .M__getitem__ (Int (j ))
394+ if err != nil {
395+ if s .s .firstErr == nil {
396+ s .s .firstErr = err
397+ }
398+ return
399+ }
400+ _ , err = s .s .l .M__setitem__ (Int (i ), itemJ )
401+ if err != nil {
402+ if s .s .firstErr == nil {
403+ s .s .firstErr = err
404+ }
405+ }
406+ _ , err = s .s .l .M__setitem__ (Int (j ), itemI )
407+ if err != nil {
408+ if s .s .firstErr == nil {
409+ s .s .firstErr = err
410+ }
411+ }
412+ }
413+
414+ func (s ptrSortable ) Less (i , j int ) bool {
415+ itemI , err := s .s .l .M__getitem__ (Int (i ))
416+ if err != nil {
417+ if s .s .firstErr == nil {
418+ s .s .firstErr = err
419+ }
420+ return false
421+ }
422+ itemJ , err := s .s .l .M__getitem__ (Int (j ))
423+ if err != nil {
424+ if s .s .firstErr == nil {
425+ s .s .firstErr = err
426+ }
427+ return false
428+ }
429+
430+ if s .s .keyFunc != None {
431+ itemI , err = Call (s .s .keyFunc , Tuple {itemI }, nil )
432+ if err != nil {
433+ if s .s .firstErr == nil {
434+ s .s .firstErr = err
435+ }
436+ return false
437+ }
438+ itemJ , err = Call (s .s .keyFunc , Tuple {itemJ }, nil )
439+ if err != nil {
440+ if s .s .firstErr == nil {
441+ s .s .firstErr = err
442+ }
443+ return false
444+ }
445+ }
446+
447+ var cmpResult Object
448+ if s .s .reverse {
449+ cmpResult , err = Lt (itemJ , itemI )
450+ } else {
451+ cmpResult , err = Lt (itemI , itemJ )
452+ }
453+
454+ if err != nil {
455+ if s .s .firstErr == nil {
456+ s .s .firstErr = err
457+ }
458+ return false
459+ }
460+
461+ if boolResult , ok := cmpResult .(Bool ); ok {
462+ return bool (boolResult )
463+ }
464+
465+ return false
466+ }
467+
468+ // SortInPlace sorts the given List in place using a stable sort.
469+ // kwargs can have the keys "key" and "reverse".
470+ func SortInPlace (l * List , kwargs StringDict , funcName string ) error {
471+ var keyFunc Object
472+ var reverse Object
473+ err := ParseTupleAndKeywords (nil , kwargs , "|$OO:" + funcName , []string {"key" , "reverse" }, & keyFunc , & reverse )
474+ if err != nil {
475+ return err
476+ }
477+ if keyFunc == nil {
478+ keyFunc = None
479+ }
480+ if reverse == nil {
481+ reverse = False
482+ }
483+ // FIXME: requires the same bool-check like CPython (or better "|$Op" that doesn't panic on nil).
484+ s := ptrSortable {& sortable {l , keyFunc , ObjectIsTrue (reverse ), nil }}
485+ sort .Stable (s )
486+ return s .s .firstErr
487+ }
0 commit comments