github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/type.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package grumpy 16 17 import ( 18 "fmt" 19 "reflect" 20 ) 21 22 type typeFlag int 23 24 const ( 25 // Set when instances can be created via __new__. This is the default. 26 // We need to be able to prohibit instantiation of certain internal 27 // types like NoneType. CPython accomplishes this via tp_new == NULL but 28 // we don't have a tp_new. 29 typeFlagInstantiable typeFlag = 1 << iota 30 // Set when the type can be used as a base class. This is the default. 31 // Corresponds to the Py_TPFLAGS_BASETYPE flag in CPython. 32 typeFlagBasetype typeFlag = 1 << iota 33 typeFlagDefault = typeFlagInstantiable | typeFlagBasetype 34 ) 35 36 // Type represents Python 'type' objects. 37 type Type struct { 38 Object 39 name string `attr:"__name__"` 40 basis reflect.Type 41 bases []*Type 42 mro []*Type 43 flags typeFlag 44 slots typeSlots 45 } 46 47 var basisTypes = map[reflect.Type]*Type{ 48 objectBasis: ObjectType, 49 typeBasis: TypeType, 50 } 51 52 // newClass creates a Python type with the given name, base classes and type 53 // dict. It is similar to the Python expression 'type(name, bases, dict)'. 54 func newClass(f *Frame, meta *Type, name string, bases []*Type, dict *Dict) (*Type, *BaseException) { 55 numBases := len(bases) 56 if numBases == 0 { 57 return nil, f.RaiseType(TypeErrorType, "class must have base classes") 58 } 59 var basis reflect.Type 60 for _, base := range bases { 61 if base.flags&typeFlagBasetype == 0 { 62 format := "type '%s' is not an acceptable base type" 63 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, base.Name())) 64 } 65 basis = basisSelect(basis, base.basis) 66 } 67 if basis == nil { 68 return nil, f.RaiseType(TypeErrorType, "class layout error") 69 } 70 t := newType(meta, name, basis, bases, dict) 71 // Populate slots for any special methods overridden in dict. 72 slotsValue := reflect.ValueOf(&t.slots).Elem() 73 for i := 0; i < numSlots; i++ { 74 dictFunc, raised := dict.GetItemString(f, slotNames[i]) 75 if raised != nil { 76 return nil, raised 77 } 78 if dictFunc != nil { 79 slotField := slotsValue.Field(i) 80 slotValue := reflect.New(slotField.Type().Elem()) 81 if slotValue.Interface().(slot).wrapCallable(dictFunc) { 82 slotField.Set(slotValue) 83 } 84 } 85 } 86 if err := prepareType(t); err != "" { 87 return nil, f.RaiseType(TypeErrorType, err) 88 } 89 // Set the __module__ attr if it's not already specified. 90 mod, raised := dict.GetItemString(f, "__module__") 91 if raised != nil { 92 return nil, raised 93 } 94 if mod == nil { 95 if raised := dict.SetItemString(f, "__module__", builtinStr.ToObject()); raised != nil { 96 return nil, raised 97 } 98 } 99 return t, nil 100 } 101 102 func newType(meta *Type, name string, basis reflect.Type, bases []*Type, dict *Dict) *Type { 103 return &Type{ 104 Object: Object{typ: meta, dict: dict}, 105 name: name, 106 basis: basis, 107 bases: bases, 108 flags: typeFlagDefault, 109 } 110 } 111 112 func newBasisType(name string, basis reflect.Type, basisFunc interface{}, base *Type) *Type { 113 if _, ok := basisTypes[basis]; ok { 114 logFatal(fmt.Sprintf("type for basis already exists: %s", basis)) 115 } 116 if basis.Kind() != reflect.Struct { 117 logFatal(fmt.Sprintf("basis must be a struct not: %s", basis.Kind())) 118 } 119 if basis.NumField() == 0 { 120 logFatal(fmt.Sprintf("1st field of basis must be base type's basis")) 121 } 122 if basis.Field(0).Type != base.basis { 123 logFatal(fmt.Sprintf("1st field of basis must be base type's basis not: %s", basis.Field(0).Type)) 124 } 125 basisFuncValue := reflect.ValueOf(basisFunc) 126 basisFuncType := basisFuncValue.Type() 127 if basisFuncValue.Kind() != reflect.Func || basisFuncType.NumIn() != 1 || basisFuncType.NumOut() != 1 || 128 basisFuncType.In(0) != reflect.PtrTo(objectBasis) || basisFuncType.Out(0) != reflect.PtrTo(basis) { 129 logFatal(fmt.Sprintf("expected basis func of type func(*Object) *%s", nativeTypeName(basis))) 130 } 131 t := newType(TypeType, name, basis, []*Type{base}, nil) 132 t.slots.Basis = &basisSlot{func(o *Object) reflect.Value { 133 return basisFuncValue.Call([]reflect.Value{reflect.ValueOf(o)})[0].Elem() 134 }} 135 basisTypes[basis] = t 136 return t 137 } 138 139 func newSimpleType(name string, base *Type) *Type { 140 return newType(TypeType, name, base.basis, []*Type{base}, nil) 141 } 142 143 // prepareBuiltinType initializes the builtin typ by populating dict with 144 // struct field descriptors and slot wrappers, and then calling prepareType. 145 func prepareBuiltinType(typ *Type, init builtinTypeInit) { 146 dict := map[string]*Object{"__module__": builtinStr.ToObject()} 147 if init != nil { 148 init(dict) 149 } 150 // For basis types, export field descriptors. 151 if basis := typ.basis; basisTypes[basis] == typ { 152 numFields := basis.NumField() 153 for i := 0; i < numFields; i++ { 154 field := basis.Field(i) 155 if attr := field.Tag.Get("attr"); attr != "" { 156 fieldMode := fieldDescriptorRO 157 if mode := field.Tag.Get("attr_mode"); mode == "rw" { 158 fieldMode = fieldDescriptorRW 159 } 160 dict[attr] = makeStructFieldDescriptor(typ, field.Name, attr, fieldMode) 161 } 162 } 163 } 164 // Create dict entries for slot methods. 165 slotsValue := reflect.ValueOf(&typ.slots).Elem() 166 for i := 0; i < numSlots; i++ { 167 slotField := slotsValue.Field(i) 168 if !slotField.IsNil() { 169 slot := slotField.Interface().(slot) 170 if fun := slot.makeCallable(typ, slotNames[i]); fun != nil { 171 dict[slotNames[i]] = fun 172 } 173 } 174 } 175 typ.setDict(newStringDict(dict)) 176 if err := prepareType(typ); err != "" { 177 logFatal(err) 178 } 179 } 180 181 // prepareType calculates typ's mro and inherits its flags and slots from its 182 // base classes. 183 func prepareType(typ *Type) string { 184 typ.mro = mroCalc(typ) 185 if typ.mro == nil { 186 return fmt.Sprintf("mro error for: %s", typ.name) 187 } 188 for _, base := range typ.mro { 189 if base.flags&typeFlagInstantiable == 0 { 190 typ.flags &^= typeFlagInstantiable 191 } 192 if base.flags&typeFlagBasetype == 0 { 193 typ.flags &^= typeFlagBasetype 194 } 195 } 196 // Inherit slots from typ's mro. 197 slotsValue := reflect.ValueOf(&typ.slots).Elem() 198 for i := 0; i < numSlots; i++ { 199 slotField := slotsValue.Field(i) 200 if slotField.IsNil() { 201 for _, base := range typ.mro { 202 baseSlotFunc := reflect.ValueOf(base.slots).Field(i) 203 if !baseSlotFunc.IsNil() { 204 slotField.Set(baseSlotFunc) 205 break 206 } 207 } 208 } 209 } 210 return "" 211 } 212 213 // Precondition: At least one of seqs is non-empty. 214 func mroMerge(seqs [][]*Type) []*Type { 215 var res []*Type 216 numSeqs := len(seqs) 217 hasNonEmptySeqs := true 218 for hasNonEmptySeqs { 219 var cand *Type 220 for i := 0; i < numSeqs && cand == nil; i++ { 221 // The next candidate will be absent from or at the head 222 // of all lists. If we try a candidate and we find it's 223 // somewhere past the head of one of the lists, reject. 224 seq := seqs[i] 225 if len(seq) == 0 { 226 continue 227 } 228 cand = seq[0] 229 RejectCandidate: 230 for _, seq := range seqs { 231 numElems := len(seq) 232 for j := 1; j < numElems; j++ { 233 if seq[j] == cand { 234 cand = nil 235 break RejectCandidate 236 } 237 } 238 } 239 } 240 if cand == nil { 241 // We could not find a candidate meaning that the 242 // hierarchy is inconsistent. 243 return nil 244 } 245 res = append(res, cand) 246 hasNonEmptySeqs = false 247 for i, seq := range seqs { 248 if len(seq) > 0 { 249 if seq[0] == cand { 250 // Remove the candidate from all lists 251 // (it will only be found at the head of 252 // any list because otherwise it would 253 // have been rejected above.) 254 seqs[i] = seq[1:] 255 } 256 if len(seqs[i]) > 0 { 257 hasNonEmptySeqs = true 258 } 259 } 260 } 261 } 262 return res 263 } 264 265 func mroCalc(t *Type) []*Type { 266 seqs := [][]*Type{{t}} 267 for _, b := range t.bases { 268 seqs = append(seqs, b.mro) 269 } 270 seqs = append(seqs, t.bases) 271 return mroMerge(seqs) 272 } 273 274 func toTypeUnsafe(o *Object) *Type { 275 return (*Type)(o.toPointer()) 276 } 277 278 // ToObject upcasts t to an Object. 279 func (t *Type) ToObject() *Object { 280 return &t.Object 281 } 282 283 // Name returns t's name field. 284 func (t *Type) Name() string { 285 return t.name 286 } 287 288 // FullName returns t's fully qualified name including the module. 289 func (t *Type) FullName(f *Frame) (string, *BaseException) { 290 moduleAttr, raised := t.Dict().GetItemString(f, "__module__") 291 if raised != nil { 292 return "", raised 293 } 294 if moduleAttr == nil { 295 return t.Name(), nil 296 } 297 if moduleAttr.isInstance(StrType) { 298 if s := toStrUnsafe(moduleAttr).Value(); s != "__builtin__" { 299 return fmt.Sprintf("%s.%s", s, t.Name()), nil 300 } 301 } 302 return t.Name(), nil 303 } 304 305 func (t *Type) isSubclass(super *Type) bool { 306 for _, b := range t.mro { 307 if b == super { 308 return true 309 } 310 } 311 return false 312 } 313 314 func (t *Type) mroLookup(f *Frame, name *Str) (*Object, *BaseException) { 315 for _, t := range t.mro { 316 v, raised := t.Dict().GetItem(f, name.ToObject()) 317 if v != nil || raised != nil { 318 return v, raised 319 } 320 } 321 return nil, nil 322 } 323 324 var typeBasis = reflect.TypeOf(Type{}) 325 326 func typeBasisFunc(o *Object) reflect.Value { 327 return reflect.ValueOf(toTypeUnsafe(o)).Elem() 328 } 329 330 // TypeType is the object representing the Python 'type' type. 331 // 332 // Don't use newType() since that depends on the initialization of 333 // TypeType. 334 var TypeType = &Type{ 335 name: "type", 336 basis: typeBasis, 337 bases: []*Type{ObjectType}, 338 flags: typeFlagDefault, 339 slots: typeSlots{Basis: &basisSlot{typeBasisFunc}}, 340 } 341 342 func typeCall(f *Frame, callable *Object, args Args, kwargs KWArgs) (*Object, *BaseException) { 343 t := toTypeUnsafe(callable) 344 newFunc := t.slots.New 345 if newFunc == nil { 346 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("type %s has no __new__", t.Name())) 347 } 348 o, raised := newFunc.Fn(f, t, args, kwargs) 349 if raised != nil { 350 return nil, raised 351 } 352 if init := o.Type().slots.Init; init != nil { 353 if _, raised := init.Fn(f, o, args, kwargs); raised != nil { 354 return nil, raised 355 } 356 } 357 return o, nil 358 } 359 360 // typeGetAttribute is very similar to objectGetAttribute except that it uses 361 // MRO to resolve dict attributes rather than just the type's own dict and the 362 // exception message is slightly different. 363 func typeGetAttribute(f *Frame, o *Object, name *Str) (*Object, *BaseException) { 364 t := toTypeUnsafe(o) 365 // Look for a data descriptor in the metaclass. 366 var metaGet *getSlot 367 metaType := t.typ 368 metaAttr, raised := metaType.mroLookup(f, name) 369 if raised != nil { 370 return nil, raised 371 } 372 if metaAttr != nil { 373 metaGet = metaAttr.typ.slots.Get 374 if metaGet != nil && (metaAttr.typ.slots.Set != nil || metaAttr.typ.slots.Delete != nil) { 375 return metaGet.Fn(f, metaAttr, t.ToObject(), metaType) 376 } 377 } 378 // Look in dict of this type and its bases. 379 attr, raised := t.mroLookup(f, name) 380 if raised != nil { 381 return nil, raised 382 } 383 if attr != nil { 384 if get := attr.typ.slots.Get; get != nil { 385 return get.Fn(f, attr, None, t) 386 } 387 return attr, nil 388 } 389 // Use the (non-data) descriptor from the metaclass. 390 if metaGet != nil { 391 return metaGet.Fn(f, metaAttr, t.ToObject(), metaType) 392 } 393 // Return the ordinary attr from metaclass. 394 if metaAttr != nil { 395 return metaAttr, nil 396 } 397 msg := fmt.Sprintf("type object '%s' has no attribute '%s'", t.Name(), name.Value()) 398 return nil, f.RaiseType(AttributeErrorType, msg) 399 } 400 401 func typeNew(f *Frame, t *Type, args Args, kwargs KWArgs) (*Object, *BaseException) { 402 switch len(args) { 403 case 0: 404 return nil, f.RaiseType(TypeErrorType, "type() takes 1 or 3 arguments") 405 case 1: 406 return args[0].typ.ToObject(), nil 407 } 408 // case 3+ 409 if raised := checkMethodArgs(f, "__new__", args, StrType, TupleType, DictType); raised != nil { 410 return nil, raised 411 } 412 name := toStrUnsafe(args[0]).Value() 413 bases := toTupleUnsafe(args[1]).elems 414 dict := toDictUnsafe(args[2]) 415 baseTypes := make([]*Type, len(bases)) 416 meta := t 417 for i, o := range bases { 418 if !o.isInstance(TypeType) { 419 s, raised := Repr(f, o) 420 if raised != nil { 421 return nil, raised 422 } 423 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("not a valid base class: %s", s.Value())) 424 } 425 // Choose the most derived metaclass among all the bases to be 426 // the metaclass for the new type. 427 if o.typ.isSubclass(meta) { 428 meta = o.typ 429 } else if !meta.isSubclass(o.typ) { 430 msg := "metaclass conflict: the metaclass of a derived class must " + 431 "a be a (non-strict) subclass of the metaclasses of all its bases" 432 return nil, f.RaiseType(TypeErrorType, msg) 433 } 434 baseTypes[i] = toTypeUnsafe(o) 435 } 436 ret, raised := newClass(f, meta, name, baseTypes, dict) 437 if raised != nil { 438 return nil, raised 439 } 440 return ret.ToObject(), nil 441 } 442 443 func typeRepr(f *Frame, o *Object) (*Object, *BaseException) { 444 s, raised := toTypeUnsafe(o).FullName(f) 445 if raised != nil { 446 return nil, raised 447 } 448 return NewStr(fmt.Sprintf("<type '%s'>", s)).ToObject(), nil 449 } 450 451 func initTypeType(map[string]*Object) { 452 TypeType.typ = TypeType 453 TypeType.slots.Call = &callSlot{typeCall} 454 TypeType.slots.GetAttribute = &getAttributeSlot{typeGetAttribute} 455 TypeType.slots.New = &newSlot{typeNew} 456 TypeType.slots.Repr = &unaryOpSlot{typeRepr} 457 } 458 459 // basisParent returns the immediate ancestor of basis, which is its first 460 // field. Returns nil when basis is objectBasis (the root of basis hierarchy.) 461 func basisParent(basis reflect.Type) reflect.Type { 462 if basis == objectBasis { 463 return nil 464 } 465 return basis.Field(0).Type 466 } 467 468 // basisSelect returns b1 if b2 inherits from it, b2 if b1 inherits from b2, 469 // otherwise nil. b1 can be nil in which case b2 is always returned. 470 func basisSelect(b1, b2 reflect.Type) reflect.Type { 471 if b1 == nil { 472 return b2 473 } 474 // Search up b1's inheritance chain to see if b2 is present. 475 basis := b1 476 for basis != nil && basis != b2 { 477 basis = basisParent(basis) 478 } 479 if basis != nil { 480 return b1 481 } 482 // Search up b2's inheritance chain to see if b1 is present. 483 basis = b2 484 for basis != nil && basis != b1 { 485 basis = basisParent(basis) 486 } 487 if basis != nil { 488 return b2 489 } 490 return nil 491 }