this repo has no description
at trunk 6393 lines 223 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include <unistd.h> 3 4#include <cerrno> 5#include <cmath> 6#include <sstream> 7 8#include "attributedict.h" 9#include "builtins.h" 10#include "bytearray-builtins.h" 11#include "bytes-builtins.h" 12#include "byteslike.h" 13#include "capi.h" 14#include "debugging.h" 15#include "dict-builtins.h" 16#include "exception-builtins.h" 17#include "file.h" 18#include "float-builtins.h" 19#include "float-conversion.h" 20#include "heap-profiler.h" 21#include "int-builtins.h" 22#include "list-builtins.h" 23#include "memoryview-builtins.h" 24#include "module-builtins.h" 25#include "modules.h" 26#include "mro.h" 27#include "object-builtins.h" 28#include "range-builtins.h" 29#include "set-builtins.h" 30#include "slice-builtins.h" 31#include "str-builtins.h" 32#include "strarray-builtins.h" 33#include "structseq-builtins.h" 34#include "super-builtins.h" 35#include "traceback-builtins.h" 36#include "tuple-builtins.h" 37#include "type-builtins.h" 38#include "unicode.h" 39#include "vector.h" 40 41namespace py { 42 43static RawObject raiseRequiresFromCaller(Thread* thread, Arguments args, 44 SymbolId expected_type) { 45 HandleScope scope(thread); 46 Function function(&scope, 47 thread->currentFrame()->previousFrame()->function()); 48 Str function_name(&scope, function.name()); 49 Object obj(&scope, args.get(0)); 50 return thread->raiseWithFmt( 51 LayoutId::kTypeError, 52 "'%S' for '%Y' objects doesn't apply to a '%T' object", &function_name, 53 expected_type, &obj); 54} 55 56bool FUNC(_builtins, _bool_check_intrinsic)(Thread* thread) { 57 thread->stackSetTop(Bool::fromBool(thread->stackPop().isBool())); 58 return true; 59} 60 61bool FUNC(_builtins, _bool_guard_intrinsic)(Thread* thread) { 62 if (thread->stackTop().isBool()) { 63 thread->stackPop(); 64 thread->stackSetTop(NoneType::object()); 65 return true; 66 } 67 return false; 68} 69 70bool FUNC(_builtins, _bytearray_check_intrinsic)(Thread* thread) { 71 thread->stackSetTop(Bool::fromBool( 72 thread->runtime()->isInstanceOfBytearray(thread->stackPop()))); 73 return true; 74} 75 76bool FUNC(_builtins, _bytearray_guard_intrinsic)(Thread* thread) { 77 if (thread->runtime()->isInstanceOfBytearray(thread->stackTop())) { 78 thread->stackPop(); 79 thread->stackSetTop(NoneType::object()); 80 return true; 81 } 82 return false; 83} 84 85bool FUNC(_builtins, _bytearray_len_intrinsic)(Thread* thread) { 86 RawObject arg = thread->stackPop(); 87 if (arg.isBytearray()) { 88 thread->stackSetTop(SmallInt::fromWord(Bytearray::cast(arg).numItems())); 89 return true; 90 } 91 return false; 92} 93 94bool FUNC(_builtins, _bytes_check_intrinsic)(Thread* thread) { 95 thread->stackSetTop( 96 Bool::fromBool(thread->runtime()->isInstanceOfBytes(thread->stackPop()))); 97 return true; 98} 99 100bool FUNC(_builtins, _bytes_guard_intrinsic)(Thread* thread) { 101 if (thread->runtime()->isInstanceOfBytes(thread->stackTop())) { 102 thread->stackPop(); 103 thread->stackSetTop(NoneType::object()); 104 return true; 105 } 106 return false; 107} 108 109bool FUNC(_builtins, _bytes_len_intrinsic)(Thread* thread) { 110 RawObject arg = thread->stackPeek(0); 111 if (arg.isBytes()) { 112 thread->stackPop(); 113 thread->stackSetTop(SmallInt::fromWord(Bytes::cast(arg).length())); 114 return true; 115 } 116 return false; 117} 118 119bool FUNC(_builtins, _byteslike_check_intrinsic)(Thread* thread) { 120 thread->stackSetTop( 121 Bool::fromBool(thread->runtime()->isByteslike(thread->stackPop()))); 122 return true; 123} 124 125bool FUNC(_builtins, _byteslike_guard_intrinsic)(Thread* thread) { 126 if (thread->runtime()->isByteslike(thread->stackTop())) { 127 thread->stackPop(); 128 thread->stackSetTop(NoneType::object()); 129 return true; 130 } 131 return false; 132} 133 134bool FUNC(_builtins, _complex_check_intrinsic)(Thread* thread) { 135 thread->stackSetTop(Bool::fromBool( 136 thread->runtime()->isInstanceOfComplex(thread->stackPop()))); 137 return true; 138} 139 140bool FUNC(_builtins, _deque_guard_intrinsic)(Thread* thread) { 141 if (thread->runtime()->isInstanceOfDeque(thread->stackTop())) { 142 thread->stackPop(); 143 thread->stackSetTop(NoneType::object()); 144 return true; 145 } 146 return false; 147} 148 149bool FUNC(_builtins, _dict_check_intrinsic)(Thread* thread) { 150 thread->stackSetTop( 151 Bool::fromBool(thread->runtime()->isInstanceOfDict(thread->stackPop()))); 152 return true; 153} 154 155bool FUNC(_builtins, _dict_check_exact_intrinsic)(Thread* thread) { 156 thread->stackSetTop(Bool::fromBool(thread->stackPop().isDict())); 157 return true; 158} 159 160bool FUNC(_builtins, _dict_guard_intrinsic)(Thread* thread) { 161 if (thread->runtime()->isInstanceOfDict(thread->stackTop())) { 162 thread->stackPop(); 163 thread->stackSetTop(NoneType::object()); 164 return true; 165 } 166 return false; 167} 168 169bool FUNC(_builtins, _dict_len_intrinsic)(Thread* thread) { 170 RawObject arg = thread->stackPeek(0); 171 if (arg.isDict()) { 172 thread->stackPop(); 173 thread->stackSetTop(SmallInt::fromWord(Dict::cast(arg).numItems())); 174 return true; 175 } 176 return false; 177} 178 179bool FUNC(_builtins, _float_check_intrinsic)(Thread* thread) { 180 thread->stackSetTop( 181 Bool::fromBool(thread->runtime()->isInstanceOfFloat(thread->stackPop()))); 182 return true; 183} 184 185bool FUNC(_builtins, _float_check_exact_intrinsic)(Thread* thread) { 186 thread->stackSetTop(Bool::fromBool(thread->stackPop().isFloat())); 187 return true; 188} 189 190bool FUNC(_builtins, _float_guard_intrinsic)(Thread* thread) { 191 if (thread->runtime()->isInstanceOfFloat(thread->stackTop())) { 192 thread->stackPop(); 193 thread->stackSetTop(NoneType::object()); 194 return true; 195 } 196 return false; 197} 198 199bool FUNC(_builtins, _frozenset_check_intrinsic)(Thread* thread) { 200 thread->stackSetTop(Bool::fromBool( 201 thread->runtime()->isInstanceOfFrozenSet(thread->stackPop()))); 202 return true; 203} 204 205bool FUNC(_builtins, _frozenset_guard_intrinsic)(Thread* thread) { 206 if (thread->runtime()->isInstanceOfFrozenSet(thread->stackTop())) { 207 thread->stackPop(); 208 thread->stackSetTop(NoneType::object()); 209 return true; 210 } 211 return false; 212} 213 214bool FUNC(_builtins, _function_guard_intrinsic)(Thread* thread) { 215 if (thread->stackTop().isFunction()) { 216 thread->stackPop(); 217 thread->stackSetTop(NoneType::object()); 218 return true; 219 } 220 return false; 221} 222 223bool FUNC(_builtins, _int_check_intrinsic)(Thread* thread) { 224 thread->stackSetTop( 225 Bool::fromBool(thread->runtime()->isInstanceOfInt(thread->stackPop()))); 226 return true; 227} 228 229bool FUNC(_builtins, _int_check_exact_intrinsic)(Thread* thread) { 230 RawObject arg = thread->stackPop(); 231 thread->stackSetTop(Bool::fromBool(arg.isSmallInt() || arg.isLargeInt())); 232 return true; 233} 234 235bool FUNC(_builtins, _int_guard_intrinsic)(Thread* thread) { 236 if (thread->runtime()->isInstanceOfInt(thread->stackTop())) { 237 thread->stackPop(); 238 thread->stackSetTop(NoneType::object()); 239 return true; 240 } 241 return false; 242} 243 244bool FUNC(_builtins, _list_append_intrinsic)(Thread* thread) { 245 RawObject arg0 = thread->stackPeek(1); 246 if (!thread->runtime()->isInstanceOfList(arg0)) { 247 return false; 248 } 249 RawList self = arg0.rawCast<RawList>(); 250 word num_items = self.numItems(); 251 if (self.capacity() > num_items) { 252 self.setNumItems(num_items + 1); 253 self.atPut(num_items, thread->stackPeek(0)); 254 thread->stackDrop(2); 255 thread->stackSetTop(NoneType::object()); 256 return true; 257 } 258 return false; 259} 260 261bool FUNC(_builtins, _list_check_intrinsic)(Thread* thread) { 262 thread->stackSetTop( 263 Bool::fromBool(thread->runtime()->isInstanceOfList(thread->stackPop()))); 264 return true; 265} 266 267bool FUNC(_builtins, _list_check_exact_intrinsic)(Thread* thread) { 268 thread->stackSetTop(Bool::fromBool(thread->stackPop().isList())); 269 return true; 270} 271 272RawObject FUNC(_builtins, _list_ctor)(Thread* thread, Arguments args) { 273 Runtime* runtime = thread->runtime(); 274 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kList), "unexpected cls"); 275 RawObject iterable_raw = args.get(1); 276 if (iterable_raw == runtime->emptyTuple()) { 277 return runtime->newList(); 278 } 279 HandleScope scope(thread); 280 Object iterable(&scope, iterable_raw); 281 List self(&scope, runtime->newList()); 282 word src_length; 283 Tuple src(&scope, runtime->emptyTuple()); 284 if (iterable.isList()) { 285 src = List::cast(*iterable).items(); 286 src_length = List::cast(*iterable).numItems(); 287 } else if (iterable.isTuple()) { 288 src = *iterable; 289 src_length = src.length(); 290 } else { 291 Object result(&scope, thread->invokeMethod2(self, ID(extend), iterable)); 292 if (result.isError()) return *result; 293 return *self; 294 } 295 listExtend(thread, self, src, src_length); 296 return *self; 297} 298 299bool FUNC(_builtins, _list_getitem_intrinsic)(Thread* thread) { 300 RawObject arg0 = thread->stackPeek(1); 301 if (!arg0.isList()) { 302 return false; 303 } 304 RawObject arg1 = thread->stackPeek(0); 305 word idx; 306 if (arg1.isSmallInt()) { 307 idx = SmallInt::cast(arg1).value(); 308 } else if (arg1.isBool()) { 309 idx = Bool::cast(arg1).value(); 310 } else { 311 return false; 312 } 313 RawList self = List::cast(arg0); 314 if (0 <= idx && idx < self.numItems()) { 315 thread->stackDrop(2); 316 thread->stackSetTop(self.at(idx)); 317 return true; 318 } 319 return false; 320} 321 322bool FUNC(_builtins, _list_guard_intrinsic)(Thread* thread) { 323 if (thread->runtime()->isInstanceOfList(thread->stackTop())) { 324 thread->stackPop(); 325 thread->stackSetTop(NoneType::object()); 326 return true; 327 } 328 return false; 329} 330 331bool FUNC(_builtins, _list_len_intrinsic)(Thread* thread) { 332 RawObject arg = thread->stackPeek(0); 333 if (arg.isList()) { 334 thread->stackPop(); 335 thread->stackSetTop(SmallInt::fromWord(List::cast(arg).numItems())); 336 return true; 337 } 338 return false; 339} 340 341bool FUNC(_builtins, _list_setitem_intrinsic)(Thread* thread) { 342 RawObject arg0 = thread->stackPeek(2); 343 if (!arg0.isList()) { 344 return false; 345 } 346 RawObject arg1 = thread->stackPeek(1); 347 word idx; 348 if (arg1.isSmallInt()) { 349 idx = SmallInt::cast(arg1).value(); 350 } else if (arg1.isBool()) { 351 idx = Bool::cast(arg1).value(); 352 } else { 353 return false; 354 } 355 RawList self = List::cast(arg0); 356 if (idx < 0 || idx >= self.numItems()) { 357 return false; 358 } 359 self.atPut(idx, thread->stackPeek(0)); 360 thread->stackDrop(3); 361 thread->stackSetTop(NoneType::object()); 362 return true; 363} 364 365bool FUNC(_builtins, _memoryview_guard_intrinsic)(Thread* thread) { 366 if (thread->stackTop().isMemoryView()) { 367 thread->stackPop(); 368 thread->stackSetTop(NoneType::object()); 369 return true; 370 } 371 return false; 372} 373 374bool FUNC(_builtins, _range_check_intrinsic)(Thread* thread) { 375 thread->stackSetTop(Bool::fromBool(thread->stackPop().isRange())); 376 return true; 377} 378 379bool FUNC(_builtins, _range_guard_intrinsic)(Thread* thread) { 380 if (thread->stackTop().isRange()) { 381 thread->stackPop(); 382 thread->stackSetTop(NoneType::object()); 383 return true; 384 } 385 return false; 386} 387 388bool FUNC(_builtins, _seq_index_intrinsic)(Thread* thread) { 389 thread->stackSetTop( 390 SmallInt::fromWord(SeqIterator::cast(thread->stackPop()).index())); 391 return true; 392} 393 394bool FUNC(_builtins, _seq_iterable_intrinsic)(Thread* thread) { 395 thread->stackSetTop(SeqIterator::cast(thread->stackPop()).iterable()); 396 return true; 397} 398 399bool FUNC(_builtins, _seq_set_index_intrinsic)(Thread* thread) { 400 RawObject index = thread->stackPop(); 401 RawObject seq_iter = thread->stackPop(); 402 SeqIterator::cast(seq_iter).setIndex(Int::cast(index).asWord()); 403 return true; 404} 405 406bool FUNC(_builtins, _seq_set_iterable_intrinsic)(Thread* thread) { 407 RawObject iterable = thread->stackPop(); 408 RawObject seq_iter = thread->stackPop(); 409 SeqIterator::cast(seq_iter).setIterable(iterable); 410 return true; 411} 412 413bool FUNC(_builtins, _set_check_intrinsic)(Thread* thread) { 414 thread->stackSetTop( 415 Bool::fromBool(thread->runtime()->isInstanceOfSet(thread->stackPop()))); 416 return true; 417} 418 419bool FUNC(_builtins, _set_guard_intrinsic)(Thread* thread) { 420 if (thread->runtime()->isInstanceOfSet(thread->stackTop())) { 421 thread->stackPop(); 422 thread->stackSetTop(NoneType::object()); 423 return true; 424 } 425 return false; 426} 427 428bool FUNC(_builtins, _set_len_intrinsic)(Thread* thread) { 429 RawObject arg = thread->stackPeek(0); 430 if (arg.isSet()) { 431 thread->stackPop(); 432 thread->stackSetTop(SmallInt::fromWord(Set::cast(arg).numItems())); 433 return true; 434 } 435 return false; 436} 437 438bool FUNC(_builtins, _slice_check_intrinsic)(Thread* thread) { 439 thread->stackSetTop(Bool::fromBool(thread->stackPop().isSlice())); 440 return true; 441} 442 443bool FUNC(_builtins, _slice_guard_intrinsic)(Thread* thread) { 444 if (thread->stackTop().isSlice()) { 445 thread->stackPop(); 446 thread->stackSetTop(NoneType::object()); 447 return true; 448 } 449 return false; 450} 451 452bool FUNC(_builtins, _str_check_intrinsic)(Thread* thread) { 453 thread->stackSetTop( 454 Bool::fromBool(thread->runtime()->isInstanceOfStr(thread->stackPop()))); 455 return true; 456} 457 458bool FUNC(_builtins, _str_check_exact_intrinsic)(Thread* thread) { 459 thread->stackSetTop(Bool::fromBool(thread->stackPop().isStr())); 460 return true; 461} 462 463bool FUNC(_builtins, _str_ctor_intrinsic)(Thread* thread) { 464 // The type signature of _str_ctor is 465 // def _str_ctor(cls, obj=_Unbound, encoding=_Unbound, errors=_Unbound): 466 // 467 // `_str_ctor` is available internally so locating it in the stack tells us 468 // how many arguments are given in the presence of optional arguments. 469 RawObject callee = 470 Type::cast(thread->runtime()->typeAt(LayoutId::kStr)).ctor(); 471 if (callee == thread->stackPeek(1)) { 472 // Only `cls` is given: `str()` is executed. 473 thread->stackDrop(1); 474 thread->stackSetTop(Str::empty()); 475 return true; 476 } 477 if (callee == thread->stackPeek(2)) { 478 // `cls` and `obj` are given: `str(s)` is executed. 479 RawObject obj = thread->stackPeek(0); 480 if (obj.isStr()) { 481 thread->stackSetAt(2, obj); 482 thread->stackDrop(2); 483 return true; 484 } 485 } 486 return false; 487} 488 489bool FUNC(_builtins, _str_guard_intrinsic)(Thread* thread) { 490 if (thread->runtime()->isInstanceOfStr(thread->stackTop())) { 491 thread->stackPop(); 492 thread->stackSetTop(NoneType::object()); 493 return true; 494 } 495 return false; 496} 497 498bool FUNC(_builtins, _str_len_intrinsic)(Thread* thread) { 499 RawObject arg = thread->stackPeek(0); 500 if (arg.isStr()) { 501 thread->stackPop(); 502 thread->stackSetTop(SmallInt::fromWord(Str::cast(arg).codePointLength())); 503 return true; 504 } 505 return false; 506} 507 508bool FUNC(_builtins, _tuple_check_intrinsic)(Thread* thread) { 509 thread->stackSetTop( 510 Bool::fromBool(thread->runtime()->isInstanceOfTuple(thread->stackPop()))); 511 return true; 512} 513 514bool FUNC(_builtins, _tuple_check_exact_intrinsic)(Thread* thread) { 515 thread->stackSetTop(Bool::fromBool(thread->stackPop().isTuple())); 516 return true; 517} 518 519bool FUNC(_builtins, _tuple_getitem_intrinsic)(Thread* thread) { 520 RawObject arg0 = thread->stackPeek(1); 521 if (!arg0.isTuple()) { 522 return false; 523 } 524 RawObject arg1 = thread->stackPeek(0); 525 word idx; 526 if (arg1.isSmallInt()) { 527 idx = SmallInt::cast(arg1).value(); 528 } else if (arg1.isBool()) { 529 idx = Bool::cast(arg1).value(); 530 } else { 531 return false; 532 } 533 RawTuple self = Tuple::cast(arg0); 534 if (0 <= idx && idx < self.length()) { 535 thread->stackDrop(2); 536 thread->stackSetTop(self.at(idx)); 537 return true; 538 } 539 return false; 540} 541 542bool FUNC(_builtins, _tuple_guard_intrinsic)(Thread* thread) { 543 if (thread->runtime()->isInstanceOfTuple(thread->stackTop())) { 544 thread->stackPop(); 545 thread->stackSetTop(NoneType::object()); 546 return true; 547 } 548 return false; 549} 550 551bool FUNC(_builtins, _tuple_len_intrinsic)(Thread* thread) { 552 RawObject arg = thread->stackPeek(0); 553 if (arg.isTuple()) { 554 thread->stackPop(); 555 thread->stackSetTop(SmallInt::fromWord(Tuple::cast(arg).length())); 556 return true; 557 } 558 return false; 559} 560 561bool FUNC(_builtins, _type_intrinsic)(Thread* thread) { 562 thread->stackSetTop(thread->runtime()->typeOf(thread->stackPop())); 563 return true; 564} 565 566bool FUNC(_builtins, _type_check_intrinsic)(Thread* thread) { 567 thread->stackSetTop( 568 Bool::fromBool(thread->runtime()->isInstanceOfType(thread->stackPop()))); 569 return true; 570} 571 572bool FUNC(_builtins, _type_check_exact_intrinsic)(Thread* thread) { 573 thread->stackSetTop(Bool::fromBool(thread->stackPop().isType())); 574 return true; 575} 576 577bool FUNC(_builtins, _type_guard_intrinsic)(Thread* thread) { 578 if (thread->runtime()->isInstanceOfType(thread->stackTop())) { 579 thread->stackPop(); 580 thread->stackSetTop(NoneType::object()); 581 return true; 582 } 583 return false; 584} 585 586bool FUNC(_builtins, _type_subclass_guard_intrinsic)(Thread* thread) { 587 RawObject subclass = thread->stackPeek(0); 588 RawObject superclass = thread->stackPeek(1); 589 if (subclass == superclass && subclass.isType()) { 590 thread->stackDrop(2); 591 thread->stackSetTop(NoneType::object()); 592 return true; 593 } 594 return false; 595} 596 597bool FUNC(_builtins, _weakref_check_intrinsic)(Thread* thread) { 598 thread->stackSetTop(Bool::fromBool( 599 thread->runtime()->isInstanceOfWeakRef(thread->stackPop()))); 600 return true; 601} 602 603bool FUNC(_builtins, _weakref_guard_intrinsic)(Thread* thread) { 604 if (thread->runtime()->isInstanceOfWeakRef(thread->stackTop())) { 605 thread->stackPop(); 606 thread->stackSetTop(NoneType::object()); 607 return true; 608 } 609 return false; 610} 611 612void FUNC(_builtins, __init_module__)(Thread* thread, const Module& module, 613 View<byte> bytecode) { 614 HandleScope scope(thread); 615 Object unbound_value(&scope, Unbound::object()); 616 moduleAtPutById(thread, module, ID(_Unbound), unbound_value); 617 618 Object compile_flags_mask(&scope, 619 SmallInt::fromWord(Code::kCompileFlagsMask)); 620 moduleAtPutById(thread, module, ID(_compile_flags_mask), compile_flags_mask); 621 622 Object maxunicode(&scope, SmallInt::fromWord(kMaxUnicode)); 623 moduleAtPutById(thread, module, ID(maxunicode), maxunicode); 624 625 // We did not initialize the `builtins` module yet, so we point 626 // `__builtins__` to this module instead. 627 moduleAtPutById(thread, module, ID(__builtins__), module); 628 629 executeFrozenModule(thread, module, bytecode); 630} 631 632RawObject FUNC(_builtins, _ContextVar_guard)(Thread* thread, Arguments args) { 633 if (args.get(0).isContextVar()) { 634 return NoneType::object(); 635 } 636 return raiseRequiresFromCaller(thread, args, ID(ContextVar)); 637} 638 639RawObject FUNC(_builtins, _Token_guard)(Thread* thread, Arguments args) { 640 if (args.get(0).isToken()) { 641 return NoneType::object(); 642 } 643 return raiseRequiresFromCaller(thread, args, ID(Token)); 644} 645 646RawObject FUNC(_builtins, _address)(Thread* thread, Arguments args) { 647 return thread->runtime()->newInt(args.get(0).raw()); 648} 649 650RawObject FUNC(_builtins, _anyset_check)(Thread* thread, Arguments args) { 651 Runtime* runtime = thread->runtime(); 652 RawObject arg = args.get(0); 653 return Bool::fromBool(runtime->isInstanceOfSet(arg) || 654 runtime->isInstanceOfFrozenSet(arg)); 655} 656 657RawObject FUNC(_builtins, _async_generator_guard)(Thread* thread, 658 Arguments args) { 659 if (args.get(0).isAsyncGenerator()) { 660 return NoneType::object(); 661 } 662 return raiseRequiresFromCaller(thread, args, ID(async_generator)); 663} 664 665RawObject FUNC(_builtins, _base_exception_cause)(Thread* thread, 666 Arguments args) { 667 HandleScope scope(thread); 668 Runtime* runtime = thread->runtime(); 669 Object self(&scope, args.get(0)); 670 if (!runtime->isInstanceOfBaseException(*self)) { 671 return thread->raiseRequiresType(self, ID(BaseException)); 672 } 673 BaseException exc(&scope, *self); 674 return exc.cause(); 675} 676 677RawObject FUNC(_builtins, _base_exception_context)(Thread* thread, 678 Arguments args) { 679 HandleScope scope(thread); 680 Runtime* runtime = thread->runtime(); 681 Object self(&scope, args.get(0)); 682 if (!runtime->isInstanceOfBaseException(*self)) { 683 return thread->raiseRequiresType(self, ID(BaseException)); 684 } 685 BaseException exc(&scope, *self); 686 return exc.context(); 687} 688 689RawObject FUNC(_builtins, _base_exception_set_cause)(Thread* thread, 690 Arguments args) { 691 HandleScope scope(thread); 692 Runtime* runtime = thread->runtime(); 693 Object self(&scope, args.get(0)); 694 if (!runtime->isInstanceOfBaseException(*self)) { 695 return thread->raiseRequiresType(self, ID(BaseException)); 696 } 697 BaseException exc(&scope, *self); 698 Object value(&scope, args.get(1)); 699 if (!value.isNoneType() && !runtime->isInstanceOfBaseException(*value)) { 700 return thread->raiseRequiresType(value, ID(BaseException)); 701 } 702 exc.setCause(*value); 703 return NoneType::object(); 704} 705 706RawObject FUNC(_builtins, _base_exception_set_context)(Thread* thread, 707 Arguments args) { 708 HandleScope scope(thread); 709 Runtime* runtime = thread->runtime(); 710 Object self(&scope, args.get(0)); 711 if (!runtime->isInstanceOfBaseException(*self)) { 712 return thread->raiseRequiresType(self, ID(BaseException)); 713 } 714 BaseException exc(&scope, *self); 715 Object value(&scope, args.get(1)); 716 if (!value.isNoneType() && !runtime->isInstanceOfBaseException(*value)) { 717 return thread->raiseRequiresType(value, ID(BaseException)); 718 } 719 exc.setContext(*value); 720 return NoneType::object(); 721} 722 723RawObject FUNC(_builtins, _base_exception_set_traceback)(Thread* thread, 724 Arguments args) { 725 HandleScope scope(thread); 726 Runtime* runtime = thread->runtime(); 727 Object self(&scope, args.get(0)); 728 if (!runtime->isInstanceOfBaseException(*self)) { 729 return thread->raiseRequiresType(self, ID(BaseException)); 730 } 731 BaseException exc(&scope, *self); 732 Object value(&scope, args.get(1)); 733 if (!value.isNoneType() && !value.isTraceback()) { 734 return thread->raiseRequiresType(value, ID(traceback)); 735 } 736 exc.setTraceback(*value); 737 return NoneType::object(); 738} 739 740RawObject FUNC(_builtins, _base_exception_traceback)(Thread* thread, 741 Arguments args) { 742 HandleScope scope(thread); 743 Runtime* runtime = thread->runtime(); 744 Object self(&scope, args.get(0)); 745 if (!runtime->isInstanceOfBaseException(*self)) { 746 return thread->raiseRequiresType(self, ID(BaseException)); 747 } 748 BaseException exc(&scope, *self); 749 return exc.traceback(); 750} 751 752RawObject FUNC(_builtins, _bool_check)(Thread*, Arguments args) { 753 return Bool::fromBool(args.get(0).isBool()); 754} 755 756RawObject FUNC(_builtins, _bool_guard)(Thread* thread, Arguments args) { 757 if (args.get(0).isBool()) { 758 return NoneType::object(); 759 } 760 return raiseRequiresFromCaller(thread, args, ID(bool)); 761} 762 763RawObject FUNC(_builtins, _bound_method)(Thread* thread, Arguments args) { 764 HandleScope scope(thread); 765 Object function(&scope, args.get(0)); 766 Object owner(&scope, args.get(1)); 767 return thread->runtime()->newBoundMethod(function, owner); 768} 769 770RawObject FUNC(_builtins, _bound_method_guard)(Thread* thread, Arguments args) { 771 if (args.get(0).isBoundMethod()) { 772 return NoneType::object(); 773 } 774 return raiseRequiresFromCaller(thread, args, ID(method)); 775} 776 777RawObject FUNC(_builtins, _builtin_type)(Thread* thread, Arguments args) { 778 HandleScope scope(thread); 779 Object name(&scope, args.get(0)); 780 name = attributeName(thread, name); 781 if (name.isErrorException()) return *name; 782 Object result(&scope, findBuiltinTypeWithName(thread, name)); 783 CHECK(!result.isErrorNotFound(), "Built-in type not found"); 784 return *result; 785} 786 787RawObject FUNC(_builtins, _byte_guard)(Thread* thread, Arguments args) { 788 HandleScope scope(thread); 789 Runtime* runtime = thread->runtime(); 790 Object obj(&scope, args.get(0)); 791 if (runtime->isInstanceOfBytes(*obj)) { 792 Bytes bytes(&scope, bytesUnderlying(*obj)); 793 if (bytes.length() == 1) { 794 return SmallInt::fromWord(bytes.byteAt(0)); 795 } 796 } else if (runtime->isInstanceOfBytearray(*obj)) { 797 Bytearray array(&scope, *obj); 798 if (array.numItems() == 1) { 799 return SmallInt::fromWord(array.byteAt(0)); 800 } 801 } 802 Function function(&scope, 803 thread->currentFrame()->previousFrame()->function()); 804 Str function_name(&scope, function.name()); 805 return thread->raiseWithFmt( 806 LayoutId::kTypeError, 807 "%S() argument 2 must be a byte string of length 1, not %T", 808 &function_name, &obj); 809} 810 811RawObject FUNC(_builtins, _bytearray_append)(Thread* thread, Arguments args) { 812 Runtime* runtime = thread->runtime(); 813 HandleScope scope(thread); 814 Object self_obj(&scope, args.get(0)); 815 if (!runtime->isInstanceOfBytearray(*self_obj)) { 816 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 817 } 818 Bytearray self(&scope, *self_obj); 819 Object item_obj(&scope, args.get(1)); 820 if (!runtime->isInstanceOfInt(*item_obj)) { 821 return Unbound::object(); 822 } 823 OptInt<byte> item_opt = intUnderlying(*item_obj).asInt<byte>(); 824 if (item_opt.error != CastError::None) { 825 return thread->raiseWithFmt(LayoutId::kValueError, 826 "byte must be in range(0, 256)"); 827 } 828 bytearrayAdd(thread, runtime, self, item_opt.value); 829 return NoneType::object(); 830} 831 832RawObject FUNC(_builtins, _bytearray_clear)(Thread* thread, Arguments args) { 833 HandleScope scope(thread); 834 Bytearray self(&scope, args.get(0)); 835 self.downsize(0); 836 return NoneType::object(); 837} 838 839RawObject FUNC(_builtins, _bytearray_contains)(Thread* thread, Arguments args) { 840 HandleScope scope(thread); 841 Runtime* runtime = thread->runtime(); 842 Object self_obj(&scope, args.get(0)); 843 if (!runtime->isInstanceOfBytearray(*self_obj)) { 844 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 845 } 846 Object key_obj(&scope, args.get(1)); 847 if (!runtime->isInstanceOfInt(*key_obj)) { 848 return Unbound::object(); 849 } 850 OptInt<byte> key_opt = intUnderlying(*key_obj).asInt<byte>(); 851 if (key_opt.error != CastError::None) { 852 return thread->raiseWithFmt(LayoutId::kValueError, 853 "byte must be in range(0, 256)"); 854 } 855 Bytearray self(&scope, *self_obj); 856 MutableBytes bytes(&scope, self.items()); 857 return Bool::fromBool(bytes.findByte(key_opt.value, 0, self.numItems()) >= 0); 858} 859 860RawObject FUNC(_builtins, _bytearray_contains_byteslike)(Thread* thread, 861 Arguments args) { 862 HandleScope scope(thread); 863 864 Object self_obj(&scope, args.get(0)); 865 if (!thread->runtime()->isInstanceOfBytearray(*self_obj)) { 866 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 867 } 868 869 Byteslike key(&scope, thread, args.get(1)); 870 if (!key.isValid()) { 871 Object key_obj(&scope, args.get(1)); 872 return thread->raiseWithFmt(LayoutId::kTypeError, 873 "a bytes-like object is required, not '%T'", 874 &key_obj); 875 } 876 877 Bytearray self(&scope, *self_obj); 878 MutableBytes bytes(&scope, self.items()); 879 880 if (key.length() == 0) { 881 // CPython returns true for: b'' in b'abc'. 882 return Bool::fromBool(true); 883 } 884 885 return Bool::fromBool( 886 Utils::memoryFind(reinterpret_cast<byte*>(bytes.address()), 887 bytes.length(), reinterpret_cast<byte*>(key.address()), 888 key.length()) != -1); 889} 890 891RawObject FUNC(_builtins, _bytearray_copy)(Thread* thread, Arguments args) { 892 HandleScope scope(thread); 893 Runtime* runtime = thread->runtime(); 894 Object self_obj(&scope, args.get(0)); 895 if (!runtime->isInstanceOfBytearray(*self_obj)) { 896 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 897 } 898 Bytearray self(&scope, *self_obj); 899 Bytes src(&scope, self.items()); 900 MutableBytes dst(&scope, runtime->mutableBytesFromBytes(thread, src)); 901 Bytearray result(&scope, runtime->newBytearray()); 902 result.setItems(*dst); 903 result.setNumItems(self.numItems()); 904 return *result; 905} 906 907RawObject FUNC(_builtins, _bytearray_check)(Thread* thread, Arguments args) { 908 return Bool::fromBool(thread->runtime()->isInstanceOfBytearray(args.get(0))); 909} 910 911RawObject FUNC(_builtins, _bytearray_guard)(Thread* thread, Arguments args) { 912 if (thread->runtime()->isInstanceOfBytearray(args.get(0))) { 913 return NoneType::object(); 914 } 915 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 916} 917 918RawObject FUNC(_builtins, _bytearray_delitem)(Thread* thread, Arguments args) { 919 HandleScope scope(thread); 920 Bytearray self(&scope, args.get(0)); 921 word length = self.numItems(); 922 word idx = intUnderlying(args.get(1)).asWordSaturated(); 923 if (idx < 0) { 924 idx += length; 925 } 926 if (idx < 0 || idx >= length) { 927 return thread->raiseWithFmt(LayoutId::kIndexError, 928 "bytearray index out of range"); 929 } 930 word last_idx = length - 1; 931 MutableBytes self_bytes(&scope, self.items()); 932 self_bytes.replaceFromWithStartAt(idx, DataArray::cast(self.items()), 933 last_idx - idx, idx + 1); 934 self.setNumItems(last_idx); 935 return NoneType::object(); 936} 937 938RawObject FUNC(_builtins, _bytearray_delslice)(Thread* thread, Arguments args) { 939 // This function deletes elements that are specified by a slice by copying. 940 // It compacts to the left elements in the slice range and then copies 941 // elements after the slice into the free area. The self element count is 942 // decremented and elements in the unused part of the self are overwritten 943 // with None. 944 HandleScope scope(thread); 945 Bytearray self(&scope, args.get(0)); 946 947 word start = SmallInt::cast(args.get(1)).value(); 948 word stop = SmallInt::cast(args.get(2)).value(); 949 word step = SmallInt::cast(args.get(3)).value(); 950 951 word slice_length = Slice::length(start, stop, step); 952 DCHECK_BOUND(slice_length, self.numItems()); 953 if (slice_length == 0) { 954 // Nothing to delete 955 return NoneType::object(); 956 } 957 if (slice_length == self.numItems()) { 958 // Delete all the items 959 self.setNumItems(0); 960 return NoneType::object(); 961 } 962 if (step < 0) { 963 // Adjust step to make iterating easier 964 start = start + step * (slice_length - 1); 965 step = -step; 966 } 967 DCHECK_INDEX(start, self.numItems()); 968 DCHECK(step <= self.numItems() || slice_length == 1, 969 "Step should be in bounds or only one element should be sliced"); 970 // Sliding compaction of elements out of the slice to the left 971 // Invariant: At each iteration of the loop, `fast` is the index of an 972 // element addressed by the slice. 973 // Invariant: At each iteration of the inner loop, `slow` is the index of a 974 // location to where we are relocating a slice addressed element. It is *not* 975 // addressed by the slice. 976 word fast = start; 977 MutableBytes self_bytes(&scope, self.items()); 978 for (word i = 1; i < slice_length; i++) { 979 DCHECK_INDEX(fast, self.numItems()); 980 word slow = fast + 1; 981 fast += step; 982 for (; slow < fast; slow++) { 983 self_bytes.byteAtPut(slow - i, self_bytes.byteAt(slow)); 984 } 985 } 986 // Copy elements into the space where the deleted elements were 987 for (word i = fast + 1; i < self.numItems(); i++) { 988 self_bytes.byteAtPut(i - slice_length, self_bytes.byteAt(i)); 989 } 990 self.setNumItems(self.numItems() - slice_length); 991 return NoneType::object(); 992} 993 994RawObject FUNC(_builtins, _bytearray_getitem)(Thread* thread, Arguments args) { 995 HandleScope scope(thread); 996 Runtime* runtime = thread->runtime(); 997 Object self_obj(&scope, args.get(0)); 998 if (!runtime->isInstanceOfBytearray(*self_obj)) { 999 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 1000 } 1001 Bytearray self(&scope, *self_obj); 1002 Object key(&scope, args.get(1)); 1003 if (runtime->isInstanceOfInt(*key)) { 1004 key = intUnderlying(*key); 1005 if (key.isLargeInt()) { 1006 return thread->raiseWithFmt(LayoutId::kIndexError, 1007 "cannot fit '%T' into an index-sized integer", 1008 &key); 1009 } 1010 word index = Int::cast(*key).asWord(); 1011 word length = self.numItems(); 1012 if (index < 0 || index >= length) { 1013 if (index < 0) { 1014 index += length; 1015 } 1016 if (index < 0 || index >= length) { 1017 return thread->raiseWithFmt(LayoutId::kIndexError, 1018 "bytearray index out of range"); 1019 } 1020 } 1021 return SmallInt::fromWord(self.byteAt(index)); 1022 } 1023 1024 word start, stop; 1025 if (!tryUnpackSlice(key, &start, &stop)) { 1026 return Unbound::object(); 1027 } 1028 1029 word result_len = Slice::adjustIndices(self.numItems(), &start, &stop, 1); 1030 if (result_len == 0) { 1031 return runtime->newBytearray(); 1032 } 1033 1034 Bytearray result(&scope, runtime->newBytearray()); 1035 MutableBytes result_bytes(&scope, 1036 runtime->newMutableBytesUninitialized(result_len)); 1037 MutableBytes src_bytes(&scope, self.items()); 1038 result_bytes.replaceFromWithStartAt(0, *src_bytes, result_len, start); 1039 result.setItems(*result_bytes); 1040 result.setNumItems(result_len); 1041 return *result; 1042} 1043 1044RawObject FUNC(_builtins, _bytearray_getslice)(Thread* thread, Arguments args) { 1045 HandleScope scope(thread); 1046 Bytearray self(&scope, args.get(0)); 1047 word start = SmallInt::cast(args.get(1)).value(); 1048 word stop = SmallInt::cast(args.get(2)).value(); 1049 word step = SmallInt::cast(args.get(3)).value(); 1050 word len = Slice::length(start, stop, step); 1051 Runtime* runtime = thread->runtime(); 1052 Bytearray result(&scope, runtime->newBytearray()); 1053 runtime->bytearrayEnsureCapacity(thread, result, len); 1054 result.setNumItems(len); 1055 for (word i = 0, idx = start; i < len; i++, idx += step) { 1056 result.byteAtPut(i, self.byteAt(idx)); 1057 } 1058 return *result; 1059} 1060 1061RawObject FUNC(_builtins, _bytearray_ljust)(Thread* thread, Arguments args) { 1062 HandleScope scope(thread); 1063 Runtime* runtime = thread->runtime(); 1064 Object self_obj(&scope, args.get(0)); 1065 if (!runtime->isInstanceOfBytearray(*self_obj)) { 1066 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 1067 } 1068 1069 word width; 1070 Object width_obj(&scope, args.get(1)); 1071 if (runtime->isInstanceOfInt(*width_obj)) { 1072 width = intUnderlying(args.get(1)).asWordSaturated(); 1073 if (!SmallInt::isValid(width)) { 1074 return thread->raiseWithFmt( 1075 LayoutId::kOverflowError, 1076 "Python int too large to convert to C ssize_t"); 1077 } 1078 } else { 1079 return Unbound::object(); 1080 } 1081 1082 byte fill; 1083 Object fillbyte_obj(&scope, args.get(2)); 1084 if (runtime->isInstanceOfBytes(*fillbyte_obj)) { 1085 Bytes fillbyte(&scope, bytesUnderlying(*fillbyte_obj)); 1086 if (fillbyte.length() != 1) { 1087 return Unbound::object(); 1088 } 1089 fill = fillbyte.byteAt(0); 1090 } else if (runtime->isInstanceOfBytearray(*fillbyte_obj)) { 1091 Bytearray fillbyte(&scope, *fillbyte_obj); 1092 if (fillbyte.numItems() != 1) { 1093 return Unbound::object(); 1094 } 1095 fill = fillbyte.byteAt(0); 1096 } else { 1097 return Unbound::object(); 1098 } 1099 1100 Bytearray self(&scope, *self_obj); 1101 word self_length = self.numItems(); 1102 word result_length = Utils::maximum(width, self_length); 1103 MutableBytes buffer(&scope, 1104 runtime->newMutableBytesUninitialized(result_length)); 1105 buffer.replaceFromWith(0, DataArray::cast(self.items()), self_length); 1106 buffer.replaceFromWithByte(self_length, fill, result_length - self_length); 1107 1108 Bytearray result(&scope, runtime->newBytearray()); 1109 result.setItems(*buffer); 1110 result.setNumItems(result_length); 1111 return *result; 1112} 1113 1114RawObject FUNC(_builtins, _bytearray_rjust)(Thread* thread, Arguments args) { 1115 HandleScope scope(thread); 1116 Runtime* runtime = thread->runtime(); 1117 Object self_obj(&scope, args.get(0)); 1118 if (!runtime->isInstanceOfBytearray(*self_obj)) { 1119 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 1120 } 1121 1122 word width; 1123 Object width_obj(&scope, args.get(1)); 1124 if (runtime->isInstanceOfInt(*width_obj)) { 1125 width = intUnderlying(args.get(1)).asWordSaturated(); 1126 if (!SmallInt::isValid(width)) { 1127 return thread->raiseWithFmt( 1128 LayoutId::kOverflowError, 1129 "Python int too large to convert to C ssize_t"); 1130 } 1131 } else { 1132 return Unbound::object(); 1133 } 1134 1135 byte fill; 1136 Object fillbyte_obj(&scope, args.get(2)); 1137 if (runtime->isInstanceOfBytes(*fillbyte_obj)) { 1138 Bytes fillbyte(&scope, bytesUnderlying(*fillbyte_obj)); 1139 if (fillbyte.length() != 1) { 1140 return Unbound::object(); 1141 } 1142 fill = fillbyte.byteAt(0); 1143 } else if (runtime->isInstanceOfBytearray(*fillbyte_obj)) { 1144 Bytearray fillbyte(&scope, *fillbyte_obj); 1145 if (fillbyte.numItems() != 1) { 1146 return Unbound::object(); 1147 } 1148 fill = fillbyte.byteAt(0); 1149 } else { 1150 return Unbound::object(); 1151 } 1152 1153 Bytearray self(&scope, *self_obj); 1154 word self_length = self.numItems(); 1155 word result_length = Utils::maximum(width, self_length); 1156 word pad_length = result_length - self_length; 1157 MutableBytes buffer(&scope, 1158 runtime->newMutableBytesUninitialized(result_length)); 1159 buffer.replaceFromWithByte(0, fill, pad_length); 1160 buffer.replaceFromWith(pad_length, DataArray::cast(self.items()), 1161 self_length); 1162 1163 Bytearray result(&scope, runtime->newBytearray()); 1164 result.setItems(*buffer); 1165 result.setNumItems(result_length); 1166 return *result; 1167} 1168 1169RawObject FUNC(_builtins, _bytearray_setitem)(Thread* thread, Arguments args) { 1170 HandleScope scope(thread); 1171 Bytearray self(&scope, args.get(0)); 1172 word index = intUnderlying(args.get(1)).asWordSaturated(); 1173 if (!SmallInt::isValid(index)) { 1174 Object key_obj(&scope, args.get(1)); 1175 return thread->raiseWithFmt(LayoutId::kIndexError, 1176 "cannot fit '%T' into an index-sized integer", 1177 &key_obj); 1178 } 1179 word length = self.numItems(); 1180 if (index < 0) { 1181 index += length; 1182 } 1183 if (index < 0 || index >= length) { 1184 return thread->raiseWithFmt(LayoutId::kIndexError, "index out of range"); 1185 } 1186 word val = intUnderlying(args.get(2)).asWordSaturated(); 1187 if (val < 0 || val > kMaxByte) { 1188 return thread->raiseWithFmt(LayoutId::kValueError, 1189 "byte must be in range(0, 256)"); 1190 } 1191 self.byteAtPut(index, val); 1192 return NoneType::object(); 1193} 1194 1195RawObject FUNC(_builtins, _bytearray_setslice)(Thread* thread, Arguments args) { 1196 HandleScope scope(thread); 1197 Bytearray self(&scope, args.get(0)); 1198 word start = SmallInt::cast(args.get(1)).value(); 1199 word stop = SmallInt::cast(args.get(2)).value(); 1200 word step = SmallInt::cast(args.get(3)).value(); 1201 Byteslike src(&scope, thread, args.get(4)); 1202 DCHECK(src.isValid(), "argument must be a byteslike"); 1203 1204 // Make sure that the degenerate case of a slice assignment where start is 1205 // greater than stop inserts before the start and not the stop. For example, 1206 // b[5:2] = ... should inserts before 5, not before 2. 1207 if ((step < 0 && start < stop) || (step > 0 && start > stop)) { 1208 stop = start; 1209 } 1210 1211 Runtime* runtime = thread->runtime(); 1212 word src_length = src.length(); 1213 1214 if (step == 1) { 1215 word growth = src_length - (stop - start); 1216 word new_length = self.numItems() + growth; 1217 if (self == args.get(4)) { 1218 // Rare case when replacing lhs with elements of rhs when lhs == rhs. 1219 // Will always have growth >= 0. 1220 if (growth == 0) { 1221 return NoneType::object(); 1222 } 1223 runtime->bytearrayEnsureCapacity(thread, self, new_length); 1224 self.setNumItems(new_length); 1225 MutableBytes dst_bytes(&scope, self.items()); 1226 dst_bytes.replaceFromWith(start, *dst_bytes, src_length); 1227 dst_bytes.replaceFromWithStartAt(start + src_length, *dst_bytes, 1228 src_length - stop, start + stop); 1229 return NoneType::object(); 1230 } 1231 if (growth == 0) { 1232 // Assignment does not change the length of the bytearray. Do nothing. 1233 } else if (growth > 0) { 1234 // Assignment grows the length of the bytearray. Ensure there is enough 1235 // free space in the underlying tuple for the new bytes and move stuff 1236 // out of the way. 1237 runtime->bytearrayEnsureCapacity(thread, self, new_length); 1238 // Make the free space part of the bytearray. Must happen before shifting 1239 // so we can index into the free space. 1240 self.setNumItems(new_length); 1241 // Shift some bytes to the right. 1242 self.replaceFromWithStartAt(start + growth, *self, 1243 new_length - growth - start, start); 1244 } else { 1245 // Growth is negative so assignment shrinks the length of the bytearray. 1246 // Shift some bytes to the left. 1247 self.replaceFromWithStartAt(start, *self, new_length - start, 1248 start - growth); 1249 // Remove the free space from the length of the bytearray. Must happen 1250 // after shifting and clearing so we can index into the free space. 1251 self.setNumItems(new_length); 1252 } 1253 MutableBytes dst_bytes(&scope, self.items()); 1254 // Copy new elements into the middle 1255 dst_bytes.replaceFromWithByteslike(start, src, src_length); 1256 return NoneType::object(); 1257 } 1258 1259 word slice_length = Slice::length(start, stop, step); 1260 if (slice_length != src_length) { 1261 return thread->raiseWithFmt( 1262 LayoutId::kValueError, 1263 "attempt to assign bytes of size %w to extended slice of size %w", 1264 src_length, slice_length); 1265 } 1266 1267 MutableBytes dst_bytes(&scope, self.items()); 1268 for (word dst_idx = start, src_idx = 0; src_idx < src_length; 1269 dst_idx += step, src_idx++) { 1270 dst_bytes.byteAtPut(dst_idx, src.byteAt(src_idx)); 1271 } 1272 return NoneType::object(); 1273} 1274 1275RawObject FUNC(_builtins, _bytes_check)(Thread* thread, Arguments args) { 1276 return Bool::fromBool(thread->runtime()->isInstanceOfBytes(args.get(0))); 1277} 1278 1279RawObject FUNC(_builtins, _bytes_contains)(Thread* thread, Arguments args) { 1280 HandleScope scope(thread); 1281 Runtime* runtime = thread->runtime(); 1282 Object self_obj(&scope, args.get(0)); 1283 if (!runtime->isInstanceOfBytes(*self_obj)) { 1284 return raiseRequiresFromCaller(thread, args, ID(bytes)); 1285 } 1286 Object key_obj(&scope, args.get(1)); 1287 if (!runtime->isInstanceOfInt(*key_obj)) { 1288 return Unbound::object(); 1289 } 1290 OptInt<byte> key_opt = intUnderlying(*key_obj).asInt<byte>(); 1291 if (key_opt.error != CastError::None) { 1292 return thread->raiseWithFmt(LayoutId::kValueError, 1293 "byte must be in range(0, 256)"); 1294 } 1295 Bytes self(&scope, *self_obj); 1296 return Bool::fromBool(self.findByte(key_opt.value, 0, self.length()) >= 0); 1297} 1298 1299RawObject FUNC(_builtins, _bytes_decode)(Thread* thread, Arguments args) { 1300 HandleScope scope(thread); 1301 Object bytes_obj(&scope, args.get(0)); 1302 if (!bytes_obj.isBytes()) { 1303 return Unbound::object(); 1304 } 1305 Bytes bytes(&scope, *bytes_obj); 1306 static RawSmallStr ascii = SmallStr::fromCStr("ascii"); 1307 static RawSmallStr utf8 = SmallStr::fromCStr("utf-8"); 1308 static RawSmallStr latin1 = SmallStr::fromCStr("latin-1"); 1309 Str enc(&scope, args.get(1)); 1310 if (enc != ascii && enc != utf8 && enc != latin1 && 1311 enc.compareCStr("iso-8859-1") != 0) { 1312 return Unbound::object(); 1313 } 1314 return bytesDecodeASCII(thread, bytes); 1315} 1316 1317RawObject FUNC(_builtins, _bytes_decode_ascii)(Thread* thread, Arguments args) { 1318 HandleScope scope(thread); 1319 Object bytes_obj(&scope, args.get(0)); 1320 if (!bytes_obj.isBytes()) { 1321 return Unbound::object(); 1322 } 1323 Bytes bytes(&scope, *bytes_obj); 1324 return bytesDecodeASCII(thread, bytes); 1325} 1326 1327RawObject FUNC(_builtins, _bytes_decode_utf_8)(Thread* thread, Arguments args) { 1328 HandleScope scope(thread); 1329 Object bytes_obj(&scope, args.get(0)); 1330 if (!bytes_obj.isBytes()) { 1331 return Unbound::object(); 1332 } 1333 Bytes bytes(&scope, *bytes_obj); 1334 return bytesDecodeASCII(thread, bytes); 1335} 1336 1337RawObject FUNC(_builtins, _bytes_guard)(Thread* thread, Arguments args) { 1338 if (thread->runtime()->isInstanceOfBytes(args.get(0))) { 1339 return NoneType::object(); 1340 } 1341 return raiseRequiresFromCaller(thread, args, ID(bytes)); 1342} 1343 1344RawObject FUNC(_builtins, _bytearray_join)(Thread* thread, Arguments args) { 1345 HandleScope scope(thread); 1346 Object sep_obj(&scope, args.get(0)); 1347 Runtime* runtime = thread->runtime(); 1348 if (!runtime->isInstanceOfBytearray(*sep_obj)) { 1349 return raiseRequiresFromCaller(thread, args, ID(bytearray)); 1350 } 1351 Bytearray sep(&scope, args.get(0)); 1352 Bytes sep_bytes(&scope, sep.items()); 1353 Object iterable(&scope, args.get(1)); 1354 Tuple tuple(&scope, runtime->emptyTuple()); 1355 word length; 1356 if (iterable.isList()) { 1357 tuple = List::cast(*iterable).items(); 1358 length = List::cast(*iterable).numItems(); 1359 } else if (iterable.isTuple()) { 1360 tuple = *iterable; 1361 length = tuple.length(); 1362 } else { 1363 // Collect items into list in Python and call again 1364 return Unbound::object(); 1365 } 1366 Object joined(&scope, 1367 bytesJoin(thread, sep_bytes, sep.numItems(), tuple, length)); 1368 if (joined.isErrorException()) { 1369 return *joined; 1370 } 1371 Bytearray result(&scope, runtime->newBytearray()); 1372 result.setItems(*joined); 1373 result.setNumItems(Bytes::cast(*joined).length()); 1374 return *result; 1375} 1376 1377RawObject FUNC(_builtins, _bytearray_len)(Thread* thread, Arguments args) { 1378 HandleScope scope(thread); 1379 Bytearray self(&scope, args.get(0)); 1380 return SmallInt::fromWord(self.numItems()); 1381} 1382 1383RawObject FUNC(_builtins, _bytes_from_bytes)(Thread* thread, Arguments args) { 1384 HandleScope scope(thread); 1385 Type type(&scope, args.get(0)); 1386 DCHECK(type.builtinBase() == LayoutId::kBytes, "type must subclass bytes"); 1387 Object value(&scope, bytesUnderlying(args.get(1))); 1388 if (type.isBuiltin()) return *value; 1389 Layout type_layout(&scope, type.instanceLayout()); 1390 UserBytesBase instance(&scope, thread->runtime()->newInstance(type_layout)); 1391 instance.setValue(*value); 1392 return *instance; 1393} 1394 1395RawObject FUNC(_builtins, _bytes_from_ints)(Thread* thread, Arguments args) { 1396 HandleScope scope(thread); 1397 Object src(&scope, args.get(0)); 1398 Runtime* runtime = thread->runtime(); 1399 // TODO(T38246066): buffers other than bytes, bytearray 1400 if (runtime->isInstanceOfBytes(*src)) { 1401 return *src; 1402 } 1403 if (runtime->isInstanceOfBytearray(*src)) { 1404 Bytearray source(&scope, *src); 1405 return bytearrayAsBytes(thread, source); 1406 } 1407 if (src.isList()) { 1408 List source(&scope, *src); 1409 Tuple items(&scope, source.items()); 1410 return runtime->bytesFromTuple(thread, items, source.numItems()); 1411 } 1412 if (src.isTuple()) { 1413 Tuple source(&scope, *src); 1414 return runtime->bytesFromTuple(thread, source, source.length()); 1415 } 1416 if (runtime->isInstanceOfStr(*src)) { 1417 return thread->raiseWithFmt(LayoutId::kTypeError, 1418 "cannot convert '%T' object to bytes", &src); 1419 } 1420 // Slow path: iterate over source in Python, collect into list, and call again 1421 return NoneType::object(); 1422} 1423 1424RawObject FUNC(_builtins, _bytes_getitem)(Thread* thread, Arguments args) { 1425 HandleScope scope(thread); 1426 Runtime* runtime = thread->runtime(); 1427 Object self_obj(&scope, args.get(0)); 1428 if (!runtime->isInstanceOfBytes(*self_obj)) { 1429 return raiseRequiresFromCaller(thread, args, ID(bytes)); 1430 } 1431 Bytes self(&scope, bytesUnderlying(*self_obj)); 1432 1433 Object key(&scope, args.get(1)); 1434 if (runtime->isInstanceOfInt(*key)) { 1435 key = intUnderlying(*key); 1436 if (key.isLargeInt()) { 1437 return thread->raiseWithFmt(LayoutId::kIndexError, 1438 "cannot fit '%T' into an index-sized integer", 1439 &key); 1440 } 1441 word index = Int::cast(*key).asWord(); 1442 word length = self.length(); 1443 if (index < 0 || index >= length) { 1444 if (index < 0) { 1445 index += length; 1446 } 1447 if (index < 0 || index >= length) { 1448 return thread->raiseWithFmt(LayoutId::kIndexError, 1449 "index out of range"); 1450 } 1451 } 1452 return SmallInt::fromWord(self.byteAt(index)); 1453 } 1454 1455 word start, stop; 1456 if (!tryUnpackSlice(key, &start, &stop)) { 1457 return Unbound::object(); 1458 } 1459 1460 word result_len = Slice::adjustIndices(self.length(), &start, &stop, 1); 1461 return bytesSubseq(thread, self, start, result_len); 1462} 1463 1464RawObject FUNC(_builtins, _bytes_getslice)(Thread* thread, Arguments args) { 1465 HandleScope scope(thread); 1466 Bytes self(&scope, bytesUnderlying(args.get(0))); 1467 word start = SmallInt::cast(args.get(1)).value(); 1468 word stop = SmallInt::cast(args.get(2)).value(); 1469 word step = SmallInt::cast(args.get(3)).value(); 1470 return thread->runtime()->bytesSlice(thread, self, start, stop, step); 1471} 1472 1473RawObject FUNC(_builtins, _bytes_join)(Thread* thread, Arguments args) { 1474 HandleScope scope(thread); 1475 Object self_obj(&scope, args.get(0)); 1476 Runtime* runtime = thread->runtime(); 1477 if (!runtime->isInstanceOfBytes(*self_obj)) { 1478 return raiseRequiresFromCaller(thread, args, ID(bytes)); 1479 } 1480 Bytes self(&scope, bytesUnderlying(*self_obj)); 1481 Object iterable(&scope, args.get(1)); 1482 Tuple tuple(&scope, runtime->emptyTuple()); 1483 word length; 1484 if (iterable.isList()) { 1485 tuple = List::cast(*iterable).items(); 1486 length = List::cast(*iterable).numItems(); 1487 } else if (iterable.isTuple()) { 1488 tuple = *iterable; 1489 length = Tuple::cast(*iterable).length(); 1490 } else { 1491 // Collect items into list in Python and call again 1492 return Unbound::object(); 1493 } 1494 return bytesJoin(thread, self, self.length(), tuple, length); 1495} 1496 1497RawObject FUNC(_builtins, _bytes_len)(Thread*, Arguments args) { 1498 return SmallInt::fromWord(bytesUnderlying(args.get(0)).length()); 1499} 1500 1501RawObject FUNC(_builtins, _bytes_ljust)(Thread* thread, Arguments args) { 1502 HandleScope scope(thread); 1503 Runtime* runtime = thread->runtime(); 1504 Object self_obj(&scope, args.get(0)); 1505 if (!runtime->isInstanceOfBytes(*self_obj)) { 1506 return raiseRequiresFromCaller(thread, args, ID(bytes)); 1507 } 1508 1509 Object width_obj(&scope, args.get(1)); 1510 if (!runtime->isInstanceOfInt(*width_obj)) { 1511 return Unbound::object(); 1512 } 1513 1514 Int width_int(&scope, intUnderlying(*width_obj)); 1515 if (width_int.isLargeInt()) { 1516 return thread->raiseWithFmt(LayoutId::kOverflowError, 1517 "Python int too large to convert to C ssize_t"); 1518 } 1519 word width = width_int.asWord(); 1520 1521 byte fill; 1522 Object fillbyte_obj(&scope, args.get(2)); 1523 if (runtime->isInstanceOfBytes(*fillbyte_obj)) { 1524 Bytes fillbyte(&scope, bytesUnderlying(*fillbyte_obj)); 1525 if (fillbyte.length() != 1) { 1526 return Unbound::object(); 1527 } 1528 fill = fillbyte.byteAt(0); 1529 } else if (runtime->isInstanceOfBytearray(*fillbyte_obj)) { 1530 Bytearray fillbyte(&scope, *fillbyte_obj); 1531 if (fillbyte.numItems() != 1) { 1532 return Unbound::object(); 1533 } 1534 fill = fillbyte.byteAt(0); 1535 } else { 1536 return Unbound::object(); 1537 } 1538 1539 Bytes self(&scope, *self_obj); 1540 word self_length = self.length(); 1541 if (self_length >= width) { 1542 return *self_obj; 1543 } 1544 1545 if (width <= SmallBytes::kMaxLength) { 1546 byte buffer[SmallBytes::kMaxLength]; 1547 1548 std::memset(buffer, fill, SmallBytes::kMaxLength); 1549 self.copyTo(buffer, self_length); 1550 1551 return SmallBytes::fromBytes({buffer, width}); 1552 } 1553 1554 MutableBytes buffer(&scope, runtime->newMutableBytesUninitialized(width)); 1555 buffer.replaceFromWithBytes(0, *self, self_length); 1556 buffer.replaceFromWithByte(self_length, fill, width - self_length); 1557 1558 return buffer.becomeImmutable(); 1559} 1560 1561RawObject FUNC(_builtins, _bytes_maketrans)(Thread* thread, Arguments args) { 1562 HandleScope scope(thread); 1563 Object from_obj(&scope, args.get(0)); 1564 Object to_obj(&scope, args.get(1)); 1565 word length; 1566 Runtime* runtime = thread->runtime(); 1567 if (runtime->isInstanceOfBytes(*from_obj)) { 1568 Bytes bytes(&scope, bytesUnderlying(*from_obj)); 1569 length = bytes.length(); 1570 from_obj = *bytes; 1571 } else if (runtime->isInstanceOfBytearray(*from_obj)) { 1572 Bytearray array(&scope, *from_obj); 1573 length = array.numItems(); 1574 from_obj = array.items(); 1575 } else { 1576 UNIMPLEMENTED("bytes-like other than bytes or bytearray"); 1577 } 1578 if (runtime->isInstanceOfBytes(*to_obj)) { 1579 Bytes bytes(&scope, bytesUnderlying(*to_obj)); 1580 DCHECK(bytes.length() == length, "lengths should already be the same"); 1581 to_obj = *bytes; 1582 } else if (runtime->isInstanceOfBytearray(*to_obj)) { 1583 Bytearray array(&scope, *to_obj); 1584 DCHECK(array.numItems() == length, "lengths should already be the same"); 1585 to_obj = array.items(); 1586 } else { 1587 UNIMPLEMENTED("bytes-like other than bytes or bytearray"); 1588 } 1589 Bytes from(&scope, *from_obj); 1590 Bytes to(&scope, *to_obj); 1591 byte table[kByteTranslationTableLength]; 1592 for (word i = 0; i < kByteTranslationTableLength; i++) { 1593 table[i] = i; 1594 } 1595 for (word i = 0; i < length; i++) { 1596 table[from.byteAt(i)] = to.byteAt(i); 1597 } 1598 return runtime->newBytesWithAll(table); 1599} 1600 1601RawObject FUNC(_builtins, _bytes_repeat)(Thread* thread, Arguments args) { 1602 HandleScope scope(thread); 1603 Bytes self(&scope, bytesUnderlying(args.get(0))); 1604 // TODO(T55084422): unify bounds checking 1605 word count = intUnderlying(args.get(1)).asWordSaturated(); 1606 if (!SmallInt::isValid(count)) { 1607 Object count_obj(&scope, args.get(1)); 1608 return thread->raiseWithFmt(LayoutId::kOverflowError, 1609 "cannot fit '%T' into an index-sized integer", 1610 &count_obj); 1611 } 1612 // NOTE: unlike __mul__, we raise a value error for negative count 1613 if (count < 0) { 1614 return thread->raiseWithFmt(LayoutId::kValueError, "negative count"); 1615 } 1616 return thread->runtime()->bytesRepeat(thread, self, self.length(), count); 1617} 1618 1619RawObject FUNC(_builtins, _bytes_replace)(Thread* thread, Arguments args) { 1620 Runtime* runtime = thread->runtime(); 1621 HandleScope scope(thread); 1622 Object self_obj(&scope, args.get(0)); 1623 Object old_bytes_obj(&scope, args.get(1)); 1624 Object new_bytes_obj(&scope, args.get(2)); 1625 Object count_obj(&scope, args.get(3)); 1626 1627 // Type Checks 1628 if (!runtime->isInstanceOfBytes(*self_obj)) { 1629 return raiseRequiresFromCaller(thread, args, ID(bytes)); 1630 } 1631 if (!runtime->isByteslike(*old_bytes_obj)) { 1632 return thread->raiseWithFmt(LayoutId::kTypeError, 1633 "a bytes-like object is required, not '%T'", 1634 &old_bytes_obj); 1635 } 1636 if (!runtime->isByteslike(*new_bytes_obj)) { 1637 return thread->raiseWithFmt(LayoutId::kTypeError, 1638 "a bytes-like object is required, not '%T'", 1639 &new_bytes_obj); 1640 } 1641 if (runtime->isInstanceOfFloat(*count_obj)) { 1642 return thread->raiseWithFmt(LayoutId::kTypeError, 1643 "integer argument expected, got float", 1644 &count_obj); 1645 } 1646 if (!runtime->isInstanceOfInt(*count_obj)) { 1647 return Unbound::object(); 1648 } 1649 if (!count_obj.isSmallInt()) { 1650 UNIMPLEMENTED("handle if count is a LargeInt"); 1651 } 1652 1653 // Byteslike breakdown for oldbytes and newbytes 1654 word old_bytes_len; 1655 if (runtime->isInstanceOfBytes(*old_bytes_obj)) { 1656 Bytes bytes(&scope, bytesUnderlying(*old_bytes_obj)); 1657 old_bytes_obj = *bytes; 1658 old_bytes_len = bytes.length(); 1659 } else if (runtime->isInstanceOfBytearray(*old_bytes_obj)) { 1660 Bytearray bytearray(&scope, *old_bytes_obj); 1661 old_bytes_obj = bytearray.items(); 1662 old_bytes_len = bytearray.numItems(); 1663 } else { 1664 // TODO(T38246066): support buffer protocol 1665 UNIMPLEMENTED("bytes-like other than bytes or bytearray"); 1666 } 1667 word new_bytes_len; 1668 if (runtime->isInstanceOfBytes(*new_bytes_obj)) { 1669 Bytes bytes(&scope, bytesUnderlying(*new_bytes_obj)); 1670 new_bytes_obj = *bytes; 1671 new_bytes_len = bytes.length(); 1672 } else if (runtime->isInstanceOfBytearray(*new_bytes_obj)) { 1673 Bytearray bytearray(&scope, *new_bytes_obj); 1674 new_bytes_obj = bytearray.items(); 1675 new_bytes_len = bytearray.numItems(); 1676 } else { 1677 // TODO(T38246066): support buffer protocol 1678 UNIMPLEMENTED("bytes-like other than bytes or bytearray"); 1679 } 1680 1681 Bytes self(&scope, *self_obj); 1682 Bytes old_bytes(&scope, *old_bytes_obj); 1683 Bytes new_bytes(&scope, *new_bytes_obj); 1684 word count = intUnderlying(*count_obj).asWordSaturated(); 1685 return runtime->bytesReplace(thread, self, old_bytes, old_bytes_len, 1686 new_bytes, new_bytes_len, count); 1687} 1688 1689RawObject FUNC(_builtins, _bytes_split)(Thread* thread, Arguments args) { 1690 HandleScope scope(thread); 1691 Bytes self(&scope, bytesUnderlying(args.get(0))); 1692 Object sep_obj(&scope, args.get(1)); 1693 Int maxsplit_int(&scope, intUnderlying(args.get(2))); 1694 if (maxsplit_int.numDigits() > 1) { 1695 return thread->raiseWithFmt(LayoutId::kOverflowError, 1696 "Python int too large to convert to C ssize_t"); 1697 } 1698 word maxsplit = maxsplit_int.asWord(); 1699 if (maxsplit < 0) { 1700 maxsplit = kMaxWord; 1701 } 1702 word sep_len; 1703 Runtime* runtime = thread->runtime(); 1704 if (runtime->isInstanceOfBytes(*sep_obj)) { 1705 Bytes sep(&scope, bytesUnderlying(*sep_obj)); 1706 sep_obj = *sep; 1707 sep_len = sep.length(); 1708 } else if (runtime->isInstanceOfBytearray(*sep_obj)) { 1709 Bytearray sep(&scope, *sep_obj); 1710 sep_obj = sep.items(); 1711 sep_len = sep.numItems(); 1712 } else { 1713 // TODO(T38246066): support buffer protocol 1714 UNIMPLEMENTED("bytes-like other than bytes or bytearray"); 1715 } 1716 if (sep_len == 0) { 1717 return thread->raiseWithFmt(LayoutId::kValueError, "empty separator"); 1718 } 1719 Bytes sep(&scope, *sep_obj); 1720 word self_len = self.length(); 1721 1722 // First pass: calculate the length of the result list. 1723 word splits = 0; 1724 word start = 0; 1725 while (splits < maxsplit) { 1726 word end = bytesFind(self, self_len, sep, sep_len, start, self_len); 1727 if (end < 0) { 1728 break; 1729 } 1730 splits++; 1731 start = end + sep_len; 1732 } 1733 word result_len = splits + 1; 1734 1735 // Second pass: write subsequences into result list. 1736 List result(&scope, runtime->newList()); 1737 MutableTuple buffer(&scope, runtime->newMutableTuple(result_len)); 1738 start = 0; 1739 for (word i = 0; i < splits; i++) { 1740 word end = bytesFind(self, self_len, sep, sep_len, start, self_len); 1741 DCHECK(end != -1, "already found in first pass"); 1742 buffer.atPut(i, bytesSubseq(thread, self, start, end - start)); 1743 start = end + sep_len; 1744 } 1745 buffer.atPut(splits, bytesSubseq(thread, self, start, self_len - start)); 1746 result.setItems(*buffer); 1747 result.setNumItems(result_len); 1748 return *result; 1749} 1750 1751RawObject FUNC(_builtins, _bytes_split_whitespace)(Thread* thread, 1752 Arguments args) { 1753 HandleScope scope(thread); 1754 Bytes self(&scope, bytesUnderlying(args.get(0))); 1755 Int maxsplit_int(&scope, intUnderlying(args.get(1))); 1756 if (maxsplit_int.numDigits() > 1) { 1757 return thread->raiseWithFmt(LayoutId::kOverflowError, 1758 "Python int too large to convert to C ssize_t"); 1759 } 1760 word self_len = self.length(); 1761 word maxsplit = maxsplit_int.asWord(); 1762 if (maxsplit < 0) { 1763 maxsplit = kMaxWord; 1764 } 1765 1766 // First pass: calculate the length of the result list. 1767 word splits = 0; 1768 word index = 0; 1769 while (splits < maxsplit) { 1770 while (index < self_len && ASCII::isSpace(self.byteAt(index))) { 1771 index++; 1772 } 1773 if (index == self_len) break; 1774 index++; 1775 while (index < self_len && !ASCII::isSpace(self.byteAt(index))) { 1776 index++; 1777 } 1778 splits++; 1779 } 1780 while (index < self_len && ASCII::isSpace(self.byteAt(index))) { 1781 index++; 1782 } 1783 bool has_remaining = index < self_len; 1784 word result_len = has_remaining ? splits + 1 : splits; 1785 1786 // Second pass: write subsequences into result list. 1787 Runtime* runtime = thread->runtime(); 1788 List result(&scope, runtime->newList()); 1789 if (result_len == 0) return *result; 1790 MutableTuple buffer(&scope, runtime->newMutableTuple(result_len)); 1791 index = 0; 1792 for (word i = 0; i < splits; i++) { 1793 while (ASCII::isSpace(self.byteAt(index))) { 1794 index++; 1795 } 1796 word start = index++; 1797 while (index < self_len && !ASCII::isSpace(self.byteAt(index))) { 1798 index++; 1799 } 1800 buffer.atPut(i, bytesSubseq(thread, self, start, index - start)); 1801 } 1802 if (has_remaining) { 1803 while (ASCII::isSpace(self.byteAt(index))) { 1804 index++; 1805 } 1806 buffer.atPut(splits, bytesSubseq(thread, self, index, self_len - index)); 1807 } 1808 result.setItems(*buffer); 1809 result.setNumItems(result_len); 1810 return *result; 1811} 1812 1813RawObject FUNC(_builtins, _byteslike_check)(Thread* thread, Arguments args) { 1814 return Bool::fromBool(thread->runtime()->isByteslike(args.get(0))); 1815} 1816 1817RawObject FUNC(_builtins, _byteslike_compare_digest)(Thread* thread, 1818 Arguments args) { 1819 Runtime* runtime = thread->runtime(); 1820 HandleScope scope(thread); 1821 Object left_obj(&scope, args.get(0)); 1822 Object right_obj(&scope, args.get(1)); 1823 DCHECK(runtime->isInstanceOfBytes(*left_obj) || 1824 runtime->isInstanceOfBytearray(*left_obj), 1825 "_byteslike_compare_digest requires 'bytes' or 'bytearray' instance"); 1826 DCHECK(runtime->isInstanceOfBytes(*right_obj) || 1827 runtime->isInstanceOfBytearray(*right_obj), 1828 "_byteslike_compare_digest requires 'bytes' or 'bytearray' instance"); 1829 // TODO(T57794178): Use volatile 1830 Bytes left(&scope, Bytes::empty()); 1831 Bytes right(&scope, Bytes::empty()); 1832 word left_len = 0; 1833 word right_len = 0; 1834 if (runtime->isInstanceOfBytes(*left_obj)) { 1835 left = bytesUnderlying(*left_obj); 1836 left_len = left.length(); 1837 } else { 1838 Bytearray byte_array(&scope, *left_obj); 1839 left = byte_array.items(); 1840 left_len = byte_array.numItems(); 1841 } 1842 if (runtime->isInstanceOfBytes(*right_obj)) { 1843 right = bytesUnderlying(*right_obj); 1844 right_len = right.length(); 1845 } else { 1846 Bytearray byte_array(&scope, *right_obj); 1847 right = byte_array.items(); 1848 right_len = byte_array.numItems(); 1849 } 1850 word length = Utils::minimum(left_len, right_len); 1851 word result = (right_len == left_len) ? 0 : 1; 1852 for (word i = 0; i < length; i++) { 1853 result |= left.byteAt(i) ^ right.byteAt(i); 1854 } 1855 return Bool::fromBool(result == 0); 1856} 1857 1858RawObject FUNC(_builtins, _byteslike_count)(Thread* thread, Arguments args) { 1859 HandleScope scope(thread); 1860 Runtime* runtime = thread->runtime(); 1861 Object self_obj(&scope, args.get(0)); 1862 word haystack_len; 1863 if (runtime->isInstanceOfBytes(*self_obj)) { 1864 Bytes self(&scope, bytesUnderlying(*self_obj)); 1865 self_obj = *self; 1866 haystack_len = self.length(); 1867 } else if (runtime->isInstanceOfBytearray(*self_obj)) { 1868 Bytearray self(&scope, *self_obj); 1869 self_obj = self.items(); 1870 haystack_len = self.numItems(); 1871 } else { 1872 // TODO(T38246066): support buffer protocol 1873 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 1874 } 1875 Object sub_obj(&scope, args.get(1)); 1876 word needle_len; 1877 if (runtime->isInstanceOfBytes(*sub_obj)) { 1878 Bytes sub(&scope, bytesUnderlying(*sub_obj)); 1879 sub_obj = *sub; 1880 needle_len = sub.length(); 1881 } else if (runtime->isInstanceOfBytearray(*sub_obj)) { 1882 Bytearray sub(&scope, *sub_obj); 1883 sub_obj = sub.items(); 1884 needle_len = sub.numItems(); 1885 } else if (runtime->isInstanceOfInt(*sub_obj)) { 1886 word sub = intUnderlying(*sub_obj).asWordSaturated(); 1887 if (sub < 0 || sub > kMaxByte) { 1888 return thread->raiseWithFmt(LayoutId::kValueError, 1889 "byte must be in range(0, 256)"); 1890 } 1891 sub_obj = runtime->newBytes(1, sub); 1892 needle_len = 1; 1893 } else { 1894 // TODO(T38246066): support buffer protocol 1895 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 1896 } 1897 Bytes haystack(&scope, *self_obj); 1898 Bytes needle(&scope, *sub_obj); 1899 Object start_obj(&scope, args.get(2)); 1900 Object stop_obj(&scope, args.get(3)); 1901 word start = intUnderlying(*start_obj).asWordSaturated(); 1902 word end = intUnderlying(*stop_obj).asWordSaturated(); 1903 return SmallInt::fromWord( 1904 bytesCount(haystack, haystack_len, needle, needle_len, start, end)); 1905} 1906 1907RawObject FUNC(_builtins, _byteslike_endswith)(Thread* thread, Arguments args) { 1908 HandleScope scope(thread); 1909 Runtime* runtime = thread->runtime(); 1910 Object self_obj(&scope, args.get(0)); 1911 word self_len; 1912 if (runtime->isInstanceOfBytes(*self_obj)) { 1913 Bytes self(&scope, bytesUnderlying(*self_obj)); 1914 self_obj = *self; 1915 self_len = self.length(); 1916 } else if (runtime->isInstanceOfBytearray(*self_obj)) { 1917 Bytearray self(&scope, *self_obj); 1918 self_obj = self.items(); 1919 self_len = self.numItems(); 1920 } else { 1921 UNREACHABLE("self has an unexpected type"); 1922 } 1923 DCHECK(self_obj.isBytes(), 1924 "bytes-like object not resolved to underlying bytes"); 1925 Object suffix_obj(&scope, args.get(1)); 1926 word suffix_len; 1927 if (runtime->isInstanceOfBytes(*suffix_obj)) { 1928 Bytes suffix(&scope, bytesUnderlying(*suffix_obj)); 1929 suffix_obj = *suffix; 1930 suffix_len = suffix.length(); 1931 } else if (runtime->isInstanceOfBytearray(*suffix_obj)) { 1932 Bytearray suffix(&scope, *suffix_obj); 1933 suffix_obj = suffix.items(); 1934 suffix_len = suffix.numItems(); 1935 } else { 1936 // TODO(T38246066): support buffer protocol 1937 return thread->raiseWithFmt( 1938 LayoutId::kTypeError, 1939 "endswith first arg must be bytes or a tuple of bytes, not %T", 1940 &suffix_obj); 1941 } 1942 Bytes self(&scope, *self_obj); 1943 Bytes suffix(&scope, *suffix_obj); 1944 Object start_obj(&scope, args.get(2)); 1945 Object end_obj(&scope, args.get(3)); 1946 Int start(&scope, start_obj.isUnbound() ? Int::cast(SmallInt::fromWord(0)) 1947 : intUnderlying(*start_obj)); 1948 Int end(&scope, end_obj.isUnbound() ? Int::cast(SmallInt::fromWord(self_len)) 1949 : intUnderlying(*end_obj)); 1950 return runtime->bytesEndsWith(self, self_len, suffix, suffix_len, 1951 start.asWordSaturated(), end.asWordSaturated()); 1952} 1953 1954RawObject FUNC(_builtins, _byteslike_find_byteslike)(Thread* thread, 1955 Arguments args) { 1956 HandleScope scope(thread); 1957 Runtime* runtime = thread->runtime(); 1958 Object self_obj(&scope, args.get(0)); 1959 word haystack_len; 1960 if (runtime->isInstanceOfBytes(*self_obj)) { 1961 Bytes self(&scope, bytesUnderlying(*self_obj)); 1962 self_obj = *self; 1963 haystack_len = self.length(); 1964 } else if (runtime->isInstanceOfBytearray(*self_obj)) { 1965 Bytearray self(&scope, *self_obj); 1966 self_obj = self.items(); 1967 haystack_len = self.numItems(); 1968 } else { 1969 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 1970 } 1971 Object sub_obj(&scope, args.get(1)); 1972 word needle_len; 1973 if (runtime->isInstanceOfBytes(*sub_obj)) { 1974 Bytes sub(&scope, bytesUnderlying(*sub_obj)); 1975 sub_obj = *sub; 1976 needle_len = sub.length(); 1977 } else if (runtime->isInstanceOfBytearray(*sub_obj)) { 1978 Bytearray sub(&scope, *sub_obj); 1979 sub_obj = sub.items(); 1980 needle_len = sub.numItems(); 1981 } else { 1982 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 1983 } 1984 Bytes haystack(&scope, *self_obj); 1985 Bytes needle(&scope, *sub_obj); 1986 word start = intUnderlying(args.get(2)).asWordSaturated(); 1987 word end = intUnderlying(args.get(3)).asWordSaturated(); 1988 return SmallInt::fromWord( 1989 bytesFind(haystack, haystack_len, needle, needle_len, start, end)); 1990} 1991 1992RawObject FUNC(_builtins, _byteslike_find_int)(Thread* thread, Arguments args) { 1993 HandleScope scope(thread); 1994 Runtime* runtime = thread->runtime(); 1995 word needle = intUnderlying(args.get(1)).asWordSaturated(); 1996 if (needle < 0 || needle > kMaxByte) { 1997 return thread->raiseWithFmt(LayoutId::kValueError, 1998 "byte must be in range(0, 256)"); 1999 } 2000 Object self_obj(&scope, args.get(0)); 2001 word start = intUnderlying(args.get(2)).asWordSaturated(); 2002 word end = intUnderlying(args.get(3)).asWordSaturated(); 2003 Bytes haystack(&scope, Bytes::empty()); 2004 word length; 2005 if (runtime->isInstanceOfBytes(*self_obj)) { 2006 haystack = bytesUnderlying(*self_obj); 2007 length = haystack.length(); 2008 } else if (runtime->isInstanceOfBytearray(*self_obj)) { 2009 Bytearray self(&scope, *self_obj); 2010 haystack = self.items(); 2011 length = self.numItems(); 2012 } else { 2013 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 2014 } 2015 Slice::adjustSearchIndices(&start, &end, length); 2016 return SmallInt::fromWord(haystack.findByte(needle, start, end - start)); 2017} 2018 2019RawObject FUNC(_builtins, _byteslike_guard)(Thread* thread, Arguments args) { 2020 HandleScope scope(thread); 2021 Object obj(&scope, args.get(0)); 2022 if (thread->runtime()->isByteslike(*obj)) { 2023 return NoneType::object(); 2024 } 2025 return thread->raiseWithFmt( 2026 LayoutId::kTypeError, "a bytes-like object is required, not '%T'", &obj); 2027} 2028 2029RawObject FUNC(_builtins, _byteslike_rfind_byteslike)(Thread* thread, 2030 Arguments args) { 2031 HandleScope scope(thread); 2032 Runtime* runtime = thread->runtime(); 2033 Object self_obj(&scope, args.get(0)); 2034 word haystack_len; 2035 if (runtime->isInstanceOfBytes(*self_obj)) { 2036 Bytes self(&scope, bytesUnderlying(*self_obj)); 2037 self_obj = *self; 2038 haystack_len = self.length(); 2039 } else if (runtime->isInstanceOfBytearray(*self_obj)) { 2040 Bytearray self(&scope, *self_obj); 2041 self_obj = self.items(); 2042 haystack_len = self.numItems(); 2043 } else { 2044 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 2045 } 2046 Object sub_obj(&scope, args.get(1)); 2047 word needle_len; 2048 if (runtime->isInstanceOfBytes(*sub_obj)) { 2049 Bytes sub(&scope, bytesUnderlying(*sub_obj)); 2050 sub_obj = *sub; 2051 needle_len = sub.length(); 2052 } else if (runtime->isInstanceOfBytearray(*sub_obj)) { 2053 Bytearray sub(&scope, *sub_obj); 2054 sub_obj = sub.items(); 2055 needle_len = sub.numItems(); 2056 } else { 2057 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 2058 } 2059 Bytes haystack(&scope, *self_obj); 2060 Bytes needle(&scope, *sub_obj); 2061 word start = intUnderlying(args.get(2)).asWordSaturated(); 2062 word end = intUnderlying(args.get(3)).asWordSaturated(); 2063 return SmallInt::fromWord( 2064 bytesRFind(haystack, haystack_len, needle, needle_len, start, end)); 2065} 2066 2067RawObject FUNC(_builtins, _byteslike_rfind_int)(Thread* thread, 2068 Arguments args) { 2069 HandleScope scope(thread); 2070 Runtime* runtime = thread->runtime(); 2071 word sub = intUnderlying(args.get(1)).asWordSaturated(); 2072 if (sub < 0 || sub > kMaxByte) { 2073 return thread->raiseWithFmt(LayoutId::kValueError, 2074 "byte must be in range(0, 256)"); 2075 } 2076 Bytes needle(&scope, runtime->newBytes(1, sub)); 2077 Object self_obj(&scope, args.get(0)); 2078 word start = intUnderlying(args.get(2)).asWordSaturated(); 2079 word end = intUnderlying(args.get(3)).asWordSaturated(); 2080 if (runtime->isInstanceOfBytes(*self_obj)) { 2081 Bytes haystack(&scope, bytesUnderlying(*self_obj)); 2082 return SmallInt::fromWord(bytesRFind(haystack, haystack.length(), needle, 2083 needle.length(), start, end)); 2084 } 2085 if (runtime->isInstanceOfBytearray(*self_obj)) { 2086 Bytearray self(&scope, *self_obj); 2087 Bytes haystack(&scope, self.items()); 2088 return SmallInt::fromWord(bytesRFind(haystack, self.numItems(), needle, 2089 needle.length(), start, end)); 2090 } 2091 UNIMPLEMENTED("bytes-like other than bytes, bytearray"); 2092} 2093 2094RawObject FUNC(_builtins, _byteslike_startswith)(Thread* thread, 2095 Arguments args) { 2096 HandleScope scope(thread); 2097 Runtime* runtime = thread->runtime(); 2098 Object self_obj(&scope, args.get(0)); 2099 word self_len; 2100 if (runtime->isInstanceOfBytes(*self_obj)) { 2101 Bytes self(&scope, bytesUnderlying(*self_obj)); 2102 self_obj = *self; 2103 self_len = self.length(); 2104 } else if (runtime->isInstanceOfBytearray(*self_obj)) { 2105 Bytearray self(&scope, *self_obj); 2106 self_obj = self.items(); 2107 self_len = self.numItems(); 2108 } else { 2109 UNREACHABLE("self has an unexpected type"); 2110 } 2111 DCHECK(self_obj.isBytes(), 2112 "bytes-like object not resolved to underlying bytes"); 2113 Object prefix_obj(&scope, args.get(1)); 2114 word prefix_len; 2115 if (runtime->isInstanceOfBytes(*prefix_obj)) { 2116 Bytes prefix(&scope, bytesUnderlying(*prefix_obj)); 2117 prefix_obj = *prefix; 2118 prefix_len = prefix.length(); 2119 } else if (runtime->isInstanceOfBytearray(*prefix_obj)) { 2120 Bytearray prefix(&scope, *prefix_obj); 2121 prefix_obj = prefix.items(); 2122 prefix_len = prefix.numItems(); 2123 } else { 2124 // TODO(T38246066): support buffer protocol 2125 return thread->raiseWithFmt( 2126 LayoutId::kTypeError, 2127 "startswith first arg must be bytes or a tuple of bytes, not %T", 2128 &prefix_obj); 2129 } 2130 Bytes self(&scope, *self_obj); 2131 Bytes prefix(&scope, *prefix_obj); 2132 word start = intUnderlying(args.get(2)).asWordSaturated(); 2133 word end = intUnderlying(args.get(3)).asWordSaturated(); 2134 return runtime->bytesStartsWith(self, self_len, prefix, prefix_len, start, 2135 end); 2136} 2137 2138RawObject FUNC(_builtins, _caller_function)(Thread* thread, Arguments) { 2139 return thread->currentFrame()->previousFrame()->previousFrame()->function(); 2140} 2141 2142RawObject FUNC(_builtins, _caller_locals)(Thread* thread, Arguments) { 2143 return frameLocals(thread, 2144 thread->currentFrame()->previousFrame()->previousFrame()); 2145} 2146 2147RawObject FUNC(_builtins, _classmethod)(Thread* thread, Arguments args) { 2148 HandleScope scope(thread); 2149 ClassMethod result(&scope, thread->runtime()->newClassMethod()); 2150 result.setFunction(args.get(0)); 2151 return *result; 2152} 2153 2154static RawObject isAbstract(Thread* thread, const Object& obj) { 2155 HandleScope scope(thread); 2156 Runtime* runtime = thread->runtime(); 2157 // TODO(T47800709): make this lookup more efficient 2158 Object abstract( 2159 &scope, runtime->attributeAtById(thread, obj, ID(__isabstractmethod__))); 2160 if (abstract.isError()) { 2161 Object given(&scope, thread->pendingExceptionType()); 2162 Object exc(&scope, runtime->typeAt(LayoutId::kAttributeError)); 2163 if (givenExceptionMatches(thread, given, exc)) { 2164 thread->clearPendingException(); 2165 return Bool::falseObj(); 2166 } 2167 return *abstract; 2168 } 2169 return Interpreter::isTrue(thread, *abstract); 2170} 2171 2172RawObject FUNC(_builtins, _classmethod_isabstract)(Thread* thread, 2173 Arguments args) { 2174 HandleScope scope(thread); 2175 Object self_obj(&scope, args.get(0)); 2176 if (!thread->runtime()->isInstanceOfClassMethod(*self_obj)) { 2177 return thread->raiseRequiresType(self_obj, ID(classmethod)); 2178 } 2179 ClassMethod self(&scope, *self_obj); 2180 Object func(&scope, self.function()); 2181 return isAbstract(thread, func); 2182} 2183 2184RawObject FUNC(_builtins, _code_check)(Thread*, Arguments args) { 2185 return Bool::fromBool(args.get(0).isCode()); 2186} 2187 2188RawObject FUNC(_builtins, _code_guard)(Thread* thread, Arguments args) { 2189 if (args.get(0).isCode()) { 2190 return NoneType::object(); 2191 } 2192 return raiseRequiresFromCaller(thread, args, ID(code)); 2193} 2194 2195RawObject FUNC(_builtins, _code_new)(Thread* thread, Arguments args) { 2196 HandleScope scope(thread); 2197 Object cls(&scope, args.get(0)); 2198 Runtime* runtime = thread->runtime(); 2199 if (cls != runtime->typeAt(LayoutId::kCode)) { 2200 return thread->raiseWithFmt(LayoutId::kTypeError, "require code class"); 2201 } 2202 word argcount = intUnderlying(args.get(1)).asWord(); 2203 if (argcount < 0) { 2204 return thread->raiseWithFmt(LayoutId::kValueError, 2205 "argcount must not be negative"); 2206 } 2207 word posonlyargcount = intUnderlying(args.get(2)).asWord(); 2208 if (posonlyargcount < 0) { 2209 return thread->raiseWithFmt(LayoutId::kValueError, 2210 "posonlyargcount must not be negative"); 2211 } 2212 word kwonlyargcount = intUnderlying(args.get(3)).asWord(); 2213 if (kwonlyargcount < 0) { 2214 return thread->raiseWithFmt(LayoutId::kValueError, 2215 "kwonlyargcount must not be negative"); 2216 } 2217 word nlocals = intUnderlying(args.get(4)).asWord(); 2218 if (nlocals < 0) { 2219 return thread->raiseWithFmt(LayoutId::kValueError, 2220 "nlocals must not be negative"); 2221 } 2222 2223 word stacksize = intUnderlying(args.get(5)).asWord(); 2224 word flags = intUnderlying(args.get(6)).asWord(); 2225 if (argcount < posonlyargcount || stacksize < 0 || flags < 0) { 2226 return thread->raiseBadInternalCall(); 2227 } 2228 2229 Object code(&scope, args.get(7)); 2230 Object consts(&scope, args.get(8)); 2231 Object names(&scope, args.get(9)); 2232 Object varnames(&scope, args.get(10)); 2233 Object filename(&scope, args.get(11)); 2234 Object name(&scope, args.get(12)); 2235 word firstlineno = intUnderlying(args.get(13)).asWord(); 2236 Object lnotab(&scope, args.get(14)); 2237 Object freevars(&scope, args.get(15)); 2238 Object cellvars(&scope, args.get(16)); 2239 return runtime->newCode(argcount, posonlyargcount, kwonlyargcount, nlocals, 2240 stacksize, flags, code, consts, names, varnames, 2241 freevars, cellvars, filename, name, firstlineno, 2242 lnotab); 2243} 2244 2245RawObject FUNC(_builtins, _code_set_filename)(Thread* thread, Arguments args) { 2246 HandleScope scope(thread); 2247 Object code_obj(&scope, args.get(0)); 2248 CHECK(code_obj.isCode(), "Expected code to be a code object"); 2249 Code code(&scope, *code_obj); 2250 Object filename(&scope, args.get(1)); 2251 CHECK(thread->runtime()->isInstanceOfStr(*filename), 2252 "Expected value to be a str"); 2253 code.setFilename(*filename); 2254 return NoneType::object(); 2255} 2256 2257RawObject FUNC(_builtins, _complex_check)(Thread* thread, Arguments args) { 2258 return Bool::fromBool(thread->runtime()->isInstanceOfComplex(args.get(0))); 2259} 2260 2261RawObject FUNC(_builtins, _complex_checkexact)(Thread*, Arguments args) { 2262 return Bool::fromBool(args.get(0).isComplex()); 2263} 2264 2265RawObject FUNC(_builtins, _complex_imag)(Thread* thread, Arguments args) { 2266 HandleScope scope(thread); 2267 Object self_obj(&scope, args.get(0)); 2268 Runtime* runtime = thread->runtime(); 2269 if (!runtime->isInstanceOfComplex(*self_obj)) { 2270 return thread->raiseRequiresType(self_obj, ID(complex)); 2271 } 2272 Complex self(&scope, complexUnderlying(*self_obj)); 2273 return runtime->newFloat(self.imag()); 2274} 2275 2276static bool unpackNumeric(const Object& val, double* real, double* imag) { 2277 switch (val.layoutId()) { 2278 case LayoutId::kBool: 2279 *real = Bool::cast(*val).value(); 2280 *imag = 0.0; 2281 return true; 2282 case LayoutId::kComplex: 2283 *real = Complex::cast(*val).real(); 2284 *imag = Complex::cast(*val).imag(); 2285 return true; 2286 case LayoutId::kFloat: 2287 *real = Float::cast(*val).value(); 2288 *imag = 0.0; 2289 return true; 2290 case LayoutId::kSmallInt: 2291 *real = SmallInt::cast(*val).value(); 2292 *imag = 0.0; 2293 return true; 2294 case LayoutId::kUnbound: 2295 *real = 0.0; 2296 *imag = 0.0; 2297 return true; 2298 default: 2299 return false; 2300 } 2301} 2302 2303RawObject FUNC(_builtins, _complex_new)(Thread* thread, Arguments args) { 2304 HandleScope scope(thread); 2305 Type cls(&scope, args.get(0)); 2306 DCHECK(cls.builtinBase() == LayoutId::kComplex, "cls must subclass complex"); 2307 Object real_obj(&scope, args.get(1)); 2308 Object imag_obj(&scope, args.get(2)); 2309 if (real_obj.isComplex() && imag_obj.isUnbound() && cls.isBuiltin()) { 2310 return *real_obj; 2311 } 2312 2313 double real1, imag1, real2, imag2; 2314 if (!unpackNumeric(real_obj, &real1, &imag1) || 2315 !unpackNumeric(imag_obj, &real2, &imag2)) { 2316 return Unbound::object(); 2317 } 2318 2319 double real = real1 - imag2; 2320 double imag = imag1 + real2; 2321 2322 Runtime* runtime = thread->runtime(); 2323 if (cls.isBuiltin()) { 2324 return runtime->newComplex(real, imag); 2325 } 2326 2327 Layout layout(&scope, cls.instanceLayout()); 2328 UserComplexBase result(&scope, runtime->newInstance(layout)); 2329 result.setValue(runtime->newComplex(real, imag)); 2330 return *result; 2331} 2332 2333RawObject FUNC(_builtins, _complex_real)(Thread* thread, Arguments args) { 2334 HandleScope scope(thread); 2335 Object self_obj(&scope, args.get(0)); 2336 Runtime* runtime = thread->runtime(); 2337 if (!runtime->isInstanceOfComplex(*self_obj)) { 2338 return thread->raiseRequiresType(self_obj, ID(complex)); 2339 } 2340 Complex self(&scope, complexUnderlying(*self_obj)); 2341 return runtime->newFloat(self.real()); 2342} 2343 2344RawObject FUNC(_builtins, _compute_mro)(Thread* thread, Arguments args) { 2345 HandleScope scope(thread); 2346 Type type(&scope, args.get(0)); 2347 return computeMro(thread, type); 2348} 2349 2350RawObject FUNC(_builtins, _debug_dump)(Thread* thread, Arguments args) { 2351 HandleScope scope(thread); 2352 Object object(&scope, args.get(0)); 2353 std::stringstream stream; 2354 dumpExtended(stream, *object); 2355 return thread->runtime()->newStrFromCStr(stream.str().c_str()); 2356} 2357 2358RawObject FUNC(_builtins, _deque_guard)(Thread* thread, Arguments args) { 2359 if (thread->runtime()->isInstanceOfDeque(args.get(0))) { 2360 return NoneType::object(); 2361 } 2362 return raiseRequiresFromCaller(thread, args, ID(deque)); 2363} 2364 2365RawObject FUNC(_builtins, _dict_check)(Thread* thread, Arguments args) { 2366 return Bool::fromBool(thread->runtime()->isInstanceOfDict(args.get(0))); 2367} 2368 2369RawObject FUNC(_builtins, _dict_check_exact)(Thread*, Arguments args) { 2370 return Bool::fromBool(args.get(0).isDict()); 2371} 2372 2373RawObject FUNC(_builtins, _dict_get)(Thread* thread, Arguments args) { 2374 HandleScope scope(thread); 2375 Object self(&scope, args.get(0)); 2376 Object key(&scope, args.get(1)); 2377 Object default_obj(&scope, args.get(2)); 2378 Runtime* runtime = thread->runtime(); 2379 if (!runtime->isInstanceOfDict(*self)) { 2380 return thread->raiseRequiresType(self, ID(dict)); 2381 } 2382 Dict dict(&scope, *self); 2383 2384 // Check key hash 2385 Object hash_obj(&scope, Interpreter::hash(thread, key)); 2386 if (hash_obj.isErrorException()) return *hash_obj; 2387 word hash = SmallInt::cast(*hash_obj).value(); 2388 Object result(&scope, dictAt(thread, dict, key, hash)); 2389 if (result.isErrorNotFound()) return *default_obj; 2390 return *result; 2391} 2392 2393RawObject FUNC(_builtins, _dict_guard)(Thread* thread, Arguments args) { 2394 if (thread->runtime()->isInstanceOfDict(args.get(0))) { 2395 return NoneType::object(); 2396 } 2397 return raiseRequiresFromCaller(thread, args, ID(dict)); 2398} 2399 2400RawObject FUNC(_builtins, _dict_items_guard)(Thread* thread, Arguments args) { 2401 if (args.get(0).isDictItems()) return NoneType::object(); 2402 return raiseRequiresFromCaller(thread, args, ID(dict_items)); 2403} 2404 2405RawObject FUNC(_builtins, _dict_keys_guard)(Thread* thread, Arguments args) { 2406 if (args.get(0).isDictKeys()) return NoneType::object(); 2407 return raiseRequiresFromCaller(thread, args, ID(dict_keys)); 2408} 2409 2410RawObject FUNC(_builtins, _dict_len)(Thread* thread, Arguments args) { 2411 HandleScope scope(thread); 2412 Dict self(&scope, args.get(0)); 2413 return SmallInt::fromWord(self.numItems()); 2414} 2415 2416RawObject FUNC(_builtins, _dict_setitem)(Thread* thread, Arguments args) { 2417 HandleScope scope(thread); 2418 Object self(&scope, args.get(0)); 2419 Object key(&scope, args.get(1)); 2420 Object value(&scope, args.get(2)); 2421 Runtime* runtime = thread->runtime(); 2422 if (!runtime->isInstanceOfDict(*self)) { 2423 return thread->raiseRequiresType(self, ID(dict)); 2424 } 2425 Dict dict(&scope, *self); 2426 Object hash_obj(&scope, Interpreter::hash(thread, key)); 2427 if (hash_obj.isErrorException()) return *hash_obj; 2428 word hash = SmallInt::cast(*hash_obj).value(); 2429 Object result(&scope, dictAtPut(thread, dict, key, hash, value)); 2430 if (result.isErrorException()) return *result; 2431 return NoneType::object(); 2432} 2433 2434RawObject FUNC(_builtins, _dict_update)(Thread* thread, Arguments args) { 2435 HandleScope scope(thread); 2436 Object self_obj(&scope, args.get(0)); 2437 Runtime* runtime = thread->runtime(); 2438 if (!runtime->isInstanceOfDict(*self_obj)) { 2439 return raiseRequiresFromCaller(thread, args, ID(dict)); 2440 } 2441 Dict self(&scope, *self_obj); 2442 Object other(&scope, args.get(1)); 2443 2444 if (!other.isUnbound()) { 2445 RawObject result = dictMergeOverride(thread, self, other); 2446 if (result.isError()) { 2447 if (thread->pendingExceptionMatches(LayoutId::kAttributeError)) { 2448 // no `keys` attribute, bail out to managed code to try tuple unpacking 2449 thread->clearPendingException(); 2450 return Unbound::object(); 2451 } 2452 return result; 2453 } 2454 } 2455 2456 Object kwargs(&scope, args.get(2)); 2457 return dictMergeOverride(thread, self, kwargs); 2458} 2459 2460RawObject FUNC(_builtins, _divmod)(Thread* thread, Arguments args) { 2461 HandleScope scope(thread); 2462 Object number(&scope, args.get(0)); 2463 Object divisor(&scope, args.get(1)); 2464 return Interpreter::binaryOperation(thread, Interpreter::BinaryOp::DIVMOD, 2465 number, divisor); 2466} 2467 2468RawObject FUNC(_builtins, _exec)(Thread* thread, Arguments args) { 2469 HandleScope scope(thread); 2470 Code code(&scope, args.get(0)); 2471 Module module(&scope, args.get(1)); 2472 Object implicit_globals(&scope, args.get(2)); 2473 return thread->exec(code, module, implicit_globals); 2474} 2475 2476RawObject FUNC(_builtins, _float_check)(Thread* thread, Arguments args) { 2477 return Bool::fromBool(thread->runtime()->isInstanceOfFloat(args.get(0))); 2478} 2479 2480RawObject FUNC(_builtins, _float_check_exact)(Thread*, Arguments args) { 2481 return Bool::fromBool(args.get(0).isFloat()); 2482} 2483 2484static double floatDivmod(double x, double y, double* remainder) { 2485 double mod = std::fmod(x, y); 2486 double div = (x - mod) / y; 2487 2488 if (mod != 0.0) { 2489 if ((y < 0.0) != (mod < 0.0)) { 2490 mod += y; 2491 div -= 1.0; 2492 } 2493 } else { 2494 mod = std::copysign(0.0, y); 2495 } 2496 2497 double floordiv = 0; 2498 if (div != 0.0) { 2499 floordiv = std::floor(div); 2500 if (div - floordiv > 0.5) { 2501 floordiv += 1.0; 2502 } 2503 } else { 2504 floordiv = std::copysign(0.0, x / y); 2505 } 2506 2507 *remainder = mod; 2508 return floordiv; 2509} 2510 2511RawObject FUNC(_builtins, _float_divmod)(Thread* thread, Arguments args) { 2512 HandleScope scope(thread); 2513 2514 double left = floatUnderlying(args.get(0)).value(); 2515 double divisor = floatUnderlying(args.get(1)).value(); 2516 if (divisor == 0.0) { 2517 return thread->raiseWithFmt(LayoutId::kZeroDivisionError, "float divmod()"); 2518 } 2519 2520 double remainder; 2521 double quotient = floatDivmod(left, divisor, &remainder); 2522 Runtime* runtime = thread->runtime(); 2523 Object quotient_obj(&scope, runtime->newFloat(quotient)); 2524 Object remainder_obj(&scope, runtime->newFloat(remainder)); 2525 return runtime->newTupleWith2(quotient_obj, remainder_obj); 2526} 2527 2528RawObject FUNC(_builtins, _float_format)(Thread* thread, Arguments args) { 2529 HandleScope scope(thread); 2530 double value = floatUnderlying(args.get(0)).value(); 2531 Str format_code(&scope, args.get(1)); 2532 DCHECK(format_code.length() == 1, "expected len(format_code) == 1"); 2533 char format_code_char = format_code.byteAt(0); 2534 DCHECK(format_code_char == 'e' || format_code_char == 'E' || 2535 format_code_char == 'f' || format_code_char == 'F' || 2536 format_code_char == 'g' || format_code_char == 'G' || 2537 format_code_char == 'r', 2538 "expected format_code in 'eEfFgGr'"); 2539 SmallInt precision(&scope, args.get(2)); 2540 Bool always_add_sign(&scope, args.get(3)); 2541 Bool add_dot_0(&scope, args.get(4)); 2542 Bool use_alt_formatting(&scope, args.get(5)); 2543 unique_c_ptr<char> c_str(doubleToString( 2544 value, format_code_char, precision.value(), always_add_sign.value(), 2545 add_dot_0.value(), use_alt_formatting.value(), nullptr)); 2546 return thread->runtime()->newStrFromCStr(c_str.get()); 2547} 2548 2549RawObject FUNC(_builtins, _float_guard)(Thread* thread, Arguments args) { 2550 if (thread->runtime()->isInstanceOfFloat(args.get(0))) { 2551 return NoneType::object(); 2552 } 2553 return raiseRequiresFromCaller(thread, args, ID(float)); 2554} 2555 2556static RawObject floatNew(Thread* thread, const Type& type, RawObject flt) { 2557 DCHECK(flt.isFloat(), "unexpected type when creating float"); 2558 if (type.isBuiltin()) return flt; 2559 HandleScope scope(thread); 2560 Layout type_layout(&scope, type.instanceLayout()); 2561 UserFloatBase instance(&scope, thread->runtime()->newInstance(type_layout)); 2562 instance.setValue(flt); 2563 return *instance; 2564} 2565 2566static RawObject floatNewFromDigits(Thread* thread, const Type& type, 2567 const char* str, word length) { 2568 const char* last = str + length - 1; 2569 // strip spaces 2570 while (str < last && ASCII::isSpace(*str)) { 2571 str++; 2572 } 2573 while (last > str && ASCII::isSpace(*last)) { 2574 last--; 2575 } 2576 2577 RawObject float_obj = floatFromDigits(thread, str, last - str + 1); 2578 if (float_obj.isErrorException()) { 2579 return float_obj; 2580 } 2581 2582 return floatNew(thread, type, float_obj); 2583} 2584 2585RawObject FUNC(_builtins, _float_new_from_byteslike)(Thread* thread, 2586 Arguments args) { 2587 HandleScope scope(thread); 2588 Type type(&scope, args.get(0)); 2589 Object arg(&scope, args.get(1)); 2590 Runtime* runtime = thread->runtime(); 2591 Bytes underlying(&scope, Bytes::empty()); 2592 word length; 2593 if (runtime->isInstanceOfBytes(*arg)) { 2594 underlying = bytesUnderlying(*arg); 2595 length = underlying.length(); 2596 } else { 2597 // TODO(T57022841): follow full CPython conversion for bytes-like objects 2598 UNIMPLEMENTED("float.__new__ from byteslike"); 2599 } 2600 unique_c_ptr<byte> c_str(reinterpret_cast<byte*>(std::malloc(length + 1))); 2601 c_str.get()[length] = '\0'; 2602 underlying.copyTo(c_str.get(), length); 2603 return floatNewFromDigits(thread, type, reinterpret_cast<char*>(c_str.get()), 2604 length); 2605} 2606 2607RawObject FUNC(_builtins, _float_new_from_float)(Thread* thread, 2608 Arguments args) { 2609 HandleScope scope(thread); 2610 Type type(&scope, args.get(0)); 2611 return floatNew(thread, type, args.get(1)); 2612} 2613 2614RawObject FUNC(_builtins, _float_new_from_str)(Thread* thread, Arguments args) { 2615 HandleScope scope(thread); 2616 Type type(&scope, args.get(0)); 2617 Object arg(&scope, args.get(1)); 2618 Str str(&scope, strUnderlying(*arg)); 2619 unique_c_ptr<char> c_str(str.toCStr()); 2620 word length = str.length(); 2621 return floatNewFromDigits(thread, type, c_str.get(), length); 2622} 2623 2624RawObject FUNC(_builtins, _float_signbit)(Thread*, Arguments args) { 2625 double value = floatUnderlying(args.get(0)).value(); 2626 return Bool::fromBool(std::signbit(value)); 2627} 2628 2629RawObject FUNC(_builtins, _frozenset_check)(Thread* thread, Arguments args) { 2630 return Bool::fromBool(thread->runtime()->isInstanceOfFrozenSet(args.get(0))); 2631} 2632 2633RawObject FUNC(_builtins, _frozenset_guard)(Thread* thread, Arguments args) { 2634 if (thread->runtime()->isInstanceOfFrozenSet(args.get(0))) { 2635 return NoneType::object(); 2636 } 2637 return raiseRequiresFromCaller(thread, args, ID(frozenset)); 2638} 2639 2640RawObject FUNC(_builtins, _function_annotations)(Thread* thread, 2641 Arguments args) { 2642 HandleScope scope(thread); 2643 Object self(&scope, args.get(0)); 2644 if (!self.isFunction()) { 2645 return thread->raiseRequiresType(self, ID(function)); 2646 } 2647 Function function(&scope, *self); 2648 Object annotations(&scope, function.annotations()); 2649 if (annotations.isNoneType()) { 2650 annotations = thread->runtime()->newDict(); 2651 function.setAnnotations(*annotations); 2652 } 2653 return *annotations; 2654} 2655 2656RawObject FUNC(_builtins, _function_closure)(Thread* thread, Arguments args) { 2657 HandleScope scope(thread); 2658 Object self(&scope, args.get(0)); 2659 if (!self.isFunction()) { 2660 return thread->raiseRequiresType(self, ID(function)); 2661 } 2662 Function function(&scope, *self); 2663 return function.closure(); 2664} 2665 2666RawObject FUNC(_builtins, _function_defaults)(Thread* thread, Arguments args) { 2667 HandleScope scope(thread); 2668 Object self(&scope, args.get(0)); 2669 if (!self.isFunction()) { 2670 return thread->raiseRequiresType(self, ID(function)); 2671 } 2672 Function function(&scope, *self); 2673 return function.defaults(); 2674} 2675 2676RawObject FUNC(_builtins, _function_globals)(Thread* thread, Arguments args) { 2677 HandleScope scope(thread); 2678 Object self(&scope, args.get(0)); 2679 if (!self.isFunction()) { 2680 return thread->raiseRequiresType(self, ID(function)); 2681 } 2682 Function function(&scope, *self); 2683 // extension functions created via C-API have no associated module. 2684 if (function.moduleObject().isNoneType()) { 2685 return thread->runtime()->newDict(); 2686 } 2687 Module module(&scope, function.moduleObject()); 2688 return module.moduleProxy(); 2689} 2690 2691RawObject FUNC(_builtins, _function_guard)(Thread* thread, Arguments args) { 2692 if (args.get(0).isFunction()) { 2693 return NoneType::object(); 2694 } 2695 return raiseRequiresFromCaller(thread, args, ID(function)); 2696} 2697 2698RawObject FUNC(_builtins, _function_kwdefaults)(Thread* thread, 2699 Arguments args) { 2700 HandleScope scope(thread); 2701 Object self(&scope, args.get(0)); 2702 if (!self.isFunction()) { 2703 return thread->raiseRequiresType(self, ID(function)); 2704 } 2705 Function function(&scope, *self); 2706 return function.kwDefaults(); 2707} 2708 2709RawObject FUNC(_builtins, _function_lineno)(Thread* thread, Arguments args) { 2710 HandleScope scope(thread); 2711 Function function(&scope, args.get(0)); 2712 SmallInt pc(&scope, args.get(1)); 2713 Code code(&scope, function.code()); 2714 return SmallInt::fromWord(code.offsetToLineNum(pc.value())); 2715} 2716 2717RawObject FUNC(_builtins, _function_new)(Thread* thread, Arguments args) { 2718 HandleScope scope(thread); 2719 Object cls_obj(&scope, args.get(0)); 2720 Runtime* runtime = thread->runtime(); 2721 if (!runtime->isInstanceOfType(*cls_obj)) { 2722 return thread->raiseRequiresType(cls_obj, ID(function)); 2723 } 2724 Type cls(&scope, *cls_obj); 2725 if (cls.builtinBase() != LayoutId::kFunction) { 2726 return thread->raiseWithFmt(LayoutId::kTypeError, 2727 "not a subtype of function"); 2728 } 2729 Object code_obj(&scope, args.get(1)); 2730 if (!code_obj.isCode()) { 2731 return thread->raiseRequiresType(code_obj, ID(code)); 2732 } 2733 Object module(&scope, args.get(2)); 2734 if (!runtime->isInstanceOfModule(*module)) { 2735 return thread->raiseRequiresType(module, ID(module)); 2736 } 2737 Code code(&scope, *code_obj); 2738 Object empty_qualname(&scope, NoneType::object()); 2739 Object result(&scope, runtime->newFunctionWithCode(thread, empty_qualname, 2740 code, module)); 2741 if (result.isFunction()) { 2742 Function new_function(&scope, *result); 2743 2744 Object name(&scope, args.get(3)); 2745 if (runtime->isInstanceOfStr(*name)) { 2746 new_function.setName(*name); 2747 } else if (!name.isNoneType()) { 2748 return thread->raiseWithFmt(LayoutId::kTypeError, 2749 "arg 3 (name) must be None or string", &name); 2750 } 2751 Object defaults(&scope, args.get(4)); 2752 if (runtime->isInstanceOfTuple(*defaults)) { 2753 new_function.setDefaults(*defaults); 2754 } else if (!defaults.isNoneType()) { 2755 return thread->raiseWithFmt(LayoutId::kTypeError, 2756 "arg 4 (defaults) must be None or tuple", 2757 &defaults); 2758 } 2759 Object closure(&scope, args.get(5)); 2760 if (runtime->isInstanceOfTuple(*closure)) { 2761 new_function.setClosure(*closure); 2762 } else if (!closure.isNoneType()) { 2763 return thread->raiseWithFmt(LayoutId::kTypeError, 2764 "arg 5 (closure) must be None or tuple", 2765 &closure); 2766 } 2767 return *new_function; 2768 } 2769 return *result; 2770} 2771 2772RawObject FUNC(_builtins, _function_set_annotations)(Thread* thread, 2773 Arguments args) { 2774 HandleScope scope(thread); 2775 Object self(&scope, args.get(0)); 2776 if (!self.isFunction()) { 2777 return thread->raiseRequiresType(self, ID(function)); 2778 } 2779 Function function(&scope, *self); 2780 Object annotations(&scope, args.get(1)); 2781 if (thread->runtime()->isInstanceOfDict(*annotations) || 2782 annotations.isNoneType()) { 2783 function.setAnnotations(*annotations); 2784 return NoneType::object(); 2785 } 2786 return thread->raiseRequiresType(annotations, ID(dict)); 2787} 2788 2789RawObject FUNC(_builtins, _function_set_defaults)(Thread* thread, 2790 Arguments args) { 2791 HandleScope scope(thread); 2792 Object self(&scope, args.get(0)); 2793 if (!self.isFunction()) { 2794 return thread->raiseRequiresType(self, ID(function)); 2795 } 2796 Function function(&scope, *self); 2797 Object defaults(&scope, args.get(1)); 2798 if (defaults.isNoneType()) { 2799 function.setDefaults(*defaults); 2800 return NoneType::object(); 2801 } 2802 if (thread->runtime()->isInstanceOfTuple(*defaults)) { 2803 function.setDefaults(tupleUnderlying(*defaults)); 2804 return NoneType::object(); 2805 } 2806 return thread->raiseRequiresType(defaults, ID(tuple)); 2807} 2808 2809RawObject FUNC(_builtins, _function_set_kwdefaults)(Thread* thread, 2810 Arguments args) { 2811 HandleScope scope(thread); 2812 Object self(&scope, args.get(0)); 2813 if (!self.isFunction()) { 2814 return thread->raiseRequiresType(self, ID(function)); 2815 } 2816 Function function(&scope, *self); 2817 Object kwdefaults(&scope, args.get(1)); 2818 if (thread->runtime()->isInstanceOfDict(*kwdefaults) || 2819 kwdefaults.isNoneType()) { 2820 function.setKwDefaults(*kwdefaults); 2821 return NoneType::object(); 2822 } 2823 return thread->raiseRequiresType(kwdefaults, ID(dict)); 2824} 2825 2826RawObject FUNC(_builtins, _gc)(Thread* thread, Arguments) { 2827 thread->runtime()->collectGarbage(); 2828 return NoneType::object(); 2829} 2830 2831RawObject FUNC(_builtins, _get_asyncgen_hooks)(Thread* thread, Arguments) { 2832 HandleScope scope(thread); 2833 Object firstiter(&scope, thread->asyncgenHooksFirstIter()); 2834 Object finalizer(&scope, thread->asyncgenHooksFinalizer()); 2835 return thread->runtime()->newTupleWith2(firstiter, finalizer); 2836} 2837 2838RawObject FUNC(_builtins, _get_member_byte)(Thread* thread, Arguments args) { 2839 auto addr = Int::cast(args.get(0)).asCPtr(); 2840 char value = 0; 2841 std::memcpy(&value, reinterpret_cast<void*>(addr), 1); 2842 return thread->runtime()->newInt(value); 2843} 2844 2845RawObject FUNC(_builtins, _get_member_char)(Thread*, Arguments args) { 2846 auto addr = Int::cast(args.get(0)).asCPtr(); 2847 return SmallStr::fromCodePoint(*reinterpret_cast<byte*>(addr)); 2848} 2849 2850RawObject FUNC(_builtins, _get_member_double)(Thread* thread, Arguments args) { 2851 auto addr = Int::cast(args.get(0)).asCPtr(); 2852 double value = 0.0; 2853 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2854 return thread->runtime()->newFloat(value); 2855} 2856 2857RawObject FUNC(_builtins, _get_member_float)(Thread* thread, Arguments args) { 2858 auto addr = Int::cast(args.get(0)).asCPtr(); 2859 float value = 0.0; 2860 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2861 return thread->runtime()->newFloat(value); 2862} 2863 2864RawObject FUNC(_builtins, _get_member_int)(Thread* thread, Arguments args) { 2865 auto addr = Int::cast(args.get(0)).asCPtr(); 2866 int value = 0; 2867 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2868 return thread->runtime()->newInt(value); 2869} 2870 2871RawObject FUNC(_builtins, _get_member_long)(Thread* thread, Arguments args) { 2872 auto addr = Int::cast(args.get(0)).asCPtr(); 2873 long value = 0; 2874 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2875 return thread->runtime()->newInt(value); 2876} 2877 2878RawObject FUNC(_builtins, _get_member_pyobject)(Thread* thread, 2879 Arguments args) { 2880 return objectGetMember(thread, args.get(0), args.get(1)); 2881} 2882 2883RawObject FUNC(_builtins, _get_member_short)(Thread* thread, Arguments args) { 2884 auto addr = Int::cast(args.get(0)).asCPtr(); 2885 short value = 0; 2886 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2887 return thread->runtime()->newInt(value); 2888} 2889 2890RawObject FUNC(_builtins, _get_member_string)(Thread* thread, Arguments args) { 2891 auto addr = Int::cast(args.get(0)).asCPtr(); 2892 if (*reinterpret_cast<char**>(addr) == nullptr) return NoneType::object(); 2893 return thread->runtime()->newStrFromCStr(*reinterpret_cast<char**>(addr)); 2894} 2895 2896RawObject FUNC(_builtins, _get_member_ubyte)(Thread* thread, Arguments args) { 2897 auto addr = Int::cast(args.get(0)).asCPtr(); 2898 unsigned char value = 0; 2899 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2900 return thread->runtime()->newIntFromUnsigned(value); 2901} 2902 2903RawObject FUNC(_builtins, _get_member_uint)(Thread* thread, Arguments args) { 2904 auto addr = Int::cast(args.get(0)).asCPtr(); 2905 unsigned int value = 0; 2906 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2907 return thread->runtime()->newIntFromUnsigned(value); 2908} 2909 2910RawObject FUNC(_builtins, _get_member_ulong)(Thread* thread, Arguments args) { 2911 auto addr = Int::cast(args.get(0)).asCPtr(); 2912 unsigned long value = 0; 2913 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2914 return thread->runtime()->newIntFromUnsigned(value); 2915} 2916 2917RawObject FUNC(_builtins, _get_member_ushort)(Thread* thread, Arguments args) { 2918 auto addr = Int::cast(args.get(0)).asCPtr(); 2919 unsigned short value = 0; 2920 std::memcpy(&value, reinterpret_cast<void*>(addr), sizeof(value)); 2921 return thread->runtime()->newIntFromUnsigned(value); 2922} 2923 2924RawObject FUNC(_builtins, _heap_dump)(Thread* thread, Arguments args) { 2925 HandleScope scope(thread); 2926 Str filename(&scope, args.get(0)); 2927 unique_c_ptr<char> filename_str(filename.toCStr()); 2928 return heapDump(thread, filename_str.get()); 2929} 2930 2931RawObject FUNC(_builtins, _instance_dunder_dict_set)(Thread* thread, 2932 Arguments args) { 2933 HandleScope scope(thread); 2934 Instance instance(&scope, args.get(0)); 2935 Object dict_obj(&scope, args.get(1)); 2936 Runtime* runtime = thread->runtime(); 2937 if (!dict_obj.isDict()) { 2938 if (runtime->isInstanceOfDict(*dict_obj)) { 2939 // TODO(T64971317): Support dict subclass. 2940 UNIMPLEMENTED("dict subclass is not supported yet."); 2941 } 2942 return thread->raiseWithFmt(LayoutId::kTypeError, 2943 "__dict__ must be set to a dictionary, " 2944 "not a '%T'", 2945 &dict_obj); 2946 } 2947 Layout layout(&scope, runtime->layoutAt(instance.layoutId())); 2948 // Set in-object attribute values to None. 2949 Tuple in_object(&scope, layout.inObjectAttributes()); 2950 word num_in_object_attr = in_object.length(); 2951 for (word i = 0; i < num_in_object_attr; i++) { 2952 Tuple entry(&scope, in_object.at(i)); 2953 AttributeInfo info(entry.at(1)); 2954 instance.instanceVariableAtPut(info.offset(), NoneType::object()); 2955 } 2956 Type type(&scope, layout.describedType()); 2957 if (type.isBuiltin()) { 2958 // TODO(T65043421): Support builtin type. 2959 UNIMPLEMENTED("_instance_dunder_dict_set(builtin_type_object)"); 2960 } 2961 Layout new_layout( 2962 &scope, runtime->typeDictOnlyLayout(thread, type, num_in_object_attr)); 2963 DCHECK(new_layout.hasDictOverflow(), "dict overflow is expected"); 2964 instance.setLayoutId(new_layout.id()); 2965 instance.instanceVariableAtPut(new_layout.dictOverflowOffset(), *dict_obj); 2966 return NoneType::object(); 2967} 2968 2969RawObject FUNC(_builtins, _instance_delattr)(Thread* thread, Arguments args) { 2970 HandleScope scope(thread); 2971 Instance instance(&scope, args.get(0)); 2972 Object name(&scope, args.get(1)); 2973 name = attributeName(thread, name); 2974 if (name.isErrorException()) return *name; 2975 return instanceDelAttr(thread, instance, name); 2976} 2977 2978RawObject FUNC(_builtins, _instance_getattr)(Thread* thread, Arguments args) { 2979 HandleScope scope(thread); 2980 Instance instance(&scope, args.get(0)); 2981 Object name(&scope, args.get(1)); 2982 name = attributeName(thread, name); 2983 if (name.isErrorException()) return *name; 2984 Object result(&scope, instanceGetAttribute(thread, instance, name)); 2985 return result.isErrorNotFound() ? Unbound::object() : *result; 2986} 2987 2988RawObject FUNC(_builtins, _instance_guard)(Thread* thread, Arguments args) { 2989 if (args.get(0).isInstance()) { 2990 return NoneType::object(); 2991 } 2992 return raiseRequiresFromCaller(thread, args, ID(instance)); 2993} 2994 2995RawObject FUNC(_builtins, _instance_overflow_dict)(Thread* thread, 2996 Arguments args) { 2997 HandleScope scope(thread); 2998 Object object(&scope, args.get(0)); 2999 Runtime* runtime = thread->runtime(); 3000 Layout layout(&scope, runtime->layoutOf(*object)); 3001 CHECK(layout.hasDictOverflow(), "expected dict overflow layout"); 3002 word offset = layout.dictOverflowOffset(); 3003 Instance instance(&scope, *object); 3004 Object overflow_dict_obj(&scope, instance.instanceVariableAt(offset)); 3005 if (overflow_dict_obj.isNoneType()) { 3006 overflow_dict_obj = runtime->newDict(); 3007 instance.instanceVariableAtPut(offset, *overflow_dict_obj); 3008 } 3009 return *overflow_dict_obj; 3010} 3011 3012RawObject FUNC(_builtins, _instance_setattr)(Thread* thread, Arguments args) { 3013 HandleScope scope(thread); 3014 Instance instance(&scope, args.get(0)); 3015 Object name(&scope, args.get(1)); 3016 name = attributeName(thread, name); 3017 if (name.isErrorException()) return *name; 3018 Object value(&scope, args.get(2)); 3019 return instanceSetAttr(thread, instance, name, value); 3020} 3021 3022RawObject FUNC(_builtins, _int_check)(Thread* thread, Arguments args) { 3023 return Bool::fromBool(thread->runtime()->isInstanceOfInt(args.get(0))); 3024} 3025 3026RawObject FUNC(_builtins, _int_check_exact)(Thread*, Arguments args) { 3027 RawObject arg = args.get(0); 3028 return Bool::fromBool(arg.isSmallInt() || arg.isLargeInt()); 3029} 3030 3031RawObject FUNC(_builtins, _instancemethod_func)(Thread* thread, 3032 Arguments args) { 3033 HandleScope scope(thread); 3034 Object obj(&scope, args.get(0)); 3035 if (!obj.isInstanceMethod()) { 3036 return thread->raiseRequiresType(obj, ID(instancemethod)); 3037 } 3038 return InstanceMethod::cast(*obj).function(); 3039} 3040 3041static RawObject positiveIntFromSmallStrWithBase10(RawSmallStr str) { 3042 word length = str.length(); 3043 if (length == 0) { 3044 return NoneType::object(); 3045 } 3046 word result = 0; 3047 for (word i = 0; i < length; i++) { 3048 byte b = str.byteAt(i); 3049 if ('0' <= b && b <= '9') { 3050 result *= 10; 3051 result += b - '0'; 3052 } else { 3053 return NoneType::object(); 3054 } 3055 } 3056 return SmallInt::fromWord(result); 3057} 3058 3059RawObject FUNC(_builtins, _int_ctor)(Thread* thread, Arguments args) { 3060 Runtime* runtime = thread->runtime(); 3061 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kInt), "unexpected cls"); 3062 RawObject x_raw = args.get(1); 3063 RawObject base_raw = args.get(2); 3064 LayoutId x_layout_id = x_raw.layoutId(); 3065 if (base_raw.isUnbound()) { 3066 switch (x_layout_id) { 3067 case LayoutId::kSmallInt: 3068 return x_raw; 3069 case LayoutId::kBool: 3070 return SmallInt::fromWord(Bool::cast(x_raw).value()); 3071 case LayoutId::kFloat: 3072 return intFromDouble(thread, Float::cast(x_raw).value()); 3073 case LayoutId::kSmallStr: { 3074 RawObject result = 3075 positiveIntFromSmallStrWithBase10(SmallStr::cast(x_raw)); 3076 if (!result.isNoneType()) { 3077 return result; 3078 } 3079 break; 3080 } 3081 case LayoutId::kUnbound: 3082 return SmallInt::fromWord(0); 3083 default: 3084 break; 3085 } 3086 } 3087 HandleScope scope(thread); 3088 Type cls(&scope, args.get(0)); 3089 Object x(&scope, x_raw); 3090 Object base(&scope, base_raw); 3091 return thread->invokeFunction3(ID(_builtins), ID(_type_dunder_call), cls, x, 3092 base); 3093} 3094 3095RawObject FUNC(_builtins, _int_ctor_obj)(Thread* thread, Arguments args) { 3096 Runtime* runtime = thread->runtime(); 3097 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kInt), "unexpected cls"); 3098 RawObject x_raw = args.get(1); 3099 LayoutId x_layout_id = x_raw.layoutId(); 3100 switch (x_layout_id) { 3101 case LayoutId::kSmallInt: 3102 return x_raw; 3103 case LayoutId::kBool: 3104 return SmallInt::fromWord(Bool::cast(x_raw).value()); 3105 case LayoutId::kFloat: 3106 return intFromDouble(thread, Float::cast(x_raw).value()); 3107 case LayoutId::kSmallStr: { 3108 RawObject result = 3109 positiveIntFromSmallStrWithBase10(SmallStr::cast(x_raw)); 3110 if (!result.isNoneType()) { 3111 return result; 3112 } 3113 break; 3114 } 3115 default: 3116 break; 3117 } 3118 HandleScope scope(thread); 3119 Type cls(&scope, args.get(0)); 3120 Object x(&scope, x_raw); 3121 Object base(&scope, Unbound::object()); 3122 return thread->invokeFunction3(ID(_builtins), ID(_type_dunder_call), cls, x, 3123 base); 3124} 3125 3126static RawObject intOrUserSubclass(Thread* thread, const Type& type, 3127 const Object& value) { 3128 DCHECK(value.isSmallInt() || value.isLargeInt(), 3129 "builtin value should have type int"); 3130 DCHECK(type.builtinBase() == LayoutId::kInt, "type must subclass int"); 3131 if (type.isBuiltin()) return *value; 3132 HandleScope scope(thread); 3133 Layout layout(&scope, type.instanceLayout()); 3134 UserIntBase instance(&scope, thread->runtime()->newInstance(layout)); 3135 instance.setValue(*value); 3136 return *instance; 3137} 3138 3139RawObject FUNC(_builtins, _int_from_bytes)(Thread* thread, Arguments args) { 3140 HandleScope scope(thread); 3141 Runtime* runtime = thread->runtime(); 3142 3143 Type type(&scope, args.get(0)); 3144 Bytes bytes(&scope, args.get(1)); 3145 Bool byteorder_big(&scope, args.get(2)); 3146 endian endianness = byteorder_big.value() ? endian::big : endian::little; 3147 Bool signed_arg(&scope, args.get(3)); 3148 bool is_signed = signed_arg == Bool::trueObj(); 3149 Int value(&scope, runtime->bytesToInt(thread, bytes, endianness, is_signed)); 3150 return intOrUserSubclass(thread, type, value); 3151} 3152 3153RawObject FUNC(_builtins, _int_guard)(Thread* thread, Arguments args) { 3154 if (thread->runtime()->isInstanceOfInt(args.get(0))) { 3155 return NoneType::object(); 3156 } 3157 return raiseRequiresFromCaller(thread, args, ID(int)); 3158} 3159 3160static word digitValue(byte digit, word base) { 3161 if ('0' <= digit && digit < '0' + base) return digit - '0'; 3162 // Bases 2-10 are limited to numerals, but all greater bases can use letters 3163 // too. 3164 if (base <= 10) return -1; 3165 if ('a' <= digit && digit < 'a' + base - 10) return digit - 'a' + 10; 3166 if ('A' <= digit && digit < 'A' + base - 10) return digit - 'A' + 10; 3167 return -1; 3168} 3169 3170static word inferBase(byte second_byte) { 3171 switch (second_byte) { 3172 case 'x': 3173 case 'X': 3174 return 16; 3175 case 'o': 3176 case 'O': 3177 return 8; 3178 case 'b': 3179 case 'B': 3180 return 2; 3181 default: 3182 return 10; 3183 } 3184} 3185 3186static RawObject intFromByteslike(Thread* thread, const Byteslike& byteslike, 3187 word length, word base) { 3188 DCHECK_BOUND(length, byteslike.length()); 3189 DCHECK(base == 0 || (base >= 2 && base <= 36), "invalid base"); 3190 if (length <= 0) return Error::error(); 3191 3192 // Clamp the length at the last whitespace character. 3193 word idx = length; 3194 byte b = byteslike.byteAt(--idx); 3195 while (ASCII::isSpace(b)) { 3196 if (idx <= 0) return Error::error(); 3197 b = byteslike.byteAt(--idx); 3198 } 3199 length = idx + 1; 3200 3201 // Start the index from the first non-zero whitespace character. 3202 idx = 0; 3203 if (idx >= length) return Error::error(); 3204 b = byteslike.byteAt(idx++); 3205 while (ASCII::isSpace(b)) { 3206 if (idx >= length) return Error::error(); 3207 b = byteslike.byteAt(idx++); 3208 } 3209 word sign = 1; 3210 switch (b) { 3211 case '-': 3212 sign = -1; 3213 // fall through 3214 case '+': 3215 if (idx >= length) return Error::error(); 3216 b = byteslike.byteAt(idx++); 3217 break; 3218 } 3219 3220 word inferred_base = 10; 3221 if (b == '0') { 3222 if (idx >= length) return SmallInt::fromWord(0); 3223 inferred_base = inferBase(byteslike.byteAt(idx)); 3224 if (base == 0) base = inferred_base; 3225 if (inferred_base != 10 && base == inferred_base) { 3226 if (++idx >= length) return Error::error(); 3227 b = byteslike.byteAt(idx++); 3228 } 3229 } else if (base == 0) { 3230 base = 10; 3231 } 3232 3233 Runtime* runtime = thread->runtime(); 3234 HandleScope scope(thread); 3235 Int result(&scope, SmallInt::fromWord(0)); 3236 Int digit(&scope, SmallInt::fromWord(0)); 3237 Int base_obj(&scope, SmallInt::fromWord(base)); 3238 word num_start = idx; 3239 for (;;) { 3240 if (b == '_') { 3241 // No leading underscores unless the number has a prefix 3242 if (idx == num_start && inferred_base == 10) return Error::error(); 3243 // No trailing underscores 3244 if (idx >= length) return Error::error(); 3245 b = byteslike.byteAt(idx++); 3246 } 3247 word digit_val = digitValue(b, base); 3248 if (digit_val == -1) return Error::error(); 3249 digit = Int::cast(SmallInt::fromWord(digit_val)); 3250 result = runtime->intAdd(thread, result, digit); 3251 if (idx >= length) break; 3252 b = byteslike.byteAt(idx++); 3253 result = runtime->intMultiply(thread, result, base_obj); 3254 } 3255 if (sign < 0) { 3256 result = runtime->intNegate(thread, result); 3257 } 3258 return *result; 3259} 3260 3261RawObject FUNC(_builtins, _int_new_from_byteslike)(Thread* thread, 3262 Arguments args) { 3263 HandleScope scope(thread); 3264 Type type(&scope, args.get(0)); 3265 Byteslike byteslike(&scope, thread, args.get(1)); 3266 word base = intUnderlying(args.get(2)).asWord(); 3267 Object result(&scope, 3268 intFromByteslike(thread, byteslike, byteslike.length(), base)); 3269 if (result.isError()) { 3270 Str repr(&scope, byteslikeReprSmartQuotes(thread, byteslike)); 3271 return thread->raiseWithFmt(LayoutId::kValueError, 3272 "invalid literal for int() with base %w: %S", 3273 base, &repr); 3274 } 3275 return intOrUserSubclass(thread, type, result); 3276} 3277 3278RawObject FUNC(_builtins, _int_new_from_int)(Thread* thread, Arguments args) { 3279 HandleScope scope(thread); 3280 Type type(&scope, args.get(0)); 3281 Object value(&scope, args.get(1)); 3282 if (value.isBool()) { 3283 value = convertBoolToInt(*value); 3284 } else if (!value.isSmallInt() && !value.isLargeInt()) { 3285 value = intUnderlying(*value); 3286 } 3287 return intOrUserSubclass(thread, type, value); 3288} 3289 3290static RawObject intFromStr(Thread* thread, const Str& str, word base) { 3291 DCHECK(base == 0 || (base >= 2 && base <= 36), "invalid base"); 3292 // CPython allows leading whitespace in the integer literal 3293 word start = strFindFirstNonWhitespace(str); 3294 if (str.length() - start == 0) { 3295 return Error::error(); 3296 } 3297 word sign = 1; 3298 if (str.byteAt(start) == '-') { 3299 sign = -1; 3300 start += 1; 3301 } else if (str.byteAt(start) == '+') { 3302 start += 1; 3303 } 3304 if (str.length() - start == 0) { 3305 // Just the sign 3306 return Error::error(); 3307 } 3308 if (str.length() - start == 1) { 3309 // Single digit, potentially with +/- 3310 word result = digitValue(str.byteAt(start), base == 0 ? 10 : base); 3311 if (result == -1) return Error::error(); 3312 return SmallInt::fromWord(sign * result); 3313 } 3314 // Decimal literals start at the index 0 (no prefix). 3315 // Octal literals (0oFOO), hex literals (0xFOO), and binary literals (0bFOO) 3316 // start at index 2. 3317 word inferred_base = 10; 3318 if (str.byteAt(start) == '0' && start + 1 < str.length()) { 3319 inferred_base = inferBase(str.byteAt(start + 1)); 3320 } 3321 if (base == 0) { 3322 base = inferred_base; 3323 } 3324 if (base == 2 || base == 8 || base == 16) { 3325 if (base == inferred_base) { 3326 // This handles integer literals with a base prefix, e.g. 3327 // * int("0b1", 0) => 1, where the base is inferred from the prefix 3328 // * int("0b1", 2) => 1, where the prefix matches the provided base 3329 // 3330 // If the prefix does not match the provided base, then we treat it as 3331 // part as part of the number, e.g. 3332 // * int("0b1", 10) => ValueError 3333 // * int("0b1", 16) => 177 3334 start += 2; 3335 } 3336 if (str.length() - start == 0) { 3337 // Just the prefix: 0x, 0b, 0o, etc 3338 return Error::error(); 3339 } 3340 } 3341 Runtime* runtime = thread->runtime(); 3342 HandleScope scope(thread); 3343 Int result(&scope, SmallInt::fromWord(0)); 3344 Int digit(&scope, SmallInt::fromWord(0)); 3345 Int base_obj(&scope, SmallInt::fromWord(base)); 3346 for (word i = start; i < str.length(); i++) { 3347 byte digit_char = str.byteAt(i); 3348 if (digit_char == '_') { 3349 // No leading underscores unless the number has a prefix 3350 if (i == start && inferred_base == 10) return Error::error(); 3351 // No trailing underscores 3352 if (i + 1 == str.length()) return Error::error(); 3353 digit_char = str.byteAt(++i); 3354 } 3355 word digit_val = digitValue(digit_char, base); 3356 if (digit_val == -1) return Error::error(); 3357 digit = Int::cast(SmallInt::fromWord(digit_val)); 3358 result = runtime->intMultiply(thread, result, base_obj); 3359 result = runtime->intAdd(thread, result, digit); 3360 } 3361 if (sign < 0) { 3362 result = runtime->intNegate(thread, result); 3363 } 3364 return *result; 3365} 3366 3367RawObject FUNC(_builtins, _int_new_from_str)(Thread* thread, Arguments args) { 3368 HandleScope scope(thread); 3369 Type type(&scope, args.get(0)); 3370 Str str(&scope, args.get(1)); 3371 word base = intUnderlying(args.get(2)).asWord(); 3372 Object result(&scope, intFromStr(thread, str, base)); 3373 if (result.isError()) { 3374 Str repr(&scope, thread->invokeMethod1(str, ID(__repr__))); 3375 return thread->raiseWithFmt(LayoutId::kValueError, 3376 "invalid literal for int() with base %w: %S", 3377 base == 0 ? 10 : base, &repr); 3378 } 3379 return intOrUserSubclass(thread, type, result); 3380} 3381 3382RawObject FUNC(_builtins, _iter)(Thread* thread, Arguments args) { 3383 HandleScope scope(thread); 3384 Object object(&scope, args.get(0)); 3385 return Interpreter::createIterator(thread, object); 3386} 3387 3388static RawObject unpackFunction(const Object& obj) { 3389 if (obj.isStaticMethod()) { 3390 return StaticMethod::cast(*obj).function(); 3391 } 3392 if (obj.isClassMethod()) { 3393 return ClassMethod::cast(*obj).function(); 3394 } 3395 if (obj.isBoundMethod()) { 3396 return BoundMethod::cast(*obj).function(); 3397 } 3398 if (obj.isInstanceMethod()) { 3399 return InstanceMethod::cast(*obj).function(); 3400 } 3401 return *obj; 3402} 3403 3404RawObject FUNC(_builtins, _jit)(Thread* thread, Arguments args) { 3405 HandleScope scope(thread); 3406 Object obj(&scope, args.get(0)); 3407 obj = unpackFunction(obj); 3408 if (!obj.isFunction()) { 3409 // TODO(T90869918): Support unpacking property (fget, fset, fdel). 3410 return Bool::falseObj(); 3411 } 3412 Function function(&scope, *obj); 3413 if (!canCompileFunction(thread, function)) { 3414 return Bool::falseObj(); 3415 } 3416 compileFunction(thread, function); 3417 return Bool::trueObj(); 3418} 3419 3420RawObject FUNC(_builtins, _jit_iscompiled)(Thread* thread, Arguments args) { 3421 HandleScope scope(thread); 3422 Object obj(&scope, args.get(0)); 3423 obj = unpackFunction(obj); 3424 if (!obj.isFunction()) { 3425 // TODO(T90869918): Support unpacking property (fget, fset, fdel). 3426 return Bool::falseObj(); 3427 } 3428 Function function(&scope, *obj); 3429 return Bool::fromBool(function.isCompiled()); 3430} 3431 3432RawObject FUNC(_builtins, _list_append)(Thread* thread, Arguments args) { 3433 HandleScope scope(thread); 3434 Object self(&scope, args.get(0)); 3435 Runtime* runtime = thread->runtime(); 3436 if (!runtime->isInstanceOfList(*self)) { 3437 return thread->raiseWithFmt( 3438 LayoutId::kTypeError, 3439 "'append' for 'list' objects doesn't apply to a '%T' object", &self); 3440 } 3441 List list(&scope, *self); 3442 Object value(&scope, args.get(1)); 3443 runtime->listAdd(thread, list, value); 3444 return NoneType::object(); 3445} 3446 3447RawObject FUNC(_builtins, _list_check)(Thread* thread, Arguments args) { 3448 return Bool::fromBool(thread->runtime()->isInstanceOfList(args.get(0))); 3449} 3450 3451RawObject FUNC(_builtins, _list_check_exact)(Thread*, Arguments args) { 3452 return Bool::fromBool(args.get(0).isList()); 3453} 3454 3455RawObject FUNC(_builtins, _list_delitem)(Thread* thread, Arguments args) { 3456 HandleScope scope(thread); 3457 List self(&scope, args.get(0)); 3458 word length = self.numItems(); 3459 word idx = intUnderlying(args.get(1)).asWordSaturated(); 3460 if (idx < 0) { 3461 idx += length; 3462 } 3463 if (idx < 0 || idx >= length) { 3464 return thread->raiseWithFmt(LayoutId::kIndexError, 3465 "list assignment index out of range"); 3466 } 3467 listPop(thread, self, idx); 3468 return NoneType::object(); 3469} 3470 3471RawObject FUNC(_builtins, _list_delslice)(Thread* thread, Arguments args) { 3472 // This function deletes elements that are specified by a slice by copying. 3473 // It compacts to the left elements in the slice range and then copies 3474 // elements after the slice into the free area. The list element count is 3475 // decremented and elements in the unused part of the list are overwritten 3476 // with None. 3477 HandleScope scope(thread); 3478 List list(&scope, args.get(0)); 3479 3480 word start = SmallInt::cast(args.get(1)).value(); 3481 word stop = SmallInt::cast(args.get(2)).value(); 3482 word step = SmallInt::cast(args.get(3)).value(); 3483 3484 word slice_length = Slice::length(start, stop, step); 3485 DCHECK(slice_length >= 0, "slice length should be positive"); 3486 if (slice_length == 0) { 3487 // Nothing to delete 3488 return NoneType::object(); 3489 } 3490 if (slice_length == list.numItems()) { 3491 // Delete all the items 3492 list.clearFrom(0); 3493 return NoneType::object(); 3494 } 3495 if (step < 0) { 3496 // Adjust step to make iterating easier 3497 start = start + step * (slice_length - 1); 3498 step = -step; 3499 } 3500 DCHECK(start >= 0, "start should be positive"); 3501 DCHECK(start < list.numItems(), "start should be in bounds"); 3502 DCHECK(step <= list.numItems() || slice_length == 1, 3503 "Step should be in bounds or only one element should be sliced"); 3504 // Sliding compaction of elements out of the slice to the left 3505 // Invariant: At each iteration of the loop, `fast` is the index of an 3506 // element addressed by the slice. 3507 // Invariant: At each iteration of the inner loop, `slow` is the index of a 3508 // location to where we are relocating a slice addressed element. It is *not* 3509 // addressed by the slice. 3510 word fast = start; 3511 for (word i = 1; i < slice_length; i++) { 3512 DCHECK_INDEX(fast, list.numItems()); 3513 word slow = fast + 1; 3514 fast += step; 3515 for (; slow < fast; slow++) { 3516 list.atPut(slow - i, list.at(slow)); 3517 } 3518 } 3519 // Copy elements into the space where the deleted elements were 3520 for (word i = fast + 1; i < list.numItems(); i++) { 3521 list.atPut(i - slice_length, list.at(i)); 3522 } 3523 word new_length = list.numItems() - slice_length; 3524 DCHECK(new_length >= 0, "new_length must be positive"); 3525 // Untrack all deleted elements 3526 list.clearFrom(new_length); 3527 return NoneType::object(); 3528} 3529 3530RawObject FUNC(_builtins, _list_extend)(Thread* thread, Arguments args) { 3531 HandleScope scope(thread); 3532 Runtime* runtime = thread->runtime(); 3533 Object self_obj(&scope, args.get(0)); 3534 if (!runtime->isInstanceOfList(*self_obj)) { 3535 return thread->raiseRequiresType(self_obj, ID(list)); 3536 } 3537 List self(&scope, *self_obj); 3538 Object other(&scope, args.get(1)); 3539 3540 word src_length; 3541 Tuple src(&scope, runtime->emptyTuple()); 3542 if (other.isList()) { 3543 src = List::cast(*other).items(); 3544 src_length = List::cast(*other).numItems(); 3545 } else if (other.isTuple()) { 3546 src = *other; 3547 src_length = src.length(); 3548 } else { 3549 return Unbound::object(); 3550 } 3551 3552 listExtend(thread, self, src, src_length); 3553 return NoneType::object(); 3554} 3555 3556RawObject FUNC(_builtins, _list_getitem)(Thread* thread, Arguments args) { 3557 HandleScope scope(thread); 3558 Object self_obj(&scope, args.get(0)); 3559 Runtime* runtime = thread->runtime(); 3560 if (!runtime->isInstanceOfList(*self_obj)) { 3561 return raiseRequiresFromCaller(thread, args, ID(list)); 3562 } 3563 Object key(&scope, args.get(1)); 3564 if (runtime->isInstanceOfInt(*key)) { 3565 word index = intUnderlying(*key).asWordSaturated(); 3566 if (!SmallInt::isValid(index)) { 3567 return thread->raiseWithFmt(LayoutId::kIndexError, 3568 "cannot fit '%T' into an index-sized integer", 3569 &key); 3570 } 3571 List self(&scope, *self_obj); 3572 word length = self.numItems(); 3573 if (index < 0) { 3574 index += length; 3575 } 3576 if (index < 0 || index >= length) { 3577 return thread->raiseWithFmt(LayoutId::kIndexError, 3578 "list index out of range"); 3579 } 3580 return self.at(index); 3581 } 3582 3583 word start, stop; 3584 if (!tryUnpackSlice(key, &start, &stop)) { 3585 return Unbound::object(); 3586 } 3587 3588 List self(&scope, *self_obj); 3589 word result_len = Slice::adjustIndices(self.numItems(), &start, &stop, 1); 3590 if (result_len == 0) { 3591 return runtime->newList(); 3592 } 3593 Tuple src(&scope, self.items()); 3594 MutableTuple dst(&scope, runtime->newMutableTuple(result_len)); 3595 dst.replaceFromWithStartAt(0, *src, result_len, start); 3596 List result(&scope, runtime->newList()); 3597 result.setItems(*dst); 3598 result.setNumItems(result_len); 3599 return *result; 3600} 3601 3602RawObject FUNC(_builtins, _list_getslice)(Thread* thread, Arguments args) { 3603 HandleScope scope(thread); 3604 List self(&scope, args.get(0)); 3605 word start = SmallInt::cast(args.get(1)).value(); 3606 word stop = SmallInt::cast(args.get(2)).value(); 3607 word step = SmallInt::cast(args.get(3)).value(); 3608 return listSlice(thread, self, start, stop, step); 3609} 3610 3611RawObject FUNC(_builtins, _list_guard)(Thread* thread, Arguments args) { 3612 if (thread->runtime()->isInstanceOfList(args.get(0))) { 3613 return NoneType::object(); 3614 } 3615 return raiseRequiresFromCaller(thread, args, ID(list)); 3616} 3617 3618RawObject FUNC(_builtins, _list_len)(Thread* thread, Arguments args) { 3619 HandleScope scope(thread); 3620 List self(&scope, args.get(0)); 3621 return SmallInt::fromWord(self.numItems()); 3622} 3623 3624RawObject FUNC(_builtins, _list_new)(Thread* thread, Arguments args) { 3625 HandleScope scope(thread); 3626 word size = SmallInt::cast(args.get(0)).value(); 3627 Runtime* runtime = thread->runtime(); 3628 List result(&scope, runtime->newList()); 3629 if (size > 0) { 3630 MutableTuple items(&scope, runtime->newMutableTuple(size)); 3631 result.setItems(*items); 3632 result.setNumItems(size); 3633 items.fill(args.get(1)); 3634 } 3635 return *result; 3636} 3637 3638RawObject FUNC(_builtins, _list_sort)(Thread* thread, Arguments args) { 3639 HandleScope scope(thread); 3640 CHECK(thread->runtime()->isInstanceOfList(args.get(0)), 3641 "Unsupported argument type for 'ls'"); 3642 List list(&scope, args.get(0)); 3643 return listSort(thread, list); 3644} 3645 3646RawObject FUNC(_builtins, _list_sort_by_key)(Thread* thread, Arguments args) { 3647 HandleScope scope(thread); 3648 CHECK(thread->runtime()->isInstanceOfList(args.get(0)), 3649 "Unsupported argument type for 'ls'"); 3650 List list(&scope, args.get(0)); 3651 return listSortWithCompareMethod(thread, list, ID(_lt_key)); 3652} 3653 3654static RawObject listSetSlice(Thread* thread, const List& self, word start, 3655 word stop, word step, const Tuple& src, 3656 word src_length) { 3657 // Make sure that the degenerate case of a slice assignment where start is 3658 // greater than stop inserts before the start and not the stop. For example, 3659 // b[5:2] = ... should inserts before 5, not before 2. 3660 if ((step < 0 && start < stop) || (step > 0 && start > stop)) { 3661 stop = start; 3662 } 3663 3664 if (step == 1) { 3665 word growth = src_length - (stop - start); 3666 word new_length = self.numItems() + growth; 3667 if (growth == 0) { 3668 // Assignment does not change the length of the list. Do nothing. 3669 } else if (growth > 0) { 3670 // Assignment grows the length of the list. Ensure there is enough free 3671 // space in the underlying tuple for the new items and move stuff out of 3672 // the way. 3673 thread->runtime()->listEnsureCapacity(thread, self, new_length); 3674 // Make the free space part of the list. Must happen before shifting so 3675 // we can index into the free space. 3676 self.setNumItems(new_length); 3677 // Shift some items to the right. 3678 self.replaceFromWithStartAt(start + growth, *self, 3679 new_length - growth - start, start); 3680 } else { 3681 // Growth is negative so assignment shrinks the length of the list. 3682 // Shift some items to the left. 3683 self.replaceFromWithStartAt(start, *self, new_length - start, 3684 start - growth); 3685 // Do not retain references in the unused part of the list. 3686 self.clearFrom(new_length); 3687 // Remove the free space from the length of the list. Must happen after 3688 // shifting and clearing so we can index into the free space. 3689 self.setNumItems(new_length); 3690 } 3691 3692 // Copy new elements into the middle 3693 if (new_length > 0) { 3694 MutableTuple::cast(self.items()).replaceFromWith(start, *src, src_length); 3695 } 3696 return NoneType::object(); 3697 } 3698 3699 word slice_length = Slice::length(start, stop, step); 3700 if (slice_length != src_length) { 3701 return thread->raiseWithFmt( 3702 LayoutId::kValueError, 3703 "attempt to assign sequence of size %w to extended slice of size " 3704 "%w", 3705 src_length, slice_length); 3706 } 3707 HandleScope scope(thread); 3708 MutableTuple dst_items(&scope, self.items()); 3709 for (word dst_idx = start, src_idx = 0; src_idx < src_length; 3710 dst_idx += step, src_idx++) { 3711 dst_items.atPut(dst_idx, src.at(src_idx)); 3712 } 3713 return NoneType::object(); 3714} 3715 3716RawObject FUNC(_builtins, _list_setitem)(Thread* thread, Arguments args) { 3717 HandleScope scope(thread); 3718 Runtime* runtime = thread->runtime(); 3719 Object self_obj(&scope, args.get(0)); 3720 if (!runtime->isInstanceOfList(*self_obj)) { 3721 return thread->raiseRequiresType(self_obj, ID(list)); 3722 } 3723 Object key(&scope, args.get(1)); 3724 if (runtime->isInstanceOfInt(*key)) { 3725 word index = intUnderlying(*key).asWordSaturated(); 3726 if (!SmallInt::isValid(index)) { 3727 return thread->raiseWithFmt(LayoutId::kIndexError, 3728 "cannot fit '%T' into an index-sized integer", 3729 &key); 3730 } 3731 3732 List self(&scope, *self_obj); 3733 word length = self.numItems(); 3734 if (index < 0) { 3735 index += length; 3736 } 3737 if (index < 0 || index >= length) { 3738 return thread->raiseWithFmt(LayoutId::kIndexError, 3739 "list assignment index out of range"); 3740 } 3741 3742 self.atPut(index, args.get(2)); 3743 return NoneType::object(); 3744 } 3745 3746 word start, stop; 3747 if (!tryUnpackSlice(key, &start, &stop)) { 3748 return Unbound::object(); 3749 } 3750 3751 Object src(&scope, args.get(2)); 3752 Tuple src_tuple(&scope, runtime->emptyTuple()); 3753 word src_length; 3754 if (src.isList()) { 3755 if (self_obj == src) { 3756 return Unbound::object(); 3757 } 3758 RawList src_list = List::cast(*src); 3759 src_tuple = src_list.items(); 3760 src_length = src_list.numItems(); 3761 } else if (src.isTuple()) { 3762 src_tuple = *src; 3763 src_length = src_tuple.length(); 3764 } else { 3765 return Unbound::object(); 3766 } 3767 3768 List self(&scope, *self_obj); 3769 Slice::adjustIndices(self.numItems(), &start, &stop, 1); 3770 return listSetSlice(thread, self, start, stop, 1, src_tuple, src_length); 3771} 3772 3773RawObject FUNC(_builtins, _list_setslice)(Thread* thread, Arguments args) { 3774 HandleScope scope(thread); 3775 Runtime* runtime = thread->runtime(); 3776 3777 List self(&scope, args.get(0)); 3778 Object src(&scope, args.get(4)); 3779 Tuple src_tuple(&scope, runtime->emptyTuple()); 3780 word src_length; 3781 if (src.isList()) { 3782 RawList src_list = List::cast(*src); 3783 src_tuple = src_list.items(); 3784 src_length = src_list.numItems(); 3785 if (self == src) { 3786 // This copy avoids complicated indexing logic in a rare case of 3787 // replacing lhs with elements of rhs when lhs == rhs. It can likely be 3788 // re-written to avoid allocation if necessary. 3789 src_tuple = runtime->tupleSubseq(thread, src_tuple, 0, src_length); 3790 } 3791 } else if (src.isTuple()) { 3792 src_tuple = *src; 3793 src_length = src_tuple.length(); 3794 } else { 3795 return Unbound::object(); 3796 } 3797 3798 word start = SmallInt::cast(args.get(1)).value(); 3799 word stop = SmallInt::cast(args.get(2)).value(); 3800 word step = SmallInt::cast(args.get(3)).value(); 3801 return listSetSlice(thread, self, start, stop, step, src_tuple, src_length); 3802} 3803 3804RawObject FUNC(_builtins, _list_swap)(Thread* thread, Arguments args) { 3805 HandleScope scope(thread); 3806 List list(&scope, args.get(0)); 3807 word i = SmallInt::cast(args.get(1)).value(); 3808 word j = SmallInt::cast(args.get(2)).value(); 3809 list.swap(i, j); 3810 return NoneType::object(); 3811} 3812 3813RawObject FUNC(_builtins, _memoryview_getitem)(Thread* thread, Arguments args) { 3814 HandleScope scope(thread); 3815 Object self_obj(&scope, args.get(0)); 3816 if (!self_obj.isMemoryView()) { 3817 return raiseRequiresFromCaller(thread, args, ID(memoryview)); 3818 } 3819 MemoryView self(&scope, *self_obj); 3820 3821 Object key_obj(&scope, args.get(1)); 3822 if (!thread->runtime()->isInstanceOfInt(*key_obj)) { 3823 return Unbound::object(); 3824 } 3825 word index = intUnderlying(*key_obj).asWordSaturated(); 3826 if (!SmallInt::isValid(index)) { 3827 return thread->raiseWithFmt(LayoutId::kIndexError, 3828 "cannot fit '%T' into an index-sized integer", 3829 &key_obj); 3830 } 3831 word index_abs = std::abs(index); 3832 word length = self.length(); 3833 word item_size = memoryviewItemsize(thread, self); 3834 word byte_index; 3835 if (__builtin_mul_overflow(index_abs, item_size, &byte_index) || 3836 length == 0) { 3837 return thread->raiseWithFmt(LayoutId::kIndexError, "index out of bounds"); 3838 } 3839 if (index < 0) { 3840 byte_index = length - byte_index; 3841 } 3842 if (byte_index + (item_size - 1) >= length) { 3843 return thread->raiseWithFmt(LayoutId::kIndexError, "index out of bounds"); 3844 } 3845 return memoryviewGetitem(thread, self, byte_index); 3846} 3847 3848RawObject FUNC(_builtins, _memoryview_getslice)(Thread* thread, 3849 Arguments args) { 3850 HandleScope scope(thread); 3851 Object self_obj(&scope, args.get(0)); 3852 if (!self_obj.isMemoryView()) { 3853 return thread->raiseRequiresType(self_obj, ID(memoryview)); 3854 } 3855 MemoryView self(&scope, *self_obj); 3856 Int start_int(&scope, intUnderlying(args.get(1))); 3857 word start = start_int.asWord(); 3858 Int stop_int(&scope, intUnderlying(args.get(2))); 3859 word stop = stop_int.asWord(); 3860 Int step_int(&scope, intUnderlying(args.get(3))); 3861 word step = step_int.asWord(); 3862 return memoryviewGetslice(thread, self, start, stop, step); 3863} 3864 3865RawObject FUNC(_builtins, _mappingproxy_guard)(Thread* thread, Arguments args) { 3866 if (args.get(0).isMappingProxy()) { 3867 return NoneType::object(); 3868 } 3869 return raiseRequiresFromCaller(thread, args, ID(mappingproxy)); 3870} 3871 3872RawObject FUNC(_builtins, _mappingproxy_mapping)(Thread* thread, 3873 Arguments args) { 3874 HandleScope scope(thread); 3875 MappingProxy mappingproxy(&scope, args.get(0)); 3876 return mappingproxy.mapping(); 3877} 3878 3879RawObject FUNC(_builtins, _mappingproxy_set_mapping)(Thread* thread, 3880 Arguments args) { 3881 HandleScope scope(thread); 3882 MappingProxy mappingproxy(&scope, args.get(0)); 3883 mappingproxy.setMapping(args.get(1)); 3884 return *mappingproxy; 3885} 3886 3887RawObject FUNC(_builtins, _memoryview_check)(Thread*, Arguments args) { 3888 return Bool::fromBool(args.get(0).isMemoryView()); 3889} 3890 3891RawObject FUNC(_builtins, _memoryview_guard)(Thread* thread, Arguments args) { 3892 if (args.get(0).isMemoryView()) { 3893 return NoneType::object(); 3894 } 3895 return raiseRequiresFromCaller(thread, args, ID(memoryview)); 3896} 3897 3898RawObject FUNC(_builtins, _memoryview_itemsize)(Thread* thread, 3899 Arguments args) { 3900 HandleScope scope(thread); 3901 Object self_obj(&scope, args.get(0)); 3902 if (!self_obj.isMemoryView()) { 3903 return thread->raiseRequiresType(self_obj, ID(memoryview)); 3904 } 3905 MemoryView self(&scope, *self_obj); 3906 return SmallInt::fromWord(memoryviewItemsize(thread, self)); 3907} 3908 3909RawObject FUNC(_builtins, _memoryview_nbytes)(Thread* thread, Arguments args) { 3910 HandleScope scope(thread); 3911 Object self_obj(&scope, args.get(0)); 3912 if (!self_obj.isMemoryView()) { 3913 return thread->raiseRequiresType(self_obj, ID(memoryview)); 3914 } 3915 MemoryView self(&scope, *self_obj); 3916 return SmallInt::fromWord(self.length()); 3917} 3918 3919RawObject FUNC(_builtins, _memoryview_setitem)(Thread* thread, Arguments args) { 3920 HandleScope scope(thread); 3921 Object self_obj(&scope, args.get(0)); 3922 if (!self_obj.isMemoryView()) { 3923 return raiseRequiresFromCaller(thread, args, ID(memoryview)); 3924 } 3925 MemoryView self(&scope, *self_obj); 3926 if (self.readOnly()) { 3927 return thread->raiseWithFmt(LayoutId::kTypeError, 3928 "cannot modify read-only memory"); 3929 } 3930 Object index_obj(&scope, args.get(1)); 3931 if (!index_obj.isInt()) return Unbound::object(); 3932 Int index_int(&scope, *index_obj); 3933 word index = index_int.asWord(); 3934 word item_size = memoryviewItemsize(thread, self); 3935 word byte_index = (index < 0 ? -index : index) * item_size; 3936 if (byte_index + item_size > self.length()) { 3937 return thread->raiseWithFmt(LayoutId::kIndexError, "index out of bounds"); 3938 } 3939 if (index < 0) { 3940 byte_index = self.length() - byte_index; 3941 } 3942 3943 Object value(&scope, args.get(2)); 3944 return memoryviewSetitem(thread, self, byte_index, value); 3945} 3946 3947RawObject FUNC(_builtins, _memoryview_setslice)(Thread* thread, 3948 Arguments args) { 3949 HandleScope scope(thread); 3950 Object self_obj(&scope, args.get(0)); 3951 if (!self_obj.isMemoryView()) { 3952 return thread->raiseRequiresType(self_obj, ID(memoryview)); 3953 } 3954 MemoryView self(&scope, *self_obj); 3955 if (self.readOnly()) { 3956 return thread->raiseWithFmt(LayoutId::kTypeError, 3957 "cannot modify read-only memory"); 3958 } 3959 Int start_int(&scope, intUnderlying(args.get(1))); 3960 word start = start_int.asWord(); 3961 Int stop_int(&scope, intUnderlying(args.get(2))); 3962 word stop = stop_int.asWord(); 3963 Int step_int(&scope, intUnderlying(args.get(3))); 3964 word step = step_int.asWord(); 3965 word slice_len = Slice::adjustIndices(self.length(), &start, &stop, step); 3966 Object value(&scope, args.get(4)); 3967 return memoryviewSetslice(thread, self, start, stop, step, slice_len, value); 3968} 3969 3970RawObject FUNC(_builtins, _memoryview_start)(Thread*, Arguments args) { 3971 return SmallInt::fromWord(MemoryView::cast(args.get(0)).start()); 3972} 3973 3974RawObject FUNC(_builtins, _mmap_check)(Thread* thread, Arguments args) { 3975 return Bool::fromBool(thread->runtime()->isInstanceOfMmap(args.get(0))); 3976} 3977 3978RawObject FUNC(_builtins, _module_dir)(Thread* thread, Arguments args) { 3979 HandleScope scope(thread); 3980 Module self(&scope, args.get(0)); 3981 return moduleKeys(thread, self); 3982} 3983 3984RawObject FUNC(_builtins, _module_proxy)(Thread* thread, Arguments args) { 3985 HandleScope scope(thread); 3986 Object self_obj(&scope, args.get(0)); 3987 if (!thread->runtime()->isInstanceOfModule(*self_obj)) { 3988 return thread->raiseRequiresType(self_obj, ID(module)); 3989 } 3990 Module module(&scope, *self_obj); 3991 return module.moduleProxy(); 3992} 3993 3994RawObject FUNC(_builtins, _module_proxy_check)(Thread*, Arguments args) { 3995 return Bool::fromBool(args.get(0).isModuleProxy()); 3996} 3997 3998RawObject FUNC(_builtins, _module_proxy_guard)(Thread* thread, Arguments args) { 3999 if (args.get(0).isModuleProxy()) { 4000 return NoneType::object(); 4001 } 4002 return raiseRequiresFromCaller(thread, args, ID(module_proxy)); 4003} 4004 4005RawObject FUNC(_builtins, _module_proxy_keys)(Thread* thread, Arguments args) { 4006 HandleScope scope(thread); 4007 Object self_obj(&scope, args.get(0)); 4008 if (!self_obj.isModuleProxy()) { 4009 return thread->raiseRequiresType(self_obj, ID(module_proxy)); 4010 } 4011 ModuleProxy self(&scope, *self_obj); 4012 Module module(&scope, self.module()); 4013 DCHECK(module.moduleProxy() == self, "module.proxy != proxy.module"); 4014 return moduleKeys(thread, module); 4015} 4016 4017RawObject FUNC(_builtins, _module_proxy_setitem)(Thread* thread, 4018 Arguments args) { 4019 HandleScope scope(thread); 4020 Object self_obj(&scope, args.get(0)); 4021 if (!self_obj.isModuleProxy()) { 4022 return thread->raiseRequiresType(self_obj, ID(module_proxy)); 4023 } 4024 ModuleProxy self(&scope, *self_obj); 4025 Object name(&scope, args.get(1)); 4026 name = attributeName(thread, name); 4027 if (name.isErrorException()) return *name; 4028 Object value(&scope, args.get(2)); 4029 Module module(&scope, self.module()); 4030 DCHECK(module.moduleProxy() == self, "module.proxy != proxy.module"); 4031 return moduleAtPut(thread, module, name, value); 4032} 4033 4034RawObject FUNC(_builtins, _module_proxy_values)(Thread* thread, 4035 Arguments args) { 4036 HandleScope scope(thread); 4037 Object self_obj(&scope, args.get(0)); 4038 if (!self_obj.isModuleProxy()) { 4039 return thread->raiseRequiresType(self_obj, ID(module_proxy)); 4040 } 4041 ModuleProxy self(&scope, *self_obj); 4042 Module module(&scope, self.module()); 4043 DCHECK(module.moduleProxy() == self, "module.proxy != proxy.module"); 4044 return moduleValues(thread, module); 4045} 4046 4047RawObject FUNC(_builtins, _object_class_set)(Thread* thread, Arguments args) { 4048 HandleScope scope(thread); 4049 Runtime* runtime = thread->runtime(); 4050 Object self(&scope, args.get(0)); 4051 4052 // Disallow setting __class__ on builtin instances 4053 Type instance_type(&scope, runtime->typeOf(*self)); 4054 if (instance_type.isBuiltin()) { 4055 return thread->raiseWithFmt( 4056 LayoutId::kTypeError, 4057 "__class__ assignment only supported for user types"); 4058 } 4059 4060 // The new class must be an instance of type 4061 Object new_type_object(&scope, args.get(1)); 4062 if (!runtime->isInstanceOfType(*new_type_object)) { 4063 return thread->raiseWithFmt(LayoutId::kTypeError, 4064 "__class__ must be a type, not a '%T' object", 4065 &new_type_object); 4066 } 4067 4068 Type new_type(&scope, *new_type_object); 4069 return typeSetDunderClass(thread, self, new_type); 4070} 4071 4072RawObject FUNC(_builtins, _object_keys)(Thread* thread, Arguments args) { 4073 HandleScope scope(thread); 4074 Object object(&scope, args.get(0)); 4075 Runtime* runtime = thread->runtime(); 4076 Layout layout(&scope, runtime->layoutOf(*object)); 4077 List result(&scope, runtime->newList()); 4078 // Add in-object attributes 4079 Tuple in_object(&scope, layout.inObjectAttributes()); 4080 word in_object_length = in_object.length(); 4081 word result_length = in_object_length; 4082 if (layout.hasTupleOverflow()) { 4083 result_length += Tuple::cast(layout.overflowAttributes()).length(); 4084 // TODO(emacs): Pre-size the tuple in `result' to be result_length. 4085 static_cast<void>(result_length); 4086 } 4087 for (word i = 0; i < in_object_length; i++) { 4088 Tuple pair(&scope, in_object.at(i)); 4089 Object name(&scope, pair.at(0)); 4090 if (name.isNoneType()) continue; 4091 AttributeInfo info(pair.at(1)); 4092 if (info.isHidden()) continue; 4093 runtime->listAdd(thread, result, name); 4094 } 4095 // Add overflow attributes 4096 if (layout.hasTupleOverflow()) { 4097 Tuple overflow(&scope, layout.overflowAttributes()); 4098 for (word i = 0, length = overflow.length(); i < length; i++) { 4099 Tuple pair(&scope, overflow.at(i)); 4100 Object name(&scope, pair.at(0)); 4101 if (name == SmallInt::fromWord(0)) continue; 4102 runtime->listAdd(thread, result, name); 4103 } 4104 } else if (layout.hasDictOverflow()) { 4105 // TODO(T57446141): Dict overflow should be handled by a __dict__ descriptor 4106 // on the type, like `type` or `function` 4107 Instance instance(&scope, *object); 4108 Object overflow_obj( 4109 &scope, instance.instanceVariableAt(layout.dictOverflowOffset())); 4110 if (!overflow_obj.isNoneType()) { 4111 Dict overflow(&scope, *overflow_obj); 4112 Object key(&scope, NoneType::object()); 4113 Object value(&scope, NoneType::object()); 4114 for (word i = 0; dictNextItem(overflow, &i, &key, &value);) { 4115 runtime->listAdd(thread, result, key); 4116 } 4117 } 4118 } 4119 return *result; 4120} 4121 4122RawObject FUNC(_builtins, _object_type_getattr)(Thread* thread, 4123 Arguments args) { 4124 HandleScope scope(thread); 4125 Object instance(&scope, args.get(0)); 4126 Object name(&scope, args.get(1)); 4127 DCHECK(name.isStr(), 4128 "_object_type_hasattr should only receive string literals"); 4129 Runtime* runtime = thread->runtime(); 4130 DCHECK(runtime->isInternedStr(thread, name), 4131 "string literals that look like names should be interned"); 4132 Type type(&scope, runtime->typeOf(*instance)); 4133 Object attr(&scope, typeLookupInMro(thread, *type, *name)); 4134 if (attr.isErrorNotFound()) { 4135 return Unbound::object(); 4136 } 4137 if (attr.isFunction()) { 4138 return runtime->newBoundMethod(attr, instance); 4139 } 4140 return resolveDescriptorGet(thread, attr, instance, type); 4141} 4142 4143RawObject FUNC(_builtins, _object_type_hasattr)(Thread* thread, 4144 Arguments args) { 4145 HandleScope scope(thread); 4146 Type type(&scope, thread->runtime()->typeOf(args.get(0))); 4147 Object name(&scope, args.get(1)); 4148 name = attributeName(thread, name); 4149 if (name.isErrorException()) return *name; 4150 Object result(&scope, typeLookupInMro(thread, *type, *name)); 4151 return Bool::fromBool(!result.isErrorNotFound()); 4152} 4153 4154RawObject FUNC(_builtins, _os_write)(Thread* thread, Arguments args) { 4155 HandleScope scope(thread); 4156 Object fd_obj(&scope, args.get(0)); 4157 CHECK(fd_obj.isSmallInt(), "fd must be small int"); 4158 Object byteslike_obj(&scope, args.get(1)); 4159 Byteslike byteslike_buf(&scope, thread, *byteslike_obj); 4160 DCHECK(byteslike_buf.isValid(), "bytes-like object is invalid"); 4161 size_t count = byteslike_buf.length(); 4162 std::unique_ptr<byte[]> buffer(new byte[count]); 4163 // TODO(T87798648): We should avoid copies for LargeBytes/DataArray. 4164 byteslike_buf.copyTo(buffer.get(), count); 4165 int fd = SmallInt::cast(*fd_obj).value(); 4166 ssize_t result = File::write(fd, buffer.get(), count); 4167 if (result < 0) { 4168 return thread->raiseOSErrorFromErrno(-result); 4169 } 4170 return SmallInt::fromWord(result); 4171} 4172 4173RawObject FUNC(_builtins, _os_error_subclass_from_errno)(Thread* thread, 4174 Arguments args) { 4175 HandleScope scope(thread); 4176 Int errno_value(&scope, intUnderlying(args.get(0))); 4177 LayoutId subclass = errorLayoutFromErrno(errno_value.asWord()); 4178 return thread->runtime()->typeAt(subclass); 4179} 4180 4181RawObject FUNC(_builtins, _profiler_exclude)(Thread* thread, Arguments args) { 4182 HandleScope scope(thread); 4183 Object callable(&scope, args.get(0)); 4184 4185 word opcodes_begin = thread->opcodeCount(); 4186 bool enabled = thread->profilingEnabled(); 4187 thread->disableProfiling(); 4188 Object result(&scope, Interpreter::call0(thread, callable)); 4189 4190 word slack = thread->opcodeCount() - opcodes_begin; 4191 thread->countOpcodes(-slack); 4192 if (enabled) { 4193 thread->enableProfiling(); 4194 } 4195 return *result; 4196} 4197 4198static void warnImpreciseCounting(Thread* thread) { 4199 // The interpreter switching mechanism is currently only applied in a 4200 // lightweight fashion meaning that recursive interpreter instances further 4201 // up the stackframe won't actually switch to a counting interpreter. 4202 bool should_warn = false; 4203 for (Frame* frame = thread->currentFrame()->previousFrame(); 4204 !frame->isSentinel() && !frame->previousFrame()->isSentinel(); 4205 frame = frame->previousFrame()) { 4206 if (frame->isNative() || 4207 (frame->returnMode() & Frame::kExitRecursiveInterpreter) != 0) { 4208 should_warn = true; 4209 break; 4210 } 4211 } 4212 if (should_warn) { 4213 HandleScope scope(thread); 4214 Runtime* runtime = thread->runtime(); 4215 Object message(&scope, runtime->newStrFromCStr( 4216 "Interpreter switching to count opcodes does " 4217 "not affect outer stackframes yet.")); 4218 Object category(&scope, runtime->typeAt(LayoutId::kRuntimeWarning)); 4219 if (ensureBuiltinModuleById(thread, ID(warnings)).isErrorException() || 4220 thread->invokeFunction2(ID(warnings), ID(warn), message, category) 4221 .isErrorException()) { 4222 thread->ignorePendingException(); 4223 } 4224 } 4225} 4226 4227RawObject FUNC(_builtins, _profiler_install)(Thread* thread, Arguments args) { 4228 HandleScope scope(thread); 4229 Runtime* runtime = thread->runtime(); 4230 Object new_thread_func(&scope, args.get(0)); 4231 if (!new_thread_func.isNoneType() && 4232 !runtime->isCallable(thread, new_thread_func)) { 4233 return thread->raiseWithFmt( 4234 LayoutId::kTypeError, 4235 "'_install_profiler' requires a callable or None but got '%T'", 4236 &new_thread_func); 4237 } 4238 Object call_func(&scope, args.get(1)); 4239 Object return_func(&scope, args.get(2)); 4240 if (!call_func.isNoneType() || !return_func.isNoneType()) { 4241 if (!runtime->isCallable(thread, call_func)) { 4242 return thread->raiseWithFmt( 4243 LayoutId::kTypeError, 4244 "'_install_profiler' requires a callable but got '%T'", &call_func); 4245 } 4246 if (!runtime->isCallable(thread, return_func)) { 4247 return thread->raiseWithFmt( 4248 LayoutId::kTypeError, 4249 "'_install_profiler' requires a callable but got '%T'", &return_func); 4250 } 4251 } 4252 if (new_thread_func != runtime->profilingNewThread()) { 4253 if (!new_thread_func.isNoneType()) { 4254 Object thread_data(&scope, Interpreter::call0(thread, new_thread_func)); 4255 if (thread_data.isErrorException()) return *thread_data; 4256 thread->setProfilingData(*thread_data); 4257 } else { 4258 thread->setProfilingData(NoneType::object()); 4259 } 4260 } 4261 4262 runtime->setProfiling(new_thread_func, call_func, return_func); 4263 if (call_func.isNoneType()) { 4264 runtime->interpreter()->setOpcodeCounting(false); 4265 runtime->reinitInterpreter(); 4266 thread->disableProfiling(); 4267 } else { 4268 warnImpreciseCounting(thread); 4269 runtime->interpreter()->setOpcodeCounting(true); 4270 runtime->reinitInterpreter(); 4271 thread->enableProfiling(); 4272 } 4273 return NoneType::object(); 4274} 4275 4276RawObject FUNC(_builtins, _property)(Thread* thread, Arguments args) { 4277 HandleScope scope(thread); 4278 Object getter(&scope, args.get(0)); 4279 Object setter(&scope, args.get(1)); 4280 Object deleter(&scope, args.get(2)); 4281 // TODO(T42363565) Do something with the doc argument. 4282 return thread->runtime()->newProperty(getter, setter, deleter); 4283} 4284 4285RawObject FUNC(_builtins, _property_isabstract)(Thread* thread, 4286 Arguments args) { 4287 HandleScope scope(thread); 4288 Object self_obj(&scope, args.get(0)); 4289 if (!thread->runtime()->isInstanceOfProperty(*self_obj)) { 4290 return thread->raiseRequiresType(self_obj, ID(property)); 4291 } 4292 Property self(&scope, *self_obj); 4293 Object getter(&scope, self.getter()); 4294 Object abstract(&scope, isAbstract(thread, getter)); 4295 if (abstract != Bool::falseObj()) { 4296 return *abstract; 4297 } 4298 Object setter(&scope, self.setter()); 4299 if ((abstract = isAbstract(thread, setter)) != Bool::falseObj()) { 4300 return *abstract; 4301 } 4302 Object deleter(&scope, self.deleter()); 4303 return isAbstract(thread, deleter); 4304} 4305 4306RawObject FUNC(_builtins, _pyobject_offset)(Thread* thread, Arguments args) { 4307 HandleScope scope(thread); 4308 NativeProxy proxy(&scope, args.get(0)); 4309 uword addr = reinterpret_cast<uword>(Int::cast(proxy.native()).asCPtr()); 4310 addr += Int::cast(args.get(1)).asWord(); 4311 return thread->runtime()->newIntFromCPtr(reinterpret_cast<void*>(addr)); 4312} 4313 4314RawObject FUNC(_builtins, _range_check)(Thread*, Arguments args) { 4315 return Bool::fromBool(args.get(0).isRange()); 4316} 4317 4318RawObject FUNC(_builtins, _range_ctor_start_stop)(Thread* thread, 4319 Arguments args) { 4320 Runtime* runtime = thread->runtime(); 4321 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kRange), "unexpected cls"); 4322 HandleScope scope(thread); 4323 Object start(&scope, args.get(1)); 4324 if (!start.isSmallInt()) { 4325 start = intFromIndex(thread, start); 4326 if (start.isError()) { 4327 return *start; 4328 } 4329 } 4330 Object stop(&scope, args.get(2)); 4331 if (!stop.isSmallInt()) { 4332 stop = intFromIndex(thread, stop); 4333 if (stop.isError()) { 4334 return *stop; 4335 } 4336 } 4337 Object step(&scope, SmallInt::fromWord(1)); 4338 return runtime->newRange(start, stop, step); 4339} 4340 4341RawObject FUNC(_builtins, _range_ctor_start_stop_step)(Thread* thread, 4342 Arguments args) { 4343 Runtime* runtime = thread->runtime(); 4344 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kRange), "unexpected cls"); 4345 HandleScope scope(thread); 4346 Object start(&scope, args.get(1)); 4347 if (!start.isSmallInt()) { 4348 start = intFromIndex(thread, start); 4349 if (start.isError()) { 4350 return *start; 4351 } 4352 } 4353 Object stop(&scope, args.get(2)); 4354 if (!stop.isSmallInt()) { 4355 stop = intFromIndex(thread, stop); 4356 if (stop.isError()) { 4357 return *stop; 4358 } 4359 } 4360 Object step(&scope, args.get(3)); 4361 if (!step.isSmallInt()) { 4362 step = intFromIndex(thread, step); 4363 if (step.isError()) { 4364 return *step; 4365 } 4366 } 4367 Int step_int(&scope, intUnderlying(*step)); 4368 if (step_int.isZero()) { 4369 return thread->raiseWithFmt(LayoutId::kValueError, 4370 "range() arg 3 must not be zero"); 4371 } 4372 return runtime->newRange(start, stop, step); 4373} 4374 4375RawObject FUNC(_builtins, _range_ctor_stop)(Thread* thread, Arguments args) { 4376 Runtime* runtime = thread->runtime(); 4377 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kRange), "unexpected cls"); 4378 HandleScope scope(thread); 4379 Object start(&scope, SmallInt::fromWord(0)); 4380 Object stop(&scope, args.get(1)); 4381 if (!stop.isSmallInt()) { 4382 stop = intFromIndex(thread, stop); 4383 if (stop.isError()) { 4384 return *stop; 4385 } 4386 } 4387 Object step(&scope, SmallInt::fromWord(1)); 4388 return runtime->newRange(start, stop, step); 4389} 4390 4391RawObject FUNC(_builtins, _range_guard)(Thread* thread, Arguments args) { 4392 if (args.get(0).isRange()) { 4393 return NoneType::object(); 4394 } 4395 return raiseRequiresFromCaller(thread, args, ID(range)); 4396} 4397 4398RawObject FUNC(_builtins, _range_len)(Thread* thread, Arguments args) { 4399 HandleScope scope(thread); 4400 Range self(&scope, args.get(0)); 4401 Object start(&scope, self.start()); 4402 Object stop(&scope, self.stop()); 4403 Object step(&scope, self.step()); 4404 return rangeLen(thread, start, stop, step); 4405} 4406 4407RawObject FUNC(_builtins, _readline)(Thread* thread, Arguments args) { 4408 HandleScope scope(thread); 4409 Str prompt(&scope, strUnderlying(args.get(0))); 4410 word length = prompt.length(); 4411 std::unique_ptr<char[]> prompt_buf(new char[length + 1]); 4412 prompt.copyTo(reinterpret_cast<byte*>(prompt_buf.get()), length); 4413 prompt_buf.get()[length] = '\0'; 4414 char* line = PyOS_Readline(stdin, stdout, prompt_buf.get()); 4415 if (line == nullptr) { 4416 CHECK(thread->hasPendingException(), "there must be an exception raised"); 4417 return Error::exception(); 4418 } 4419 Object result(&scope, thread->runtime()->newStrFromCStr(line)); 4420 std::free(line); 4421 return *result; 4422} 4423 4424RawObject FUNC(_builtins, _repr_enter)(Thread* thread, Arguments args) { 4425 HandleScope scope(thread); 4426 Object obj(&scope, args.get(0)); 4427 return thread->reprEnter(obj); 4428} 4429 4430RawObject FUNC(_builtins, _repr_leave)(Thread* thread, Arguments args) { 4431 HandleScope scope(thread); 4432 Object obj(&scope, args.get(0)); 4433 thread->reprLeave(obj); 4434 return NoneType::object(); 4435} 4436 4437RawObject FUNC(_builtins, _seq_index)(Thread* thread, Arguments args) { 4438 HandleScope scope(thread); 4439 SeqIterator self(&scope, args.get(0)); 4440 return SmallInt::fromWord(self.index()); 4441} 4442 4443RawObject FUNC(_builtins, _seq_iterable)(Thread* thread, Arguments args) { 4444 HandleScope scope(thread); 4445 SeqIterator self(&scope, args.get(0)); 4446 return self.iterable(); 4447} 4448 4449RawObject FUNC(_builtins, _seq_set_index)(Thread* thread, Arguments args) { 4450 HandleScope scope(thread); 4451 SeqIterator self(&scope, args.get(0)); 4452 Int index(&scope, args.get(1)); 4453 self.setIndex(index.asWord()); 4454 return NoneType::object(); 4455} 4456 4457RawObject FUNC(_builtins, _seq_set_iterable)(Thread* thread, Arguments args) { 4458 HandleScope scope(thread); 4459 SeqIterator self(&scope, args.get(0)); 4460 Object iterable(&scope, args.get(1)); 4461 self.setIterable(*iterable); 4462 return NoneType::object(); 4463} 4464 4465RawObject FUNC(_builtins, _set_check)(Thread* thread, Arguments args) { 4466 return Bool::fromBool(thread->runtime()->isInstanceOfSet(args.get(0))); 4467} 4468 4469RawObject FUNC(_builtins, 4470 _set_function_flag_iterable_coroutine)(Thread* thread, 4471 Arguments args) { 4472 HandleScope scope(thread); 4473 Object function_obj(&scope, args.get(0)); 4474 if (!function_obj.isFunction()) { 4475 return thread->raiseWithFmt(LayoutId::kTypeError, 4476 "can only be called with a 'function' object"); 4477 } 4478 Function function(&scope, *function_obj); 4479 Code original_code(&scope, function.code()); 4480 Object code_code(&scope, original_code.code()); 4481 Object consts(&scope, original_code.consts()); 4482 Object names(&scope, original_code.names()); 4483 Object varnames(&scope, original_code.varnames()); 4484 Object freevars(&scope, original_code.freevars()); 4485 Object cellvars(&scope, original_code.cellvars()); 4486 Object filename(&scope, original_code.filename()); 4487 Object name(&scope, original_code.name()); 4488 Object lnotab(&scope, original_code.lnotab()); 4489 Code new_code( 4490 &scope, 4491 thread->runtime()->newCode( 4492 original_code.argcount(), original_code.posonlyargcount(), 4493 original_code.kwonlyargcount(), original_code.nlocals(), 4494 original_code.stacksize(), 4495 original_code.flags() | RawFunction::Flags::kIterableCoroutine, 4496 code_code, consts, names, varnames, freevars, cellvars, filename, 4497 name, original_code.firstlineno(), lnotab)); 4498 new_code.setIntrinsic(original_code.intrinsic()); 4499 function.setCode(*new_code); 4500 function.setFlags(function.flags() | Function::Flags::kIterableCoroutine); 4501 return NoneType::object(); 4502} 4503 4504RawObject FUNC(_builtins, _set_ctor)(Thread* thread, Arguments args) { 4505 Runtime* runtime = thread->runtime(); 4506 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kSet), "unexpected cls"); 4507 RawObject iterable_raw = args.get(1); 4508 if (iterable_raw == runtime->emptyTuple()) { 4509 return runtime->newSet(); 4510 } 4511 HandleScope scope(thread); 4512 Object iterable(&scope, iterable_raw); 4513 Set self(&scope, runtime->newSet()); 4514 return setUpdate(thread, self, iterable); 4515} 4516 4517RawObject FUNC(_builtins, _set_guard)(Thread* thread, Arguments args) { 4518 if (thread->runtime()->isInstanceOfSet(args.get(0))) { 4519 return NoneType::object(); 4520 } 4521 return raiseRequiresFromCaller(thread, args, ID(set)); 4522} 4523 4524RawObject FUNC(_builtins, _set_len)(Thread* thread, Arguments args) { 4525 HandleScope scope(thread); 4526 Set self(&scope, args.get(0)); 4527 return SmallInt::fromWord(self.numItems()); 4528} 4529 4530RawObject FUNC(_builtins, _set_member_double)(Thread*, Arguments args) { 4531 auto addr = Int::cast(args.get(0)).asCPtr(); 4532 double value = Float::cast(args.get(1)).value(); 4533 std::memcpy(reinterpret_cast<void*>(addr), &value, sizeof(value)); 4534 return NoneType::object(); 4535} 4536 4537RawObject FUNC(_builtins, _set_member_float)(Thread*, Arguments args) { 4538 auto addr = Int::cast(args.get(0)).asCPtr(); 4539 float value = Float::cast(args.get(1)).value(); 4540 std::memcpy(reinterpret_cast<void*>(addr), &value, sizeof(value)); 4541 return NoneType::object(); 4542} 4543 4544RawObject FUNC(_builtins, _set_member_integral)(Thread*, Arguments args) { 4545 void* addr = Int::cast(args.get(0)).asCPtr(); 4546 OptInt<long long> optint = RawInt::cast(args.get(1)).asInt<long long>(); 4547 CHECK(optint.error == CastError::None, "Overflow casting to primitive type"); 4548 long long value = optint.value; 4549 word num_bytes = RawInt::cast(args.get(2)).asWord(); 4550 static_assert(endian::native == endian::little, "expected little endian"); 4551 std::memcpy(reinterpret_cast<void*>(addr), &value, num_bytes); 4552 return NoneType::object(); 4553} 4554 4555RawObject FUNC(_builtins, _set_member_integral_unsigned)(Thread*, 4556 Arguments args) { 4557 void* addr = Int::cast(args.get(0)).asCPtr(); 4558 OptInt<unsigned long long> optint = 4559 RawInt::cast(args.get(1)).asInt<unsigned long long>(); 4560 CHECK(optint.error == CastError::None, "Overflow casting to primitive type"); 4561 unsigned long long value = optint.value; 4562 word num_bytes = RawInt::cast(args.get(2)).asWord(); 4563 static_assert(endian::native == endian::little, "expected little endian"); 4564 std::memcpy(reinterpret_cast<void*>(addr), &value, num_bytes); 4565 return NoneType::object(); 4566} 4567 4568RawObject FUNC(_builtins, _set_member_pyobject)(Thread* thread, 4569 Arguments args) { 4570 objectSetMember(thread->runtime(), args.get(0), args.get(1)); 4571 return NoneType::object(); 4572} 4573 4574RawObject FUNC(_builtins, _slice_check)(Thread*, Arguments args) { 4575 return Bool::fromBool(args.get(0).isSlice()); 4576} 4577 4578RawObject FUNC(_builtins, _slice_guard)(Thread* thread, Arguments args) { 4579 if (args.get(0).isSlice()) { 4580 return NoneType::object(); 4581 } 4582 return raiseRequiresFromCaller(thread, args, ID(slice)); 4583} 4584 4585RawObject FUNC(_builtins, _slice_start)(Thread*, Arguments args) { 4586 RawObject start_obj = args.get(0); 4587 word step = SmallInt::cast(args.get(1)).value(); 4588 word length = SmallInt::cast(args.get(2)).value(); 4589 if (start_obj.isNoneType()) { 4590 return SmallInt::fromWord(step < 0 ? length - 1 : 0); 4591 } 4592 4593 word lower, upper; 4594 if (step < 0) { 4595 lower = -1; 4596 upper = length - 1; 4597 } else { 4598 lower = 0; 4599 upper = length; 4600 } 4601 4602 word start = intUnderlying(start_obj).asWordSaturated(); 4603 if (start < 0) { 4604 start = Utils::maximum(start + length, lower); 4605 } else { 4606 start = Utils::minimum(start, upper); 4607 } 4608 return SmallInt::fromWord(start); 4609} 4610 4611RawObject FUNC(_builtins, _staticmethod)(Thread* thread, Arguments args) { 4612 HandleScope scope(thread); 4613 Object function(&scope, args.get(0)); 4614 4615 StaticMethod method(&scope, thread->runtime()->newStaticMethod()); 4616 method.setFunction(*function); 4617 return *method; 4618} 4619 4620RawObject FUNC(_builtins, _slice_start_long)(Thread* thread, Arguments args) { 4621 HandleScope scope(thread); 4622 Int step(&scope, intUnderlying(args.get(1))); 4623 Int length(&scope, intUnderlying(args.get(2))); 4624 bool negative_step = step.isNegative(); 4625 Int lower(&scope, SmallInt::fromWord(negative_step ? -1 : 0)); 4626 Runtime* runtime = thread->runtime(); 4627 // upper = length + lower; if step < 0, then lower = 0 anyway 4628 Int upper(&scope, 4629 negative_step ? runtime->intAdd(thread, length, lower) : *length); 4630 Object start_obj(&scope, args.get(0)); 4631 if (start_obj.isNoneType()) { 4632 return negative_step ? *upper : *lower; 4633 } 4634 Int start(&scope, intUnderlying(*start_obj)); 4635 if (start.isNegative()) { 4636 start = runtime->intAdd(thread, start, length); 4637 if (start.compare(*lower) < 0) { 4638 start = *lower; 4639 } 4640 } else if (start.compare(*upper) > 0) { 4641 start = *upper; 4642 } 4643 return *start; 4644} 4645 4646RawObject FUNC(_builtins, _slice_step)(Thread* thread, Arguments args) { 4647 RawObject step_obj = args.get(0); 4648 if (step_obj.isNoneType()) return SmallInt::fromWord(1); 4649 RawInt step = intUnderlying(step_obj); 4650 if (step == SmallInt::fromWord(0) || step == Bool::falseObj()) { 4651 return thread->raiseWithFmt(LayoutId::kValueError, 4652 "slice step cannot be zero"); 4653 } 4654 if (step.isSmallInt()) { 4655 return step; 4656 } 4657 if (step == Bool::trueObj()) { 4658 return SmallInt::fromWord(1); 4659 } 4660 return SmallInt::fromWord(step.isNegative() ? SmallInt::kMinValue 4661 : SmallInt::kMaxValue); 4662} 4663 4664RawObject FUNC(_builtins, _slice_step_long)(Thread* thread, Arguments args) { 4665 RawObject step_obj = args.get(0); 4666 if (step_obj.isNoneType()) return SmallInt::fromWord(1); 4667 RawInt step = intUnderlying(step_obj); 4668 if (step == SmallInt::fromWord(0) || step == Bool::falseObj()) { 4669 return thread->raiseWithFmt(LayoutId::kValueError, 4670 "slice step cannot be zero"); 4671 } 4672 if (step.isSmallInt()) { 4673 return step; 4674 } 4675 if (step == Bool::trueObj()) { 4676 return SmallInt::fromWord(1); 4677 } 4678 return step; 4679} 4680 4681RawObject FUNC(_builtins, _slice_stop)(Thread*, Arguments args) { 4682 RawObject stop_obj = args.get(0); 4683 word step = SmallInt::cast(args.get(1)).value(); 4684 word length = SmallInt::cast(args.get(2)).value(); 4685 if (stop_obj.isNoneType()) { 4686 return SmallInt::fromWord(step < 0 ? -1 : length); 4687 } 4688 4689 word lower, upper; 4690 if (step < 0) { 4691 lower = -1; 4692 upper = length - 1; 4693 } else { 4694 lower = 0; 4695 upper = length; 4696 } 4697 4698 word stop = intUnderlying(stop_obj).asWordSaturated(); 4699 if (stop < 0) { 4700 stop = Utils::maximum(stop + length, lower); 4701 } else { 4702 stop = Utils::minimum(stop, upper); 4703 } 4704 return SmallInt::fromWord(stop); 4705} 4706 4707RawObject FUNC(_builtins, _slice_stop_long)(Thread* thread, Arguments args) { 4708 HandleScope scope(thread); 4709 Int step(&scope, intUnderlying(args.get(1))); 4710 Int length(&scope, intUnderlying(args.get(2))); 4711 bool negative_step = step.isNegative(); 4712 Int lower(&scope, SmallInt::fromWord(negative_step ? -1 : 0)); 4713 Runtime* runtime = thread->runtime(); 4714 // upper = length + lower; if step < 0, then lower = 0 anyway 4715 Int upper(&scope, 4716 negative_step ? runtime->intAdd(thread, length, lower) : *length); 4717 Object stop_obj(&scope, args.get(0)); 4718 if (stop_obj.isNoneType()) { 4719 return negative_step ? *lower : *upper; 4720 } 4721 Int stop(&scope, intUnderlying(*stop_obj)); 4722 if (stop.isNegative()) { 4723 stop = runtime->intAdd(thread, stop, length); 4724 if (stop.compare(*lower) < 0) { 4725 stop = *lower; 4726 } 4727 } else if (stop.compare(*upper) > 0) { 4728 stop = *upper; 4729 } 4730 return *stop; 4731} 4732 4733RawObject FUNC(_builtins, _staticmethod_isabstract)(Thread* thread, 4734 Arguments args) { 4735 HandleScope scope(thread); 4736 Object self_obj(&scope, args.get(0)); 4737 if (!thread->runtime()->isInstanceOfStaticMethod(*self_obj)) { 4738 return thread->raiseRequiresType(self_obj, ID(staticmethod)); 4739 } 4740 StaticMethod self(&scope, *self_obj); 4741 Object func(&scope, self.function()); 4742 return isAbstract(thread, func); 4743} 4744 4745RawObject FUNC(_builtins, _stop_iteration_ctor)(Thread* thread, 4746 Arguments args) { 4747 HandleScope scope(thread); 4748 Runtime* runtime = thread->runtime(); 4749 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kStopIteration), 4750 "unexpected type; should be StopIteration"); 4751 Layout layout(&scope, runtime->layoutAt(LayoutId::kStopIteration)); 4752 StopIteration self(&scope, runtime->newInstance(layout)); 4753 Object args_obj(&scope, args.get(1)); 4754 self.setArgs(*args_obj); 4755 self.setCause(Unbound::object()); 4756 self.setContext(Unbound::object()); 4757 self.setTraceback(Unbound::object()); 4758 self.setSuppressContext(RawBool::falseObj()); 4759 Tuple tuple(&scope, self.args()); 4760 if (tuple.length() > 0) self.setValue(tuple.at(0)); 4761 return *self; 4762} 4763 4764RawObject FUNC(_builtins, _str_array_clear)(Thread* thread, Arguments args) { 4765 HandleScope scope(thread); 4766 StrArray self(&scope, args.get(0)); 4767 self.setNumItems(0); 4768 return NoneType::object(); 4769} 4770 4771RawObject FUNC(_builtins, _str_array_ctor)(Thread* thread, Arguments args) { 4772 HandleScope scope(thread); 4773 Runtime* runtime = thread->runtime(); 4774 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kStrArray), 4775 "_str_array.__new__(X): X is not '_str_array'"); 4776 Object self_obj(&scope, runtime->newStrArray()); 4777 if (self_obj.isError()) return *self_obj; 4778 StrArray self(&scope, *self_obj); 4779 self.setNumItems(0); 4780 Object source_obj(&scope, args.get(1)); 4781 if (source_obj.isUnbound()) { 4782 return *self; 4783 } 4784 if (!runtime->isInstanceOfStr(*source_obj)) { 4785 return thread->raiseWithFmt(LayoutId::kTypeError, 4786 "_str_array can only be initialized with str"); 4787 } 4788 Str source(&scope, strUnderlying(*source_obj)); 4789 runtime->strArrayAddStr(thread, self, source); 4790 return *self; 4791} 4792 4793RawObject FUNC(_builtins, _str_array_iadd)(Thread* thread, Arguments args) { 4794 HandleScope scope(thread); 4795 StrArray self(&scope, args.get(0)); 4796 Str other(&scope, strUnderlying(args.get(1))); 4797 thread->runtime()->strArrayAddStr(thread, self, other); 4798 return *self; 4799} 4800 4801RawObject FUNC(_builtins, _structseq_getitem)(Thread* thread, Arguments args) { 4802 HandleScope scope(thread); 4803 Object self(&scope, args.get(0)); 4804 word index = SmallInt::cast(args.get(1)).value(); 4805 return structseqGetItem(thread, self, index); 4806} 4807 4808RawObject FUNC(_builtins, _structseq_new_type)(Thread* thread, Arguments args) { 4809 HandleScope scope(thread); 4810 Runtime* runtime = thread->runtime(); 4811 Str name(&scope, strUnderlying(args.get(0))); 4812 name = Runtime::internStr(thread, name); 4813 Tuple field_names(&scope, args.get(1)); 4814 Bool is_heaptype(&scope, args.get(2)); 4815 word num_fields = field_names.length(); 4816 if (num_fields > 0) { 4817 MutableTuple field_names_interned(&scope, 4818 runtime->newMutableTuple(num_fields)); 4819 Object field_name(&scope, NoneType::object()); 4820 for (word i = 0; i < num_fields; i++) { 4821 field_name = field_names.at(i); 4822 if (!field_name.isNoneType()) { 4823 field_name = Runtime::internStr(thread, field_name); 4824 } 4825 field_names_interned.atPut(i, *field_name); 4826 } 4827 field_names = field_names_interned.becomeImmutable(); 4828 } 4829 word num_in_sequence = args.get(3).isUnbound() 4830 ? num_fields 4831 : SmallInt::cast(args.get(3)).value(); 4832 word flags = 4833 is_heaptype.value() ? Type::Flag::kIsCPythonHeaptype : Type::Flag::kNone; 4834 flags |= Type::Flag::kIsStructseq; 4835 return structseqNewType(thread, name, field_names, num_in_sequence, flags); 4836} 4837 4838RawObject FUNC(_builtins, _structseq_setitem)(Thread* thread, Arguments args) { 4839 HandleScope scope(thread); 4840 Object self(&scope, args.get(0)); 4841 word index = SmallInt::cast(args.get(1)).value(); 4842 Object value(&scope, args.get(2)); 4843 return structseqSetItem(thread, self, index, value); 4844} 4845 4846static RawObject padString(Thread* thread, const Str& str, 4847 const SmallStr& fillchar, word str_length, 4848 word left_padding, word fill_char_length, 4849 word result_length) { 4850 // Optimize to use SmallStr for results less than the small string max length 4851 if (result_length <= SmallStr::kMaxLength) { 4852 byte buffer[SmallStr::kMaxLength]; 4853 for (word i = 0; i < left_padding; i += fill_char_length) { 4854 fillchar.copyTo(&buffer[i], fill_char_length); 4855 } 4856 str.copyTo(&buffer[left_padding], str_length); 4857 for (word i = left_padding + str_length; i < result_length; 4858 i += fill_char_length) { 4859 fillchar.copyTo(&buffer[i], fill_char_length); 4860 } 4861 4862 return SmallStr::fromBytes({buffer, result_length}); 4863 } 4864 4865 HandleScope scope(thread); 4866 4867 MutableBytes buffer( 4868 &scope, thread->runtime()->newMutableBytesUninitialized(result_length)); 4869 4870 { 4871 // In order to improve performance for string operations we write directly 4872 // to the memory address of the buffer. This operation requires NO calls 4873 // which could potentially trigger allocations in order to ensure memory 4874 // consistency. 4875 byte* dst = reinterpret_cast<byte*>(buffer.address()); 4876 4877 for (word i = 0; i < left_padding; i += fill_char_length) { 4878 fillchar.copyTo(&dst[i], fill_char_length); 4879 } 4880 str.copyTo(&dst[left_padding], str_length); 4881 for (word i = left_padding + str_length; i < result_length; 4882 i += fill_char_length) { 4883 fillchar.copyTo(&dst[i], fill_char_length); 4884 } 4885 } 4886 4887 return buffer.becomeStr(); 4888} 4889RawObject FUNC(_builtins, _str_center)(Thread* thread, Arguments args) { 4890 HandleScope scope(thread); 4891 Runtime* runtime = thread->runtime(); 4892 Object self_obj(&scope, args.get(0)); 4893 if (!runtime->isInstanceOfStr(*self_obj)) { 4894 return thread->raiseRequiresType(self_obj, ID(str)); 4895 } 4896 4897 Object width_obj(&scope, args.get(1)); 4898 if (!runtime->isInstanceOfInt(*width_obj)) { 4899 return Unbound::object(); 4900 } 4901 Int width_int(&scope, intUnderlying(*width_obj)); 4902 if (width_int.isLargeInt()) { 4903 return thread->raiseWithFmt(LayoutId::kOverflowError, 4904 "int too large to convert to an index"); 4905 } 4906 word width = width_int.asWord(); 4907 4908 Object fillchar_obj(&scope, args.get(2)); 4909 if (!runtime->isInstanceOfStr(*fillchar_obj)) { 4910 return thread->raiseWithFmt( 4911 LayoutId::kTypeError, 4912 "The fill character must be a unicode character, not a '%T'", 4913 &fillchar_obj); 4914 } 4915 4916 Str fillchar_str(&scope, strUnderlying(*fillchar_obj)); 4917 if (!fillchar_str.isSmallStr() || fillchar_str.codePointLength() != 1) { 4918 return thread->raiseWithFmt( 4919 LayoutId::kTypeError, 4920 "The fill character must be exactly one character long"); 4921 } 4922 4923 SmallStr fillchar(&scope, *fillchar_str); 4924 4925 Str self(&scope, strUnderlying(*self_obj)); 4926 4927 word self_codepoints = self.codePointLength(); 4928 if (self_codepoints >= width) { 4929 return *self; 4930 } 4931 4932 word self_length = self.length(); 4933 word fill_char_length = fillchar.length(); 4934 word fill_char_count = width - self_codepoints; 4935 word fill_length = fill_char_length * fill_char_count; 4936 word result_length = self_length + fill_length; 4937 4938 word left_padding = fill_char_count / 2; 4939 4940 // When fill characters cannot be evenly distributed place the extra on the 4941 // left. 4942 if (fill_char_count % 2 != 0 && width % 2 != 0) { 4943 left_padding += 1; 4944 } 4945 left_padding *= fill_char_length; 4946 4947 return padString(thread, self, fillchar, self_length, left_padding, 4948 fill_char_length, result_length); 4949} 4950 4951RawObject FUNC(_builtins, _str_check)(Thread* thread, Arguments args) { 4952 return Bool::fromBool(thread->runtime()->isInstanceOfStr(args.get(0))); 4953} 4954 4955RawObject FUNC(_builtins, _str_encode)(Thread* thread, Arguments args) { 4956 HandleScope scope(thread); 4957 Object str_obj(&scope, args.get(0)); 4958 if (!str_obj.isStr()) { 4959 return Unbound::object(); 4960 } 4961 Str str(&scope, *str_obj); 4962 static RawSmallStr ascii = SmallStr::fromCStr("ascii"); 4963 static RawSmallStr utf8 = SmallStr::fromCStr("utf-8"); 4964 static RawSmallStr latin1 = SmallStr::fromCStr("latin-1"); 4965 Str enc(&scope, args.get(1)); 4966 if (enc != ascii && enc != utf8 && enc != latin1 && 4967 enc.compareCStr("iso-8859-1") != 0) { 4968 return Unbound::object(); 4969 } 4970 return strEncodeASCII(thread, str); 4971} 4972 4973RawObject FUNC(_builtins, _str_encode_ascii)(Thread* thread, Arguments args) { 4974 HandleScope scope(thread); 4975 Object str_obj(&scope, args.get(0)); 4976 if (!str_obj.isStr()) { 4977 return Unbound::object(); 4978 } 4979 Str str(&scope, *str_obj); 4980 return strEncodeASCII(thread, str); 4981} 4982 4983RawObject FUNC(_builtins, _str_check_exact)(Thread*, Arguments args) { 4984 return Bool::fromBool(args.get(0).isStr()); 4985} 4986 4987RawObject FUNC(_builtins, _str_compare_digest)(Thread* thread, Arguments args) { 4988 Runtime* runtime = thread->runtime(); 4989 HandleScope scope(thread); 4990 // TODO(T57794178): Use volatile 4991 Object left_obj(&scope, args.get(0)); 4992 Object right_obj(&scope, args.get(1)); 4993 DCHECK(runtime->isInstanceOfStr(*left_obj), 4994 "_str_compare_digest requires 'str' instance"); 4995 DCHECK(runtime->isInstanceOfStr(*right_obj), 4996 "_str_compare_digest requires 'str' instance"); 4997 Str left(&scope, strUnderlying(*left_obj)); 4998 Str right(&scope, strUnderlying(*right_obj)); 4999 if (!left.isASCII() || !right.isASCII()) { 5000 return thread->raiseWithFmt( 5001 LayoutId::kTypeError, 5002 "comparing strings with non-ASCII characters is not supported"); 5003 } 5004 word left_len = left.length(); 5005 word right_len = right.length(); 5006 word length = Utils::minimum(left_len, right_len); 5007 word result = (right_len == left_len) ? 0 : 1; 5008 for (word i = 0; i < length; i++) { 5009 result |= left.byteAt(i) ^ right.byteAt(i); 5010 } 5011 return Bool::fromBool(result == 0); 5012} 5013 5014RawObject FUNC(_builtins, _str_count)(Thread* thread, Arguments args) { 5015 Runtime* runtime = thread->runtime(); 5016 DCHECK(runtime->isInstanceOfStr(args.get(0)), 5017 "_str_count requires 'str' instance"); 5018 DCHECK(runtime->isInstanceOfStr(args.get(1)), 5019 "_str_count requires 'str' instance"); 5020 HandleScope scope(thread); 5021 Str haystack(&scope, strUnderlying(args.get(0))); 5022 Str needle(&scope, strUnderlying(args.get(1))); 5023 Object start_obj(&scope, args.get(2)); 5024 Object end_obj(&scope, args.get(3)); 5025 word start = 0; 5026 if (!start_obj.isNoneType()) { 5027 start = intUnderlying(*start_obj).asWordSaturated(); 5028 } 5029 word end = kMaxWord; 5030 if (!end_obj.isNoneType()) { 5031 end = intUnderlying(*end_obj).asWordSaturated(); 5032 } 5033 return strCount(haystack, needle, start, end); 5034} 5035 5036RawObject FUNC(_builtins, _str_ctor)(Thread* thread, Arguments args) { 5037 HandleScope scope(thread); 5038 Object cls(&scope, args.get(0)); 5039 Object obj(&scope, args.get(1)); 5040 Object encoding(&scope, args.get(2)); 5041 Object errors(&scope, args.get(3)); 5042 Runtime* runtime = thread->runtime(); 5043 DCHECK(*cls == runtime->typeAt(LayoutId::kStr), "unexpected cls"); 5044 if (obj.isUnbound()) { 5045 return Str::empty(); 5046 } 5047 if (encoding.isUnbound() && errors.isUnbound() && obj.isStr()) { 5048 return *obj; 5049 } 5050 Type str_type(&scope, runtime->typeAt(LayoutId::kStr)); 5051 Object dunder_new(&scope, runtime->symbols()->at(ID(__new__))); 5052 Function str_dunder_new(&scope, 5053 typeGetAttribute(thread, str_type, dunder_new)); 5054 // TODO(T76654356): Use Thread::invokeMethodStatic. 5055 return Interpreter::call4(thread, str_dunder_new, cls, obj, encoding, errors); 5056} 5057 5058RawObject FUNC(_builtins, _str_ctor_obj)(Thread* thread, Arguments args) { 5059 { 5060 // Warning: This code is using `RawXXX` variables for performance! This is 5061 // despite the fact that we call functions that do potentially perform 5062 // memory allocations. Be careful not to break this invariant if you change 5063 // the code! 5064 DCHECK(args.get(0) == thread->runtime()->typeAt(LayoutId::kStr), 5065 "expected cls==str"); 5066 RawObject obj_raw = args.get(1); 5067 if (obj_raw.isStr()) { 5068 return obj_raw; 5069 } 5070 } 5071 HandleScope scope(thread); 5072 Runtime* runtime = thread->runtime(); 5073 Type str_type(&scope, runtime->typeAt(LayoutId::kStr)); 5074 Object dunder_new(&scope, runtime->symbols()->at(ID(__new__))); 5075 Function str_dunder_new(&scope, 5076 typeGetAttribute(thread, str_type, dunder_new)); 5077 Object cls(&scope, args.get(0)); 5078 Object obj(&scope, args.get(1)); 5079 Object encoding(&scope, Unbound::object()); 5080 Object errors(&scope, Unbound::object()); 5081 // TODO(T76654356): Use Thread::invokeMethodStatic. 5082 return Interpreter::call4(thread, str_dunder_new, cls, obj, encoding, errors); 5083} 5084 5085RawObject FUNC(_builtins, _str_endswith)(Thread* thread, Arguments args) { 5086 HandleScope scope(thread); 5087 Object start_obj(&scope, args.get(2)); 5088 Object end_obj(&scope, args.get(3)); 5089 Str self(&scope, strUnderlying(args.get(0))); 5090 Str suffix(&scope, strUnderlying(args.get(1))); 5091 5092 word len = self.codePointLength(); 5093 word start = 0; 5094 word end = len; 5095 if (!start_obj.isNoneType()) { 5096 // TODO(T55084422): bounds checking 5097 start = intUnderlying(*start_obj).asWordSaturated(); 5098 } 5099 if (!end_obj.isNoneType()) { 5100 // TODO(T55084422): bounds checking 5101 end = intUnderlying(*end_obj).asWordSaturated(); 5102 } 5103 5104 Slice::adjustSearchIndices(&start, &end, len); 5105 word suffix_len = suffix.codePointLength(); 5106 if (start + suffix_len > end) { 5107 return Bool::falseObj(); 5108 } 5109 word start_offset = thread->strOffset(self, end - suffix_len); 5110 word suffix_chars = suffix.length(); 5111 for (word i = start_offset, j = 0; j < suffix_chars; i++, j++) { 5112 if (self.byteAt(i) != suffix.byteAt(j)) { 5113 return Bool::falseObj(); 5114 } 5115 } 5116 return Bool::trueObj(); 5117} 5118 5119RawObject FUNC(_builtins, _str_escape_non_ascii)(Thread* thread, 5120 Arguments args) { 5121 HandleScope scope(thread); 5122 CHECK(thread->runtime()->isInstanceOfStr(args.get(0)), 5123 "_str_escape_non_ascii expected str instance"); 5124 Str obj(&scope, strUnderlying(args.get(0))); 5125 return strEscapeNonASCII(thread, obj); 5126} 5127 5128RawObject FUNC(_builtins, _str_find)(Thread* thread, Arguments args) { 5129 Runtime* runtime = thread->runtime(); 5130 DCHECK(runtime->isInstanceOfStr(args.get(0)), 5131 "_str_find requires 'str' instance"); 5132 DCHECK(runtime->isInstanceOfStr(args.get(1)), 5133 "_str_find requires 'str' instance"); 5134 HandleScope scope(thread); 5135 Str haystack(&scope, strUnderlying(args.get(0))); 5136 Str needle(&scope, strUnderlying(args.get(1))); 5137 Object start_obj(&scope, args.get(2)); 5138 Object end_obj(&scope, args.get(3)); 5139 if ((start_obj.isNoneType() || start_obj == SmallInt::fromWord(0)) && 5140 end_obj.isNoneType()) { 5141 return SmallInt::fromWord(strFind(haystack, needle)); 5142 } 5143 word start = 0; 5144 if (!start_obj.isNoneType()) { 5145 start = intUnderlying(*start_obj).asWordSaturated(); 5146 } 5147 word end = kMaxWord; 5148 if (!end_obj.isNoneType()) { 5149 end = intUnderlying(*end_obj).asWordSaturated(); 5150 } 5151 word result = strFindWithRange(haystack, needle, start, end); 5152 return SmallInt::fromWord(result); 5153} 5154 5155RawObject FUNC(_builtins, _str_from_str)(Thread* thread, Arguments args) { 5156 HandleScope scope(thread); 5157 Type type(&scope, args.get(0)); 5158 DCHECK(type.builtinBase() == LayoutId::kStr, "type must subclass str"); 5159 Str value(&scope, strUnderlying(args.get(1))); 5160 if (type.isBuiltin()) return *value; 5161 Layout type_layout(&scope, type.instanceLayout()); 5162 UserStrBase instance(&scope, thread->runtime()->newInstance(type_layout)); 5163 instance.setValue(*value); 5164 return *instance; 5165} 5166 5167RawObject FUNC(_builtins, _str_getitem)(Thread* thread, Arguments args) { 5168 HandleScope scope(thread); 5169 Runtime* runtime = thread->runtime(); 5170 Object self_obj(&scope, args.get(0)); 5171 if (!runtime->isInstanceOfStr(*self_obj)) { 5172 return raiseRequiresFromCaller(thread, args, ID(str)); 5173 } 5174 Object key(&scope, args.get(1)); 5175 if (runtime->isInstanceOfInt(*key)) { 5176 Str self(&scope, strUnderlying(*self_obj)); 5177 word index = intUnderlying(*key).asWordSaturated(); 5178 if (!SmallInt::isValid(index)) { 5179 return thread->raiseWithFmt(LayoutId::kIndexError, 5180 "cannot fit '%T' into an index-sized integer", 5181 &key); 5182 } 5183 if (index < 0) { 5184 index += self.codePointLength(); 5185 } 5186 if (index >= 0) { 5187 word offset = thread->strOffset(self, index); 5188 if (offset < self.length()) { 5189 word ignored; 5190 return SmallStr::fromCodePoint(self.codePointAt(offset, &ignored)); 5191 } 5192 } 5193 return thread->raiseWithFmt(LayoutId::kIndexError, 5194 "string index out of range"); 5195 } 5196 5197 word start, stop; 5198 if (!tryUnpackSlice(key, &start, &stop)) { 5199 return Unbound::object(); 5200 } 5201 5202 // Manually adjust slice bounds to avoid an extra call to codePointLength 5203 Str self(&scope, strUnderlying(*self_obj)); 5204 word start_index = adjustedStrIndex(self, start); 5205 word stop_index = adjustedStrIndex(self, stop); 5206 word length = stop_index - start_index; 5207 if (length <= 0) return Str::empty(); 5208 return strSubstr(thread, self, start_index, length); 5209} 5210 5211RawObject FUNC(_builtins, _str_getslice)(Thread* thread, Arguments args) { 5212 HandleScope scope(thread); 5213 Str self(&scope, strUnderlying(args.get(0))); 5214 word start = SmallInt::cast(args.get(1)).value(); 5215 word stop = SmallInt::cast(args.get(2)).value(); 5216 word step = SmallInt::cast(args.get(3)).value(); 5217 return thread->runtime()->strSlice(thread, self, start, stop, step); 5218} 5219 5220RawObject FUNC(_builtins, _str_guard)(Thread* thread, Arguments args) { 5221 if (thread->runtime()->isInstanceOfStr(args.get(0))) { 5222 return NoneType::object(); 5223 } 5224 return raiseRequiresFromCaller(thread, args, ID(str)); 5225} 5226 5227RawObject FUNC(_builtins, _str_ischr)(Thread*, Arguments args) { 5228 RawStr str = strUnderlying(args.get(0)); 5229 return Bool::fromBool(str.isSmallStr() && str.codePointLength() == 1); 5230} 5231 5232RawObject FUNC(_builtins, _str_join)(Thread* thread, Arguments args) { 5233 Runtime* runtime = thread->runtime(); 5234 HandleScope scope(thread); 5235 Object sep_obj(&scope, args.get(0)); 5236 if (!runtime->isInstanceOfStr(*sep_obj)) { 5237 return raiseRequiresFromCaller(thread, args, ID(str)); 5238 } 5239 Str sep(&scope, strUnderlying(*sep_obj)); 5240 Object iterable(&scope, args.get(1)); 5241 return strJoinWithTupleOrList(thread, sep, iterable); 5242} 5243 5244RawObject FUNC(_builtins, _str_len)(Thread* thread, Arguments args) { 5245 HandleScope scope(thread); 5246 Str self(&scope, strUnderlying(args.get(0))); 5247 return SmallInt::fromWord(self.codePointLength()); 5248} 5249 5250RawObject FUNC(_builtins, _str_ljust)(Thread* thread, Arguments args) { 5251 HandleScope scope(thread); 5252 Runtime* runtime = thread->runtime(); 5253 Object self_obj(&scope, args.get(0)); 5254 if (!runtime->isInstanceOfStr(*self_obj)) { 5255 return thread->raiseRequiresType(self_obj, ID(str)); 5256 } 5257 5258 Object width_obj(&scope, args.get(1)); 5259 if (!runtime->isInstanceOfInt(*width_obj)) { 5260 return Unbound::object(); 5261 } 5262 5263 Int width_int(&scope, intUnderlying(*width_obj)); 5264 if (width_int.isLargeInt()) { 5265 return thread->raiseWithFmt(LayoutId::kOverflowError, 5266 "int too large to convert to an index"); 5267 } 5268 word width = width_int.asWord(); 5269 5270 Object fillchar_obj(&scope, args.get(2)); 5271 if (!runtime->isInstanceOfStr(*fillchar_obj)) { 5272 return thread->raiseWithFmt( 5273 LayoutId::kTypeError, 5274 "The fill character must be a unicode character, not a '%T'", 5275 &fillchar_obj); 5276 } 5277 5278 Str fillchar_str(&scope, strUnderlying(*fillchar_obj)); 5279 if (!fillchar_str.isSmallStr() || fillchar_str.codePointLength() != 1) { 5280 return thread->raiseWithFmt( 5281 LayoutId::kTypeError, 5282 "The fill character must be exactly one character long"); 5283 } 5284 5285 SmallStr fillchar(&scope, *fillchar_str); 5286 5287 Str self(&scope, strUnderlying(*self_obj)); 5288 5289 word self_codepoints = self.codePointLength(); 5290 if (self_codepoints >= width) { 5291 return *self; 5292 } 5293 5294 word self_length = self.length(); 5295 word fill_char_length = fillchar.length(); 5296 word fill_char_count = width - self_codepoints; 5297 word fill_length = fill_char_length * fill_char_count; 5298 word result_length = self_length + fill_length; 5299 5300 word left_padding = 0; 5301 return padString(thread, self, fillchar, self_length, left_padding, 5302 fill_char_length, result_length); 5303} 5304RawObject FUNC(_builtins, _str_mod_fast_path)(Thread* thread, Arguments args) { 5305 Runtime* runtime = thread->runtime(); 5306 if (!runtime->isInstanceOfStr(args.get(0)) || 5307 !runtime->isInstanceOfTuple(args.get(1))) { 5308 return Unbound::object(); 5309 } 5310 HandleScope scope(thread); 5311 Str str(&scope, strUnderlying(args.get(0))); 5312 Tuple args_tuple(&scope, tupleUnderlying(args.get(1))); 5313 const word max_args = 16; 5314 word num_args = args_tuple.length(); 5315 if (num_args > max_args) { 5316 return Unbound::object(); 5317 } 5318 5319 // Scan format string for occurences of %s and remember their indexes. Also 5320 // check that the corresponding arguments are strings. 5321 word arg_indexes[max_args]; 5322 word arg_idx = 0; 5323 word result_length = 0; 5324 Object arg(&scope, Unbound::object()); 5325 word fmt_length = str.length(); 5326 for (word i = 0; i < fmt_length; i++) { 5327 if (str.byteAt(i) != '%') { 5328 result_length++; 5329 continue; 5330 } 5331 i++; 5332 if (i >= fmt_length || str.byteAt(i) != 's' || arg_idx >= num_args) { 5333 return Unbound::object(); 5334 } 5335 arg = args_tuple.at(arg_idx); 5336 if (!arg.isStr()) { 5337 return Unbound::object(); 5338 } 5339 result_length += Str::cast(*arg).length(); 5340 arg_indexes[arg_idx] = i - 1; 5341 arg_idx++; 5342 } 5343 if (arg_idx < num_args) { 5344 return Unbound::object(); 5345 } 5346 5347 // Construct resulting string. 5348 if (arg_idx == 0) { 5349 return *str; 5350 } 5351 MutableBytes result(&scope, 5352 runtime->newMutableBytesUninitialized(result_length)); 5353 word result_idx = 0; 5354 word fmt_idx = 0; 5355 Str arg_str(&scope, Str::empty()); 5356 for (word a = 0; a < num_args; a++) { 5357 word fragment_begin = fmt_idx; 5358 word fragment_length = arg_indexes[a] - fragment_begin; 5359 result.replaceFromWithStrStartAt(result_idx, *str, fragment_length, 5360 fragment_begin); 5361 result_idx += fragment_length; 5362 fmt_idx += fragment_length + 2; 5363 5364 arg_str = args_tuple.at(a); 5365 word arg_length = arg_str.length(); 5366 result.replaceFromWithStr(result_idx, *arg_str, arg_length); 5367 result_idx += arg_length; 5368 } 5369 word fragment_begin = fmt_idx; 5370 word fragment_length = fmt_length - fmt_idx; 5371 result.replaceFromWithStrStartAt(result_idx, *str, fragment_length, 5372 fragment_begin); 5373 return result.becomeStr(); 5374} 5375 5376static word strScan(const Str& haystack, word haystack_len, const Str& needle, 5377 word needle_len, 5378 word (*find_func)(const byte* haystack, word haystack_len, 5379 const byte* needle, word needle_len)) { 5380 byte haystack_buf[SmallStr::kMaxLength]; 5381 byte* haystack_ptr = haystack_buf; 5382 if (haystack.isSmallStr()) { 5383 haystack.copyTo(haystack_buf, haystack_len); 5384 } else { 5385 haystack_ptr = reinterpret_cast<byte*>(LargeStr::cast(*haystack).address()); 5386 } 5387 byte needle_buf[SmallStr::kMaxLength]; 5388 byte* needle_ptr = needle_buf; 5389 if (needle.isSmallStr()) { 5390 needle.copyTo(needle_buf, needle_len); 5391 } else { 5392 needle_ptr = reinterpret_cast<byte*>(LargeStr::cast(*needle).address()); 5393 } 5394 return (*find_func)(haystack_ptr, haystack_len, needle_ptr, needle_len); 5395} 5396 5397// Look for needle in haystack, starting from the left. Return a tuple 5398// containing: 5399// * haystack up to but not including needle 5400// * needle 5401// * haystack after and not including needle 5402// If needle is not found in haystack, return (haystack, "", "") 5403RawObject FUNC(_builtins, _str_partition)(Thread* thread, Arguments args) { 5404 HandleScope scope(thread); 5405 Str haystack(&scope, strUnderlying(args.get(0))); 5406 Str needle(&scope, strUnderlying(args.get(1))); 5407 Runtime* runtime = thread->runtime(); 5408 MutableTuple result(&scope, runtime->newMutableTuple(3)); 5409 result.atPut(0, *haystack); 5410 result.atPut(1, Str::empty()); 5411 result.atPut(2, Str::empty()); 5412 word haystack_len = haystack.length(); 5413 word needle_len = needle.length(); 5414 if (haystack_len < needle_len) { 5415 // Fast path when needle is bigger than haystack 5416 return result.becomeImmutable(); 5417 } 5418 word prefix_len = 5419 strScan(haystack, haystack_len, needle, needle_len, Utils::memoryFind); 5420 if (prefix_len < 0) return result.becomeImmutable(); 5421 result.atPut(0, strSubstr(thread, haystack, 0, prefix_len)); 5422 result.atPut(1, *needle); 5423 word suffix_start = prefix_len + needle_len; 5424 word suffix_len = haystack_len - suffix_start; 5425 result.atPut(2, strSubstr(thread, haystack, suffix_start, suffix_len)); 5426 return result.becomeImmutable(); 5427} 5428 5429RawObject FUNC(_builtins, _str_replace)(Thread* thread, Arguments args) { 5430 Runtime* runtime = thread->runtime(); 5431 HandleScope scope(thread); 5432 Str self(&scope, strUnderlying(args.get(0))); 5433 Str oldstr(&scope, strUnderlying(args.get(1))); 5434 Str newstr(&scope, strUnderlying(args.get(2))); 5435 word count = intUnderlying(args.get(3)).asWordSaturated(); 5436 return runtime->strReplace(thread, self, oldstr, newstr, count); 5437} 5438 5439RawObject FUNC(_builtins, _str_rfind)(Thread* thread, Arguments args) { 5440 Runtime* runtime = thread->runtime(); 5441 DCHECK(runtime->isInstanceOfStr(args.get(0)), 5442 "_str_rfind requires 'str' instance"); 5443 DCHECK(runtime->isInstanceOfStr(args.get(1)), 5444 "_str_rfind requires 'str' instance"); 5445 HandleScope scope(thread); 5446 Str haystack(&scope, strUnderlying(args.get(0))); 5447 Str needle(&scope, strUnderlying(args.get(1))); 5448 Object start_obj(&scope, args.get(2)); 5449 Object end_obj(&scope, args.get(3)); 5450 word start = 0; 5451 if (!start_obj.isNoneType()) { 5452 start = intUnderlying(*start_obj).asWordSaturated(); 5453 } 5454 word end = kMaxWord; 5455 if (!end_obj.isNoneType()) { 5456 end = intUnderlying(*end_obj).asWordSaturated(); 5457 } 5458 Slice::adjustSearchIndices(&start, &end, haystack.codePointLength()); 5459 word result = strRFind(haystack, needle, start, end); 5460 return SmallInt::fromWord(result); 5461} 5462 5463RawObject FUNC(_builtins, _str_rjust)(Thread* thread, Arguments args) { 5464 HandleScope scope(thread); 5465 Runtime* runtime = thread->runtime(); 5466 Object self_obj(&scope, args.get(0)); 5467 if (!runtime->isInstanceOfStr(*self_obj)) { 5468 return thread->raiseRequiresType(self_obj, ID(str)); 5469 } 5470 5471 Object width_obj(&scope, args.get(1)); 5472 if (!runtime->isInstanceOfInt(*width_obj)) { 5473 return Unbound::object(); 5474 } 5475 Int width_int(&scope, intUnderlying(*width_obj)); 5476 if (width_int.isLargeInt()) { 5477 return thread->raiseWithFmt(LayoutId::kOverflowError, 5478 "int too large to convert to an index"); 5479 } 5480 word width = width_int.asWord(); 5481 5482 Object fillchar_obj(&scope, args.get(2)); 5483 if (!runtime->isInstanceOfStr(*fillchar_obj)) { 5484 return thread->raiseWithFmt( 5485 LayoutId::kTypeError, 5486 "The fill character must be a unicode character, not a '%T'", 5487 &fillchar_obj); 5488 } 5489 5490 Str fillchar_str(&scope, strUnderlying(*fillchar_obj)); 5491 if (!fillchar_str.isSmallStr() || fillchar_str.codePointLength() != 1) { 5492 return thread->raiseWithFmt( 5493 LayoutId::kTypeError, 5494 "The fill character must be exactly one character long"); 5495 } 5496 5497 SmallStr fillchar(&scope, *fillchar_str); 5498 5499 Str self(&scope, strUnderlying(*self_obj)); 5500 5501 word self_codepoints = self.codePointLength(); 5502 if (self_codepoints >= width) { 5503 return *self; 5504 } 5505 5506 word self_length = self.length(); 5507 word fill_char_length = fillchar.length(); 5508 word fill_char_count = width - self_codepoints; 5509 word fill_length = fill_char_length * fill_char_count; 5510 word result_length = self_length + fill_length; 5511 5512 word left_padding = fill_length; 5513 return padString(thread, self, fillchar, self_length, left_padding, 5514 fill_char_length, result_length); 5515} 5516 5517// Look for needle in haystack, starting from the right. Return a tuple 5518// containing: 5519// * haystack up to but not including needle 5520// * needle 5521// * haystack after and not including needle 5522// If needle is not found in haystack, return ("", "", haystack) 5523RawObject FUNC(_builtins, _str_rpartition)(Thread* thread, Arguments args) { 5524 HandleScope scope(thread); 5525 Runtime* runtime = thread->runtime(); 5526 Str haystack(&scope, strUnderlying(args.get(0))); 5527 Str needle(&scope, strUnderlying(args.get(1))); 5528 MutableTuple result(&scope, runtime->newMutableTuple(3)); 5529 result.atPut(0, Str::empty()); 5530 result.atPut(1, Str::empty()); 5531 result.atPut(2, *haystack); 5532 word haystack_len = haystack.length(); 5533 word needle_len = needle.length(); 5534 if (haystack_len < needle_len) { 5535 // Fast path when needle is bigger than haystack 5536 return result.becomeImmutable(); 5537 } 5538 word prefix_len = strScan(haystack, haystack_len, needle, needle_len, 5539 Utils::memoryFindReverse); 5540 if (prefix_len < 0) return result.becomeImmutable(); 5541 result.atPut(0, strSubstr(thread, haystack, 0, prefix_len)); 5542 result.atPut(1, *needle); 5543 word suffix_start = prefix_len + needle_len; 5544 word suffix_len = haystack_len - suffix_start; 5545 result.atPut(2, strSubstr(thread, haystack, suffix_start, suffix_len)); 5546 return result.becomeImmutable(); 5547} 5548 5549static RawObject strSplitWhitespace(Thread* thread, const Str& self, 5550 word maxsplit) { 5551 HandleScope scope(thread); 5552 Runtime* runtime = thread->runtime(); 5553 List result(&scope, runtime->newList()); 5554 if (maxsplit < 0) { 5555 maxsplit = kMaxWord; 5556 } 5557 word self_length = self.length(); 5558 word num_split = 0; 5559 Str substr(&scope, Str::empty()); 5560 for (word i = 0, j = 0; j < self_length; i = self.offsetByCodePoints(j, 1)) { 5561 // Find beginning of next word 5562 { 5563 word num_bytes; 5564 while (i < self_length && 5565 Unicode::isSpace(self.codePointAt(i, &num_bytes))) { 5566 i += num_bytes; 5567 } 5568 } 5569 if (i == self_length) { 5570 // End of string; finished 5571 break; 5572 } 5573 5574 // Find end of next word 5575 if (maxsplit == num_split) { 5576 // Take the rest of the string 5577 j = self_length; 5578 } else { 5579 j = self.offsetByCodePoints(i, 1); 5580 { 5581 word num_bytes; 5582 while (j < self_length && 5583 !Unicode::isSpace(self.codePointAt(j, &num_bytes))) { 5584 j += num_bytes; 5585 } 5586 } 5587 num_split += 1; 5588 } 5589 substr = strSubstr(thread, self, i, j - i); 5590 runtime->listAdd(thread, result, substr); 5591 } 5592 return *result; 5593} 5594 5595RawObject FUNC(_builtins, _str_split)(Thread* thread, Arguments args) { 5596 HandleScope scope(thread); 5597 Str self(&scope, strUnderlying(args.get(0))); 5598 Object sep_obj(&scope, args.get(1)); 5599 word maxsplit = intUnderlying(args.get(2)).asWordSaturated(); 5600 if (sep_obj.isNoneType()) { 5601 return strSplitWhitespace(thread, self, maxsplit); 5602 } 5603 Str sep(&scope, strUnderlying(*sep_obj)); 5604 if (sep.length() == 0) { 5605 return thread->raiseWithFmt(LayoutId::kValueError, "empty separator"); 5606 } 5607 if (maxsplit < 0) { 5608 maxsplit = kMaxWord; 5609 } 5610 return strSplit(thread, self, sep, maxsplit); 5611} 5612 5613RawObject FUNC(_builtins, _str_splitlines)(Thread* thread, Arguments args) { 5614 Runtime* runtime = thread->runtime(); 5615 DCHECK(runtime->isInstanceOfStr(args.get(0)), 5616 "_str_splitlines requires 'str' instance"); 5617 DCHECK(runtime->isInstanceOfInt(args.get(1)), 5618 "_str_splitlines requires 'int' instance"); 5619 HandleScope scope(thread); 5620 Str self(&scope, args.get(0)); 5621 bool keepends = !intUnderlying(args.get(1)).isZero(); 5622 return strSplitlines(thread, self, keepends); 5623} 5624 5625RawObject FUNC(_builtins, _str_startswith)(Thread* thread, Arguments args) { 5626 HandleScope scope(thread); 5627 Object start_obj(&scope, args.get(2)); 5628 Object end_obj(&scope, args.get(3)); 5629 Str self(&scope, strUnderlying(args.get(0))); 5630 Str prefix(&scope, strUnderlying(args.get(1))); 5631 5632 word len = self.codePointLength(); 5633 word start = 0; 5634 word end = len; 5635 if (!start_obj.isNoneType()) { 5636 // TODO(T55084422): bounds checking 5637 start = intUnderlying(*start_obj).asWordSaturated(); 5638 } 5639 if (!end_obj.isNoneType()) { 5640 // TODO(T55084422): bounds checking 5641 end = intUnderlying(*end_obj).asWordSaturated(); 5642 } 5643 5644 Slice::adjustSearchIndices(&start, &end, len); 5645 if (start + prefix.codePointLength() > end) { 5646 return Bool::falseObj(); 5647 } 5648 word start_offset = thread->strOffset(self, start); 5649 word prefix_chars = prefix.length(); 5650 for (word i = start_offset, j = 0; j < prefix_chars; i++, j++) { 5651 if (self.byteAt(i) != prefix.byteAt(j)) { 5652 return Bool::falseObj(); 5653 } 5654 } 5655 return Bool::trueObj(); 5656} 5657 5658RawObject FUNC(_builtins, _str_translate)(Thread* thread, Arguments args) { 5659 HandleScope scope(thread); 5660 Runtime* runtime = thread->runtime(); 5661 Object self_obj(&scope, strUnderlying(args.get(0))); 5662 if (!runtime->isInstanceOfStr(*self_obj)) { 5663 return raiseRequiresFromCaller(thread, args, ID(str)); 5664 } 5665 Str self(&scope, *self_obj); 5666 Object table_obj(&scope, args.get(1)); 5667 if (!runtime->isInstanceOfStr(*table_obj)) { 5668 return Unbound::object(); 5669 } 5670 Str table(&scope, strUnderlying(*table_obj)); 5671 return strTranslateASCII(thread, self, table); 5672} 5673 5674RawObject FUNC(_builtins, _super)(Thread* thread, Arguments args) { 5675 HandleScope scope(thread); 5676 Object cls(&scope, args.get(0)); 5677 Super result(&scope, thread->runtime()->newSuper()); 5678 result.setType(*cls); 5679 result.setObject(*cls); 5680 result.setObjectType(*cls); 5681 return *result; 5682} 5683 5684RawObject FUNC(_builtins, _super_ctor)(Thread* thread, Arguments args) { 5685 HandleScope scope(thread); 5686 Runtime* runtime = thread->runtime(); 5687 DCHECK(args.get(0) == runtime->typeAt(LayoutId::kSuper), 5688 "super.__new__(X): X is not 'super'"); 5689 Super self(&scope, runtime->newSuper()); 5690 Object type(&scope, args.get(1)); 5691 Object type_or_obj(&scope, args.get(2)); 5692 Frame* frame = thread->currentFrame(); 5693 // frame is for _super_ctor, previous frame is caller of super() 5694 DCHECK(!frame->isSentinel(), "_super_ctor must have a frame"); 5695 return superInit(thread, self, type, type_or_obj, frame->previousFrame()); 5696} 5697 5698RawObject FUNC(_builtins, _traceback_frame_get)(Thread* thread, 5699 Arguments args) { 5700 Runtime* runtime = thread->runtime(); 5701 HandleScope scope(thread); 5702 Object self_obj(&scope, args.get(0)); 5703 if (!self_obj.isTraceback()) { 5704 return raiseRequiresFromCaller(thread, args, ID(traceback)); 5705 } 5706 Traceback self(&scope, *self_obj); 5707 Object function(&scope, self.function()); 5708 Object lasti(&scope, self.lasti()); 5709 FrameProxy new_frame(&scope, runtime->newFrameProxy(thread, function, lasti)); 5710 // TODO(T91250285): Figure out a way to initialize the frame's locals dict 5711 new_frame.setLocals(runtime->newDict()); 5712 return *new_frame; 5713} 5714 5715RawObject FUNC(_builtins, _traceback_lineno_get)(Thread* thread, 5716 Arguments args) { 5717 HandleScope scope(thread); 5718 Object self_obj(&scope, args.get(0)); 5719 if (!self_obj.isTraceback()) { 5720 return raiseRequiresFromCaller(thread, args, ID(traceback)); 5721 } 5722 Traceback self(&scope, *self_obj); 5723 Object lineno(&scope, self.lineno()); 5724 if (!lineno.isNoneType()) { 5725 return *lineno; 5726 } 5727 5728 Function function(&scope, self.function()); 5729 Object code_obj(&scope, function.code()); 5730 if (code_obj.isCode()) { 5731 Code code(&scope, *code_obj); 5732 if (!code.isNative() && code.lnotab().isBytes()) { 5733 word lasti = SmallInt::cast(self.lasti()).value(); 5734 lineno = SmallInt::fromWord(code.offsetToLineNum(lasti)); 5735 self.setLineno(*lineno); 5736 } 5737 } 5738 return *lineno; 5739} 5740 5741RawObject FUNC(_builtins, _traceback_next_get)(Thread* thread, Arguments args) { 5742 HandleScope scope(thread); 5743 Object self_obj(&scope, args.get(0)); 5744 if (!self_obj.isTraceback()) { 5745 return raiseRequiresFromCaller(thread, args, ID(traceback)); 5746 } 5747 Traceback self(&scope, *self_obj); 5748 return self.next(); 5749} 5750 5751RawObject FUNC(_builtins, _traceback_next_set)(Thread* thread, Arguments args) { 5752 HandleScope scope(thread); 5753 Object self_obj(&scope, args.get(0)); 5754 if (!self_obj.isTraceback()) { 5755 return raiseRequiresFromCaller(thread, args, ID(traceback)); 5756 } 5757 Traceback self(&scope, *self_obj); 5758 Object next(&scope, args.get(1)); 5759 if (next.isNoneType()) { 5760 self.setNext(NoneType::object()); 5761 return NoneType::object(); 5762 } 5763 if (!next.isTraceback()) { 5764 return thread->raiseWithFmt(LayoutId::kTypeError, 5765 "expected traceback object, got '%T", &next); 5766 } 5767 5768 Object cursor(&scope, *next); 5769 while (cursor.isTraceback()) { 5770 if (cursor == self) { 5771 return thread->raiseWithFmt(LayoutId::kValueError, 5772 "traceback loop detected"); 5773 } 5774 cursor = Traceback::cast(*cursor).next(); 5775 } 5776 DCHECK(cursor.isNoneType(), "tb_next should be a traceback or None"); 5777 self.setNext(*next); 5778 return NoneType::object(); 5779} 5780 5781RawObject FUNC(_builtins, _tuple_check)(Thread* thread, Arguments args) { 5782 return Bool::fromBool(thread->runtime()->isInstanceOfTuple(args.get(0))); 5783} 5784 5785RawObject FUNC(_builtins, _tuple_check_exact)(Thread*, Arguments args) { 5786 return Bool::fromBool(args.get(0).isTuple()); 5787} 5788 5789RawObject FUNC(_builtins, _tuple_getitem)(Thread* thread, Arguments args) { 5790 HandleScope scope(thread); 5791 Object self_obj(&scope, args.get(0)); 5792 Runtime* runtime = thread->runtime(); 5793 if (!runtime->isInstanceOfTuple(*self_obj)) { 5794 return raiseRequiresFromCaller(thread, args, ID(tuple)); 5795 } 5796 Object key(&scope, args.get(1)); 5797 if (runtime->isInstanceOfInt(*key)) { 5798 word index = intUnderlying(*key).asWordSaturated(); 5799 if (!SmallInt::isValid(index)) { 5800 return thread->raiseWithFmt(LayoutId::kIndexError, 5801 "cannot fit '%T' into an index-sized integer", 5802 &key); 5803 } 5804 Tuple self(&scope, tupleUnderlying(*self_obj)); 5805 word length = self.length(); 5806 if (index < 0) { 5807 index += length; 5808 } 5809 if (index < 0 || index >= length) { 5810 return thread->raiseWithFmt(LayoutId::kIndexError, 5811 "tuple index out of range"); 5812 } 5813 return self.at(index); 5814 } 5815 5816 word start, stop; 5817 if (!tryUnpackSlice(key, &start, &stop)) { 5818 return Unbound::object(); 5819 } 5820 5821 Tuple self(&scope, tupleUnderlying(*self_obj)); 5822 word length = self.length(); 5823 word result_len = Slice::adjustIndices(length, &start, &stop, 1); 5824 if (result_len == length) { 5825 return *self; 5826 } 5827 return runtime->tupleSubseq(thread, self, start, result_len); 5828} 5829 5830RawObject FUNC(_builtins, _tuple_getslice)(Thread* thread, Arguments args) { 5831 HandleScope scope(thread); 5832 Tuple self(&scope, tupleUnderlying(args.get(0))); 5833 word start = SmallInt::cast(args.get(1)).value(); 5834 word stop = SmallInt::cast(args.get(2)).value(); 5835 word step = SmallInt::cast(args.get(3)).value(); 5836 return tupleSlice(thread, self, start, stop, step); 5837} 5838 5839RawObject FUNC(_builtins, _tuple_guard)(Thread* thread, Arguments args) { 5840 if (thread->runtime()->isInstanceOfTuple(args.get(0))) { 5841 return NoneType::object(); 5842 } 5843 return raiseRequiresFromCaller(thread, args, ID(tuple)); 5844} 5845 5846RawObject FUNC(_builtins, _tuple_len)(Thread*, Arguments args) { 5847 return SmallInt::fromWord(tupleUnderlying(args.get(0)).length()); 5848} 5849 5850RawObject FUNC(_builtins, _tuple_new)(Thread* thread, Arguments args) { 5851 HandleScope scope(thread); 5852 Type type(&scope, args.get(0)); 5853 Runtime* runtime = thread->runtime(); 5854 DCHECK(type != runtime->typeAt(LayoutId::kTuple), "cls must not be tuple"); 5855 DCHECK(args.get(1).isTuple(), "old_tuple must be exact tuple"); 5856 Layout layout(&scope, type.instanceLayout()); 5857 UserTupleBase instance(&scope, runtime->newInstance(layout)); 5858 instance.setValue(args.get(1)); 5859 return *instance; 5860} 5861 5862RawObject FUNC(_builtins, _type)(Thread* thread, Arguments args) { 5863 return thread->runtime()->typeOf(args.get(0)); 5864} 5865 5866RawObject FUNC(_builtins, _type_ctor)(Thread* thread, Arguments args) { 5867 DCHECK(args.get(0) == thread->runtime()->typeAt(LayoutId::kType), 5868 "expected cls==type"); 5869 return thread->runtime()->typeOf(args.get(1)); 5870} 5871 5872RawObject FUNC(_builtins, _type_abstractmethods_del)(Thread* thread, 5873 Arguments args) { 5874 HandleScope scope(thread); 5875 Object self_obj(&scope, args.get(0)); 5876 if (!thread->runtime()->isInstanceOfType(*self_obj)) { 5877 return thread->raiseRequiresType(self_obj, ID(type)); 5878 } 5879 Type type(&scope, *self_obj); 5880 if (type.abstractMethods().isUnbound()) { 5881 Object name(&scope, 5882 thread->runtime()->symbols()->at(ID(__abstractmethods__))); 5883 return thread->raise(LayoutId::kAttributeError, *name); 5884 } 5885 type.setAbstractMethods(Unbound::object()); 5886 type.setFlagsAndBuiltinBase( 5887 static_cast<Type::Flag>(type.flags() & ~Type::Flag::kIsAbstract), 5888 type.builtinBase()); 5889 return NoneType::object(); 5890} 5891 5892RawObject FUNC(_builtins, _type_abstractmethods_get)(Thread* thread, 5893 Arguments args) { 5894 HandleScope scope(thread); 5895 Object self_obj(&scope, args.get(0)); 5896 if (!thread->runtime()->isInstanceOfType(*self_obj)) { 5897 return thread->raiseRequiresType(self_obj, ID(type)); 5898 } 5899 Type type(&scope, *self_obj); 5900 Object methods(&scope, type.abstractMethods()); 5901 if (!methods.isUnbound()) { 5902 return *methods; 5903 } 5904 Object name(&scope, 5905 thread->runtime()->symbols()->at(ID(__abstractmethods__))); 5906 return thread->raise(LayoutId::kAttributeError, *name); 5907} 5908 5909RawObject FUNC(_builtins, _type_abstractmethods_set)(Thread* thread, 5910 Arguments args) { 5911 HandleScope scope(thread); 5912 Object self_obj(&scope, args.get(0)); 5913 if (!thread->runtime()->isInstanceOfType(*self_obj)) { 5914 return thread->raiseRequiresType(self_obj, ID(type)); 5915 } 5916 Type type(&scope, *self_obj); 5917 Object abstract(&scope, Interpreter::isTrue(thread, args.get(1))); 5918 if (abstract.isError()) return *abstract; 5919 type.setAbstractMethods(args.get(1)); 5920 if (Bool::cast(*abstract).value()) { 5921 type.setFlagsAndBuiltinBase( 5922 static_cast<Type::Flag>(type.flags() | Type::Flag::kIsAbstract), 5923 type.builtinBase()); 5924 } 5925 return NoneType::object(); 5926} 5927 5928RawObject FUNC(_builtins, _type_bases_del)(Thread* thread, Arguments args) { 5929 HandleScope scope(thread); 5930 Object self_obj(&scope, args.get(0)); 5931 if (!thread->runtime()->isInstanceOfType(*self_obj)) { 5932 return thread->raiseRequiresType(self_obj, ID(type)); 5933 } 5934 Type type(&scope, *self_obj); 5935 Str name(&scope, strUnderlying(type.name())); 5936 return thread->raiseWithFmt(LayoutId::kTypeError, "can't delete %S.__bases__", 5937 &name); 5938} 5939 5940RawObject FUNC(_builtins, _type_bases_get)(Thread* thread, Arguments args) { 5941 HandleScope scope(thread); 5942 Object self_obj(&scope, args.get(0)); 5943 if (!thread->runtime()->isInstanceOfType(*self_obj)) { 5944 return thread->raiseRequiresType(self_obj, ID(type)); 5945 } 5946 Type type(&scope, *self_obj); 5947 return type.bases(); 5948} 5949 5950RawObject FUNC(_builtins, _type_bases_set)(Thread*, Arguments) { 5951 UNIMPLEMENTED("type.__bases__ setter"); 5952} 5953 5954RawObject FUNC(_builtins, _type_check)(Thread* thread, Arguments args) { 5955 return Bool::fromBool(thread->runtime()->isInstanceOfType(args.get(0))); 5956} 5957 5958RawObject FUNC(_builtins, _type_check_exact)(Thread*, Arguments args) { 5959 return Bool::fromBool(args.get(0).isType()); 5960} 5961 5962RawObject FUNC(_builtins, _type_dunder_call)(Thread* thread, Arguments args) { 5963 HandleScope scope(thread); 5964 Runtime* runtime = thread->runtime(); 5965 Object self_obj(&scope, args.get(0)); 5966 Tuple pargs(&scope, args.get(1)); 5967 Dict kwargs(&scope, args.get(2)); 5968 word pargs_length = pargs.length(); 5969 bool is_kwargs_empty = kwargs.numItems() == 0; 5970 // Shortcut for type(x) calls. 5971 if (pargs_length == 1 && is_kwargs_empty && 5972 self_obj == runtime->typeAt(LayoutId::kType)) { 5973 return runtime->typeOf(pargs.at(0)); 5974 } 5975 5976 if (!runtime->isInstanceOfType(*self_obj)) { 5977 return thread->raiseWithFmt( 5978 LayoutId::kTypeError, 5979 "'__call__' for '%Y' objects doesn't apply to a '%T' object", ID(type), 5980 &self_obj); 5981 } 5982 Type self(&scope, *self_obj); 5983 5984 // `instance = self.__new__(...)` 5985 Object instance(&scope, NoneType::object()); 5986 Object call_args_obj(&scope, NoneType::object()); 5987 bool use_object_dunder_new = 5988 self.isType() && self.hasFlag(Type::Flag::kHasObjectDunderNew); 5989 if (use_object_dunder_new) { 5990 // Most common case `__new__` was not overridden and is just 5991 // `object.__new__`. 5992 instance = objectNew(thread, self); 5993 if (instance.isErrorException()) return *instance; 5994 } else { 5995 Object dunder_new(&scope, Unbound::object()); 5996 Object dunder_new_name(&scope, runtime->symbols()->at(ID(__new__))); 5997 if (self.isType()) { 5998 // Metaclass is "type" so we do not need to check for __new__ being a 5999 // datadescriptor and we can look it up directly on the type. 6000 dunder_new = typeLookupInMro(thread, *self, *dunder_new_name); 6001 } 6002 if (dunder_new.isStaticMethod()) { 6003 // Next most common case `__new__` is overridden with a normal function 6004 dunder_new = StaticMethod::cast(*dunder_new).function(); 6005 } else { 6006 // Finally fallback to complete lookup for corner cases 6007 dunder_new = typeGetAttribute(thread, self, dunder_new_name); 6008 } 6009 6010 CHECK(!dunder_new.isError(), "self must have __new__"); 6011 thread->stackPush(*dunder_new); 6012 if (is_kwargs_empty) { 6013 thread->stackPush(*self); 6014 for (word i = 0; i < pargs_length; ++i) { 6015 thread->stackPush(pargs.at(i)); 6016 } 6017 instance = Interpreter::call(thread, pargs_length + 1); 6018 } else { 6019 MutableTuple call_args(&scope, 6020 runtime->newMutableTuple(pargs_length + 1)); 6021 call_args.atPut(0, *self); 6022 call_args.replaceFromWith(1, *pargs, pargs_length); 6023 thread->stackPush(call_args.becomeImmutable()); 6024 thread->stackPush(*kwargs); 6025 instance = Interpreter::callEx(thread, CallFunctionExFlag::VAR_KEYWORDS); 6026 call_args_obj = *call_args; 6027 } 6028 if (instance.isErrorException()) return *instance; 6029 if (!typeIsSubclass(runtime->typeOf(*instance), *self)) { 6030 return *instance; 6031 } 6032 } 6033 6034 // instance.__init__(...) 6035 Object dunder_init_name(&scope, runtime->symbols()->at(ID(__init__))); 6036 Object dunder_init(&scope, typeGetAttribute(thread, self, dunder_init_name)); 6037 // `object.__init__` does nothing, we may be able to just skip things. 6038 // The exception to the rule being `object.__init__` raising errors when 6039 // arguments are provided and nothing is overridden. 6040 if (dunder_init != runtime->objectDunderInit() || 6041 (use_object_dunder_new && 6042 (pargs.length() != 0 || kwargs.numItems() != 0))) { 6043 CHECK(!dunder_init.isError(), "self must have __init__"); 6044 Object result(&scope, NoneType::object()); 6045 thread->stackPush(*dunder_init); 6046 if (is_kwargs_empty) { 6047 thread->stackPush(*instance); 6048 for (word i = 0; i < pargs_length; ++i) { 6049 thread->stackPush(pargs.at(i)); 6050 } 6051 result = Interpreter::call(thread, pargs_length + 1); 6052 } else { 6053 if (!call_args_obj.isMutableTuple()) { 6054 MutableTuple call_args(&scope, 6055 runtime->newMutableTuple(pargs_length + 1)); 6056 call_args.atPut(0, *instance); 6057 call_args.replaceFromWith(1, *pargs, pargs_length); 6058 call_args_obj = *call_args; 6059 } else { 6060 MutableTuple::cast(*call_args_obj).atPut(0, *instance); 6061 } 6062 thread->stackPush(*call_args_obj); 6063 thread->stackPush(*kwargs); 6064 result = Interpreter::callEx(thread, CallFunctionExFlag::VAR_KEYWORDS); 6065 } 6066 if (result.isErrorException()) return *result; 6067 if (!result.isNoneType()) { 6068 Object type_name(&scope, self.name()); 6069 return thread->raiseWithFmt(LayoutId::kTypeError, 6070 "%S.__init__ returned non None", &type_name); 6071 } 6072 } 6073 return *instance; 6074} 6075 6076RawObject FUNC(_builtins, _type_guard)(Thread* thread, Arguments args) { 6077 if (thread->runtime()->isInstanceOfType(args.get(0))) { 6078 return NoneType::object(); 6079 } 6080 return raiseRequiresFromCaller(thread, args, ID(type)); 6081} 6082 6083RawObject FUNC(_builtins, _type_issubclass)(Thread*, Arguments args) { 6084 return Bool::fromBool(typeIsSubclass(args.get(0), args.get(1))); 6085} 6086 6087bool FUNC(_builtins, _type_issubclass_intrinsic)(Thread* thread) { 6088 RawObject subclass = thread->stackPeek(1); 6089 RawObject superclass = thread->stackPeek(0); 6090 thread->stackDrop(2); 6091 thread->stackSetTop(Bool::fromBool(typeIsSubclass(subclass, superclass))); 6092 return true; 6093} 6094 6095RawObject FUNC(_builtins, _type_module_get)(Thread* thread, Arguments args) { 6096 HandleScope scope(thread); 6097 Object self_obj(&scope, args.get(0)); 6098 Runtime* runtime = thread->runtime(); 6099 if (!runtime->isInstanceOfType(*self_obj)) { 6100 return thread->raiseRequiresType(self_obj, ID(type)); 6101 } 6102 Type type(&scope, *self_obj); 6103 // If this is called on Type itself, typeAtById won't find __module__, and 6104 // the type isn't a CPython heap type, but it should still return builtins 6105 if (type.isBuiltin() && type.builtinBase() == LayoutId::kType) { 6106 return runtime->symbols()->at(ID(builtins)); 6107 } 6108 Object result(&scope, typeAtById(thread, type, ID(__module__))); 6109 if (result.isErrorNotFound()) { 6110 if (!type.isCPythonHeaptype()) { 6111 return runtime->symbols()->at(ID(builtins)); 6112 } 6113 Object name(&scope, runtime->symbols()->at(ID(__module__))); 6114 return objectRaiseAttributeError(thread, type, name); 6115 } 6116 return *result; 6117} 6118 6119RawObject FUNC(_builtins, _type_module_set)(Thread* thread, Arguments args) { 6120 HandleScope scope(thread); 6121 Object self_obj(&scope, args.get(0)); 6122 Runtime* runtime = thread->runtime(); 6123 if (!runtime->isInstanceOfType(*self_obj)) { 6124 return thread->raiseRequiresType(self_obj, ID(type)); 6125 } 6126 Type type(&scope, *self_obj); 6127 Object value(&scope, args.get(1)); 6128 if (!type.hasMutableDict()) { 6129 return raiseTypeErrorCannotSetImmutable(thread, type); 6130 } 6131 typeAtPutById(thread, type, ID(__module__), value); 6132 return NoneType::object(); 6133} 6134 6135RawObject FUNC(_builtins, _type_name_get)(Thread* thread, Arguments args) { 6136 HandleScope scope(thread); 6137 Object self_obj(&scope, args.get(0)); 6138 Runtime* runtime = thread->runtime(); 6139 if (!runtime->isInstanceOfType(*self_obj)) { 6140 return thread->raiseRequiresType(self_obj, ID(type)); 6141 } 6142 Type type(&scope, *self_obj); 6143 return type.name(); 6144} 6145 6146RawObject FUNC(_builtins, _type_name_set)(Thread* thread, Arguments args) { 6147 HandleScope scope(thread); 6148 Object self_obj(&scope, args.get(0)); 6149 Runtime* runtime = thread->runtime(); 6150 if (!runtime->isInstanceOfType(*self_obj)) { 6151 return thread->raiseRequiresType(self_obj, ID(type)); 6152 } 6153 Type type(&scope, *self_obj); 6154 if (!type.hasMutableDict()) { 6155 return raiseTypeErrorCannotSetImmutable(thread, type); 6156 } 6157 6158 Object value(&scope, args.get(1)); 6159 if (!runtime->isInstanceOfStr(*value)) { 6160 Object type_name(&scope, type.name()); 6161 return thread->raiseWithFmt( 6162 LayoutId::kTypeError, "can only assign string to %S.__name__, not '%T'", 6163 &type_name, &value); 6164 } 6165 type.setName(*value); 6166 return NoneType::object(); 6167} 6168 6169RawObject FUNC(_builtins, _type_new)(Thread* thread, Arguments args) { 6170 HandleScope scope(thread); 6171 Type metaclass(&scope, args.get(0)); 6172 Str name(&scope, strUnderlying(args.get(1))); 6173 Tuple bases(&scope, tupleUnderlying(args.get(2))); 6174 Dict dict(&scope, args.get(3)); 6175 Bool is_heaptype(&scope, args.get(4)); 6176 6177 word flags = Type::Flag::kIsBasetype; 6178 flags |= 6179 is_heaptype.value() ? Type::Flag::kIsCPythonHeaptype : Type::Flag::kNone; 6180 return typeNew(thread, metaclass, name, bases, dict, flags, 6181 /*inherit_slots=*/true, /*add_instance_dict=*/true); 6182} 6183 6184RawObject FUNC(_builtins, _type_proxy)(Thread* thread, Arguments args) { 6185 HandleScope scope(thread); 6186 Type type(&scope, args.get(0)); 6187 if (type.proxy().isNoneType()) { 6188 type.setProxy(thread->runtime()->newTypeProxy(type)); 6189 } 6190 return type.proxy(); 6191} 6192 6193RawObject FUNC(_builtins, _type_proxy_check)(Thread*, Arguments args) { 6194 return Bool::fromBool(args.get(0).isTypeProxy()); 6195} 6196 6197RawObject FUNC(_builtins, _type_proxy_get)(Thread* thread, Arguments args) { 6198 HandleScope scope(thread); 6199 TypeProxy self(&scope, args.get(0)); 6200 Object name(&scope, args.get(1)); 6201 name = attributeName(thread, name); 6202 if (name.isErrorException()) return *name; 6203 Object default_obj(&scope, args.get(2)); 6204 Type type(&scope, self.type()); 6205 Object result(&scope, typeAt(type, name)); 6206 if (result.isError()) { 6207 return *default_obj; 6208 } 6209 return *result; 6210} 6211 6212RawObject FUNC(_builtins, _type_proxy_guard)(Thread* thread, Arguments args) { 6213 if (args.get(0).isTypeProxy()) { 6214 return NoneType::object(); 6215 } 6216 return raiseRequiresFromCaller(thread, args, ID(type_proxy)); 6217} 6218 6219RawObject FUNC(_builtins, _type_proxy_keys)(Thread* thread, Arguments args) { 6220 HandleScope scope(thread); 6221 TypeProxy self(&scope, args.get(0)); 6222 Type type(&scope, self.type()); 6223 return typeKeys(thread, type); 6224} 6225 6226RawObject FUNC(_builtins, _type_proxy_len)(Thread* thread, Arguments args) { 6227 HandleScope scope(thread); 6228 TypeProxy self(&scope, args.get(0)); 6229 Type type(&scope, self.type()); 6230 return SmallInt::fromWord(typeLen(thread, type)); 6231} 6232 6233RawObject FUNC(_builtins, _type_proxy_values)(Thread* thread, Arguments args) { 6234 HandleScope scope(thread); 6235 TypeProxy self(&scope, args.get(0)); 6236 Type type(&scope, self.type()); 6237 return typeValues(thread, type); 6238} 6239 6240RawObject FUNC(_builtins, _type_qualname_get)(Thread* thread, Arguments args) { 6241 HandleScope scope(thread); 6242 Object self_obj(&scope, args.get(0)); 6243 Runtime* runtime = thread->runtime(); 6244 if (!runtime->isInstanceOfType(*self_obj)) { 6245 return thread->raiseRequiresType(self_obj, ID(type)); 6246 } 6247 Type type(&scope, *self_obj); 6248 return type.qualname(); 6249} 6250 6251RawObject FUNC(_builtins, _type_qualname_set)(Thread* thread, Arguments args) { 6252 HandleScope scope(thread); 6253 Object self_obj(&scope, args.get(0)); 6254 Runtime* runtime = thread->runtime(); 6255 if (!runtime->isInstanceOfType(*self_obj)) { 6256 return thread->raiseRequiresType(self_obj, ID(type)); 6257 } 6258 Type type(&scope, *self_obj); 6259 if (!type.hasMutableDict()) { 6260 return raiseTypeErrorCannotSetImmutable(thread, type); 6261 } 6262 6263 Object value(&scope, args.get(1)); 6264 if (!runtime->isInstanceOfStr(*value)) { 6265 Object type_name(&scope, type.name()); 6266 return thread->raiseWithFmt( 6267 LayoutId::kTypeError, 6268 "can only assign string to %S.__qualname__, not '%T'", &type_name, 6269 &value); 6270 } 6271 type.setQualname(*value); 6272 return NoneType::object(); 6273} 6274 6275RawObject FUNC(_builtins, _type_subclass_guard)(Thread* thread, 6276 Arguments args) { 6277 RawObject subclass_obj = args.get(0); 6278 if (!thread->runtime()->isInstanceOfType(subclass_obj)) { 6279 return raiseRequiresFromCaller(thread, args, ID(type)); 6280 } 6281 RawObject superclass_obj = args.get(1); 6282 if (typeIsSubclass(subclass_obj, superclass_obj)) { 6283 return NoneType::object(); 6284 } 6285 HandleScope scope(thread); 6286 Type subclass(&scope, subclass_obj); 6287 Type superclass(&scope, superclass_obj); 6288 Function function(&scope, 6289 thread->currentFrame()->previousFrame()->function()); 6290 Str function_name(&scope, function.name()); 6291 Str subclass_name(&scope, subclass.name()); 6292 Str superclass_name(&scope, superclass.name()); 6293 return thread->raiseWithFmt(LayoutId::kTypeError, 6294 "'%S': '%S' is not a subclass of '%S'", 6295 &function_name, &subclass_name, &superclass_name); 6296} 6297 6298RawObject FUNC(_builtins, _unimplemented)(Thread* thread, Arguments) { 6299 HandleScope scope(thread); 6300 6301 // Environment override? 6302 const char* pyro_raise_on_unimplemented = 6303 std::getenv("PYRO_RAISE_ON_UNIMPLEMENTED"); 6304 bool raise_instead_of_abort = 6305 (pyro_raise_on_unimplemented != nullptr && 6306 ::strcmp(pyro_raise_on_unimplemented, "1") == 0); 6307 6308 // If sys.PYRO_RAISE_ON_UNIMPLEMENTED is set to a true value 6309 if (!raise_instead_of_abort) { 6310 Object sys_dot_pyro_raise_on_unimplemented( 6311 &scope, thread->runtime()->lookupNameInModule( 6312 thread, ID(sys), ID(PYRO_RAISE_ON_UNIMPLEMENTED))); 6313 if (!sys_dot_pyro_raise_on_unimplemented.isError()) { 6314 Object o(&scope, Interpreter::isTrue( 6315 thread, *sys_dot_pyro_raise_on_unimplemented)); 6316 raise_instead_of_abort = (!o.isError()) && (*o == Bool::trueObj()); 6317 } 6318 } 6319 6320 if (raise_instead_of_abort) { 6321 return thread->raiseWithFmt(LayoutId::kNotImplementedError, 6322 "overrode _unimplemented abort"); 6323 } 6324 thread->runtime()->printTraceback(thread, File::kStderr); 6325 6326 // Attempt to identify the calling function. 6327 Object function_obj(&scope, 6328 thread->currentFrame()->previousFrame()->function()); 6329 if (!function_obj.isError()) { 6330 Function function(&scope, *function_obj); 6331 Str function_name(&scope, function.name()); 6332 unique_c_ptr<char> name_cstr(function_name.toCStr()); 6333 fprintf(stderr, "\n'_unimplemented' called in function '%s'\n", 6334 name_cstr.get()); 6335 } else { 6336 fputs("\n'_unimplemented' called.\n", stderr); 6337 } 6338 fputs( 6339 "\nuse env PYRO_RAISE_ON_UNIMPLEMENTED=1 or" 6340 "\nsys.PYRO_RAISE_ON_UNIMPLEMENTED=True to raise instead of abort.\n", 6341 stderr); 6342 6343 std::abort(); 6344} 6345 6346RawObject FUNC(_builtins, _warn)(Thread* thread, Arguments args) { 6347 HandleScope scope(thread); 6348 Object message(&scope, args.get(0)); 6349 Object category(&scope, args.get(1)); 6350 Object stacklevel(&scope, args.get(2)); 6351 Object source(&scope, args.get(3)); 6352 return thread->invokeFunction4(ID(warnings), ID(warn), message, category, 6353 stacklevel, source); 6354} 6355 6356RawObject FUNC(_builtins, _weakref_callback)(Thread* thread, Arguments args) { 6357 HandleScope scope(thread); 6358 Object self_obj(&scope, args.get(0)); 6359 Runtime* runtime = thread->runtime(); 6360 if (!runtime->isInstanceOfWeakRef(*self_obj)) { 6361 return thread->raiseRequiresType(self_obj, ID(weakref)); 6362 } 6363 WeakRef self(&scope, weakRefUnderlying(*self_obj)); 6364 Object callback(&scope, self.callback()); 6365 if (callback.isNoneType()) { 6366 return *callback; 6367 } 6368 return BoundMethod::cast(*callback).function(); 6369} 6370 6371RawObject FUNC(_builtins, _weakref_check)(Thread* thread, Arguments args) { 6372 return Bool::fromBool(thread->runtime()->isInstanceOfWeakRef(args.get(0))); 6373} 6374 6375RawObject FUNC(_builtins, _weakref_guard)(Thread* thread, Arguments args) { 6376 if (thread->runtime()->isInstanceOfWeakRef(args.get(0))) { 6377 return NoneType::object(); 6378 } 6379 return raiseRequiresFromCaller(thread, args, ID(weakref)); 6380} 6381 6382RawObject FUNC(_builtins, _weakref_referent)(Thread* thread, Arguments args) { 6383 HandleScope scope(thread); 6384 Object self_obj(&scope, args.get(0)); 6385 Runtime* runtime = thread->runtime(); 6386 if (!runtime->isInstanceOfWeakRef(*self_obj)) { 6387 return thread->raiseRequiresType(self_obj, ID(weakref)); 6388 } 6389 WeakRef self(&scope, weakRefUnderlying(*self_obj)); 6390 return self.referent(); 6391} 6392 6393} // namespace py