this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "builtins-module.h"
3
4#include <cerrno>
5#include <cmath>
6#include <csignal>
7
8#include "attributedict.h"
9#include "builtins.h"
10#include "bytes-builtins.h"
11#include "capi.h"
12#include "dict-builtins.h"
13#include "exception-builtins.h"
14#include "formatter.h"
15#include "int-builtins.h"
16#include "list-builtins.h"
17#include "marshal.h"
18#include "module-builtins.h"
19#include "modules.h"
20#include "object-builtins.h"
21#include "objects.h"
22#include "range-builtins.h"
23#include "runtime.h"
24#include "set-builtins.h"
25#include "str-builtins.h"
26#include "tuple-builtins.h"
27#include "type-builtins.h"
28
29namespace py {
30
31RawObject delAttribute(Thread* thread, const Object& object,
32 const Object& name) {
33 HandleScope scope(thread);
34 Object interned(&scope, attributeName(thread, name));
35 if (interned.isErrorException()) return *interned;
36 Object result(&scope,
37 thread->runtime()->attributeDel(thread, object, interned));
38 if (result.isErrorException()) return *result;
39 return NoneType::object();
40}
41
42RawObject getAttribute(Thread* thread, const Object& object,
43 const Object& name) {
44 HandleScope scope(thread);
45 Object interned(&scope, attributeName(thread, name));
46 if (interned.isErrorException()) return *interned;
47 return thread->runtime()->attributeAt(thread, object, interned);
48}
49
50static RawObject getAttributeWithDefault(Thread* thread, const Object& object,
51 const Object& name) {
52 HandleScope scope(thread);
53 Object interned(&scope, attributeName(thread, name));
54 if (interned.isErrorException()) return *interned;
55 LoadAttrKind kind;
56 Object location(&scope, Unbound::object());
57 return thread->runtime()->attributeAtSetLocation(thread, object, interned,
58 &kind, &location);
59}
60
61RawObject hasAttribute(Thread* thread, const Object& object,
62 const Object& name) {
63 HandleScope scope(thread);
64 Object interned(&scope, attributeName(thread, name));
65 if (interned.isErrorException()) return *interned;
66
67 LoadAttrKind kind;
68 Object location(&scope, Unbound::object());
69 Object result(&scope, thread->runtime()->attributeAtSetLocation(
70 thread, object, interned, &kind, &location));
71 if (result.isErrorNotFound()) {
72 return Bool::falseObj();
73 }
74 if (!result.isErrorException()) {
75 return Bool::trueObj();
76 }
77 if (!thread->pendingExceptionMatches(LayoutId::kAttributeError)) {
78 return *result;
79 }
80 thread->clearPendingException();
81 return Bool::falseObj();
82}
83
84RawObject setAttribute(Thread* thread, const Object& object, const Object& name,
85 const Object& value) {
86 HandleScope scope(thread);
87 Object interned(&scope, attributeName(thread, name));
88 if (interned.isErrorException()) return *interned;
89
90 Object result(
91 &scope, thread->invokeMethod3(object, ID(__setattr__), interned, value));
92 if (result.isErrorException()) return *result;
93 return NoneType::object();
94}
95
96bool FUNC(builtins, _index_intrinsic)(Thread* thread) {
97 RawObject value = thread->stackTop();
98 if (thread->runtime()->isInstanceOfInt(value)) {
99 thread->stackPop();
100 thread->stackSetTop(value);
101 return true;
102 }
103 return false;
104}
105
106bool FUNC(builtins, _index_or_int_intrinsic)(Thread* thread) {
107 RawObject value = thread->stackTop();
108 if (value.isBool()) {
109 thread->stackPop();
110 thread->stackSetTop(convertBoolToInt(value));
111 return true;
112 }
113 if (value.isSmallInt() || value.isLargeInt()) {
114 thread->stackPop();
115 thread->stackSetTop(value);
116 }
117 return false;
118}
119
120bool FUNC(builtins, _obj_as_int_intrinsic)(Thread* thread) {
121 RawObject value = thread->stackTop();
122 if (value.isBool()) {
123 thread->stackPop();
124 thread->stackSetTop(convertBoolToInt(value));
125 return true;
126 }
127 if (thread->runtime()->isInstanceOfInt(value)) {
128 thread->stackPop();
129 thread->stackSetTop(intUnderlying(value));
130 return true;
131 }
132 return false;
133}
134
135bool FUNC(builtins, abs_intrinsic)(Thread* thread) {
136 RawObject obj = thread->stackTop();
137 if (obj.isSmallInt()) {
138 thread->stackPop();
139 word value = SmallInt::cast(obj).value();
140 if (value < 0) {
141 obj = SmallInt::fromWord(-value);
142 }
143 thread->stackSetTop(obj);
144 return true;
145 }
146 if (obj.isFloat()) {
147 thread->stackPop();
148 double value = Float::cast(obj).value();
149 thread->stackSetTop(thread->runtime()->newFloat(std::fabs(value)));
150 return true;
151 }
152 return false;
153}
154
155bool FUNC(builtins, next_intrinsic)(Thread* thread) {
156 RawObject value = thread->stackTop();
157 switch (value.layoutId()) {
158 case LayoutId::kDictKeyIterator: {
159 HandleScope scope(thread);
160 DictKeyIterator iter(&scope, value);
161 RawObject result = dictKeyIteratorNext(thread, iter);
162 if (result.isErrorNoMoreItems()) {
163 return false;
164 }
165 thread->stackPop();
166 thread->stackSetTop(result);
167 return true;
168 }
169 case LayoutId::kListIterator: {
170 HandleScope scope(thread);
171 ListIterator list_iterator(&scope, value);
172 RawObject result = listIteratorNext(thread, list_iterator);
173 if (result.isErrorOutOfBounds()) {
174 return false;
175 }
176 thread->stackPop();
177 thread->stackSetTop(result);
178 return true;
179 }
180 case LayoutId::kRangeIterator: {
181 HandleScope scope(thread);
182 RangeIterator iter(&scope, value);
183 RawObject result = rangeIteratorNext(iter);
184 if (result.isErrorNoMoreItems()) {
185 return false;
186 }
187 thread->stackPop();
188 thread->stackSetTop(result);
189 return true;
190 }
191 case LayoutId::kSetIterator: {
192 HandleScope scope(thread);
193 SetIterator set_iterator(&scope, value);
194 RawObject result = setIteratorNext(thread, set_iterator);
195 if (result.isErrorNoMoreItems()) {
196 return false;
197 }
198 thread->stackPop();
199 thread->stackSetTop(result);
200 return true;
201 }
202 case LayoutId::kStrIterator: {
203 HandleScope scope(thread);
204 StrIterator str_iterator(&scope, value);
205 RawObject result = strIteratorNext(thread, str_iterator);
206 if (result.isErrorNoMoreItems()) {
207 return false;
208 }
209 thread->stackPop();
210 thread->stackSetTop(result);
211 return true;
212 }
213 case LayoutId::kTupleIterator: {
214 HandleScope scope(thread);
215 TupleIterator tuple_iterator(&scope, value);
216 RawObject result = tupleIteratorNext(thread, tuple_iterator);
217 if (result.isErrorNoMoreItems()) {
218 return false;
219 }
220 thread->stackPop();
221 thread->stackSetTop(result);
222 return true;
223 }
224 default: {
225 return false;
226 }
227 }
228}
229
230bool FUNC(builtins, _number_check_intrinsic)(Thread* thread) {
231 Runtime* runtime = thread->runtime();
232 RawObject arg = thread->stackTop();
233 if (runtime->isInstanceOfInt(arg) || runtime->isInstanceOfFloat(arg)) {
234 thread->stackPop();
235 thread->stackSetTop(Bool::trueObj());
236 return true;
237 }
238 return false;
239}
240
241bool FUNC(builtins, _slice_index_intrinsic)(Thread* thread) {
242 RawObject value = thread->stackPeek(0);
243 if (value.isNoneType() || thread->runtime()->isInstanceOfInt(value)) {
244 thread->stackPop();
245 thread->stackSetTop(value);
246 return true;
247 }
248 return false;
249}
250
251bool FUNC(builtins, _slice_index_not_none_intrinsic)(Thread* thread) {
252 RawObject value = thread->stackTop();
253 if (thread->runtime()->isInstanceOfInt(value)) {
254 thread->stackPop();
255 thread->stackSetTop(value);
256 return true;
257 }
258 return false;
259}
260
261bool FUNC(builtins, isinstance_intrinsic)(Thread* thread) {
262 RawObject obj = thread->stackPeek(1);
263 RawObject type = thread->stackPeek(0);
264 Runtime* runtime = thread->runtime();
265 RawType obj_type = runtime->typeOf(obj);
266 if (obj_type == type) {
267 thread->stackDrop(2);
268 thread->stackSetTop(Bool::trueObj());
269 return true;
270 }
271 if (type.isType()) {
272 if (typeIsSubclass(obj_type, type)) {
273 thread->stackDrop(2);
274 thread->stackSetTop(Bool::trueObj());
275 return true;
276 }
277 if (obj_type.hasFlag(Type::Flag::kHasObjectDunderClass)) {
278 // obj_type.__class__ is object.__class__, so type(obj) is guaranteed to
279 // be obj_type. See _object_class_set implementation.
280 thread->stackDrop(2);
281 thread->stackSetTop(Bool::falseObj());
282 return true;
283 }
284 } else if (type.isTuple()) {
285 RawTuple types = Tuple::cast(type);
286 word length = types.length();
287 for (word i = 0; i < length; i++) {
288 RawObject item = types.at(i);
289 if (!item.isType()) {
290 return false;
291 }
292 if (typeIsSubclass(obj_type, item)) {
293 thread->stackDrop(2);
294 thread->stackSetTop(Bool::trueObj());
295 return true;
296 }
297 }
298 }
299 return false;
300}
301
302bool FUNC(builtins, len_intrinsic)(Thread* thread) {
303 RawObject arg = thread->stackTop();
304 word length;
305 switch (arg.layoutId()) {
306 case LayoutId::kBytearray:
307 length = Bytearray::cast(arg).numItems();
308 break;
309 case LayoutId::kDict:
310 length = Dict::cast(arg).numItems();
311 break;
312 case LayoutId::kFrozenSet:
313 length = FrozenSet::cast(arg).numItems();
314 break;
315 case LayoutId::kLargeBytes:
316 length = LargeBytes::cast(arg).length();
317 break;
318 case LayoutId::kLargeStr:
319 length = LargeStr::cast(arg).codePointLength();
320 break;
321 case LayoutId::kList:
322 length = List::cast(arg).numItems();
323 break;
324 case LayoutId::kSet:
325 length = Set::cast(arg).numItems();
326 break;
327 case LayoutId::kSmallBytes:
328 length = SmallBytes::cast(arg).length();
329 break;
330 case LayoutId::kSmallStr:
331 length = SmallStr::cast(arg).codePointLength();
332 break;
333 case LayoutId::kTuple:
334 length = Tuple::cast(arg).length();
335 break;
336 default:
337 return false;
338 }
339 thread->stackPop();
340 thread->stackSetTop(SmallInt::fromWord(length));
341 return true;
342}
343
344void FUNC(builtins, __init_module__)(Thread* thread, const Module& module,
345 View<byte> bytecode) {
346 Runtime* runtime = thread->runtime();
347 runtime->setBuiltinsModuleId(module.id());
348 runtime->cacheBuildClass(thread, module);
349 HandleScope scope(thread);
350
351 // Add module variables
352 {
353 Object dunder_debug(&scope, Bool::falseObj());
354 moduleAtPutById(thread, module, ID(__debug__), dunder_debug);
355
356 Object false_obj(&scope, Bool::falseObj());
357 moduleAtPutById(thread, module, ID(False), false_obj);
358
359 Object none(&scope, NoneType::object());
360 moduleAtPutById(thread, module, ID(None), none);
361
362 Object not_implemented(&scope, NotImplementedType::object());
363 moduleAtPutById(thread, module, ID(NotImplemented), not_implemented);
364
365 Object true_obj(&scope, Bool::trueObj());
366 moduleAtPutById(thread, module, ID(True), true_obj);
367 }
368
369 executeFrozenModule(thread, module, bytecode);
370}
371
372static RawObject calculateMetaclass(Thread* thread, const Type& metaclass_type,
373 const Tuple& bases) {
374 Runtime* runtime = thread->runtime();
375 RawObject result = *metaclass_type;
376 for (word i = 0, num_bases = bases.length(); i < num_bases; i++) {
377 RawObject base_type = runtime->typeOf(bases.at(i));
378 if (typeIsSubclass(base_type, result)) {
379 result = base_type;
380 } else if (!typeIsSubclass(result, base_type)) {
381 return thread->raiseWithFmt(
382 LayoutId::kTypeError,
383 "metaclass conflict: the metaclass of a derived class must be a "
384 "(non-strict) subclass of the metaclasses of all its bases");
385 }
386 }
387 return result;
388}
389
390RawObject FUNC(builtins, bin)(Thread* thread, Arguments args) {
391 HandleScope scope(thread);
392 Object number(&scope, args.get(0));
393 number = intFromIndex(thread, number);
394 if (number.isError()) {
395 return *number;
396 }
397 Int number_int(&scope, intUnderlying(*number));
398 return formatIntBinarySimple(thread, number_int);
399}
400
401RawObject FUNC(builtins, delattr)(Thread* thread, Arguments args) {
402 HandleScope scope(thread);
403 Object self(&scope, args.get(0));
404 Object name(&scope, args.get(1));
405 Object result(&scope, delAttribute(thread, self, name));
406 return *result;
407}
408
409static RawObject replaceNonTypeBases(Thread* thread, const Tuple& bases) {
410 Runtime* runtime = thread->runtime();
411 word num_bases = bases.length();
412 bool has_nontype_base = false;
413 for (word i = 0; i < num_bases; i++) {
414 if (!runtime->isInstanceOfType(bases.at(i))) {
415 has_nontype_base = true;
416 break;
417 }
418 }
419 if (!has_nontype_base) {
420 return *bases;
421 }
422 HandleScope scope(thread);
423 List new_bases(&scope, runtime->newList());
424 Object base(&scope, NoneType::object());
425 Object replacements(&scope, NoneType::object());
426 Tuple entries(&scope, runtime->emptyTuple());
427 for (word i = 0; i < num_bases; i++) {
428 base = bases.at(i);
429 if (runtime->isInstanceOfType(*base)) {
430 runtime->listAdd(thread, new_bases, base);
431 continue;
432 }
433 replacements = thread->invokeMethod2(base, ID(__mro_entries__), bases);
434 if (replacements.isErrorException()) return *replacements;
435 if (replacements.isErrorNotFound()) {
436 runtime->listAdd(thread, new_bases, base);
437 continue;
438 }
439 if (!replacements.isTuple()) {
440 return thread->raiseWithFmt(LayoutId::kTypeError,
441 "__mro_entries__ must return a tuple");
442 }
443 entries = *replacements;
444 listExtend(thread, new_bases, entries, entries.length());
445 }
446 Tuple new_bases_items(&scope, new_bases.items());
447 return runtime->tupleSubseq(thread, new_bases_items, 0, new_bases.numItems());
448}
449
450static void pickBuiltinTypeCtorFunction(Thread* thread, const Type& type) {
451 HandleScope scope(thread);
452 Object ctor(&scope, NoneType::object());
453 LayoutId layout_id = type.instanceLayoutId();
454 Runtime* runtime = thread->runtime();
455 switch (layout_id) {
456 case LayoutId::kInt: {
457 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
458 ctor = moduleAtById(thread, under_builtins, ID(_int_ctor));
459 break;
460 }
461 case LayoutId::kList: {
462 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
463 ctor = moduleAtById(thread, under_builtins, ID(_list_ctor));
464 break;
465 }
466 case LayoutId::kRange: {
467 // range args are messy. Use __new__ as the default ctor but cache a
468 // specialized version in the interpreter if possible at a given
469 // callsite.
470 ctor = typeAtById(thread, type, ID(__new__));
471 DCHECK(ctor.isStaticMethod(), "expected staticmethod");
472 ctor = StaticMethod::cast(*ctor).function();
473 break;
474 }
475 case LayoutId::kSet: {
476 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
477 ctor = moduleAtById(thread, under_builtins, ID(_set_ctor));
478 break;
479 }
480 case LayoutId::kStr: {
481 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
482 ctor = moduleAtById(thread, under_builtins, ID(_str_ctor));
483 break;
484 }
485 case LayoutId::kStopIteration: {
486 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
487 ctor = moduleAtById(thread, under_builtins, ID(_stop_iteration_ctor));
488 break;
489 }
490 case LayoutId::kStrArray: {
491 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
492 ctor = moduleAtById(thread, under_builtins, ID(_str_array_ctor));
493 break;
494 }
495 case LayoutId::kSuper: {
496 Module under_builtins(&scope, runtime->findModuleById(ID(_builtins)));
497 ctor = moduleAtById(thread, under_builtins, ID(_super_ctor));
498 break;
499 }
500 default: {
501 if (typeAtById(thread, type, ID(__init__)).isErrorNotFound()) {
502 // Use __new__ as _ctor if __init__ is undefined.
503 Object dunder_new(&scope, typeAtById(thread, type, ID(__new__)));
504 if (!dunder_new.isErrorNotFound()) {
505 ctor = StaticMethod::cast(*dunder_new).function();
506 }
507 }
508 }
509 }
510 if (ctor.isNoneType()) {
511 ctor = runtime->lookupNameInModule(thread, ID(_builtins),
512 ID(_type_dunder_call));
513 }
514 CHECK(ctor.isFunction(), "ctor is expected to be a function");
515 type.setCtor(*ctor);
516}
517
518RawObject FUNC(builtins, __build_class__)(Thread* thread, Arguments args) {
519 Runtime* runtime = thread->runtime();
520 HandleScope scope(thread);
521 Object body_obj(&scope, args.get(0));
522 if (!body_obj.isFunction()) {
523 return thread->raiseWithFmt(LayoutId::kTypeError,
524 "__build_class__: func must be a function");
525 }
526 Function body(&scope, *body_obj);
527 Object name(&scope, args.get(1));
528 if (!runtime->isInstanceOfStr(*name)) {
529 return thread->raiseWithFmt(LayoutId::kTypeError,
530 "__build_class__: name is not a string");
531 }
532 Object metaclass(&scope, args.get(2));
533 Object bootstrap(&scope, args.get(3));
534 Tuple orig_bases(&scope, args.get(4));
535 Tuple bases(&scope, *orig_bases);
536 Dict kwargs(&scope, args.get(5));
537
538 if (bootstrap == Bool::trueObj()) {
539 CHECK(name.isStr(), "bootstrap class names must not be str subclass");
540 name = Runtime::internStr(thread, name);
541 Object type_obj(&scope, findBuiltinTypeWithName(thread, name));
542 CHECK(!type_obj.isErrorNotFound(), "Unknown builtin type");
543 Type type(&scope, *type_obj);
544
545 if (bases.length() == 0 && name != runtime->symbols()->at(ID(object))) {
546 bases = runtime->implicitBases();
547 }
548 Tuple builtin_bases(&scope, type.bases());
549 word bases_length = bases.length();
550 CHECK(builtin_bases.length() == bases_length, "mismatching bases for '%s'",
551 Str::cast(*name).toCStr());
552 for (word i = 0; i < bases_length; i++) {
553 CHECK(builtin_bases.at(i) == bases.at(i), "mismatching bases for '%s'",
554 Str::cast(*name).toCStr());
555 }
556
557 if (type.mro().isNoneType()) {
558 Type superclass(&scope, bases.at(0));
559 DCHECK(!superclass.mro().isNoneType(), "superclass not initialized yet");
560 Tuple superclass_mro(&scope, superclass.mro());
561 word mro_length = superclass_mro.length() + 1;
562 MutableTuple mro(&scope, runtime->newMutableTuple(mro_length));
563 mro.atPut(0, *type);
564 mro.replaceFromWith(1, *superclass_mro, mro_length - 1);
565 type.setMro(mro.becomeImmutable());
566 }
567
568 Dict type_dict(&scope, runtime->newDict());
569 Object result(&scope,
570 thread->callFunctionWithImplicitGlobals(body, type_dict));
571 if (result.isError()) return *result;
572 CHECK(!typeAssignFromDict(thread, type, type_dict).isErrorException(),
573 "error while assigning bootstrap type dict");
574 // TODO(T53997177): Centralize type initialization
575 Object module_name(&scope, typeAtById(thread, type, ID(__module__)));
576 // non-heap-types in CPython have no `__module__` unless there is a
577 // "." in `tp_name`. Remove the attribute when it equals "builtins".
578 if (module_name.isStr() &&
579 Str::cast(*module_name).equals(runtime->symbols()->at(ID(builtins)))) {
580 typeRemoveById(thread, type, ID(__module__));
581 }
582
583 Object qualname(&scope, NoneType::object());
584 if (type.instanceLayoutId() == LayoutId::kType) {
585 qualname = *name;
586 // Note: `type` is the only type allowed to have a descriptor instead of
587 // a string for `__qualname__`.
588 } else {
589 qualname = typeRemoveById(thread, type, ID(__qualname__));
590 DCHECK(qualname.isStr() && Str::cast(*qualname).equals(Str::cast(*name)),
591 "unexpected __qualname__ attribute");
592 }
593 type.setQualname(*qualname);
594 typeAddDocstring(thread, type);
595
596 if (Layout::cast(type.instanceLayout()).hasTupleOverflow() &&
597 typeAtById(thread, type, ID(__dict__)).isErrorNotFound()) {
598 typeAddInstanceDict(thread, type);
599 }
600
601 if (DCHECK_IS_ON()) {
602 Object dunder_new(&scope, typeAtById(thread, type, ID(__new__)));
603 if (!dunder_new.isStaticMethod()) {
604 if (!(dunder_new.isNoneType() || dunder_new.isErrorNotFound())) {
605 DCHECK(false, "__new__ for %s should be a staticmethod",
606 Str::cast(*name).toCStr());
607 }
608 }
609 }
610
611 pickBuiltinTypeCtorFunction(thread, type);
612 runtime->builtinTypeCreated(thread, type);
613 return *type;
614 }
615
616 Object updated_bases(&scope, replaceNonTypeBases(thread, bases));
617 if (updated_bases.isErrorException()) {
618 return *updated_bases;
619 }
620 bases = *updated_bases;
621 bool metaclass_is_class;
622 if (metaclass.isUnbound()) {
623 metaclass_is_class = true;
624 if (bases.length() == 0) {
625 metaclass = runtime->typeAt(LayoutId::kType);
626 } else {
627 metaclass = runtime->typeOf(bases.at(0));
628 }
629 } else {
630 metaclass_is_class = runtime->isInstanceOfType(*metaclass);
631 }
632
633 if (metaclass_is_class) {
634 Type metaclass_type(&scope, *metaclass);
635 metaclass = calculateMetaclass(thread, metaclass_type, bases);
636 if (metaclass.isError()) return *metaclass;
637 }
638
639 Object dict_obj(&scope, NoneType::object());
640 Object prepare_method(
641 &scope, runtime->attributeAtById(thread, metaclass, ID(__prepare__)));
642 if (prepare_method.isError()) {
643 Object given(&scope, thread->pendingExceptionType());
644 Object exc(&scope, runtime->typeAt(LayoutId::kAttributeError));
645 if (!givenExceptionMatches(thread, given, exc)) {
646 return *prepare_method;
647 }
648 thread->clearPendingException();
649 dict_obj = runtime->newDict();
650 } else {
651 thread->stackPush(*prepare_method);
652 Tuple pargs(&scope, runtime->newTupleWith2(name, bases));
653 thread->stackPush(*pargs);
654 thread->stackPush(*kwargs);
655 dict_obj = Interpreter::callEx(thread, CallFunctionExFlag::VAR_KEYWORDS);
656 if (dict_obj.isError()) return *dict_obj;
657 }
658 if (!runtime->isMapping(thread, dict_obj)) {
659 if (metaclass_is_class) {
660 Type metaclass_type(&scope, *metaclass);
661 Str metaclass_type_name(&scope, metaclass_type.name());
662 return thread->raiseWithFmt(
663 LayoutId::kTypeError,
664 "%S.__prepare__() must return a mapping, not %T",
665 &metaclass_type_name, &dict_obj);
666 }
667 return thread->raiseWithFmt(
668 LayoutId::kTypeError,
669 "<metaclass>.__prepare__() must return a mapping, not %T", &dict_obj);
670 }
671 Dict type_dict(&scope, *dict_obj);
672
673 // TODO(cshapiro): might need to do some kind of callback here and we want
674 // backtraces to work correctly. The key to doing that would be to put some
675 // state on the stack in between the the incoming arguments from the builtin
676 // caller and the on-stack state for the class body function call.
677 Object body_result(&scope,
678 thread->callFunctionWithImplicitGlobals(body, type_dict));
679 if (body_result.isError()) return *body_result;
680
681 if (bases != orig_bases) {
682 dictAtPutById(thread, type_dict, ID(__orig_bases__), orig_bases);
683 }
684
685 thread->stackPush(*metaclass);
686 Tuple pargs(&scope, runtime->newTupleWith3(name, bases, type_dict));
687 thread->stackPush(*pargs);
688 thread->stackPush(*kwargs);
689 return Interpreter::callEx(thread, CallFunctionExFlag::VAR_KEYWORDS);
690}
691
692RawObject FUNC(builtins, callable)(Thread* thread, Arguments args) {
693 HandleScope scope(thread);
694 Object arg(&scope, args.get(0));
695 return Bool::fromBool(thread->runtime()->isCallable(thread, arg));
696}
697
698RawObject FUNC(builtins, chr)(Thread* thread, Arguments args) {
699 HandleScope scope(thread);
700 Object arg(&scope, args.get(0));
701 Runtime* runtime = thread->runtime();
702 if (!runtime->isInstanceOfInt(*arg)) {
703 return thread->raiseWithFmt(LayoutId::kTypeError,
704 "an integer is required (got type %T)", &arg);
705 }
706 Int num(&scope, intUnderlying(*arg));
707 if (!num.isSmallInt()) {
708 return thread->raiseWithFmt(LayoutId::kOverflowError,
709 "Python int too large to convert to C int");
710 }
711 word code_point = num.asWord();
712 if (code_point < 0 || code_point > kMaxUnicode) {
713 return thread->raiseWithFmt(LayoutId::kValueError,
714 "chr() arg not in range(0x110000)");
715 }
716 return SmallStr::fromCodePoint(static_cast<int32_t>(code_point));
717}
718
719RawObject FUNC(builtins, id)(Thread* thread, Arguments args) {
720 // NOTE: This pins a handle until the runtime exits.
721 // TODO(emacs): Either determine that this function is used so little that it
722 // does not matter or add a section to the GC to clean up handles created by
723 // id().
724 Runtime* runtime = thread->runtime();
725 return runtime->newIntFromCPtr(objectNewReference(runtime, args.get(0)));
726}
727
728RawObject FUNC(builtins, oct)(Thread* thread, Arguments args) {
729 HandleScope scope(thread);
730 Object number(&scope, args.get(0));
731 number = intFromIndex(thread, number);
732 if (number.isError()) {
733 return *number;
734 }
735 Int number_int(&scope, intUnderlying(*number));
736 return formatIntOctalSimple(thread, number_int);
737}
738
739RawObject FUNC(builtins, ord)(Thread* thread, Arguments args) {
740 HandleScope scope(thread);
741 Object obj(&scope, args.get(0));
742 Runtime* runtime = thread->runtime();
743 if (runtime->isInstanceOfBytes(*obj)) {
744 Bytes bytes(&scope, bytesUnderlying(*obj));
745 if (bytes.length() == 1) {
746 int32_t code_point = bytes.byteAt(0);
747 return SmallInt::fromWord(code_point);
748 }
749 } else if (runtime->isInstanceOfStr(*obj)) {
750 Str str(&scope, strUnderlying(*obj));
751 if (str.isSmallStr() && *str != Str::empty()) {
752 word num_bytes;
753 int32_t code_point = str.codePointAt(0, &num_bytes);
754 if (num_bytes == str.length()) {
755 return SmallInt::fromWord(code_point);
756 }
757 }
758 } else if (runtime->isInstanceOfBytearray(*obj)) {
759 Bytearray byte_array(&scope, *obj);
760 if (byte_array.numItems() == 1) {
761 int32_t code_point = byte_array.byteAt(0);
762 return SmallInt::fromWord(code_point);
763 }
764 } else {
765 return thread->raiseWithFmt(LayoutId::kTypeError,
766 "Unsupported type in builtin 'ord'");
767 }
768 return thread->raiseWithFmt(LayoutId::kTypeError,
769 "Builtin 'ord' expects string of length 1");
770}
771
772RawObject FUNC(builtins, __import__)(Thread* thread, Arguments args) {
773 // Note that this is a simplified __import__ implementation that is used
774 // during early bootstrap; it is replaced by importlib.__import__ once
775 // import lib is fully initialized.
776 HandleScope scope(thread);
777 Str name(&scope, args.get(0));
778 name = Runtime::internStr(thread, name);
779 // We ignore arg1, arg2, arg3.
780 DCHECK(args.get(4) == SmallInt::fromWord(0), "only supports level=0");
781 Runtime* runtime = thread->runtime();
782 Object module(&scope, ensureBuiltinModule(thread, name));
783 if (module.isErrorNotFound() || !runtime->isInstanceOfModule(*module)) {
784 return thread->raiseWithFmt(LayoutId::kImportError,
785 "failed to import %S (bootstrap importer)",
786 &name);
787 }
788 return *module;
789}
790
791RawObject FUNC(builtins, _debug_break)(Thread*, Arguments) {
792#if __has_builtin(__builtin_debugtrap)
793 __builtin_debugtrap();
794#elif defined(__i386__) || defined(__x86_64__)
795 __asm__ volatile("int $0x03");
796#else
797 std::raise(SIGTRAP);
798#endif
799 return NoneType::object();
800}
801
802// TODO(T39322942): Turn this into the Range constructor (__init__ or __new__)
803RawObject FUNC(builtins, getattr)(Thread* thread, Arguments args) {
804 HandleScope scope(thread);
805 Object self(&scope, args.get(0));
806 Object name(&scope, args.get(1));
807 Object default_obj(&scope, args.get(2));
808 if (!default_obj.isUnbound()) {
809 Object result(&scope, getAttributeWithDefault(thread, self, name));
810 if (result.isErrorNotFound()) {
811 return *default_obj;
812 }
813 if (result.isError()) {
814 Type given(&scope, thread->pendingExceptionType());
815 Runtime* runtime = thread->runtime();
816 Type exc(&scope, runtime->typeAt(LayoutId::kAttributeError));
817 if (givenExceptionMatches(thread, given, exc)) {
818 thread->clearPendingException();
819 return *default_obj;
820 }
821 return *result;
822 }
823 return *result;
824 }
825 return getAttribute(thread, self, name);
826}
827
828RawObject FUNC(builtins, hasattr)(Thread* thread, Arguments args) {
829 HandleScope scope(thread);
830 Object self(&scope, args.get(0));
831 Object name(&scope, args.get(1));
832 return hasAttribute(thread, self, name);
833}
834
835RawObject FUNC(builtins, hash)(Thread* thread, Arguments args) {
836 HandleScope scope(thread);
837 Object object(&scope, args.get(0));
838 return Interpreter::hash(thread, object);
839}
840
841RawObject FUNC(builtins, hex)(Thread* thread, Arguments args) {
842 HandleScope scope(thread);
843 Object number(&scope, args.get(0));
844 number = intFromIndex(thread, number);
845 if (number.isError()) {
846 return *number;
847 }
848 Int number_int(&scope, intUnderlying(*number));
849 return formatIntHexadecimalSimple(thread, number_int);
850}
851
852RawObject FUNC(builtins, setattr)(Thread* thread, Arguments args) {
853 HandleScope scope(thread);
854 Object self(&scope, args.get(0));
855 Object name(&scope, args.get(1));
856 Object value(&scope, args.get(2));
857 return setAttribute(thread, self, name, value);
858}
859
860} // namespace py