github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/native.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  	"bytes"
    19  	"fmt"
    20  	"math/big"
    21  	"reflect"
    22  	"runtime"
    23  	"sync"
    24  	"unsafe"
    25  )
    26  
    27  var (
    28  	nativeBoolMetaclassType = newBasisType("nativebooltype", reflect.TypeOf(nativeBoolMetaclass{}), toNativeBoolMetaclassUnsafe, nativeMetaclassType)
    29  	nativeFuncType          = newSimpleType("func", nativeType)
    30  	nativeMetaclassType     = newBasisType("nativetype", reflect.TypeOf(nativeMetaclass{}), toNativeMetaclassUnsafe, TypeType)
    31  	nativeSliceType         = newSimpleType("slice", nativeType)
    32  	nativeType              = newBasisType("native", reflect.TypeOf(native{}), toNativeUnsafe, ObjectType)
    33  	// Prepopulate the builtin primitive types so that WrapNative calls on
    34  	// these kinds of values resolve directly to primitive Python types.
    35  	nativeTypes = map[reflect.Type]*Type{
    36  		reflect.TypeOf(bool(false)):     BoolType,
    37  		reflect.TypeOf(complex64(0)):    ComplexType,
    38  		reflect.TypeOf(complex128(0)):   ComplexType,
    39  		reflect.TypeOf(float32(0)):      FloatType,
    40  		reflect.TypeOf(float64(0)):      FloatType,
    41  		reflect.TypeOf(int(0)):          IntType,
    42  		reflect.TypeOf(int16(0)):        IntType,
    43  		reflect.TypeOf(int32(0)):        IntType,
    44  		reflect.TypeOf(int64(0)):        IntType,
    45  		reflect.TypeOf(int8(0)):         IntType,
    46  		reflect.TypeOf(string("")):      StrType,
    47  		reflect.TypeOf(uint(0)):         IntType,
    48  		reflect.TypeOf(uint16(0)):       IntType,
    49  		reflect.TypeOf(uint32(0)):       IntType,
    50  		reflect.TypeOf(uint64(0)):       IntType,
    51  		reflect.TypeOf(uint8(0)):        IntType,
    52  		reflect.TypeOf(uintptr(0)):      IntType,
    53  		reflect.TypeOf([]rune(nil)):     UnicodeType,
    54  		reflect.TypeOf(big.Int{}):       LongType,
    55  		reflect.TypeOf((*big.Int)(nil)): LongType,
    56  	}
    57  	nativeTypesMutex  = sync.Mutex{}
    58  	sliceIteratorType = newBasisType("sliceiterator", reflect.TypeOf(sliceIterator{}), toSliceIteratorUnsafe, ObjectType)
    59  )
    60  
    61  type nativeMetaclass struct {
    62  	Type
    63  	rtype reflect.Type
    64  }
    65  
    66  func toNativeMetaclassUnsafe(o *Object) *nativeMetaclass {
    67  	return (*nativeMetaclass)(o.toPointer())
    68  }
    69  
    70  func newNativeType(rtype reflect.Type, base *Type) *Type {
    71  	t := &nativeMetaclass{
    72  		Type{
    73  			Object: Object{typ: nativeMetaclassType},
    74  			name:   nativeTypeName(rtype),
    75  			basis:  base.basis,
    76  			bases:  []*Type{base},
    77  			flags:  typeFlagDefault,
    78  		},
    79  		rtype,
    80  	}
    81  	if !base.isSubclass(nativeType) {
    82  		t.slots.Native = &nativeSlot{nativeTypedefNative}
    83  	}
    84  	return &t.Type
    85  }
    86  
    87  func nativeTypedefNative(f *Frame, o *Object) (reflect.Value, *BaseException) {
    88  	// The __native__ slot for primitive base classes (e.g. int) returns
    89  	// the corresponding primitive Go type. For typedef'd primitive types
    90  	// (e.g. type devNull int) we should return the subtype, not the
    91  	// primitive type.  So first call the primitive type's __native__ and
    92  	// then convert it to the appropriate subtype.
    93  	val, raised := o.typ.bases[0].slots.Native.Fn(f, o)
    94  	if raised != nil {
    95  		return reflect.Value{}, raised
    96  	}
    97  	return val.Convert(toNativeMetaclassUnsafe(o.typ.ToObject()).rtype), nil
    98  }
    99  
   100  func nativeMetaclassNew(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   101  	if raised := checkMethodArgs(f, "new", args, nativeMetaclassType); raised != nil {
   102  		return nil, raised
   103  	}
   104  	return WrapNative(f, reflect.New(toNativeMetaclassUnsafe(args[0]).rtype))
   105  }
   106  
   107  func initNativeMetaclassType(dict map[string]*Object) {
   108  	nativeMetaclassType.flags &^= typeFlagInstantiable | typeFlagBasetype
   109  	dict["new"] = newBuiltinFunction("new", nativeMetaclassNew).ToObject()
   110  }
   111  
   112  type nativeBoolMetaclass struct {
   113  	nativeMetaclass
   114  	trueValue  *Object
   115  	falseValue *Object
   116  }
   117  
   118  func toNativeBoolMetaclassUnsafe(o *Object) *nativeBoolMetaclass {
   119  	return (*nativeBoolMetaclass)(o.toPointer())
   120  }
   121  
   122  func newNativeBoolType(rtype reflect.Type) *Type {
   123  	t := &nativeBoolMetaclass{
   124  		nativeMetaclass: nativeMetaclass{
   125  			Type{
   126  				Object: Object{typ: nativeBoolMetaclassType},
   127  				name:   nativeTypeName(rtype),
   128  				basis:  BoolType.basis,
   129  				bases:  []*Type{BoolType},
   130  				flags:  typeFlagDefault &^ (typeFlagInstantiable | typeFlagBasetype),
   131  			},
   132  			rtype,
   133  		},
   134  	}
   135  	t.trueValue = (&Int{Object{typ: &t.nativeMetaclass.Type}, 1}).ToObject()
   136  	t.falseValue = (&Int{Object{typ: &t.nativeMetaclass.Type}, 0}).ToObject()
   137  	t.slots.Native = &nativeSlot{nativeBoolNative}
   138  	t.slots.New = &newSlot{nativeBoolNew}
   139  	return &t.nativeMetaclass.Type
   140  }
   141  
   142  func nativeBoolNative(f *Frame, o *Object) (reflect.Value, *BaseException) {
   143  	val := reflect.ValueOf(toIntUnsafe(o).IsTrue())
   144  	return val.Convert(toNativeMetaclassUnsafe(o.typ.ToObject()).rtype), nil
   145  }
   146  
   147  func nativeBoolNew(f *Frame, t *Type, args Args, kwargs KWArgs) (*Object, *BaseException) {
   148  	meta := toNativeBoolMetaclassUnsafe(t.ToObject())
   149  	argc := len(args)
   150  	if argc == 0 {
   151  		return meta.falseValue, nil
   152  	}
   153  	if argc != 1 {
   154  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("%s() takes at most 1 argument (%d given)", t.Name(), argc))
   155  	}
   156  	ret, raised := IsTrue(f, args[0])
   157  	if raised != nil {
   158  		return nil, raised
   159  	}
   160  	if ret {
   161  		return meta.trueValue, nil
   162  	}
   163  	return meta.falseValue, nil
   164  }
   165  
   166  func initNativeBoolMetaclassType(dict map[string]*Object) {
   167  	nativeBoolMetaclassType.flags &^= typeFlagInstantiable | typeFlagBasetype
   168  	dict["new"] = newBuiltinFunction("new", nativeMetaclassNew).ToObject()
   169  }
   170  
   171  type native struct {
   172  	Object
   173  	value reflect.Value
   174  }
   175  
   176  func toNativeUnsafe(o *Object) *native {
   177  	return (*native)(o.toPointer())
   178  }
   179  
   180  // ToObject upcasts n to an Object.
   181  func (n *native) ToObject() *Object {
   182  	return &n.Object
   183  }
   184  
   185  func nativeNative(f *Frame, o *Object) (reflect.Value, *BaseException) {
   186  	return toNativeUnsafe(o).value, nil
   187  }
   188  
   189  func initNativeType(map[string]*Object) {
   190  	nativeType.flags = typeFlagDefault &^ typeFlagInstantiable
   191  	nativeType.slots.Native = &nativeSlot{nativeNative}
   192  }
   193  
   194  func nativeFuncCall(f *Frame, callable *Object, args Args, kwargs KWArgs) (*Object, *BaseException) {
   195  	return nativeInvoke(f, toNativeUnsafe(callable).value, args)
   196  }
   197  
   198  func nativeFuncGetName(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   199  	if raised := checkMethodArgs(f, "_get_name", args, nativeFuncType); raised != nil {
   200  		return nil, raised
   201  	}
   202  	fun := runtime.FuncForPC(toNativeUnsafe(args[0]).value.Pointer())
   203  	return NewStr(fun.Name()).ToObject(), nil
   204  }
   205  
   206  func nativeFuncRepr(f *Frame, o *Object) (*Object, *BaseException) {
   207  	name, raised := GetAttr(f, o, internedName, NewStr("<unknown>").ToObject())
   208  	if raised != nil {
   209  		return nil, raised
   210  	}
   211  	nameStr, raised := ToStr(f, name)
   212  	if raised != nil {
   213  		return nil, raised
   214  	}
   215  	typeName := nativeTypeName(toNativeUnsafe(o).value.Type())
   216  	return NewStr(fmt.Sprintf("<%s %s at %p>", typeName, nameStr.Value(), o)).ToObject(), nil
   217  }
   218  
   219  func initNativeFuncType(dict map[string]*Object) {
   220  	dict["__name__"] = newProperty(newBuiltinFunction("_get_name", nativeFuncGetName).ToObject(), None, None).ToObject()
   221  	nativeFuncType.slots.Call = &callSlot{nativeFuncCall}
   222  	nativeFuncType.slots.Repr = &unaryOpSlot{nativeFuncRepr}
   223  }
   224  
   225  func nativeSliceGetItem(f *Frame, o, key *Object) (*Object, *BaseException) {
   226  	v := toNativeUnsafe(o).value
   227  	if key.typ.slots.Index != nil {
   228  		elem, raised := nativeSliceGetIndex(f, v, key)
   229  		if raised != nil {
   230  			return nil, raised
   231  		}
   232  		return WrapNative(f, elem)
   233  	}
   234  	if !key.isInstance(SliceType) {
   235  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("native slice indices must be integers, not %s", key.typ.Name()))
   236  	}
   237  	s := toSliceUnsafe(key)
   238  	start, stop, step, sliceLen, raised := s.calcSlice(f, v.Len())
   239  	if raised != nil {
   240  		return nil, raised
   241  	}
   242  	if step == 1 {
   243  		return WrapNative(f, v.Slice(start, stop))
   244  	}
   245  	result := reflect.MakeSlice(v.Type(), sliceLen, sliceLen)
   246  	i := 0
   247  	for j := start; j != stop; j += step {
   248  		resultElem := result.Index(i)
   249  		resultElem.Set(v.Index(j))
   250  		i++
   251  	}
   252  	return WrapNative(f, result)
   253  }
   254  
   255  func nativeSliceIter(f *Frame, o *Object) (*Object, *BaseException) {
   256  	return newSliceIterator(toNativeUnsafe(o).value), nil
   257  }
   258  
   259  func nativeSliceLen(f *Frame, o *Object) (*Object, *BaseException) {
   260  	return NewInt(toNativeUnsafe(o).value.Len()).ToObject(), nil
   261  }
   262  
   263  func nativeSliceRepr(f *Frame, o *Object) (*Object, *BaseException) {
   264  	v := toNativeUnsafe(o).value
   265  	typeName := nativeTypeName(v.Type())
   266  	if f.reprEnter(o) {
   267  		return NewStr(fmt.Sprintf("%s{...}", typeName)).ToObject(), nil
   268  	}
   269  	defer f.reprLeave(o)
   270  	numElems := v.Len()
   271  	elems := make([]*Object, numElems)
   272  	for i := 0; i < numElems; i++ {
   273  		elem, raised := WrapNative(f, v.Index(i))
   274  		if raised != nil {
   275  			return nil, raised
   276  		}
   277  		elems[i] = elem
   278  	}
   279  	repr, raised := seqRepr(f, elems)
   280  	if raised != nil {
   281  		return nil, raised
   282  	}
   283  	return NewStr(fmt.Sprintf("%s{%s}", typeName, repr)).ToObject(), nil
   284  }
   285  
   286  func nativeSliceSetItem(f *Frame, o, key, value *Object) *BaseException {
   287  	v := toNativeUnsafe(o).value
   288  	elemType := v.Type().Elem()
   289  	if key.typ.slots.Int != nil {
   290  		elem, raised := nativeSliceGetIndex(f, v, key)
   291  		if raised != nil {
   292  			return raised
   293  		}
   294  		if !elem.CanSet() {
   295  			return f.RaiseType(TypeErrorType, "cannot set slice element")
   296  		}
   297  		elemVal, raised := maybeConvertValue(f, value, elemType)
   298  		if raised != nil {
   299  			return raised
   300  		}
   301  		elem.Set(elemVal)
   302  		return nil
   303  	}
   304  	if key.isInstance(SliceType) {
   305  		s := toSliceUnsafe(key)
   306  		start, stop, step, sliceLen, raised := s.calcSlice(f, v.Len())
   307  		if raised != nil {
   308  			return raised
   309  		}
   310  		if !v.Index(start).CanSet() {
   311  			return f.RaiseType(TypeErrorType, "cannot set slice element")
   312  		}
   313  		return seqApply(f, value, func(elems []*Object, _ bool) *BaseException {
   314  			numElems := len(elems)
   315  			if sliceLen != numElems {
   316  				format := "attempt to assign sequence of size %d to slice of size %d"
   317  				return f.RaiseType(ValueErrorType, fmt.Sprintf(format, numElems, sliceLen))
   318  			}
   319  			i := 0
   320  			for j := start; j != stop; j += step {
   321  				elemVal, raised := maybeConvertValue(f, elems[i], elemType)
   322  				if raised != nil {
   323  					return raised
   324  				}
   325  				v.Index(j).Set(elemVal)
   326  				i++
   327  			}
   328  			return nil
   329  		})
   330  	}
   331  	return f.RaiseType(TypeErrorType, fmt.Sprintf("native slice indices must be integers, not %s", key.Type().Name()))
   332  }
   333  
   334  func initNativeSliceType(map[string]*Object) {
   335  	nativeSliceType.slots.GetItem = &binaryOpSlot{nativeSliceGetItem}
   336  	nativeSliceType.slots.Iter = &unaryOpSlot{nativeSliceIter}
   337  	nativeSliceType.slots.Len = &unaryOpSlot{nativeSliceLen}
   338  	nativeSliceType.slots.Repr = &unaryOpSlot{nativeSliceRepr}
   339  	nativeSliceType.slots.SetItem = &setItemSlot{nativeSliceSetItem}
   340  }
   341  
   342  func nativeSliceGetIndex(f *Frame, slice reflect.Value, key *Object) (reflect.Value, *BaseException) {
   343  	i, raised := IndexInt(f, key)
   344  	if raised != nil {
   345  		return reflect.Value{}, raised
   346  	}
   347  	i, raised = seqCheckedIndex(f, slice.Len(), i)
   348  	if raised != nil {
   349  		return reflect.Value{}, raised
   350  	}
   351  	return slice.Index(i), nil
   352  }
   353  
   354  type sliceIterator struct {
   355  	Object
   356  	slice    reflect.Value
   357  	mutex    sync.Mutex
   358  	numElems int
   359  	index    int
   360  }
   361  
   362  func newSliceIterator(slice reflect.Value) *Object {
   363  	iter := &sliceIterator{Object: Object{typ: sliceIteratorType}, slice: slice, numElems: slice.Len()}
   364  	return &iter.Object
   365  }
   366  
   367  func toSliceIteratorUnsafe(o *Object) *sliceIterator {
   368  	return (*sliceIterator)(o.toPointer())
   369  }
   370  
   371  func sliceIteratorIter(f *Frame, o *Object) (*Object, *BaseException) {
   372  	return o, nil
   373  }
   374  
   375  func sliceIteratorNext(f *Frame, o *Object) (ret *Object, raised *BaseException) {
   376  	i := toSliceIteratorUnsafe(o)
   377  	i.mutex.Lock()
   378  	if i.index < i.numElems {
   379  		ret, raised = WrapNative(f, i.slice.Index(i.index))
   380  		i.index++
   381  	} else {
   382  		raised = f.Raise(StopIterationType.ToObject(), nil, nil)
   383  	}
   384  	i.mutex.Unlock()
   385  	return ret, raised
   386  }
   387  
   388  func initSliceIteratorType(map[string]*Object) {
   389  	sliceIteratorType.flags &= ^(typeFlagBasetype | typeFlagInstantiable)
   390  	sliceIteratorType.slots.Iter = &unaryOpSlot{sliceIteratorIter}
   391  	sliceIteratorType.slots.Next = &unaryOpSlot{sliceIteratorNext}
   392  }
   393  
   394  // WrapNative takes a reflect.Value object and converts the underlying Go
   395  // object to a Python object in the following way:
   396  //
   397  // - Primitive types are converted in the way you'd expect: Go int types map to
   398  //   Python int, Go booleans to Python bool, etc. User-defined primitive Go types
   399  //   are subclasses of the Python primitives.
   400  // - *big.Int is represented by Python long.
   401  // - Functions are represented by Python type that supports calling into native
   402  //   functions.
   403  // - Interfaces are converted to their concrete held type, or None if IsNil.
   404  // - Other native types are wrapped in an opaque native type that does not
   405  //   support directly accessing the underlying object from Python. When these
   406  //   opaque objects are passed back into Go by native function calls, however,
   407  //   they will be unwrapped back to their Go representation.
   408  func WrapNative(f *Frame, v reflect.Value) (*Object, *BaseException) {
   409  	switch v.Kind() {
   410  	case reflect.Interface:
   411  		if v.IsNil() {
   412  			return None, nil
   413  		}
   414  		// Interfaces have undefined methods (Method() will return an
   415  		// invalid func value). What we really want to wrap is the
   416  		// underlying, concrete object.
   417  		v = v.Elem()
   418  	case reflect.Invalid:
   419  		panic("zero reflect.Value passed to WrapNative")
   420  	}
   421  
   422  	t := getNativeType(v.Type())
   423  
   424  	switch v.Kind() {
   425  	// ===============
   426  	// Primitive types
   427  	// ===============
   428  	// Primitive Go types are translated into primitive Python types or
   429  	// subclasses of primitive Python types.
   430  	case reflect.Bool:
   431  		i := 0
   432  		if v.Bool() {
   433  			i = 1
   434  		}
   435  		// TODO: Make native bool subtypes singletons and add support
   436  		// for __new__ so we can use t.Call() here.
   437  		return (&Int{Object{typ: t}, i}).ToObject(), nil
   438  	case reflect.Complex64:
   439  	case reflect.Complex128:
   440  		return t.Call(f, Args{NewComplex(v.Complex()).ToObject()}, nil)
   441  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
   442  		return t.Call(f, Args{NewInt(int(v.Int())).ToObject()}, nil)
   443  	// Handle potentially large ints separately in case of overflow.
   444  	case reflect.Int64:
   445  		i := v.Int()
   446  		if i < int64(MinInt) || i > int64(MaxInt) {
   447  			return NewLong(big.NewInt(i)).ToObject(), nil
   448  		}
   449  		return t.Call(f, Args{NewInt(int(i)).ToObject()}, nil)
   450  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   451  		i := v.Uint()
   452  		if i > uint64(MaxInt) {
   453  			return t.Call(f, Args{NewLong((new(big.Int).SetUint64(i))).ToObject()}, nil)
   454  		}
   455  		return t.Call(f, Args{NewInt(int(i)).ToObject()}, nil)
   456  	case reflect.Uintptr:
   457  		// Treat uintptr as a opaque data encoded as a signed integer.
   458  		i := int64(v.Uint())
   459  		if i < int64(MinInt) || i > int64(MaxInt) {
   460  			return NewLong(big.NewInt(i)).ToObject(), nil
   461  		}
   462  		return t.Call(f, Args{NewInt(int(i)).ToObject()}, nil)
   463  	case reflect.Float32, reflect.Float64:
   464  		x := v.Float()
   465  		return t.Call(f, Args{NewFloat(x).ToObject()}, nil)
   466  	case reflect.String:
   467  		return t.Call(f, Args{NewStr(v.String()).ToObject()}, nil)
   468  	case reflect.Slice:
   469  		if v.Type().Elem() == reflect.TypeOf(rune(0)) {
   470  			// Avoid reflect.Copy() and Interface()+copy() in case
   471  			// this is an unexported field.
   472  			// TODO: Implement a fast path that uses copy() when
   473  			// v.CanInterface() is true.
   474  			numRunes := v.Len()
   475  			runes := make([]rune, numRunes)
   476  			for i := 0; i < numRunes; i++ {
   477  				runes[i] = rune(v.Index(i).Int())
   478  			}
   479  			return t.Call(f, Args{NewUnicodeFromRunes(runes).ToObject()}, nil)
   480  		}
   481  
   482  	// =============
   483  	// Complex types
   484  	// =============
   485  	// Non-primitive types are always nativeType subclasses except in a few
   486  	// specific cases which we handle below.
   487  	case reflect.Ptr:
   488  		if v.IsNil() {
   489  			return None, nil
   490  		}
   491  		if v.Type() == reflect.TypeOf((*big.Int)(nil)) {
   492  			i := v.Interface().(*big.Int)
   493  			return t.Call(f, Args{NewLong(i).ToObject()}, nil)
   494  		}
   495  		if basis := v.Elem(); basisTypes[basis.Type()] != nil {
   496  			// We have a basis type that is binary compatible with
   497  			// Object.
   498  			return (*Object)(unsafe.Pointer(basis.UnsafeAddr())), nil
   499  		}
   500  	case reflect.Struct:
   501  		if i, ok := v.Interface().(big.Int); ok {
   502  			return t.Call(f, Args{NewLong(&i).ToObject()}, nil)
   503  		}
   504  	case reflect.Chan, reflect.Func, reflect.Map:
   505  		if v.IsNil() {
   506  			return None, nil
   507  		}
   508  	}
   509  	return (&native{Object{typ: t}, v}).ToObject(), nil
   510  }
   511  
   512  func getNativeType(rtype reflect.Type) *Type {
   513  	nativeTypesMutex.Lock()
   514  	t, ok := nativeTypes[rtype]
   515  	if !ok {
   516  		// Choose an appropriate base class for this kind of native
   517  		// object.
   518  		base := nativeType
   519  		switch rtype.Kind() {
   520  		case reflect.Complex64, reflect.Complex128:
   521  			base = ComplexType
   522  		case reflect.Float32, reflect.Float64:
   523  			base = FloatType
   524  		case reflect.Func:
   525  			base = nativeFuncType
   526  		case reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8, reflect.Uint, reflect.Uintptr:
   527  			base = IntType
   528  		case reflect.Array, reflect.Slice:
   529  			base = nativeSliceType
   530  		case reflect.String:
   531  			base = StrType
   532  		}
   533  		d := map[string]*Object{"__module__": builtinStr.ToObject()}
   534  		numMethod := rtype.NumMethod()
   535  		for i := 0; i < numMethod; i++ {
   536  			meth := rtype.Method(i)
   537  			// A non-empty PkgPath indicates a private method that shouldn't
   538  			// be registered.
   539  			if meth.PkgPath == "" {
   540  				d[meth.Name] = newNativeMethod(meth.Name, meth.Func)
   541  			}
   542  		}
   543  		if rtype.Kind() == reflect.Bool {
   544  			t = newNativeBoolType(rtype)
   545  		} else {
   546  			t = newNativeType(rtype, base)
   547  		}
   548  		derefed := rtype
   549  		for derefed.Kind() == reflect.Ptr {
   550  			derefed = derefed.Elem()
   551  		}
   552  		if derefed.Kind() == reflect.Struct {
   553  			for i := 0; i < derefed.NumField(); i++ {
   554  				name := derefed.Field(i).Name
   555  				d[name] = newNativeField(name, i, t)
   556  			}
   557  		}
   558  		t.setDict(newStringDict(d))
   559  		// This cannot fail since we're defining simple classes.
   560  		if err := prepareType(t); err != "" {
   561  			logFatal(err)
   562  		}
   563  	}
   564  	nativeTypes[rtype] = t
   565  	nativeTypesMutex.Unlock()
   566  	return t
   567  }
   568  
   569  func newNativeField(name string, i int, t *Type) *Object {
   570  	get := newBuiltinFunction(name, func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   571  		if raised := checkFunctionArgs(f, name, args, t); raised != nil {
   572  			return nil, raised
   573  		}
   574  		v := toNativeUnsafe(args[0]).value
   575  		for v.Type().Kind() == reflect.Ptr {
   576  			v = v.Elem()
   577  		}
   578  		return WrapNative(f, v.Field(i))
   579  	}).ToObject()
   580  	set := newBuiltinFunction(name, func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   581  		if raised := checkFunctionArgs(f, name, args, t, ObjectType); raised != nil {
   582  			return nil, raised
   583  		}
   584  		v := toNativeUnsafe(args[0]).value
   585  		for v.Type().Kind() == reflect.Ptr {
   586  			v = v.Elem()
   587  		}
   588  		field := v.Field(i)
   589  		if !field.CanSet() {
   590  			msg := fmt.Sprintf("cannot set field '%s' of type '%s'", name, t.Name())
   591  			return nil, f.RaiseType(TypeErrorType, msg)
   592  		}
   593  		v, raised := maybeConvertValue(f, args[1], field.Type())
   594  		if raised != nil {
   595  			return nil, raised
   596  		}
   597  		field.Set(v)
   598  		return None, nil
   599  	}).ToObject()
   600  	return newProperty(get, set, nil).ToObject()
   601  }
   602  
   603  func newNativeMethod(name string, fun reflect.Value) *Object {
   604  	return newBuiltinFunction(name, func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
   605  		return nativeInvoke(f, fun, args)
   606  	}).ToObject()
   607  }
   608  
   609  func maybeConvertValue(f *Frame, o *Object, expectedRType reflect.Type) (reflect.Value, *BaseException) {
   610  	if expectedRType.Kind() == reflect.Ptr {
   611  		// When the expected type is some basis pointer, check if o is
   612  		// an instance of that basis and use it if so.
   613  		if t, ok := basisTypes[expectedRType.Elem()]; ok && o.isInstance(t) {
   614  			return t.slots.Basis.Fn(o).Addr(), nil
   615  		}
   616  	}
   617  	if o == None {
   618  		switch expectedRType.Kind() {
   619  		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
   620  			return reflect.Zero(expectedRType), nil
   621  		default:
   622  			return reflect.Value{}, f.RaiseType(TypeErrorType, fmt.Sprintf("an %s is required", expectedRType))
   623  		}
   624  	}
   625  	val, raised := ToNative(f, o)
   626  	if raised != nil {
   627  		return reflect.Value{}, raised
   628  	}
   629  	rtype := val.Type()
   630  	for {
   631  		if rtype == expectedRType {
   632  			return val, nil
   633  		}
   634  		if rtype.ConvertibleTo(expectedRType) {
   635  			return val.Convert(expectedRType), nil
   636  		}
   637  		if rtype.Kind() == reflect.Ptr {
   638  			val = val.Elem()
   639  			rtype = val.Type()
   640  			continue
   641  		}
   642  		break
   643  	}
   644  	return reflect.Value{}, f.RaiseType(TypeErrorType, fmt.Sprintf("an %s is required", expectedRType))
   645  }
   646  
   647  func nativeFuncTypeName(rtype reflect.Type) string {
   648  	var buf bytes.Buffer
   649  	buf.WriteString("func(")
   650  	numIn := rtype.NumIn()
   651  	for i := 0; i < numIn; i++ {
   652  		if i > 0 {
   653  			buf.WriteString(", ")
   654  		}
   655  		buf.WriteString(nativeTypeName(rtype.In(i)))
   656  	}
   657  	buf.WriteString(")")
   658  	numOut := rtype.NumOut()
   659  	if numOut == 1 {
   660  		buf.WriteString(" ")
   661  		buf.WriteString(nativeTypeName(rtype.Out(0)))
   662  	} else if numOut > 1 {
   663  		buf.WriteString(" (")
   664  		for i := 0; i < numOut; i++ {
   665  			if i > 0 {
   666  				buf.WriteString(", ")
   667  			}
   668  			buf.WriteString(nativeTypeName(rtype.Out(i)))
   669  		}
   670  		buf.WriteString(")")
   671  	}
   672  	return buf.String()
   673  }
   674  
   675  func nativeInvoke(f *Frame, fun reflect.Value, args Args) (ret *Object, raised *BaseException) {
   676  	rtype := fun.Type()
   677  	argc := len(args)
   678  	expectedArgc := rtype.NumIn()
   679  	fixedArgc := expectedArgc
   680  	if rtype.IsVariadic() {
   681  		fixedArgc--
   682  	}
   683  	if rtype.IsVariadic() && argc < fixedArgc {
   684  		msg := fmt.Sprintf("native function takes at least %d arguments, (%d given)", fixedArgc, argc)
   685  		return nil, f.RaiseType(TypeErrorType, msg)
   686  	}
   687  	if !rtype.IsVariadic() && argc != fixedArgc {
   688  		msg := fmt.Sprintf("native function takes %d arguments, (%d given)", fixedArgc, argc)
   689  		return nil, f.RaiseType(TypeErrorType, msg)
   690  	}
   691  	// Convert all the fixed args to their native types.
   692  	nativeArgs := make([]reflect.Value, argc)
   693  	for i := 0; i < fixedArgc; i++ {
   694  		if nativeArgs[i], raised = maybeConvertValue(f, args[i], rtype.In(i)); raised != nil {
   695  			return nil, raised
   696  		}
   697  	}
   698  	if rtype.IsVariadic() {
   699  		// The last input in a variadic function is a slice with elem type of the
   700  		// var args.
   701  		elementT := rtype.In(fixedArgc).Elem()
   702  		for i := fixedArgc; i < argc; i++ {
   703  			if nativeArgs[i], raised = maybeConvertValue(f, args[i], elementT); raised != nil {
   704  				return nil, raised
   705  			}
   706  		}
   707  	}
   708  	origExc, origTb := f.RestoreExc(nil, nil)
   709  	result := fun.Call(nativeArgs)
   710  	if e, _ := f.ExcInfo(); e != nil {
   711  		return nil, e
   712  	}
   713  	f.RestoreExc(origExc, origTb)
   714  	numResults := len(result)
   715  	if numResults > 0 && result[numResults-1].Type() == reflect.TypeOf((*BaseException)(nil)) {
   716  		numResults--
   717  		result = result[:numResults]
   718  	}
   719  	// Convert the return value slice to a single value when only one value is
   720  	// returned, or to a Tuple, when many are returned.
   721  	switch numResults {
   722  	case 0:
   723  		ret = None
   724  	case 1:
   725  		ret, raised = WrapNative(f, result[0])
   726  	default:
   727  		elems := make([]*Object, numResults)
   728  		for i := 0; i < numResults; i++ {
   729  			if elems[i], raised = WrapNative(f, result[i]); raised != nil {
   730  				return nil, raised
   731  			}
   732  		}
   733  		ret = NewTuple(elems...).ToObject()
   734  	}
   735  	return ret, raised
   736  }
   737  
   738  func nativeTypeName(rtype reflect.Type) string {
   739  	if rtype.Name() != "" {
   740  		return rtype.Name()
   741  	}
   742  	switch rtype.Kind() {
   743  	case reflect.Array:
   744  		return fmt.Sprintf("[%d]%s", rtype.Len(), nativeTypeName(rtype.Elem()))
   745  	case reflect.Chan:
   746  		return fmt.Sprintf("chan %s", nativeTypeName(rtype.Elem()))
   747  	case reflect.Func:
   748  		return nativeFuncTypeName(rtype)
   749  	case reflect.Map:
   750  		return fmt.Sprintf("map[%s]%s", nativeTypeName(rtype.Key()), nativeTypeName(rtype.Elem()))
   751  	case reflect.Ptr:
   752  		return fmt.Sprintf("*%s", nativeTypeName(rtype.Elem()))
   753  	case reflect.Slice:
   754  		return fmt.Sprintf("[]%s", nativeTypeName(rtype.Elem()))
   755  	case reflect.Struct:
   756  		return "anonymous struct"
   757  	default:
   758  		return "unknown"
   759  	}
   760  }