github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/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 runtime 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 }