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  }