Commit 993a50d9 authored by Dylan Trotter's avatar Dylan Trotter

Properly instantiate metaclasses when creating new types.

parent c2cedb7d
...@@ -327,7 +327,7 @@ func runMainAndCaptureStderr(handle *ModuleHandle) (int, string, error) { ...@@ -327,7 +327,7 @@ func runMainAndCaptureStderr(handle *ModuleHandle) (int, string, error) {
var testModuleType *Type var testModuleType *Type
func init() { func init() {
testModuleType, _ = newClass(newFrame(nil), "testModule", []*Type{ModuleType}, newStringDict(map[string]*Object{ testModuleType, _ = newClass(newFrame(nil), TypeType, "testModule", []*Type{ModuleType}, newStringDict(map[string]*Object{
"__eq__": newBuiltinFunction("__eq__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { "__eq__": newBuiltinFunction("__eq__", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
if raised := checkMethodArgs(f, "__eq__", args, ModuleType, ObjectType); raised != nil { if raised := checkMethodArgs(f, "__eq__", args, ModuleType, ObjectType); raised != nil {
return nil, raised return nil, raised
......
...@@ -386,7 +386,7 @@ func TestObjectStrRepr(t *testing.T) { ...@@ -386,7 +386,7 @@ func TestObjectStrRepr(t *testing.T) {
return nil return nil
}) })
type noReprMethodBasis struct{ Object } type noReprMethodBasis struct{ Object }
noReprMethodType := newType("noReprMethod", reflect.TypeOf(noReprMethodBasis{}), []*Type{}, NewDict()) noReprMethodType := newType(TypeType, "noReprMethod", reflect.TypeOf(noReprMethodBasis{}), []*Type{}, NewDict())
noReprMethodType.mro = []*Type{noReprMethodType} noReprMethodType.mro = []*Type{noReprMethodType}
fooType := newTestClass("Foo", []*Type{ObjectType}, newTestDict("__module__", "foo.bar")) fooType := newTestClass("Foo", []*Type{ObjectType}, newTestDict("__module__", "foo.bar"))
cases := []invokeTestCase{ cases := []invokeTestCase{
......
...@@ -51,7 +51,7 @@ var basisTypes = map[reflect.Type]*Type{ ...@@ -51,7 +51,7 @@ var basisTypes = map[reflect.Type]*Type{
// newClass creates a Python type with the given name, base classes and type // newClass creates a Python type with the given name, base classes and type
// dict. It is similar to the Python expression 'type(name, bases, dict)'. // dict. It is similar to the Python expression 'type(name, bases, dict)'.
func newClass(f *Frame, name string, bases []*Type, dict *Dict) (*Type, *BaseException) { func newClass(f *Frame, meta *Type, name string, bases []*Type, dict *Dict) (*Type, *BaseException) {
numBases := len(bases) numBases := len(bases)
if numBases == 0 { if numBases == 0 {
return nil, f.RaiseType(TypeErrorType, "class must have base classes") return nil, f.RaiseType(TypeErrorType, "class must have base classes")
...@@ -67,7 +67,7 @@ func newClass(f *Frame, name string, bases []*Type, dict *Dict) (*Type, *BaseExc ...@@ -67,7 +67,7 @@ func newClass(f *Frame, name string, bases []*Type, dict *Dict) (*Type, *BaseExc
if basis == nil { if basis == nil {
return nil, f.RaiseType(TypeErrorType, "class layout error") return nil, f.RaiseType(TypeErrorType, "class layout error")
} }
t := newType(name, basis, bases, dict) t := newType(meta, name, basis, bases, dict)
// Populate slots for any special methods overridden in dict. // Populate slots for any special methods overridden in dict.
slotsValue := reflect.ValueOf(&t.slots).Elem() slotsValue := reflect.ValueOf(&t.slots).Elem()
for i := 0; i < numSlots; i++ { for i := 0; i < numSlots; i++ {
...@@ -99,9 +99,9 @@ func newClass(f *Frame, name string, bases []*Type, dict *Dict) (*Type, *BaseExc ...@@ -99,9 +99,9 @@ func newClass(f *Frame, name string, bases []*Type, dict *Dict) (*Type, *BaseExc
return t, nil return t, nil
} }
func newType(name string, basis reflect.Type, bases []*Type, dict *Dict) *Type { func newType(meta *Type, name string, basis reflect.Type, bases []*Type, dict *Dict) *Type {
return &Type{ return &Type{
Object: Object{typ: TypeType, dict: dict}, Object: Object{typ: meta, dict: dict},
name: name, name: name,
basis: basis, basis: basis,
bases: bases, bases: bases,
...@@ -128,7 +128,7 @@ func newBasisType(name string, basis reflect.Type, basisFunc interface{}, base * ...@@ -128,7 +128,7 @@ func newBasisType(name string, basis reflect.Type, basisFunc interface{}, base *
basisFuncType.In(0) != reflect.PtrTo(objectBasis) || basisFuncType.Out(0) != reflect.PtrTo(basis) { basisFuncType.In(0) != reflect.PtrTo(objectBasis) || basisFuncType.Out(0) != reflect.PtrTo(basis) {
logFatal(fmt.Sprintf("expected basis func of type func(*Object) *%s", nativeTypeName(basis))) logFatal(fmt.Sprintf("expected basis func of type func(*Object) *%s", nativeTypeName(basis)))
} }
t := newType(name, basis, []*Type{base}, nil) t := newType(TypeType, name, basis, []*Type{base}, nil)
t.slots.Basis = &basisSlot{func(o *Object) reflect.Value { t.slots.Basis = &basisSlot{func(o *Object) reflect.Value {
return basisFuncValue.Call([]reflect.Value{reflect.ValueOf(o)})[0].Elem() return basisFuncValue.Call([]reflect.Value{reflect.ValueOf(o)})[0].Elem()
}} }}
...@@ -137,7 +137,7 @@ func newBasisType(name string, basis reflect.Type, basisFunc interface{}, base * ...@@ -137,7 +137,7 @@ func newBasisType(name string, basis reflect.Type, basisFunc interface{}, base *
} }
func newSimpleType(name string, base *Type) *Type { func newSimpleType(name string, base *Type) *Type {
return newType(name, base.basis, []*Type{base}, nil) return newType(TypeType, name, base.basis, []*Type{base}, nil)
} }
// prepareBuiltinType initializes the builtin typ by populating dict with // prepareBuiltinType initializes the builtin typ by populating dict with
...@@ -395,7 +395,6 @@ func typeGetAttribute(f *Frame, o *Object, name *Str) (*Object, *BaseException) ...@@ -395,7 +395,6 @@ func typeGetAttribute(f *Frame, o *Object, name *Str) (*Object, *BaseException)
} }
func typeNew(f *Frame, t *Type, args Args, kwargs KWArgs) (*Object, *BaseException) { func typeNew(f *Frame, t *Type, args Args, kwargs KWArgs) (*Object, *BaseException) {
// TODO: Respect t as the metaclass if not specified in dict.
switch len(args) { switch len(args) {
case 0: case 0:
return nil, f.RaiseType(TypeErrorType, "type() takes 1 or 3 arguments") return nil, f.RaiseType(TypeErrorType, "type() takes 1 or 3 arguments")
...@@ -420,7 +419,7 @@ func typeNew(f *Frame, t *Type, args Args, kwargs KWArgs) (*Object, *BaseExcepti ...@@ -420,7 +419,7 @@ func typeNew(f *Frame, t *Type, args Args, kwargs KWArgs) (*Object, *BaseExcepti
} }
baseTypes[i] = toTypeUnsafe(o) baseTypes[i] = toTypeUnsafe(o)
} }
ret, raised := newClass(f, name, baseTypes, dict) ret, raised := newClass(f, t, name, baseTypes, dict)
if raised != nil { if raised != nil {
return nil, raised return nil, raised
} }
......
...@@ -42,7 +42,7 @@ func TestNewClass(t *testing.T) { ...@@ -42,7 +42,7 @@ func TestNewClass(t *testing.T) {
} }
for _, cas := range cases { for _, cas := range cases {
fun := wrapFuncForTest(func(f *Frame, bases []*Type) *BaseException { fun := wrapFuncForTest(func(f *Frame, bases []*Type) *BaseException {
cls, raised := newClass(f, "Foo", bases, NewDict()) cls, raised := newClass(f, TypeType, "Foo", bases, NewDict())
if raised != nil { if raised != nil {
return raised return raised
} }
...@@ -161,7 +161,7 @@ func TestPrepareType(t *testing.T) { ...@@ -161,7 +161,7 @@ func TestPrepareType(t *testing.T) {
} }
func makeTestType(name string, bases ...*Type) *Type { func makeTestType(name string, bases ...*Type) *Type {
return newType(name, nil, bases, NewDict()) return newType(TypeType, name, nil, bases, NewDict())
} }
func TestMroCalc(t *testing.T) { func TestMroCalc(t *testing.T) {
...@@ -461,7 +461,7 @@ func TestTypeModule(t *testing.T) { ...@@ -461,7 +461,7 @@ func TestTypeModule(t *testing.T) {
} }
func newTestClass(name string, bases []*Type, dict *Dict) *Type { func newTestClass(name string, bases []*Type, dict *Dict) *Type {
t, raised := newClass(newFrame(nil), name, bases, dict) t, raised := newClass(newFrame(nil), TypeType, name, bases, dict)
if raised != nil { if raised != nil {
panic(raised) panic(raised)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment