github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/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 runtime 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 }