this repo has no description
at trunk 166 lines 6.6 kB view raw
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