github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/list.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package grumpy
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"sort"
    21  	"sync"
    22  )
    23  
    24  // List represents Python 'list' objects.
    25  //
    26  // Lists are thread safe, however read operations are not necessarily atomic.
    27  // E.g.  given the list l = [1, 2, 3] executing del l[1] in one thread may give
    28  // repr(l) == [1, 2] in another which is never correct.
    29  type List struct {
    30  	Object
    31  	mutex sync.RWMutex
    32  	elems []*Object
    33  }
    34  
    35  // NewList returns a list containing the given elements.
    36  func NewList(elems ...*Object) *List {
    37  	l := &List{Object: Object{typ: ListType}}
    38  	numElems := len(elems)
    39  	l.resize(numElems)
    40  	for i := 0; i < numElems; i++ {
    41  		l.elems[i] = elems[i]
    42  	}
    43  	return l
    44  }
    45  
    46  func toListUnsafe(o *Object) *List {
    47  	return (*List)(o.toPointer())
    48  }
    49  
    50  // ToObject upcasts l to an Object.
    51  func (l *List) ToObject() *Object {
    52  	return &l.Object
    53  }
    54  
    55  // Append adds o to the end of l.
    56  func (l *List) Append(o *Object) {
    57  	l.mutex.Lock()
    58  	newLen := len(l.elems) + 1
    59  	l.resize(newLen)
    60  	l.elems[newLen-1] = o
    61  	l.mutex.Unlock()
    62  }
    63  
    64  // Reverse the list in place.
    65  func (l *List) Reverse() {
    66  	l.mutex.Lock()
    67  	halfLen := len(l.elems) / 2
    68  	for i := 0; i < halfLen; i++ {
    69  		j := len(l.elems) - i - 1
    70  		l.elems[i], l.elems[j] = l.elems[j], l.elems[i]
    71  	}
    72  	l.mutex.Unlock()
    73  }
    74  
    75  // DelItem removes the index'th element of l.
    76  func (l *List) DelItem(f *Frame, index int) *BaseException {
    77  	l.mutex.Lock()
    78  	numElems := len(l.elems)
    79  	i, raised := seqCheckedIndex(f, numElems, index)
    80  	if raised == nil {
    81  		copy(l.elems[i:numElems-1], l.elems[i+1:numElems])
    82  		l.elems = l.elems[:numElems-1]
    83  	}
    84  	l.mutex.Unlock()
    85  	return raised
    86  }
    87  
    88  // DelSlice removes the slice of l specified by s.
    89  func (l *List) DelSlice(f *Frame, s *Slice) *BaseException {
    90  	l.mutex.Lock()
    91  	numListElems := len(l.elems)
    92  	start, stop, step, numSliceElems, raised := s.calcSlice(f, numListElems)
    93  	if raised == nil {
    94  		if step == 1 {
    95  			copy(l.elems[start:numListElems-numSliceElems], l.elems[stop:numListElems])
    96  		} else {
    97  			j := 0
    98  			for i := start; i != stop; i += step {
    99  				next := i + step
   100  				if next > numListElems {
   101  					next = numListElems
   102  				}
   103  				dest := l.elems[i-j : next-j-1]
   104  				src := l.elems[i+1 : next]
   105  				copy(dest, src)
   106  				j++
   107  			}
   108  		}
   109  		l.elems = l.elems[:numListElems-numSliceElems]
   110  	}
   111  	l.mutex.Unlock()
   112  	return raised
   113  }
   114  
   115  // SetItem sets the index'th element of l to value.
   116  func (l *List) SetItem(f *Frame, index int, value *Object) *BaseException {
   117  	l.mutex.Lock()
   118  	i, raised := seqCheckedIndex(f, len(l.elems), index)
   119  	if raised == nil {
   120  		l.elems[i] = value
   121  	}
   122  	l.mutex.Unlock()
   123  	return raised
   124  }
   125  
   126  // SetSlice replaces the slice of l specified by s with the contents of value
   127  // (an iterable).
   128  func (l *List) SetSlice(f *Frame, s *Slice, value *Object) *BaseException {
   129  	l.mutex.Lock()
   130  	numListElems := len(l.elems)
   131  	start, stop, step, numSliceElems, raised := s.calcSlice(f, numListElems)
   132  	if raised == nil {
   133  		raised = seqApply(f, value, func(elems []*Object, _ bool) *BaseException {
   134  			numElems := len(elems)
   135  			if step == 1 {
   136  				tailElems := l.elems[stop:numListElems]
   137  				l.resize(numListElems - numSliceElems + numElems)
   138  				copy(l.elems[start+numElems:], tailElems)
   139  				copy(l.elems[start:start+numElems], elems)
   140  			} else if numSliceElems == numElems {
   141  				i := 0
   142  				for j := start; j != stop; j += step {
   143  					l.elems[j] = elems[i]
   144  					i++
   145  				}
   146  			} else {
   147  				format := "attempt to assign sequence of size %d to extended slice of size %d"
   148  				return f.RaiseType(ValueErrorType, fmt.Sprintf(format, numElems, numSliceElems))
   149  			}
   150  			return nil
   151  		})
   152  	}
   153  	l.mutex.Unlock()
   154  	return raised
   155  }
   156  
   157  // Sort reorders l so that its elements are in sorted order.
   158  func (l *List) Sort(f *Frame) (raised *BaseException) {
   159  	l.mutex.RLock()
   160  	sorter := &listSorter{f, l, nil}
   161  	defer func() {
   162  		l.mutex.RUnlock()
   163  		if val := recover(); val == nil {
   164  			return
   165  		} else if s, ok := val.(*listSorter); !ok || s != sorter {
   166  			panic(val)
   167  		}
   168  		raised = sorter.raised
   169  	}()
   170  	// Python guarantees stability.  See note (9) in:
   171  	// https://docs.python.org/2/library/stdtypes.html#mutable-sequence-types
   172  	sort.Stable(sorter)
   173  	return nil
   174  }
   175  
   176  // resize ensures that len(l.elems) == newLen, reallocating if necessary.
   177  // NOTE: l.mutex must be locked when calling resize.
   178  func (l *List) resize(newLen int) {
   179  	if cap(l.elems) < newLen {
   180  		// Borrowed from CPython's list_resize() in listobject.c.
   181  		newCap := (newLen >> 3) + 3 + newLen
   182  		if newLen >= 9 {
   183  			newCap += 3
   184  		}
   185  		newElems := make([]*Object, len(l.elems), newCap)
   186  		copy(newElems, l.elems)
   187  		l.elems = newElems
   188  	}
   189  	l.elems = l.elems[:newLen]
   190  }
   191  
   192  // ListType is the object representing the Python 'list' type.
   193  var ListType = newBasisType("list", reflect.TypeOf(List{}), toListUnsafe, ObjectType)
   194  
   195  func listAdd(f *Frame, v, w *Object) (ret *Object, raised *BaseException) {
   196  	if !w.isInstance(ListType) {
   197  		return NotImplemented, nil
   198  	}
   199  	listV, listW := toListUnsafe(v), toListUnsafe(w)
   200  	listV.mutex.RLock()
   201  	listW.mutex.RLock()
   202  	elems, raised := seqAdd(f, listV.elems, listW.elems)
   203  	if raised == nil {
   204  		ret = NewList(elems...).ToObject()
   205  	}
   206  	listW.mutex.RUnlock()
   207  	listV.mutex.RUnlock()
   208  	return ret, raised
   209  }
   210  
   211  func listAppend(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   212  	if raised := checkMethodArgs(f, "append", args, ListType, ObjectType); raised != nil {
   213  		return nil, raised
   214  	}
   215  	toListUnsafe(args[0]).Append(args[1])
   216  	return None, nil
   217  }
   218  
   219  func listCount(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   220  	if raised := checkMethodArgs(f, "count", args, ListType, ObjectType); raised != nil {
   221  		return nil, raised
   222  	}
   223  	return seqCount(f, args[0], args[1])
   224  }
   225  
   226  func listDelItem(f *Frame, o *Object, key *Object) *BaseException {
   227  	l := toListUnsafe(o)
   228  	if key.isInstance(SliceType) {
   229  		return l.DelSlice(f, toSliceUnsafe(key))
   230  	}
   231  	if key.typ.slots.Index == nil {
   232  		format := "list indices must be integers, not %s"
   233  		return f.RaiseType(TypeErrorType, fmt.Sprintf(format, key.Type().Name()))
   234  	}
   235  	index, raised := IndexInt(f, key)
   236  	if raised != nil {
   237  		return raised
   238  	}
   239  	return l.DelItem(f, index)
   240  }
   241  
   242  func listRemove(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   243  	if raised := checkMethodArgs(f, "remove", args, ListType, ObjectType); raised != nil {
   244  		return nil, raised
   245  	}
   246  	value := args[1]
   247  	l := toListUnsafe(args[0])
   248  	l.mutex.Lock()
   249  	index, raised := seqFindElem(f, l.elems, value)
   250  	if raised == nil {
   251  		if index != -1 {
   252  			l.elems = append(l.elems[:index], l.elems[index+1:]...)
   253  		} else {
   254  			raised = f.RaiseType(ValueErrorType, "list.remove(x): x not in list")
   255  		}
   256  	}
   257  	l.mutex.Unlock()
   258  	if raised != nil {
   259  		return nil, raised
   260  	}
   261  	return None, nil
   262  }
   263  
   264  func listExtend(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   265  	argc := len(args)
   266  	if argc != 2 {
   267  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("extend() takes exactly one argument (%d given)", argc))
   268  	}
   269  	return listIAdd(f, args[0], args[1])
   270  }
   271  
   272  func listContains(f *Frame, l, v *Object) (*Object, *BaseException) {
   273  	return seqContains(f, l, v)
   274  }
   275  
   276  func listEq(f *Frame, v, w *Object) (*Object, *BaseException) {
   277  	return listCompare(f, toListUnsafe(v), w, Eq)
   278  }
   279  
   280  func listGE(f *Frame, v, w *Object) (*Object, *BaseException) {
   281  	return listCompare(f, toListUnsafe(v), w, GE)
   282  }
   283  
   284  func listGetItem(f *Frame, o, key *Object) (*Object, *BaseException) {
   285  	l := toListUnsafe(o)
   286  	if key.typ.slots.Index == nil && !key.isInstance(SliceType) {
   287  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("list indices must be integers, not %s", key.typ.Name()))
   288  	}
   289  	l.mutex.RLock()
   290  	item, elems, raised := seqGetItem(f, l.elems, key)
   291  	l.mutex.RUnlock()
   292  	if raised != nil {
   293  		return nil, raised
   294  	}
   295  	if item != nil {
   296  		return item, nil
   297  	}
   298  	return NewList(elems...).ToObject(), nil
   299  }
   300  
   301  func listGT(f *Frame, v, w *Object) (*Object, *BaseException) {
   302  	return listCompare(f, toListUnsafe(v), w, GT)
   303  }
   304  
   305  func listIAdd(f *Frame, v, w *Object) (*Object, *BaseException) {
   306  	l := toListUnsafe(v)
   307  	raised := seqForEach(f, w, func(o *Object) *BaseException {
   308  		l.Append(o)
   309  		return nil
   310  	})
   311  	if raised != nil {
   312  		return nil, raised
   313  	}
   314  	return v, nil
   315  }
   316  
   317  func listIMul(f *Frame, v, w *Object) (*Object, *BaseException) {
   318  	if !w.isInstance(IntType) {
   319  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("can't multiply sequence by non-int of type '%s'", w.typ.Name()))
   320  	}
   321  	l, n := toListUnsafe(v), toIntUnsafe(w).Value()
   322  	l.mutex.Lock()
   323  	elems, raised := seqMul(f, l.elems, n)
   324  	if raised == nil {
   325  		l.elems = elems
   326  	}
   327  	l.mutex.Unlock()
   328  	if raised != nil {
   329  		return nil, raised
   330  	}
   331  	return v, nil
   332  }
   333  
   334  func listInsert(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   335  	if raised := checkMethodArgs(f, "insert", args, ListType, IntType, ObjectType); raised != nil {
   336  		return nil, raised
   337  	}
   338  	l := toListUnsafe(args[0])
   339  	l.mutex.Lock()
   340  	elems := l.elems
   341  	numElems := len(elems)
   342  	i := seqClampIndex(toIntUnsafe(args[1]).Value(), numElems)
   343  	l.resize(numElems + 1)
   344  	// TODO: The resize() above may have done a copy so we're doing a lot
   345  	// of extra work here. Optimize this.
   346  	copy(l.elems[i+1:], elems[i:])
   347  	l.elems[i] = args[2]
   348  	l.mutex.Unlock()
   349  	return None, nil
   350  }
   351  
   352  func listIter(f *Frame, o *Object) (*Object, *BaseException) {
   353  	return newListIterator(toListUnsafe(o)), nil
   354  }
   355  
   356  func listLE(f *Frame, v, w *Object) (*Object, *BaseException) {
   357  	return listCompare(f, toListUnsafe(v), w, LE)
   358  }
   359  
   360  func listLen(f *Frame, o *Object) (*Object, *BaseException) {
   361  	l := toListUnsafe(o)
   362  	l.mutex.RLock()
   363  	ret := NewInt(len(l.elems)).ToObject()
   364  	l.mutex.RUnlock()
   365  	return ret, nil
   366  }
   367  
   368  func listNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
   369  	elems, raised := seqNew(f, args)
   370  	if raised != nil {
   371  		return nil, raised
   372  	}
   373  	l := toListUnsafe(newObject(t))
   374  	l.elems = elems
   375  	return l.ToObject(), nil
   376  }
   377  
   378  func listLT(f *Frame, v, w *Object) (*Object, *BaseException) {
   379  	return listCompare(f, toListUnsafe(v), w, LT)
   380  }
   381  
   382  func listMul(f *Frame, v, w *Object) (*Object, *BaseException) {
   383  	if !w.isInstance(IntType) {
   384  		return NotImplemented, nil
   385  	}
   386  	l, n := toListUnsafe(v), toIntUnsafe(w).Value()
   387  	l.mutex.RLock()
   388  	elems, raised := seqMul(f, l.elems, n)
   389  	l.mutex.RUnlock()
   390  	if raised != nil {
   391  		return nil, raised
   392  	}
   393  	return NewList(elems...).ToObject(), nil
   394  }
   395  
   396  func listNE(f *Frame, v, w *Object) (*Object, *BaseException) {
   397  	return listCompare(f, toListUnsafe(v), w, NE)
   398  }
   399  
   400  func listIndex(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   401  	expectedTypes := []*Type{ListType, ObjectType, ObjectType, ObjectType}
   402  	argc := len(args)
   403  	var raised *BaseException
   404  	if argc == 2 || argc == 3 {
   405  		expectedTypes = expectedTypes[:argc]
   406  	}
   407  	if raised = checkMethodArgs(f, "index", args, expectedTypes...); raised != nil {
   408  		return nil, raised
   409  	}
   410  	l := toListUnsafe(args[0])
   411  	l.mutex.RLock()
   412  	numElems := len(l.elems)
   413  	start, stop := 0, numElems
   414  	if argc > 2 {
   415  		start, raised = IndexInt(f, args[2])
   416  		if raised != nil {
   417  			l.mutex.RUnlock()
   418  			return nil, raised
   419  		}
   420  	}
   421  	if argc > 3 {
   422  		stop, raised = IndexInt(f, args[3])
   423  		if raised != nil {
   424  			l.mutex.RUnlock()
   425  			return nil, raised
   426  		}
   427  	}
   428  	start, stop = adjustIndex(start, stop, numElems)
   429  	value := args[1]
   430  	index := -1
   431  	if start < numElems && start < stop {
   432  		index, raised = seqFindElem(f, l.elems[start:stop], value)
   433  	}
   434  	l.mutex.RUnlock()
   435  	if raised != nil {
   436  		return nil, raised
   437  	}
   438  	if index == -1 {
   439  		return nil, f.RaiseType(ValueErrorType, fmt.Sprintf("%v is not in list", value))
   440  	}
   441  	return NewInt(index + start).ToObject(), nil
   442  }
   443  
   444  func listPop(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   445  	argc := len(args)
   446  	expectedTypes := []*Type{ListType, ObjectType}
   447  	if argc == 1 {
   448  		expectedTypes = expectedTypes[:1]
   449  	}
   450  	if raised := checkMethodArgs(f, "pop", args, expectedTypes...); raised != nil {
   451  		return nil, raised
   452  	}
   453  	i := -1
   454  	if argc == 2 {
   455  		var raised *BaseException
   456  		i, raised = ToIntValue(f, args[1])
   457  		if raised != nil {
   458  			return nil, raised
   459  		}
   460  	}
   461  	l := toListUnsafe(args[0])
   462  	l.mutex.Lock()
   463  	numElems := len(l.elems)
   464  	if i < 0 {
   465  		i += numElems
   466  	}
   467  	var item *Object
   468  	var raised *BaseException
   469  	if i >= numElems || i < 0 {
   470  		raised = f.RaiseType(IndexErrorType, "list index out of range")
   471  	} else {
   472  		item = l.elems[i]
   473  		l.elems = append(l.elems[:i], l.elems[i+1:]...)
   474  	}
   475  	l.mutex.Unlock()
   476  	return item, raised
   477  }
   478  
   479  func listRepr(f *Frame, o *Object) (*Object, *BaseException) {
   480  	l := toListUnsafe(o)
   481  	if f.reprEnter(l.ToObject()) {
   482  		return NewStr("[...]").ToObject(), nil
   483  	}
   484  	l.mutex.RLock()
   485  	repr, raised := seqRepr(f, l.elems)
   486  	l.mutex.RUnlock()
   487  	f.reprLeave(l.ToObject())
   488  	if raised != nil {
   489  		return nil, raised
   490  	}
   491  	return NewStr(fmt.Sprintf("[%s]", repr)).ToObject(), nil
   492  }
   493  
   494  func listReverse(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   495  	if raised := checkMethodArgs(f, "reverse", args, ListType); raised != nil {
   496  		return nil, raised
   497  	}
   498  	l := toListUnsafe(args[0])
   499  	l.Reverse()
   500  	return None, nil
   501  }
   502  
   503  func listSetItem(f *Frame, o, key, value *Object) *BaseException {
   504  	l := toListUnsafe(o)
   505  	if key.typ.slots.Index != nil {
   506  		i, raised := IndexInt(f, key)
   507  		if raised != nil {
   508  			return raised
   509  		}
   510  		return l.SetItem(f, i, value)
   511  	}
   512  	if key.isInstance(SliceType) {
   513  		return l.SetSlice(f, toSliceUnsafe(key), value)
   514  	}
   515  	return f.RaiseType(TypeErrorType, fmt.Sprintf("list indices must be integers, not %s", key.Type().Name()))
   516  }
   517  
   518  func listSort(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   519  	// TODO: Support (cmp=None, key=None, reverse=False)
   520  	if raised := checkMethodArgs(f, "sort", args, ListType); raised != nil {
   521  		return nil, raised
   522  	}
   523  	l := toListUnsafe(args[0])
   524  	l.Sort(f)
   525  	return None, nil
   526  }
   527  
   528  func initListType(dict map[string]*Object) {
   529  	dict["append"] = newBuiltinFunction("append", listAppend).ToObject()
   530  	dict["count"] = newBuiltinFunction("count", listCount).ToObject()
   531  	dict["extend"] = newBuiltinFunction("extend", listExtend).ToObject()
   532  	dict["index"] = newBuiltinFunction("index", listIndex).ToObject()
   533  	dict["insert"] = newBuiltinFunction("insert", listInsert).ToObject()
   534  	dict["pop"] = newBuiltinFunction("pop", listPop).ToObject()
   535  	dict["remove"] = newBuiltinFunction("remove", listRemove).ToObject()
   536  	dict["reverse"] = newBuiltinFunction("reverse", listReverse).ToObject()
   537  	dict["sort"] = newBuiltinFunction("sort", listSort).ToObject()
   538  	ListType.slots.Add = &binaryOpSlot{listAdd}
   539  	ListType.slots.Contains = &binaryOpSlot{listContains}
   540  	ListType.slots.DelItem = &delItemSlot{listDelItem}
   541  	ListType.slots.Eq = &binaryOpSlot{listEq}
   542  	ListType.slots.GE = &binaryOpSlot{listGE}
   543  	ListType.slots.GetItem = &binaryOpSlot{listGetItem}
   544  	ListType.slots.GT = &binaryOpSlot{listGT}
   545  	ListType.slots.Hash = &unaryOpSlot{hashNotImplemented}
   546  	ListType.slots.IAdd = &binaryOpSlot{listIAdd}
   547  	ListType.slots.IMul = &binaryOpSlot{listIMul}
   548  	ListType.slots.Iter = &unaryOpSlot{listIter}
   549  	ListType.slots.LE = &binaryOpSlot{listLE}
   550  	ListType.slots.Len = &unaryOpSlot{listLen}
   551  	ListType.slots.LT = &binaryOpSlot{listLT}
   552  	ListType.slots.Mul = &binaryOpSlot{listMul}
   553  	ListType.slots.NE = &binaryOpSlot{listNE}
   554  	ListType.slots.New = &newSlot{listNew}
   555  	ListType.slots.Repr = &unaryOpSlot{listRepr}
   556  	ListType.slots.RMul = &binaryOpSlot{listMul}
   557  	ListType.slots.SetItem = &setItemSlot{listSetItem}
   558  }
   559  
   560  type listIterator struct {
   561  	Object
   562  	list  *List
   563  	mutex sync.Mutex
   564  	index int
   565  }
   566  
   567  func newListIterator(l *List) *Object {
   568  	iter := &listIterator{Object: Object{typ: listIteratorType}, list: l}
   569  	return &iter.Object
   570  }
   571  
   572  func toListIteratorUnsafe(o *Object) *listIterator {
   573  	return (*listIterator)(o.toPointer())
   574  }
   575  
   576  var listIteratorType = newBasisType("listiterator", reflect.TypeOf(listIterator{}), toListIteratorUnsafe, ObjectType)
   577  
   578  func listIteratorIter(f *Frame, o *Object) (*Object, *BaseException) {
   579  	return o, nil
   580  }
   581  
   582  func listIteratorNext(f *Frame, o *Object) (ret *Object, raised *BaseException) {
   583  	i := toListIteratorUnsafe(o)
   584  	// Ensure that no mutations happen to the list.
   585  	i.list.mutex.RLock()
   586  	i.mutex.Lock()
   587  	if i.index < len(i.list.elems) {
   588  		ret = i.list.elems[i.index]
   589  		i.index++
   590  	} else {
   591  		// Ensure that we raise StopIteration henceforth even if the
   592  		// sequence grows subsequently.
   593  		i.index = MaxInt
   594  		raised = f.Raise(StopIterationType.ToObject(), nil, nil)
   595  	}
   596  	i.mutex.Unlock()
   597  	i.list.mutex.RUnlock()
   598  	return ret, raised
   599  }
   600  
   601  func initListIteratorType(map[string]*Object) {
   602  	listIteratorType.flags &= ^(typeFlagBasetype | typeFlagInstantiable)
   603  	listIteratorType.slots.Iter = &unaryOpSlot{listIteratorIter}
   604  	listIteratorType.slots.Next = &unaryOpSlot{listIteratorNext}
   605  }
   606  
   607  func listCompare(f *Frame, v *List, w *Object, cmp binaryOpFunc) (*Object, *BaseException) {
   608  	if !w.isInstance(ListType) {
   609  		return NotImplemented, nil
   610  	}
   611  	listw := toListUnsafe(w)
   612  	// Order of locking doesn't matter since we're doing a read lock.
   613  	v.mutex.RLock()
   614  	listw.mutex.RLock()
   615  	ret, raised := seqCompare(f, v.elems, listw.elems, cmp)
   616  	listw.mutex.RUnlock()
   617  	v.mutex.RUnlock()
   618  	return ret, raised
   619  }
   620  
   621  type listSorter struct {
   622  	f      *Frame
   623  	l      *List
   624  	raised *BaseException
   625  }
   626  
   627  func (s *listSorter) Len() int {
   628  	return len(s.l.elems)
   629  }
   630  
   631  func (s *listSorter) Less(i, j int) bool {
   632  	lt, raised := LT(s.f, s.l.elems[i], s.l.elems[j])
   633  	if raised != nil {
   634  		s.raised = raised
   635  		panic(s)
   636  	}
   637  	ret, raised := IsTrue(s.f, lt)
   638  	if raised != nil {
   639  		s.raised = raised
   640  		panic(s)
   641  	}
   642  	return ret
   643  }
   644  
   645  func (s *listSorter) Swap(i, j int) {
   646  	s.l.elems[i], s.l.elems[j] = s.l.elems[j], s.l.elems[i]
   647  }