this repo has no description
at trunk 351 lines 13 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "module-builtins.h" 3 4#include "attributedict.h" 5#include "builtins.h" 6#include "capi.h" 7#include "dict-builtins.h" 8#include "frame.h" 9#include "globals.h" 10#include "ic.h" 11#include "object-builtins.h" 12#include "objects.h" 13#include "runtime.h" 14#include "thread.h" 15#include "type-builtins.h" 16 17namespace py { 18 19RawObject moduleAt(const Module& module, const Object& name) { 20 RawObject result = NoneType::object(); 21 if (!attributeAt(*module, *name, &result)) return Error::notFound(); 22 return result; 23} 24 25RawObject moduleAtById(Thread* thread, const Module& module, SymbolId id) { 26 RawObject name = thread->runtime()->symbols()->at(id); 27 RawObject result = NoneType::object(); 28 if (!attributeAt(*module, name, &result)) return Error::notFound(); 29 return result; 30} 31 32RawObject moduleDeleteAttribute(Thread* thread, const Module& module, 33 const Object& name) { 34 // Check for a descriptor with __delete__ 35 HandleScope scope(thread); 36 Runtime* runtime = thread->runtime(); 37 Type type(&scope, runtime->typeOf(*module)); 38 Object type_attr(&scope, typeLookupInMro(thread, *type, *name)); 39 if (!type_attr.isErrorNotFound() && 40 runtime->isDeleteDescriptor(thread, type_attr)) { 41 return Interpreter::callDescriptorDelete(thread, type_attr, module); 42 } 43 44 // No delete descriptor found, attempt to delete from the module dict 45 if (moduleRemove(thread, module, name).isError()) { 46 Str module_name(&scope, module.name()); 47 return thread->raiseWithFmt(LayoutId::kAttributeError, 48 "module '%S' has no attribute '%S'", 49 &module_name, &name); 50 } 51 52 return NoneType::object(); 53} 54 55RawObject moduleValueCellAtById(Thread* thread, const Module& module, 56 SymbolId id) { 57 RawObject name = thread->runtime()->symbols()->at(id); 58 RawObject result = NoneType::object(); 59 if (!attributeValueCellAt(*module, name, &result) || 60 ValueCell::cast(result).isPlaceholder()) { 61 return Error::notFound(); 62 } 63 return result; 64} 65 66RawObject moduleValueCellAt(Thread*, const Module& module, const Object& name) { 67 RawObject result = NoneType::object(); 68 if (!attributeValueCellAt(*module, *name, &result) || 69 ValueCell::cast(result).isPlaceholder()) { 70 return Error::notFound(); 71 } 72 return result; 73} 74 75static RawObject moduleValueCellAtPut(Thread* thread, const Module& module, 76 const Object& name, const Object& value) { 77 RawObject module_result = NoneType::object(); 78 if (attributeValueCellAt(*module, *name, &module_result) && 79 ValueCell::cast(module_result).isPlaceholder()) { 80 // A builtin entry is cached under the same name, so invalidate its caches. 81 HandleScope scope(thread); 82 Object builtins(&scope, moduleAtById(thread, module, ID(__builtins__))); 83 Module builtins_module(&scope, *module); 84 if (builtins.isModuleProxy()) { 85 builtins = ModuleProxy::cast(*builtins).module(); 86 } 87 if (thread->runtime()->isInstanceOfModule(*builtins)) { 88 builtins_module = *builtins; 89 RawObject builtins_result = NoneType::object(); 90 if (attributeValueCellAt(*builtins_module, *name, &builtins_result)) { 91 ValueCell builtins_value_cell(&scope, builtins_result); 92 if (!builtins_value_cell.isPlaceholder()) { 93 DCHECK(!builtins_value_cell.dependencyLink().isNoneType(), 94 "the builtin valuecell must have a dependent"); 95 icInvalidateGlobalVar(thread, builtins_value_cell); 96 } 97 } 98 } 99 } 100 return attributeAtPut(thread, module, name, value); 101} 102 103RawObject moduleAtPut(Thread* thread, const Module& module, const Object& name, 104 const Object& value) { 105 return moduleValueCellAtPut(thread, module, name, value); 106} 107 108RawObject moduleAtPutById(Thread* thread, const Module& module, SymbolId id, 109 const Object& value) { 110 HandleScope scope(thread); 111 Object name(&scope, thread->runtime()->symbols()->at(id)); 112 return moduleValueCellAtPut(thread, module, name, value); 113} 114 115RawObject moduleAtPutByCStr(Thread* thread, const Module& module, 116 const char* name_cstr, const Object& value) { 117 HandleScope scope(thread); 118 Object name(&scope, Runtime::internStrFromCStr(thread, name_cstr)); 119 return moduleValueCellAtPut(thread, module, name, value); 120} 121 122RawObject moduleKeys(Thread* thread, const Module& module) { 123 return attributeKeys(thread, module); 124} 125 126word moduleLen(Thread* thread, const Module& module) { 127 return attributeLen(thread, module); 128} 129 130RawObject moduleRaiseAttributeError(Thread* thread, const Module& module, 131 const Object& name) { 132 HandleScope scope(thread); 133 Object module_name(&scope, module.name()); 134 if (!thread->runtime()->isInstanceOfStr(*module_name)) { 135 return thread->raiseWithFmt(LayoutId::kAttributeError, 136 "module has no attribute '%S'", &name); 137 } 138 return thread->raiseWithFmt(LayoutId::kAttributeError, 139 "module '%S' has no attribute '%S'", &module_name, 140 &name); 141} 142 143RawObject moduleRemove(Thread* thread, const Module& module, 144 const Object& name) { 145 DCHECK(Runtime::isInternedStr(thread, name), "expected interned str"); 146 HandleScope scope(thread); 147 word index; 148 Object value_cell_obj(&scope, NoneType::object()); 149 if (!attributeFindForRemoval(module, name, &value_cell_obj, &index)) { 150 return Error::notFound(); 151 } 152 attributeRemove(module, index); 153 ValueCell value_cell(&scope, *value_cell_obj); 154 icInvalidateGlobalVar(thread, value_cell); 155 if (value_cell.isPlaceholder()) return Error::notFound(); 156 Object previous_value(&scope, value_cell.value()); 157 value_cell.makePlaceholder(); 158 return *previous_value; 159} 160 161RawObject moduleValues(Thread* thread, const Module& module) { 162 return attributeValues(thread, module); 163} 164 165RawObject moduleGetAttribute(Thread* thread, const Module& module, 166 const Object& name) { 167 return moduleGetAttributeSetLocation(thread, module, name, nullptr); 168} 169 170RawObject moduleGetAttributeSetLocation(Thread* thread, const Module& module, 171 const Object& name, 172 Object* location_out) { 173 HandleScope scope(thread); 174 Runtime* runtime = thread->runtime(); 175 Type module_type(&scope, runtime->typeOf(*module)); 176 // TODO(T66579052): Skip type lookups for `module` type when `name` doesn't 177 // start with "__". 178 Object attr(&scope, typeLookupInMro(thread, *module_type, *name)); 179 if (!attr.isError()) { 180 Type attr_type(&scope, runtime->typeOf(*attr)); 181 if (typeIsDataDescriptor(*attr_type)) { 182 return Interpreter::callDescriptorGet(thread, attr, module, module_type); 183 } 184 } 185 186 Object result(&scope, moduleValueCellAt(thread, module, name)); 187 DCHECK(result.isValueCell() || result.isErrorNotFound(), 188 "result must be a value cell or not found"); 189 if (!result.isErrorNotFound() && !ValueCell::cast(*result).isPlaceholder()) { 190 if (location_out != nullptr) { 191 *location_out = *result; 192 } 193 return ValueCell::cast(*result).value(); 194 } 195 196 if (!attr.isError()) { 197 Type attr_type(&scope, runtime->typeOf(*attr)); 198 if (typeIsNonDataDescriptor(*attr_type)) { 199 return Interpreter::callDescriptorGet(thread, attr, module, module_type); 200 } 201 return *attr; 202 } 203 204 Object dunder_getattr(&scope, moduleAtById(thread, module, ID(__getattr__))); 205 if (!dunder_getattr.isErrorNotFound()) { 206 return Interpreter::call1(thread, dunder_getattr, name); 207 } 208 209 return Error::notFound(); 210} 211 212RawObject moduleSetAttr(Thread* thread, const Module& module, 213 const Object& name, const Object& value) { 214 moduleAtPut(thread, module, name, value); 215 return NoneType::object(); 216} 217 218RawObject moduleInit(Thread* thread, const Module& module, const Object& name) { 219 HandleScope scope(thread); 220 Runtime* runtime = thread->runtime(); 221 module.setModuleProxy(runtime->newModuleProxy(module)); 222 if (name.isStr()) { 223 module.setName(*name); 224 } 225 module.setDef(runtime->newIntFromCPtr(nullptr)); 226 module.setState(runtime->newIntFromCPtr(nullptr)); 227 moduleAtPutById(thread, module, ID(__name__), name); 228 229 Object none(&scope, NoneType::object()); 230 moduleAtPutById(thread, module, ID(__doc__), none); 231 moduleAtPutById(thread, module, ID(__package__), none); 232 moduleAtPutById(thread, module, ID(__loader__), none); 233 moduleAtPutById(thread, module, ID(__spec__), none); 234 return NoneType::object(); 235} 236 237static const BuiltinAttribute kModuleAttributes[] = { 238 {ID(_module__attributes), RawModule::kAttributesOffset, 239 AttributeFlags::kHidden}, 240 {ID(_module__attributes_remaining), RawModule::kAttributesRemainingOffset, 241 AttributeFlags::kHidden}, 242 {ID(_module__name), RawModule::kNameOffset, AttributeFlags::kHidden}, 243 {ID(_module__def), RawModule::kDefOffset, AttributeFlags::kHidden}, 244 {ID(_module__state), RawModule::kStateOffset, AttributeFlags::kHidden}, 245 {ID(_module__proxy), RawModule::kModuleProxyOffset, 246 AttributeFlags::kHidden}, 247}; 248 249void initializeModuleType(Thread* thread) { 250 HandleScope scope(thread); 251 Type type(&scope, addBuiltinType(thread, ID(module), LayoutId::kModule, 252 /*superclass_id=*/LayoutId::kObject, 253 kModuleAttributes, Module::kSize, 254 /*basetype=*/true)); 255 word flags = static_cast<word>(type.flags()); 256 flags |= RawType::Flag::kHasCustomDict; 257 type.setFlags(static_cast<Type::Flag>(flags)); 258 Runtime* runtime = thread->runtime(); 259 Object object_type(&scope, runtime->typeAt(LayoutId::kObject)); 260 type.setMro(runtime->newTupleWith2(type, object_type)); 261} 262 263RawObject METH(module, __delattr__)(Thread* thread, Arguments args) { 264 HandleScope scope(thread); 265 Object self_obj(&scope, args.get(0)); 266 if (!thread->runtime()->isInstanceOfModule(*self_obj)) { 267 return thread->raiseRequiresType(self_obj, ID(module)); 268 } 269 Module self(&scope, *self_obj); 270 Object name(&scope, args.get(1)); 271 name = attributeName(thread, name); 272 if (name.isErrorException()) return *name; 273 return moduleDeleteAttribute(thread, self, name); 274} 275 276RawObject METH(module, __getattribute__)(Thread* thread, Arguments args) { 277 HandleScope scope(thread); 278 Object self_obj(&scope, args.get(0)); 279 Runtime* runtime = thread->runtime(); 280 if (!runtime->isInstanceOfModule(*self_obj)) { 281 return thread->raiseRequiresType(self_obj, ID(module)); 282 } 283 Module self(&scope, *self_obj); 284 Object name(&scope, args.get(1)); 285 name = attributeName(thread, name); 286 if (name.isErrorException()) return *name; 287 Object result(&scope, moduleGetAttribute(thread, self, name)); 288 if (result.isErrorNotFound()) { 289 return moduleRaiseAttributeError(thread, self, name); 290 } 291 return *result; 292} 293 294RawObject METH(module, __new__)(Thread* thread, Arguments args) { 295 HandleScope scope(thread); 296 Object cls_obj(&scope, args.get(0)); 297 Runtime* runtime = thread->runtime(); 298 if (!runtime->isInstanceOfType(*cls_obj)) { 299 return thread->raiseWithFmt( 300 LayoutId::kTypeError, "module.__new__(X): X is not a type object (%T)", 301 &cls_obj); 302 } 303 Type cls(&scope, *cls_obj); 304 if (cls.builtinBase() != LayoutId::kModule) { 305 Object cls_name(&scope, cls.name()); 306 return thread->raiseWithFmt( 307 LayoutId::kTypeError, 308 "module.__new__(%S): %S is not a subtype of module", &cls_name, 309 &cls_name); 310 } 311 Layout layout(&scope, cls.instanceLayout()); 312 Module result(&scope, runtime->newInstance(layout)); 313 attributeDictInit(thread, result); 314 result.setDef(runtime->newIntFromCPtr(nullptr)); 315 result.setId(runtime->reserveModuleId()); 316 return *result; 317} 318 319RawObject METH(module, __init__)(Thread* thread, Arguments args) { 320 HandleScope scope(thread); 321 Object self_obj(&scope, args.get(0)); 322 Runtime* runtime = thread->runtime(); 323 if (!runtime->isInstanceOfModule(*self_obj)) { 324 return thread->raiseRequiresType(self_obj, ID(module)); 325 } 326 Module self(&scope, *self_obj); 327 Object name(&scope, args.get(1)); 328 if (!runtime->isInstanceOfStr(*name)) { 329 return thread->raiseWithFmt( 330 LayoutId::kTypeError, 331 "module.__init__() argument 1 must be str, not %T", &name); 332 } 333 return moduleInit(thread, self, name); 334} 335 336RawObject METH(module, __setattr__)(Thread* thread, Arguments args) { 337 HandleScope scope(thread); 338 Object self_obj(&scope, args.get(0)); 339 Runtime* runtime = thread->runtime(); 340 if (!runtime->isInstanceOfModule(*self_obj)) { 341 return thread->raiseRequiresType(self_obj, ID(module)); 342 } 343 Module self(&scope, *self_obj); 344 Object name(&scope, args.get(1)); 345 name = attributeName(thread, name); 346 if (name.isErrorException()) return *name; 347 Object value(&scope, args.get(2)); 348 return moduleSetAttr(thread, self, name, value); 349} 350 351} // namespace py