github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/third_party/gofrontend/libgo/go/reflect/makefunc.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // MakeFunc implementation. 6 7 package reflect 8 9 import ( 10 "unsafe" 11 ) 12 13 // makeFuncImpl is the closure value implementing the function 14 // returned by MakeFunc. 15 type makeFuncImpl struct { 16 // These first three words are layed out like ffi_go_closure. 17 code uintptr 18 ffi_cif unsafe.Pointer 19 ffi_fun func(unsafe.Pointer, unsafe.Pointer) 20 21 typ *funcType 22 fn func([]Value) []Value 23 24 // For gccgo we use the same entry point for functions and for 25 // method values. 26 method int 27 rcvr Value 28 } 29 30 // MakeFunc returns a new function of the given Type 31 // that wraps the function fn. When called, that new function 32 // does the following: 33 // 34 // - converts its arguments to a slice of Values. 35 // - runs results := fn(args). 36 // - returns the results as a slice of Values, one per formal result. 37 // 38 // The implementation fn can assume that the argument Value slice 39 // has the number and type of arguments given by typ. 40 // If typ describes a variadic function, the final Value is itself 41 // a slice representing the variadic arguments, as in the 42 // body of a variadic function. The result Value slice returned by fn 43 // must have the number and type of results given by typ. 44 // 45 // The Value.Call method allows the caller to invoke a typed function 46 // in terms of Values; in contrast, MakeFunc allows the caller to implement 47 // a typed function in terms of Values. 48 // 49 // The Examples section of the documentation includes an illustration 50 // of how to use MakeFunc to build a swap function for different types. 51 // 52 func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { 53 if typ.Kind() != Func { 54 panic("reflect: call of MakeFunc with non-Func type") 55 } 56 57 t := typ.common() 58 ftyp := (*funcType)(unsafe.Pointer(t)) 59 60 impl := &makeFuncImpl{ 61 typ: ftyp, 62 fn: fn, 63 method: -1, 64 } 65 66 makeFuncFFI(ftyp, unsafe.Pointer(impl)) 67 68 return Value{t, unsafe.Pointer(&impl), flag(Func) | flagIndir} 69 } 70 71 // makeMethodValue converts v from the rcvr+method index representation 72 // of a method value to an actual method func value, which is 73 // basically the receiver value with a special bit set, into a true 74 // func value - a value holding an actual func. The output is 75 // semantically equivalent to the input as far as the user of package 76 // reflect can tell, but the true func representation can be handled 77 // by code like Convert and Interface and Assign. 78 func makeMethodValue(op string, v Value) Value { 79 if v.flag&flagMethod == 0 { 80 panic("reflect: internal error: invalid use of makeMethodValue") 81 } 82 83 // Ignoring the flagMethod bit, v describes the receiver, not the method type. 84 fl := v.flag & (flagRO | flagAddr | flagIndir) 85 fl |= flag(v.typ.Kind()) 86 rcvr := Value{v.typ, v.ptr, fl} 87 88 // v.Type returns the actual type of the method value. 89 ft := v.Type().(*rtype) 90 91 // Cause panic if method is not appropriate. 92 // The panic would still happen during the call if we omit this, 93 // but we want Interface() and other operations to fail early. 94 _, t, _ := methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift) 95 96 ftyp := (*funcType)(unsafe.Pointer(t)) 97 method := int(v.flag) >> flagMethodShift 98 99 fv := &makeFuncImpl{ 100 typ: ftyp, 101 method: method, 102 rcvr: rcvr, 103 } 104 105 makeFuncFFI(ftyp, unsafe.Pointer(fv)) 106 107 return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func) | flagIndir} 108 } 109 110 // makeValueMethod takes a method function and returns a function that 111 // takes a value receiver and calls the real method with a pointer to 112 // it. 113 func makeValueMethod(v Value) Value { 114 typ := v.typ 115 if typ.Kind() != Func { 116 panic("reflect: call of makeValueMethod with non-Func type") 117 } 118 if v.flag&flagMethodFn == 0 { 119 panic("reflect: call of makeValueMethod with non-MethodFn") 120 } 121 122 t := typ.common() 123 ftyp := (*funcType)(unsafe.Pointer(t)) 124 125 impl := &makeFuncImpl{ 126 typ: ftyp, 127 method: -2, 128 rcvr: v, 129 } 130 131 makeFuncFFI(ftyp, unsafe.Pointer(impl)) 132 133 return Value{t, unsafe.Pointer(&impl), v.flag&flagRO | flag(Func) | flagIndir} 134 } 135 136 // Call the function represented by a makeFuncImpl. 137 func (c *makeFuncImpl) call(in []Value) []Value { 138 if c.method == -1 { 139 return c.fn(in) 140 } else if c.method == -2 { 141 if c.typ.IsVariadic() { 142 return c.rcvr.CallSlice(in) 143 } else { 144 return c.rcvr.Call(in) 145 } 146 } else { 147 m := c.rcvr.Method(c.method) 148 if c.typ.IsVariadic() { 149 return m.CallSlice(in) 150 } else { 151 return m.Call(in) 152 } 153 } 154 }