this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "function-builtins.h"
3
4#include "builtins.h"
5#include "dict-builtins.h"
6#include "frame.h"
7#include "globals.h"
8#include "object-builtins.h"
9#include "objects.h"
10#include "runtime.h"
11#include "str-builtins.h"
12#include "thread.h"
13#include "type-builtins.h"
14
15namespace py {
16
17static const BuiltinAttribute kFunctionAttributes[] = {
18 // TODO(T44845145) Support assignment to __code__.
19 {ID(__code__), RawFunction::kCodeOffset, AttributeFlags::kReadOnly},
20 {ID(_function__flags), RawFunction::kFlagsOffset, AttributeFlags::kHidden},
21 {ID(_function__argcount), RawFunction::kArgcountOffset,
22 AttributeFlags::kHidden},
23 {ID(_function__total_args), RawFunction::kTotalArgsOffset,
24 AttributeFlags::kHidden},
25 {ID(_function__total_vars), RawFunction::kTotalVarsOffset,
26 AttributeFlags::kHidden},
27 {ID(_function__stack_size), RawFunction::kStacksizeOrBuiltinOffset,
28 AttributeFlags::kHidden},
29 {ID(__doc__), RawFunction::kDocOffset},
30 {ID(__name__), RawFunction::kNameOffset},
31 {ID(__qualname__), RawFunction::kQualnameOffset},
32 {ID(__module__), RawFunction::kModuleNameOffset},
33 {ID(__module_object__), RawFunction::kModuleObjectOffset},
34 {ID(_function__defaults), RawFunction::kDefaultsOffset,
35 AttributeFlags::kHidden},
36 {ID(_function__annotations), RawFunction::kAnnotationsOffset,
37 AttributeFlags::kHidden},
38 {ID(_function__kw_defaults), RawFunction::kKwDefaultsOffset,
39 AttributeFlags::kHidden},
40 {ID(_function__closure), RawFunction::kClosureOffset,
41 AttributeFlags::kHidden},
42 {ID(_function__entry), RawFunction::kEntryOffset, AttributeFlags::kHidden},
43 {ID(_function__entry_kw), RawFunction::kEntryKwOffset,
44 AttributeFlags::kHidden},
45 {ID(_function__entry_ex), RawFunction::kEntryExOffset,
46 AttributeFlags::kHidden},
47 {ID(_function__entry_asm), RawFunction::kEntryAsmOffset,
48 AttributeFlags::kHidden},
49 {ID(_function__rewritten_bytecode), RawFunction::kRewrittenBytecodeOffset,
50 AttributeFlags::kHidden},
51 {ID(_function__caches), RawFunction::kCachesOffset,
52 AttributeFlags::kHidden},
53 {ID(_function__dict), RawFunction::kDictOffset, AttributeFlags::kHidden},
54 {ID(_function__intrinsic), RawFunction::kIntrinsicOffset,
55 AttributeFlags::kHidden},
56};
57
58static const BuiltinAttribute kBoundMethodAttributes[] = {
59 {ID(__func__), RawBoundMethod::kFunctionOffset, AttributeFlags::kReadOnly},
60 {ID(__self__), RawBoundMethod::kSelfOffset, AttributeFlags::kReadOnly},
61};
62
63static const BuiltinAttribute kInstanceMethodAttributes[] = {
64 {ID(__func__), RawInstanceMethod::kFunctionOffset,
65 AttributeFlags::kReadOnly},
66};
67
68void initializeFunctionTypes(Thread* thread) {
69 HandleScope scope(thread);
70 Type type(&scope, addBuiltinType(thread, ID(function), LayoutId::kFunction,
71 /*superclass_id=*/LayoutId::kObject,
72 kFunctionAttributes, Function::kSize,
73 /*basetype=*/false));
74 Layout layout(&scope, type.instanceLayout());
75 layout.setDictOverflowOffset(RawFunction::kDictOffset);
76
77 addBuiltinType(thread, ID(method), LayoutId::kBoundMethod,
78 /*superclass_id=*/LayoutId::kObject, kBoundMethodAttributes,
79 BoundMethod::kSize, /*basetype=*/false);
80
81 addBuiltinType(thread, ID(instancemethod), LayoutId::kInstanceMethod,
82 /*superclass_id=*/LayoutId::kObject, kInstanceMethodAttributes,
83 InstanceMethod::kSize, /*basetype=*/false);
84}
85
86RawObject slotWrapperFunctionType(const Function& function) {
87 DCHECK(
88 !function.isInterpreted(),
89 "slotWrapperFunctionType does not make sense for interpreted functions");
90 // We misuse the rewrittenBytecode slot for extension functions (they do not
91 // have bytecode).
92 return function.rewrittenBytecode();
93}
94
95void slotWrapperFunctionSetType(const Function& function, const Type& type) {
96 DCHECK(!function.isInterpreted(),
97 "slotWrapperFunctionSetType does not make sense for interpreted "
98 "functions");
99 // We misuse the rewrittenBytecode slot for extension functions (they do not
100 // have bytecode).
101 function.setRewrittenBytecode(*type);
102}
103
104RawObject METH(function, __get__)(Thread* thread, Arguments args) {
105 HandleScope scope(thread);
106 Object self(&scope, args.get(0));
107 if (!self.isFunction()) {
108 return thread->raiseRequiresType(self, ID(function));
109 }
110 Object instance(&scope, args.get(1));
111 // When `instance is None` return the plain function because we are doing a
112 // lookup on a class.
113 if (instance.isNoneType()) {
114 if (args.get(2).isNoneType()) {
115 return thread->raiseWithFmt(LayoutId::kTypeError,
116 "__get__(None, None) is invalid");
117 }
118 return *self;
119 }
120 return thread->runtime()->newBoundMethod(self, instance);
121}
122
123} // namespace py