this repo has no description
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
2#pragma once
3
4#include "attributedict.h"
5#include "frame.h"
6#include "globals.h"
7#include "layout.h"
8#include "objects.h"
9#include "runtime.h"
10#include "thread.h"
11
12namespace py {
13
14constexpr View<BuiltinAttribute> kNoAttributes(nullptr, 0);
15
16// Prepare `name_obj` to be used as an attribute name: Raise a TypeError if it
17// is not a string; reject some string subclasses. Otherwise return an
18// interned string that can be used with attribute accessors.
19RawObject attributeName(Thread* thread, const Object& name_obj);
20
21RawObject attributeNameNoException(Thread* thread, const Object& name_obj);
22
23RawObject addBuiltinType(Thread* thread, SymbolId name, LayoutId layout_id,
24 LayoutId superclass_id, View<BuiltinAttribute> attrs,
25 word size, bool basetype);
26
27RawObject addImmediateBuiltinType(Thread* thread, SymbolId name,
28 LayoutId layout_id, LayoutId builtin_base,
29 LayoutId superclass_id, bool basetype);
30
31void builtinTypeEnableTupleOverflow(Thread* thread, const Type& type);
32
33// Returns the most generic base among `bases` that captures inherited
34// attributes with a fixed offset (either from __slots__ or builtin types)
35// Note that this simulates `best_base` from CPython's typeobject.c.
36RawObject computeFixedAttributeBase(Thread* thread, const Tuple& bases);
37
38RawObject findBuiltinTypeWithName(Thread* thread, const Object& name);
39
40RawObject raiseTypeErrorCannotSetImmutable(Thread* thread, const Type& type);
41
42bool typeIsSubclass(RawObject subclass, RawObject superclass);
43
44void typeAddDocstring(Thread* thread, const Type& type);
45void typeAddInstanceDict(Thread* thread, const Type& type);
46
47// Assign all key/values from the dict to the type. This interns the keys as
48// necessary or may raise an exception for invalid keys (see attributeName()).
49RawObject typeAssignFromDict(Thread* thread, const Type& type,
50 const Dict& dict);
51
52RawObject typeAt(const Type& type, const Object& name);
53
54RawObject typeAtSetLocation(RawType type, RawObject name, word hash,
55 Object* location);
56
57RawObject typeAtById(Thread* thread, const Type& type, SymbolId id);
58
59RawObject typeAtPut(Thread* thread, const Type& type, const Object& name,
60 const Object& value);
61
62RawObject typeAtPutById(Thread* thread, const Type& type, SymbolId id,
63 const Object& value);
64
65RawObject typeDeleteAttribute(Thread* thread, const Type& receiver,
66 const Object& name);
67
68RawObject typeRemove(Thread* thread, const Type& type, const Object& name);
69
70RawObject typeRemoveById(Thread* thread, const Type& type, SymbolId id);
71
72RawObject typeKeys(Thread* thread, const Type& type);
73
74word typeLen(Thread* thread, const Type& type);
75
76RawObject typeValues(Thread* thread, const Type& type);
77
78RawObject typeGetAttribute(Thread* thread, const Type& type,
79 const Object& name);
80
81RawObject typeGetAttributeSetLocation(Thread* thread, const Type& type,
82 const Object& name, Object* location_out);
83
84// Returns true if the type defines a __set__ method.
85bool typeIsDataDescriptor(RawType type);
86
87// Returns true if the type defines a __get__ method.
88bool typeIsNonDataDescriptor(RawType type);
89
90// If descr's Type has __get__(), call it with the appropriate arguments and
91// return the result. Otherwise, return descr.
92RawObject resolveDescriptorGet(Thread* thread, const Object& descr,
93 const Object& instance,
94 const Object& instance_type);
95
96RawObject typeInit(Thread* thread, const Type& type, const Str& name,
97 const Dict& dict, const Tuple& mro);
98
99// Looks up `key` in the dict of each entry in type's MRO. Returns
100// `Error::notFound()` if the name was not found.
101RawObject typeLookupInMro(Thread* thread, RawType type, RawObject name);
102
103RawObject typeLookupInMroSetLocation(Thread* thread, RawType type,
104 RawObject name, Object* location);
105
106// Looks up `id` in the dict of each entry in type's MRO. Returns
107// `Error::notFound()` if the name was not found.
108RawObject typeLookupInMroById(Thread* thread, RawType type, SymbolId id);
109
110RawObject typeNew(Thread* thread, const Type& metaclass, const Str& name,
111 const Tuple& bases, const Dict& dict, word flags,
112 bool inherit_slots, bool add_instance_dict);
113
114RawObject typeSetAttr(Thread* thread, const Type& type, const Object& name,
115 const Object& value);
116
117// Sets __class__ of self to new_type.
118// Returns None on success.
119// Raises an exception and returns Error::exception() otherwise.
120RawObject typeSetDunderClass(Thread* thread, const Object& self,
121 const Type& new_type);
122
123// Terminate the process if cache invalidation for updating attr_name in type
124// objects is unimplemented.
125void terminateIfUnimplementedTypeAttrCacheInvalidation(Thread* thread,
126 const Type& type,
127 const Object& attr_name);
128
129void initializeTypeTypes(Thread* thread);
130
131inline bool typeIsSubclass(RawObject subclass, RawObject superclass) {
132 if (DCHECK_IS_ON()) {
133 Runtime* runtime = Thread::current()->runtime();
134 DCHECK(runtime->isInstanceOfType(subclass),
135 "typeIsSubclass subclass must be a type object");
136 DCHECK(runtime->isInstanceOfType(superclass),
137 "typeIsSubclass superclass must be a type object");
138 DCHECK(Tuple::cast(subclass.rawCast<RawType>().mro()).at(0) == subclass,
139 "unexpected mro");
140 }
141 if (subclass == superclass) return true;
142 RawTuple mro = Tuple::cast(subclass.rawCast<RawType>().mro());
143 word length = mro.length();
144 for (word i = 1; i < length; i++) {
145 if (mro.at(i) == superclass) {
146 return true;
147 }
148 }
149 return false;
150}
151
152inline RawObject typeLookupInMro(Thread* thread, RawType type, RawObject name) {
153 RawTuple mro = Tuple::cast(type.mro());
154 word hash = internedStrHash(name);
155 for (word i = 0, length = mro.length(); i < length; i++) {
156 DCHECK(thread->runtime()->isInstanceOfType(mro.at(i)), "non-type in MRO");
157 RawType mro_type = mro.at(i).rawCast<RawType>();
158 RawObject result = NoneType::object();
159 if (attributeAtWithHash(mro_type, name, hash, &result)) {
160 return result;
161 }
162 }
163 return Error::notFound();
164}
165
166} // namespace py