github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/super.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  	"reflect"
    19  )
    20  
    21  var (
    22  	// superType is the object representing the Python 'super' type.
    23  	superType = newBasisType("super", reflect.TypeOf(super{}), toSuperUnsafe, ObjectType)
    24  )
    25  
    26  type super struct {
    27  	Object
    28  	sub     *Type
    29  	obj     *Object
    30  	objType *Type
    31  }
    32  
    33  func toSuperUnsafe(o *Object) *super {
    34  	return (*super)(o.toPointer())
    35  }
    36  
    37  func superInit(f *Frame, o *Object, args Args, _ KWArgs) (*Object, *BaseException) {
    38  	// TODO: Support the unbound form of super.
    39  	if raised := checkFunctionArgs(f, "__init__", args, TypeType, ObjectType); raised != nil {
    40  		return nil, raised
    41  	}
    42  	sup := toSuperUnsafe(o)
    43  	sub := toTypeUnsafe(args[0])
    44  	obj := args[1]
    45  	var objType *Type
    46  	if obj.isInstance(TypeType) && toTypeUnsafe(obj).isSubclass(sub) {
    47  		objType = toTypeUnsafe(obj)
    48  	} else if obj.isInstance(sub) {
    49  		objType = obj.typ
    50  	} else {
    51  		return nil, f.RaiseType(TypeErrorType, "super(type, obj): obj must be an instance or subtype of type")
    52  	}
    53  	sup.sub = sub
    54  	sup.obj = obj
    55  	sup.objType = objType
    56  	return None, nil
    57  }
    58  
    59  func superGetAttribute(f *Frame, o *Object, name *Str) (*Object, *BaseException) {
    60  	sup := toSuperUnsafe(o)
    61  	// Tell the truth about the __class__ attribute.
    62  	if sup.objType != nil && name.Value() != "__class__" {
    63  		mro := sup.objType.mro
    64  		n := len(mro)
    65  		// Start from the immediate mro successor to the specified type.
    66  		i := 0
    67  		for i < n && mro[i] != sup.sub {
    68  			i++
    69  		}
    70  		i++
    71  		var inst *Object
    72  		if sup.obj != sup.objType.ToObject() {
    73  			inst = sup.obj
    74  		}
    75  		// Now do normal mro lookup from the successor type.
    76  		for ; i < n; i++ {
    77  			dict := mro[i].Dict()
    78  			res, raised := dict.GetItem(f, name.ToObject())
    79  			if raised != nil {
    80  				return nil, raised
    81  			}
    82  			if res != nil {
    83  				if get := res.typ.slots.Get; get != nil {
    84  					// Found a descriptor so invoke it.
    85  					return get.Fn(f, res, inst, sup.objType)
    86  				}
    87  				return res, nil
    88  			}
    89  		}
    90  	}
    91  	// Attribute not found on base classes so lookup the attr on the super
    92  	// object itself. Most likely will AttributeError.
    93  	return objectGetAttribute(f, o, name)
    94  }
    95  
    96  func initSuperType(map[string]*Object) {
    97  	superType.slots.GetAttribute = &getAttributeSlot{superGetAttribute}
    98  	superType.slots.Init = &initSlot{superInit}
    99  }