this repo has no description
at trunk 365 lines 14 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "descriptor-builtins.h" 3 4#include "builtins.h" 5#include "frame.h" 6#include "globals.h" 7#include "object-builtins.h" 8#include "objects.h" 9#include "runtime.h" 10#include "thread.h" 11#include "type-builtins.h" 12 13namespace py { 14 15static const BuiltinAttribute kClassMethodAttributes[] = { 16 {ID(__func__), RawClassMethod::kFunctionOffset, AttributeFlags::kReadOnly}, 17}; 18 19static const BuiltinAttribute kPropertyAttributes[] = { 20 {ID(fget), RawProperty::kGetterOffset, AttributeFlags::kReadOnly}, 21 {ID(fset), RawProperty::kSetterOffset, AttributeFlags::kReadOnly}, 22 {ID(fdel), RawProperty::kDeleterOffset, AttributeFlags::kReadOnly}, 23 {ID(__doc__), RawProperty::kDocOffset}, 24}; 25 26static const BuiltinAttribute kSlotDescriptorAttributes[] = { 27 {ID(__objclass__), RawSlotDescriptor::kTypeOffset, 28 AttributeFlags::kReadOnly}, 29 {ID(__name__), RawSlotDescriptor::kNameOffset, AttributeFlags::kReadOnly}, 30 {ID(_slot_descriptor__offset), RawSlotDescriptor::kOffsetOffset, 31 AttributeFlags::kHidden}, 32}; 33 34static const BuiltinAttribute kStaticMethodAttributes[] = { 35 {ID(__func__), RawStaticMethod::kFunctionOffset, AttributeFlags::kReadOnly}, 36}; 37 38void initializeDescriptorTypes(Thread* thread) { 39 addBuiltinType(thread, ID(classmethod), LayoutId::kClassMethod, 40 /*superclass_id=*/LayoutId::kObject, kClassMethodAttributes, 41 ClassMethod::kSize, /*basetype=*/true); 42 43 addBuiltinType(thread, ID(property), LayoutId::kProperty, 44 /*superclass_id=*/LayoutId::kObject, kPropertyAttributes, 45 Property::kSize, /*basetype=*/true); 46 47 addBuiltinType(thread, ID(slot_descriptor), LayoutId::kSlotDescriptor, 48 /*superclass_id=*/LayoutId::kObject, kSlotDescriptorAttributes, 49 SlotDescriptor::kSize, /*basetype=*/false); 50 51 addBuiltinType(thread, ID(staticmethod), LayoutId::kStaticMethod, 52 /*superclass_id=*/LayoutId::kObject, kStaticMethodAttributes, 53 StaticMethod::kSize, /*basetype=*/true); 54} 55 56// classmethod 57 58RawObject METH(classmethod, __new__)(Thread* thread, Arguments args) { 59 HandleScope scope(thread); 60 Object type_obj(&scope, args.get(0)); 61 Runtime* runtime = thread->runtime(); 62 if (!runtime->isInstanceOfType(*type_obj)) { 63 return thread->raiseWithFmt(LayoutId::kTypeError, "not a type object"); 64 } 65 Type type(&scope, *type_obj); 66 if (type.builtinBase() != LayoutId::kClassMethod) { 67 return thread->raiseWithFmt(LayoutId::kTypeError, 68 "not a subtype of classmethod"); 69 } 70 Layout layout(&scope, type.instanceLayout()); 71 ClassMethod result(&scope, runtime->newInstance(layout)); 72 return *result; 73} 74 75RawObject METH(classmethod, __init__)(Thread* thread, Arguments args) { 76 HandleScope scope(thread); 77 Object self(&scope, args.get(0)); 78 if (!thread->runtime()->isInstanceOfClassMethod(*self)) { 79 return thread->raiseRequiresType(self, ID(classmethod)); 80 } 81 ClassMethod classmethod(&scope, *self); 82 Object arg(&scope, args.get(1)); 83 classmethod.setFunction(*arg); 84 return NoneType::object(); 85} 86 87RawObject METH(classmethod, __get__)(Thread* thread, Arguments args) { 88 HandleScope scope(thread); 89 Runtime* runtime = thread->runtime(); 90 Object self(&scope, args.get(0)); 91 if (!runtime->isInstanceOfClassMethod(*self)) { 92 return thread->raiseRequiresType(self, ID(classmethod)); 93 } 94 Object owner(&scope, args.get(2)); 95 96 ClassMethod classmethod(&scope, *self); 97 Object method(&scope, classmethod.function()); 98 return runtime->newBoundMethod(method, owner); 99} 100 101// slot_descriptor 102 103static RawObject slotDescriptorRaiseTypeError( 104 Thread* thread, const SlotDescriptor& slot_descriptor, 105 const Object& instance_obj) { 106 HandleScope scope(thread); 107 Str slot_descriptor_name(&scope, slot_descriptor.name()); 108 Type slot_descriptor_type(&scope, slot_descriptor.type()); 109 Str slot_descriptor_type_name(&scope, slot_descriptor_type.name()); 110 return thread->raiseWithFmt(LayoutId::kTypeError, 111 "descriptor '%S' for '%S' objects " 112 "doesn't apply to a '%T' object", 113 &slot_descriptor_name, &slot_descriptor_type_name, 114 &instance_obj); 115} 116 117RawObject slotDescriptorGet(Thread* thread, 118 const SlotDescriptor& slot_descriptor, 119 const Object& instance_obj, 120 const Object& owner_obj) { 121 if (instance_obj.isNoneType()) { 122 if (owner_obj.isNoneType()) { 123 return thread->raiseWithFmt(LayoutId::kTypeError, 124 "__get__(None, None) is invalid"); 125 } 126 return *slot_descriptor; 127 } 128 HandleScope scope(thread); 129 Type instance_type(&scope, 130 thread->runtime()->typeAt(instance_obj.layoutId())); 131 if (!typeIsSubclass(*instance_type, slot_descriptor.type())) { 132 return slotDescriptorRaiseTypeError(thread, slot_descriptor, instance_obj); 133 } 134 DCHECK(instance_type.hasFlag(Type::Flag::kHasSlots), 135 "instance type is expected to set kHasSlots"); 136 Instance instance(&scope, *instance_obj); 137 word offset = slot_descriptor.offset(); 138 DCHECK_BOUND(offset, instance.size() - kPointerSize); 139 Object attribute_value(&scope, instance.instanceVariableAt(offset)); 140 if (attribute_value.isUnbound()) { 141 Object attribute_name(&scope, slot_descriptor.name()); 142 return objectRaiseAttributeError(thread, instance, attribute_name); 143 } 144 return *attribute_value; 145} 146 147RawObject METH(slot_descriptor, __delete__)(Thread* thread, Arguments args) { 148 HandleScope scope(thread); 149 SlotDescriptor slot_descriptor(&scope, args.get(0)); 150 Object instance_obj(&scope, args.get(1)); 151 Type instance_type(&scope, 152 thread->runtime()->typeAt(instance_obj.layoutId())); 153 if (!typeIsSubclass(*instance_type, slot_descriptor.type())) { 154 return slotDescriptorRaiseTypeError(thread, slot_descriptor, instance_obj); 155 } 156 Object owner_obj(&scope, NoneType::object()); 157 Object existing_value(&scope, slotDescriptorGet(thread, slot_descriptor, 158 instance_obj, owner_obj)); 159 if (existing_value.isErrorException()) { 160 return *existing_value; 161 } 162 Instance instance(&scope, *instance_obj); 163 instance.instanceVariableAtPut(slot_descriptor.offset(), Unbound::object()); 164 return NoneType::object(); 165} 166 167RawObject METH(slot_descriptor, __get__)(Thread* thread, Arguments args) { 168 HandleScope scope(thread); 169 SlotDescriptor slot_descriptor(&scope, args.get(0)); 170 Object instance(&scope, args.get(1)); 171 Object owner(&scope, args.get(2)); 172 return slotDescriptorGet(thread, slot_descriptor, instance, owner); 173} 174 175RawObject slotDescriptorSet(Thread* thread, 176 const SlotDescriptor& slot_descriptor, 177 const Object& instance_obj, const Object& value) { 178 HandleScope scope(thread); 179 Type instance_type(&scope, 180 thread->runtime()->typeAt(instance_obj.layoutId())); 181 if (!typeIsSubclass(*instance_type, slot_descriptor.type())) { 182 return slotDescriptorRaiseTypeError(thread, slot_descriptor, instance_obj); 183 } 184 DCHECK(instance_type.hasFlag(Type::Flag::kHasSlots), 185 "instance type is expected to set kHasSlots"); 186 Instance instance(&scope, *instance_obj); 187 word offset = slot_descriptor.offset(); 188 DCHECK_BOUND(offset, instance.size() - kPointerSize); 189 instance.instanceVariableAtPut(offset, *value); 190 return NoneType::object(); 191} 192 193RawObject METH(slot_descriptor, __set__)(Thread* thread, Arguments args) { 194 HandleScope scope(thread); 195 SlotDescriptor slot_descriptor(&scope, args.get(0)); 196 Object instance(&scope, args.get(1)); 197 Object value(&scope, args.get(2)); 198 return slotDescriptorSet(thread, slot_descriptor, instance, value); 199} 200 201// staticmethod 202 203RawObject METH(staticmethod, __get__)(Thread* thread, Arguments args) { 204 HandleScope scope(thread); 205 Object self(&scope, args.get(0)); 206 if (!thread->runtime()->isInstanceOfStaticMethod(*self)) { 207 return thread->raiseRequiresType(self, ID(staticmethod)); 208 } 209 StaticMethod staticmethod(&scope, *self); 210 return staticmethod.function(); 211} 212 213RawObject METH(staticmethod, __new__)(Thread* thread, Arguments args) { 214 HandleScope scope(thread); 215 Runtime* runtime = thread->runtime(); 216 Object type_obj(&scope, args.get(0)); 217 if (!runtime->isInstanceOfType(*type_obj)) { 218 return thread->raiseWithFmt(LayoutId::kTypeError, "not a type object"); 219 } 220 Type type(&scope, *type_obj); 221 if (type.builtinBase() != LayoutId::kStaticMethod) { 222 return thread->raiseWithFmt(LayoutId::kTypeError, 223 "not a subtype of staticmethod"); 224 } 225 Layout layout(&scope, type.instanceLayout()); 226 StaticMethod result(&scope, runtime->newInstance(layout)); 227 return *result; 228} 229 230RawObject METH(staticmethod, __init__)(Thread* thread, Arguments args) { 231 HandleScope scope(thread); 232 StaticMethod staticmethod(&scope, args.get(0)); 233 Object arg(&scope, args.get(1)); 234 staticmethod.setFunction(*arg); 235 return NoneType::object(); 236} 237 238// property 239 240RawObject METH(property, __delete__)(Thread* thread, Arguments args) { 241 HandleScope scope(thread); 242 Object self_obj(&scope, args.get(0)); 243 if (!thread->runtime()->isInstanceOfProperty(*self_obj)) { 244 return thread->raiseRequiresType(self_obj, ID(property)); 245 } 246 Property self(&scope, *self_obj); 247 Object deleter(&scope, self.deleter()); 248 if (deleter.isNoneType()) { 249 return thread->raiseWithFmt(LayoutId::kAttributeError, 250 "can't delete attribute"); 251 } 252 Object instance(&scope, args.get(1)); 253 return Interpreter::call1(thread, deleter, instance); 254} 255 256RawObject METH(property, __get__)(Thread* thread, Arguments args) { 257 HandleScope scope(thread); 258 Object self_obj(&scope, args.get(0)); 259 if (!thread->runtime()->isInstanceOfProperty(*self_obj)) { 260 return thread->raiseRequiresType(self_obj, ID(property)); 261 } 262 Property self(&scope, *self_obj); 263 Object getter(&scope, self.getter()); 264 if (getter.isNoneType()) { 265 return thread->raiseWithFmt(LayoutId::kAttributeError, 266 "unreadable attribute"); 267 } 268 Object instance(&scope, args.get(1)); 269 if (instance.isNoneType()) { 270 return *self; 271 } 272 return Interpreter::call1(thread, getter, instance); 273} 274 275RawObject METH(property, __init__)(Thread* thread, Arguments args) { 276 HandleScope scope(thread); 277 Object self_obj(&scope, args.get(0)); 278 if (!thread->runtime()->isInstanceOfProperty(*self_obj)) { 279 return thread->raiseRequiresType(self_obj, ID(property)); 280 } 281 Property self(&scope, *self_obj); 282 self.setGetter(args.get(1)); 283 self.setSetter(args.get(2)); 284 self.setDeleter(args.get(3)); 285 // TODO(T42363565) Do something with the doc argument. 286 return NoneType::object(); 287} 288 289RawObject METH(property, __new__)(Thread* thread, Arguments args) { 290 HandleScope scope(thread); 291 Object type_obj(&scope, args.get(0)); 292 Runtime* runtime = thread->runtime(); 293 if (!runtime->isInstanceOfType(*type_obj)) { 294 return thread->raiseWithFmt(LayoutId::kTypeError, "not a type object"); 295 } 296 Type type(&scope, *type_obj); 297 if (type.builtinBase() != LayoutId::kProperty) { 298 return thread->raiseWithFmt(LayoutId::kTypeError, 299 "not a subtype of property"); 300 } 301 Layout layout(&scope, type.instanceLayout()); 302 Property result(&scope, runtime->newInstance(layout)); 303 return *result; 304} 305 306RawObject METH(property, __set__)(Thread* thread, Arguments args) { 307 HandleScope scope(thread); 308 Object self_obj(&scope, args.get(0)); 309 if (!thread->runtime()->isInstanceOfProperty(*self_obj)) { 310 return thread->raiseRequiresType(self_obj, ID(property)); 311 } 312 Property self(&scope, *self_obj); 313 Object setter(&scope, self.setter()); 314 if (setter.isNoneType()) { 315 return thread->raiseWithFmt(LayoutId::kAttributeError, 316 "can't set attribute"); 317 } 318 Object obj(&scope, args.get(1)); 319 Object value(&scope, args.get(2)); 320 return Interpreter::call2(thread, setter, obj, value); 321} 322 323RawObject METH(property, deleter)(Thread* thread, Arguments args) { 324 HandleScope scope(thread); 325 Runtime* runtime = thread->runtime(); 326 Object self_obj(&scope, args.get(0)); 327 if (!runtime->isInstanceOfProperty(*self_obj)) { 328 return thread->raiseRequiresType(self_obj, ID(property)); 329 } 330 Property self(&scope, *self_obj); 331 Object getter(&scope, self.getter()); 332 Object setter(&scope, self.setter()); 333 Object deleter(&scope, args.get(1)); 334 return runtime->newProperty(getter, setter, deleter); 335} 336 337RawObject METH(property, getter)(Thread* thread, Arguments args) { 338 HandleScope scope(thread); 339 Runtime* runtime = thread->runtime(); 340 Object self_obj(&scope, args.get(0)); 341 if (!runtime->isInstanceOfProperty(*self_obj)) { 342 return thread->raiseRequiresType(self_obj, ID(property)); 343 } 344 Property self(&scope, *self_obj); 345 Object getter(&scope, args.get(1)); 346 Object setter(&scope, self.setter()); 347 Object deleter(&scope, self.deleter()); 348 return runtime->newProperty(getter, setter, deleter); 349} 350 351RawObject METH(property, setter)(Thread* thread, Arguments args) { 352 HandleScope scope(thread); 353 Runtime* runtime = thread->runtime(); 354 Object self_obj(&scope, args.get(0)); 355 if (!runtime->isInstanceOfProperty(*self_obj)) { 356 return thread->raiseRequiresType(self_obj, ID(property)); 357 } 358 Property self(&scope, *self_obj); 359 Object getter(&scope, self.getter()); 360 Object setter(&scope, args.get(1)); 361 Object deleter(&scope, self.deleter()); 362 return runtime->newProperty(getter, setter, deleter); 363} 364 365} // namespace py