This repository was archived by the owner on Mar 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 635
Expand file tree
/
Copy pathsuper.go
More file actions
99 lines (91 loc) · 2.76 KB
/
super.go
File metadata and controls
99 lines (91 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package grumpy
import (
"reflect"
)
var (
// superType is the object representing the Python 'super' type.
superType = newBasisType("super", reflect.TypeOf(super{}), toSuperUnsafe, ObjectType)
)
type super struct {
Object
sub *Type
obj *Object
objType *Type
}
func toSuperUnsafe(o *Object) *super {
return (*super)(o.toPointer())
}
func superInit(f *Frame, o *Object, args Args, _ KWArgs) (*Object, *BaseException) {
// TODO: Support the unbound form of super.
if raised := checkFunctionArgs(f, "__init__", args, TypeType, ObjectType); raised != nil {
return nil, raised
}
sup := toSuperUnsafe(o)
sub := toTypeUnsafe(args[0])
obj := args[1]
var objType *Type
if obj.isInstance(TypeType) && toTypeUnsafe(obj).isSubclass(sub) {
objType = toTypeUnsafe(obj)
} else if obj.isInstance(sub) {
objType = obj.typ
} else {
return nil, f.RaiseType(TypeErrorType, "super(type, obj): obj must be an instance or subtype of type")
}
sup.sub = sub
sup.obj = obj
sup.objType = objType
return None, nil
}
func superGetAttribute(f *Frame, o *Object, name *Str) (*Object, *BaseException) {
sup := toSuperUnsafe(o)
// Tell the truth about the __class__ attribute.
if sup.objType != nil && name.Value() != "__class__" {
mro := sup.objType.mro
n := len(mro)
// Start from the immediate mro successor to the specified type.
i := 0
for i < n && mro[i] != sup.sub {
i++
}
i++
var inst *Object
if sup.obj != sup.objType.ToObject() {
inst = sup.obj
}
// Now do normal mro lookup from the successor type.
for ; i < n; i++ {
dict := mro[i].Dict()
res, raised := dict.GetItem(f, name.ToObject())
if raised != nil {
return nil, raised
}
if res != nil {
if get := res.typ.slots.Get; get != nil {
// Found a descriptor so invoke it.
return get.Fn(f, res, inst, sup.objType)
}
return res, nil
}
}
}
// Attribute not found on base classes so lookup the attr on the super
// object itself. Most likely will AttributeError.
return objectGetAttribute(f, o, name)
}
func initSuperType(map[string]*Object) {
superType.slots.GetAttribute = &getAttributeSlot{superGetAttribute}
superType.slots.Init = &initSlot{superInit}
}