this repo has no description
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