import (
"math"
"runtime"
+ "strconv"
"unsafe"
)
-const ptrSize = uintptr(unsafe.Sizeof((*byte)(nil)))
-const cannotSet = "cannot set value obtained via unexported struct field"
-
-type addr unsafe.Pointer
+const bigEndian = false // can be smarter if we find a big-endian machine
+const ptrSize = unsafe.Sizeof((*byte)(nil))
+const cannotSet = "cannot set value obtained from unexported struct field"
// TODO: This will have to go away when
// the new gc goes in.
-func memmove(adst, asrc addr, n uintptr) {
+func memmove(adst, asrc unsafe.Pointer, n uintptr) {
dst := uintptr(adst)
src := uintptr(asrc)
switch {
// careful: i is unsigned
for i := n; i > 0; {
i--
- *(*byte)(addr(dst + i)) = *(*byte)(addr(src + i))
+ *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
}
case (n|src|dst)&(ptrSize-1) != 0:
// byte copy forward
for i := uintptr(0); i < n; i++ {
- *(*byte)(addr(dst + i)) = *(*byte)(addr(src + i))
+ *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i))
}
default:
// word copy forward
for i := uintptr(0); i < n; i += ptrSize {
- *(*uintptr)(addr(dst + i)) = *(*uintptr)(addr(src + i))
+ *(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i))
}
}
}
-// Value is the common interface to reflection values.
-// The implementations of Value (e.g., ArrayValue, StructValue)
-// have additional type-specific methods.
-type Value interface {
- // Type returns the value's type.
- Type() Type
-
- // Interface returns the value as an interface{}.
- Interface() interface{}
-
- // CanSet returns whether the value can be changed.
- // Values obtained by the use of non-exported struct fields
- // can be used in Get but not Set.
- // If CanSet() returns false, calling the type-specific Set
- // will cause a crash.
- CanSet() bool
-
- // SetValue assigns v to the value; v must have the same type as the value.
- SetValue(v Value)
-
- // Addr returns a pointer to the underlying data.
- // It is for advanced clients that also
- // import the "unsafe" package.
- Addr() uintptr
-
- // Method returns a FuncValue corresponding to the value's i'th method.
- // The arguments to a Call on the returned FuncValue
- // should not include a receiver; the FuncValue will use
- // the value as the receiver.
- Method(i int) *FuncValue
+// Value is the reflection interface to a Go value.
+//
+// Not all methods apply to all kinds of values. Restrictions,
+// if any, are noted in the documentation for each method.
+// Use the Kind method to find out the kind of value before
+// calling kind-specific methods. Calling a method
+// inappropriate to the kind of type causes a run time panic.
+//
+// The zero Value represents no value.
+// Its IsValid method returns false, its Kind method returns Invalid,
+// its String method returns "<invalid Value>", and all other methods panic.
+// Most functions and methods never return an invalid value.
+// If one does, its documentation states the conditions explicitly.
+//
+// A Value can be used concurrently by multiple goroutines provided that
+// the underlying Go value can be used concurrently for the equivalent
+// direct operations.
+type Value struct {
+ // typ holds the type of the value represented by a Value.
+ typ *commonType
+
+ // val holds the 1-word representation of the value.
+ // If flag's flagIndir bit is set, then val is a pointer to the data.
+ // Otherwise val is a word holding the actual data.
+ // When the data is smaller than a word, it begins at
+ // the first byte (in the memory address sense) of val.
+ // We use unsafe.Pointer so that the garbage collector
+ // knows that val could be a pointer.
+ val unsafe.Pointer
+
+ // flag holds metadata about the value.
+ // The lowest bits are flag bits:
+ // - flagRO: obtained via unexported field, so read-only
+ // - flagIndir: val holds a pointer to the data
+ // - flagAddr: v.CanAddr is true (implies flagIndir)
+ // - flagMethod: v is a method value.
+ // The next five bits give the Kind of the value.
+ // This repeats typ.Kind() except for method values.
+ // The remaining 23+ bits give a method number for method values.
+ // If flag.kind() != Func, code can assume that flagMethod is unset.
+ // If typ.size > ptrSize, code can assume that flagIndir is set.
+ flag
+
+ // A method value represents a curried method invocation
+ // like r.Read for some receiver r. The typ+val+flag bits describe
+ // the receiver r, but the flag's Kind bits say Func (methods are
+ // functions), and the top bits of the flag give the method number
+ // in r's type's method table.
+}
+
+type flag uintptr
+
+const (
+ flagRO flag = 1 << iota
+ flagIndir
+ flagAddr
+ flagMethod
+ flagKindShift = iota
+ flagKindWidth = 5 // there are 27 kinds
+ flagKindMask flag = 1<<flagKindWidth - 1
+ flagMethodShift = flagKindShift + flagKindWidth
+)
- getAddr() addr
+func (f flag) kind() Kind {
+ return Kind((f >> flagKindShift) & flagKindMask)
}
-// value is the common implementation of most values.
-// It is embedded in other, public struct types, but always
-// with a unique tag like "uint" or "float" so that the client cannot
-// convert from, say, *UintValue to *FloatValue.
-type value struct {
- typ Type
- addr addr
- canSet bool
+// A ValueError occurs when a Value method is invoked on
+// a Value that does not support it. Such cases are documented
+// in the description of each method.
+type ValueError struct {
+ Method string
+ Kind Kind
}
-func (v *value) Type() Type { return v.typ }
+func (e *ValueError) Error() string {
+ if e.Kind == 0 {
+ return "reflect: call of " + e.Method + " on zero Value"
+ }
+ return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
+}
-func (v *value) Addr() uintptr { return uintptr(v.addr) }
+// methodName returns the name of the calling method,
+// assumed to be two stack frames above.
+func methodName() string {
+ pc, _, _, _ := runtime.Caller(2)
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ return "unknown method"
+ }
+ return f.Name()
+}
-func (v *value) getAddr() addr { return v.addr }
+// An iword is the word that would be stored in an
+// interface to represent a given value v. Specifically, if v is
+// bigger than a pointer, its word is a pointer to v's data.
+// Otherwise, its word holds the data stored
+// in its leading bytes (so is not a pointer).
+// Because the value sometimes holds a pointer, we use
+// unsafe.Pointer to represent it, so that if iword appears
+// in a struct, the garbage collector knows that might be
+// a pointer.
+type iword unsafe.Pointer
-func (v *value) Interface() interface{} {
- if typ, ok := v.typ.(*InterfaceType); ok {
- // There are two different representations of interface values,
- // one if the interface type has methods and one if it doesn't.
- // These two representations require different expressions
- // to extract correctly.
- if typ.NumMethod() == 0 {
- // Extract as interface value without methods.
- return *(*interface{})(v.addr)
- }
- // Extract from v.addr as interface value with methods.
- return *(*interface {
- m()
- })(v.addr)
+func (v Value) iword() iword {
+ if v.flag&flagIndir != 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+ // Have indirect but want direct word.
+ return loadIword(v.val, v.typ.size)
}
- return unsafe.Unreflect(v.typ, unsafe.Pointer(v.addr))
+ return iword(v.val)
}
-func (v *value) CanSet() bool { return v.canSet }
+// loadIword loads n bytes at p from memory into an iword.
+func loadIword(p unsafe.Pointer, n uintptr) iword {
+ // Run the copy ourselves instead of calling memmove
+ // to avoid moving w to the heap.
+ var w iword
+ switch n {
+ default:
+ panic("reflect: internal error: loadIword of " + strconv.Itoa(int(n)) + "-byte value")
+ case 0:
+ case 1:
+ *(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
+ case 2:
+ *(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p)
+ case 3:
+ *(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p)
+ case 4:
+ *(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p)
+ case 5:
+ *(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p)
+ case 6:
+ *(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p)
+ case 7:
+ *(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p)
+ case 8:
+ *(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p)
+ }
+ return w
+}
+
+// storeIword stores n bytes from w into p.
+func storeIword(p unsafe.Pointer, w iword, n uintptr) {
+ // Run the copy ourselves instead of calling memmove
+ // to avoid moving w to the heap.
+ switch n {
+ default:
+ panic("reflect: internal error: storeIword of " + strconv.Itoa(int(n)) + "-byte value")
+ case 0:
+ case 1:
+ *(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
+ case 2:
+ *(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w))
+ case 3:
+ *(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w))
+ case 4:
+ *(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w))
+ case 5:
+ *(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w))
+ case 6:
+ *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w))
+ case 7:
+ *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w))
+ case 8:
+ *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w))
+ }
+}
-/*
- * basic types
- */
+// emptyInterface is the header for an interface{} value.
+type emptyInterface struct {
+ typ *runtimeType
+ word iword
+}
-// BoolValue represents a bool value.
-type BoolValue struct {
- value "bool"
+// nonEmptyInterface is the header for a interface value with methods.
+type nonEmptyInterface struct {
+ // see ../runtime/iface.c:/Itab
+ itab *struct {
+ typ *runtimeType // dynamic concrete type
+ fun [100000]unsafe.Pointer // method table
+ }
+ word iword
+}
+
+// mustBe panics if f's kind is not expected.
+// Making this a method on flag instead of on Value
+// (and embedding flag in Value) means that we can write
+// the very clear v.mustBe(Bool) and have it compile into
+// v.flag.mustBe(Bool), which will only bother to copy the
+// single important word for the receiver.
+func (f flag) mustBe(expected Kind) {
+ k := f.kind()
+ if k != expected {
+ panic(&ValueError{methodName(), k})
+ }
+}
+
+// mustBeExported panics if f records that the value was obtained using
+// an unexported field.
+func (f flag) mustBeExported() {
+ if f == 0 {
+ panic(&ValueError{methodName(), 0})
+ }
+ if f&flagRO != 0 {
+ panic(methodName() + " using value obtained using unexported field")
+ }
+}
+
+// mustBeAssignable panics if f records that the value is not assignable,
+// which is to say that either it was obtained using an unexported field
+// or it is not addressable.
+func (f flag) mustBeAssignable() {
+ if f == 0 {
+ panic(&ValueError{methodName(), Invalid})
+ }
+ // Assignable if addressable and not read-only.
+ if f&flagRO != 0 {
+ panic(methodName() + " using value obtained using unexported field")
+ }
+ if f&flagAddr == 0 {
+ panic(methodName() + " using unaddressable value")
+ }
+}
+
+// Addr returns a pointer value representing the address of v.
+// It panics if CanAddr() returns false.
+// Addr is typically used to obtain a pointer to a struct field
+// or slice element in order to call a method that requires a
+// pointer receiver.
+func (v Value) Addr() Value {
+ if v.flag&flagAddr == 0 {
+ panic("reflect.Value.Addr of unaddressable value")
+ }
+ return Value{v.typ.ptrTo(), v.val, (v.flag & flagRO) | flag(Ptr)<<flagKindShift}
+}
+
+// Bool returns v's underlying value.
+// It panics if v's kind is not Bool.
+func (v Value) Bool() bool {
+ v.mustBe(Bool)
+ if v.flag&flagIndir != 0 {
+ return *(*bool)(v.val)
+ }
+ return *(*bool)(unsafe.Pointer(&v.val))
+}
+
+// Bytes returns v's underlying value.
+// It panics if v's underlying value is not a slice of bytes.
+func (v Value) Bytes() []byte {
+ v.mustBe(Slice)
+ if v.typ.Elem().Kind() != Uint8 {
+ panic("reflect.Value.Bytes of non-byte slice")
+ }
+ // Slice is always bigger than a word; assume flagIndir.
+ return *(*[]byte)(v.val)
+}
+
+// CanAddr returns true if the value's address can be obtained with Addr.
+// Such values are called addressable. A value is addressable if it is
+// an element of a slice, an element of an addressable array,
+// a field of an addressable struct, or the result of dereferencing a pointer.
+// If CanAddr returns false, calling Addr will panic.
+func (v Value) CanAddr() bool {
+ return v.flag&flagAddr != 0
}
-// Get returns the underlying bool value.
-func (v *BoolValue) Get() bool { return *(*bool)(v.addr) }
+// CanSet returns true if the value of v can be changed.
+// A Value can be changed only if it is addressable and was not
+// obtained by the use of unexported struct fields.
+// If CanSet returns false, calling Set or any type-specific
+// setter (e.g., SetBool, SetInt64) will panic.
+func (v Value) CanSet() bool {
+ return v.flag&(flagAddr|flagRO) == flagAddr
+}
+
+// Call calls the function v with the input arguments in.
+// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
+// Call panics if v's Kind is not Func.
+// It returns the output results as Values.
+// As in Go, each input argument must be assignable to the
+// type of the function's corresponding input parameter.
+// If v is a variadic function, Call creates the variadic slice parameter
+// itself, copying in the corresponding values.
+func (v Value) Call(in []Value) []Value {
+ v.mustBe(Func)
+ v.mustBeExported()
+ return v.call("Call", in)
+}
+
+// CallSlice calls the variadic function v with the input arguments in,
+// assigning the slice in[len(in)-1] to v's final variadic argument.
+// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]...).
+// Call panics if v's Kind is not Func or if v is not variadic.
+// It returns the output results as Values.
+// As in Go, each input argument must be assignable to the
+// type of the function's corresponding input parameter.
+func (v Value) CallSlice(in []Value) []Value {
+ v.mustBe(Func)
+ v.mustBeExported()
+ return v.call("CallSlice", in)
+}
+
+func (v Value) call(method string, in []Value) []Value {
+ // Get function pointer, type.
+ t := v.typ
+ var (
+ fn unsafe.Pointer
+ rcvr iword
+ )
+ if v.flag&flagMethod != 0 {
+ i := int(v.flag) >> flagMethodShift
+ if v.typ.Kind() == Interface {
+ tt := (*interfaceType)(unsafe.Pointer(v.typ))
+ if i < 0 || i >= len(tt.methods) {
+ panic("reflect: broken Value")
+ }
+ m := &tt.methods[i]
+ if m.pkgPath != nil {
+ panic(method + " of unexported method")
+ }
+ t = toCommonType(m.typ)
+ iface := (*nonEmptyInterface)(v.val)
+ if iface.itab == nil {
+ panic(method + " of method on nil interface value")
+ }
+ fn = iface.itab.fun[i]
+ rcvr = iface.word
+ } else {
+ ut := v.typ.uncommon()
+ if ut == nil || i < 0 || i >= len(ut.methods) {
+ panic("reflect: broken Value")
+ }
+ m := &ut.methods[i]
+ if m.pkgPath != nil {
+ panic(method + " of unexported method")
+ }
+ fn = m.tfn
+ t = toCommonType(m.mtyp)
+ rcvr = v.iword()
+ }
+ } else if v.flag&flagIndir != 0 {
+ fn = *(*unsafe.Pointer)(v.val)
+ } else {
+ fn = v.val
+ }
-// Set sets v to the value x.
-func (v *BoolValue) Set(x bool) {
- if !v.canSet {
- panic(cannotSet)
+ if fn == nil {
+ panic("reflect.Value.Call: call of nil function")
}
- *(*bool)(v.addr) = x
-}
-// Set sets v to the value x.
-func (v *BoolValue) SetValue(x Value) { v.Set(x.(*BoolValue).Get()) }
+ isSlice := method == "CallSlice"
+ n := t.NumIn()
+ if isSlice {
+ if !t.IsVariadic() {
+ panic("reflect: CallSlice of non-variadic function")
+ }
+ if len(in) < n {
+ panic("reflect: CallSlice with too few input arguments")
+ }
+ if len(in) > n {
+ panic("reflect: CallSlice with too many input arguments")
+ }
+ } else {
+ if t.IsVariadic() {
+ n--
+ }
+ if len(in) < n {
+ panic("reflect: Call with too few input arguments")
+ }
+ if !t.IsVariadic() && len(in) > n {
+ panic("reflect: Call with too many input arguments")
+ }
+ }
+ for _, x := range in {
+ if x.Kind() == Invalid {
+ panic("reflect: " + method + " using zero Value argument")
+ }
+ }
+ for i := 0; i < n; i++ {
+ if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
+ panic("reflect: " + method + " using " + xt.String() + " as type " + targ.String())
+ }
+ }
+ if !isSlice && t.IsVariadic() {
+ // prepare slice for remaining values
+ m := len(in) - n
+ slice := MakeSlice(t.In(n), m, m)
+ elem := t.In(n).Elem()
+ for i := 0; i < m; i++ {
+ x := in[n+i]
+ if xt := x.Type(); !xt.AssignableTo(elem) {
+ panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + method)
+ }
+ slice.Index(i).Set(x)
+ }
+ origIn := in
+ in = make([]Value, n+1)
+ copy(in[:n], origIn)
+ in[n] = slice
+ }
-// FloatValue represents a float value.
-type FloatValue struct {
- value "float"
-}
+ nin := len(in)
+ if nin != t.NumIn() {
+ panic("reflect.Value.Call: wrong argument count")
+ }
+ nout := t.NumOut()
-// Get returns the underlying int value.
-func (v *FloatValue) Get() float64 {
- switch v.typ.Kind() {
- case Float32:
- return float64(*(*float32)(v.addr))
- case Float64:
- return *(*float64)(v.addr)
+ if v.flag&flagMethod != 0 {
+ nin++
+ }
+ params := make([]unsafe.Pointer, nin)
+ off := 0
+ if v.flag&flagMethod != 0 {
+ // Hard-wired first argument.
+ p := new(iword)
+ *p = rcvr
+ params[0] = unsafe.Pointer(p)
+ off = 1
+ }
+ first_pointer := false
+ for i, pv := range in {
+ pv.mustBeExported()
+ targ := t.In(i).(*commonType)
+ pv = pv.assignTo("reflect.Value.Call", targ, nil)
+ if pv.flag&flagIndir == 0 {
+ p := new(unsafe.Pointer)
+ *p = pv.val
+ params[off] = unsafe.Pointer(p)
+ } else {
+ params[off] = pv.val
+ }
+ if i == 0 && Kind(targ.kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ) {
+ p := new(unsafe.Pointer)
+ *p = params[off]
+ params[off] = unsafe.Pointer(p)
+ first_pointer = true
+ }
+ off++
}
- panic("reflect: invalid float kind")
-}
-// Set sets v to the value x.
-func (v *FloatValue) Set(x float64) {
- if !v.canSet {
- panic(cannotSet)
+ ret := make([]Value, nout)
+ results := make([]unsafe.Pointer, nout)
+ for i := 0; i < nout; i++ {
+ v := New(t.Out(i))
+ results[i] = unsafe.Pointer(v.Pointer())
+ ret[i] = Indirect(v)
}
- switch v.typ.Kind() {
- default:
- panic("reflect: invalid float kind")
- case Float32:
- *(*float32)(v.addr) = float32(x)
- case Float64:
- *(*float64)(v.addr) = x
+
+ var pp *unsafe.Pointer
+ if len(params) > 0 {
+ pp = ¶ms[0]
+ }
+ var pr *unsafe.Pointer
+ if len(results) > 0 {
+ pr = &results[0]
}
+
+ call(t, fn, v.flag&flagMethod != 0, first_pointer, pp, pr)
+
+ return ret
}
-// Overflow returns true if x cannot be represented by the type of v.
-func (v *FloatValue) Overflow(x float64) bool {
- if v.typ.Size() == 8 {
+// gccgo specific test to see if typ is a method. We can tell by
+// looking at the string to see if there is a receiver. We need this
+// because for gccgo all methods take pointer receivers.
+func isMethod(t *commonType) bool {
+ if Kind(t.kind) != Func {
return false
}
- if x < 0 {
- x = -x
+ s := *t.string
+ parens := 0
+ params := 0
+ sawRet := false
+ for i, c := range s {
+ if c == '(' {
+ parens++
+ params++
+ } else if c == ')' {
+ parens--
+ } else if parens == 0 && c == ' ' && s[i+1] != '(' && !sawRet {
+ params++
+ sawRet = true
+ }
}
- return math.MaxFloat32 < x && x <= math.MaxFloat64
+ return params > 2
}
-// Set sets v to the value x.
-func (v *FloatValue) SetValue(x Value) { v.Set(x.(*FloatValue).Get()) }
+// Cap returns v's capacity.
+// It panics if v's Kind is not Array, Chan, or Slice.
+func (v Value) Cap() int {
+ k := v.kind()
+ switch k {
+ case Array:
+ return v.typ.Len()
+ case Chan:
+ return int(chancap(*(*iword)(v.iword())))
+ case Slice:
+ // Slice is always bigger than a word; assume flagIndir.
+ return (*SliceHeader)(v.val).Cap
+ }
+ panic(&ValueError{"reflect.Value.Cap", k})
+}
-// ComplexValue represents a complex value.
-type ComplexValue struct {
- value "complex"
+// Close closes the channel v.
+// It panics if v's Kind is not Chan.
+func (v Value) Close() {
+ v.mustBe(Chan)
+ v.mustBeExported()
+ chanclose(*(*iword)(v.iword()))
}
-// Get returns the underlying complex value.
-func (v *ComplexValue) Get() complex128 {
- switch v.typ.Kind() {
+// Complex returns v's underlying value, as a complex128.
+// It panics if v's Kind is not Complex64 or Complex128
+func (v Value) Complex() complex128 {
+ k := v.kind()
+ switch k {
case Complex64:
- return complex128(*(*complex64)(v.addr))
+ if v.flag&flagIndir != 0 {
+ return complex128(*(*complex64)(v.val))
+ }
+ return complex128(*(*complex64)(unsafe.Pointer(&v.val)))
case Complex128:
- return *(*complex128)(v.addr)
+ // complex128 is always bigger than a word; assume flagIndir.
+ return *(*complex128)(v.val)
+ }
+ panic(&ValueError{"reflect.Value.Complex", k})
+}
+
+// Elem returns the value that the interface v contains
+// or that the pointer v points to.
+// It panics if v's Kind is not Interface or Ptr.
+// It returns the zero Value if v is nil.
+func (v Value) Elem() Value {
+ k := v.kind()
+ switch k {
+ case Interface:
+ var (
+ typ *commonType
+ val unsafe.Pointer
+ )
+ if v.typ.NumMethod() == 0 {
+ eface := (*emptyInterface)(v.val)
+ if eface.typ == nil {
+ // nil interface value
+ return Value{}
+ }
+ typ = toCommonType(eface.typ)
+ val = unsafe.Pointer(eface.word)
+ } else {
+ iface := (*nonEmptyInterface)(v.val)
+ if iface.itab == nil {
+ // nil interface value
+ return Value{}
+ }
+ typ = toCommonType(iface.itab.typ)
+ val = unsafe.Pointer(iface.word)
+ }
+ fl := v.flag & flagRO
+ fl |= flag(typ.Kind()) << flagKindShift
+ if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+ fl |= flagIndir
+ }
+ return Value{typ, val, fl}
+
+ case Ptr:
+ val := v.val
+ if v.flag&flagIndir != 0 {
+ val = *(*unsafe.Pointer)(val)
+ }
+ // The returned value's address is v's value.
+ if val == nil {
+ return Value{}
+ }
+ tt := (*ptrType)(unsafe.Pointer(v.typ))
+ typ := toCommonType(tt.elem)
+ fl := v.flag&flagRO | flagIndir | flagAddr
+ fl |= flag(typ.Kind() << flagKindShift)
+ return Value{typ, val, fl}
}
- panic("reflect: invalid complex kind")
+ panic(&ValueError{"reflect.Value.Elem", k})
}
-// Set sets v to the value x.
-func (v *ComplexValue) Set(x complex128) {
- if !v.canSet {
- panic(cannotSet)
+// Field returns the i'th field of the struct v.
+// It panics if v's Kind is not Struct or i is out of range.
+func (v Value) Field(i int) Value {
+ v.mustBe(Struct)
+ tt := (*structType)(unsafe.Pointer(v.typ))
+ if i < 0 || i >= len(tt.fields) {
+ panic("reflect: Field index out of range")
+ }
+ field := &tt.fields[i]
+ typ := toCommonType(field.typ)
+
+ // Inherit permission bits from v.
+ fl := v.flag & (flagRO | flagIndir | flagAddr)
+ // Using an unexported field forces flagRO.
+ if field.pkgPath != nil {
+ fl |= flagRO
}
- switch v.typ.Kind() {
+ fl |= flag(typ.Kind()) << flagKindShift
+
+ var val unsafe.Pointer
+ switch {
+ case fl&flagIndir != 0:
+ // Indirect. Just bump pointer.
+ val = unsafe.Pointer(uintptr(v.val) + field.offset)
+ case bigEndian:
+ // Direct. Discard leading bytes.
+ val = unsafe.Pointer(uintptr(v.val) << (field.offset * 8))
default:
- panic("reflect: invalid complex kind")
- case Complex64:
- *(*complex64)(v.addr) = complex64(x)
- case Complex128:
- *(*complex128)(v.addr) = x
+ // Direct. Discard leading bytes.
+ val = unsafe.Pointer(uintptr(v.val) >> (field.offset * 8))
}
+
+ return Value{typ, val, fl}
}
-// Set sets v to the value x.
-func (v *ComplexValue) SetValue(x Value) { v.Set(x.(*ComplexValue).Get()) }
+// FieldByIndex returns the nested field corresponding to index.
+// It panics if v's Kind is not struct.
+func (v Value) FieldByIndex(index []int) Value {
+ v.mustBe(Struct)
+ for i, x := range index {
+ if i > 0 {
+ if v.Kind() == Ptr && v.Elem().Kind() == Struct {
+ v = v.Elem()
+ }
+ }
+ v = v.Field(x)
+ }
+ return v
+}
-// IntValue represents an int value.
-type IntValue struct {
- value "int"
+// FieldByName returns the struct field with the given name.
+// It returns the zero Value if no field was found.
+// It panics if v's Kind is not struct.
+func (v Value) FieldByName(name string) Value {
+ v.mustBe(Struct)
+ if f, ok := v.typ.FieldByName(name); ok {
+ return v.FieldByIndex(f.Index)
+ }
+ return Value{}
}
-// Get returns the underlying int value.
-func (v *IntValue) Get() int64 {
- switch v.typ.Kind() {
- case Int:
- return int64(*(*int)(v.addr))
- case Int8:
- return int64(*(*int8)(v.addr))
- case Int16:
- return int64(*(*int16)(v.addr))
- case Int32:
- return int64(*(*int32)(v.addr))
- case Int64:
- return *(*int64)(v.addr)
+// FieldByNameFunc returns the struct field with a name
+// that satisfies the match function.
+// It panics if v's Kind is not struct.
+// It returns the zero Value if no field was found.
+func (v Value) FieldByNameFunc(match func(string) bool) Value {
+ v.mustBe(Struct)
+ if f, ok := v.typ.FieldByNameFunc(match); ok {
+ return v.FieldByIndex(f.Index)
}
- panic("reflect: invalid int kind")
+ return Value{}
}
-// Set sets v to the value x.
-func (v *IntValue) Set(x int64) {
- if !v.canSet {
- panic(cannotSet)
+// Float returns v's underlying value, as a float64.
+// It panics if v's Kind is not Float32 or Float64
+func (v Value) Float() float64 {
+ k := v.kind()
+ switch k {
+ case Float32:
+ if v.flag&flagIndir != 0 {
+ return float64(*(*float32)(v.val))
+ }
+ return float64(*(*float32)(unsafe.Pointer(&v.val)))
+ case Float64:
+ if v.flag&flagIndir != 0 {
+ return *(*float64)(v.val)
+ }
+ return *(*float64)(unsafe.Pointer(&v.val))
}
- switch v.typ.Kind() {
- default:
- panic("reflect: invalid int kind")
+ panic(&ValueError{"reflect.Value.Float", k})
+}
+
+// Index returns v's i'th element.
+// It panics if v's Kind is not Array or Slice or i is out of range.
+func (v Value) Index(i int) Value {
+ k := v.kind()
+ switch k {
+ case Array:
+ tt := (*arrayType)(unsafe.Pointer(v.typ))
+ if i < 0 || i > int(tt.len) {
+ panic("reflect: array index out of range")
+ }
+ typ := toCommonType(tt.elem)
+ fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
+ fl |= flag(typ.Kind()) << flagKindShift
+ offset := uintptr(i) * typ.size
+
+ var val unsafe.Pointer
+ switch {
+ case fl&flagIndir != 0:
+ // Indirect. Just bump pointer.
+ val = unsafe.Pointer(uintptr(v.val) + offset)
+ case bigEndian:
+ // Direct. Discard leading bytes.
+ val = unsafe.Pointer(uintptr(v.val) << (offset * 8))
+ default:
+ // Direct. Discard leading bytes.
+ val = unsafe.Pointer(uintptr(v.val) >> (offset * 8))
+ }
+ return Value{typ, val, fl}
+
+ case Slice:
+ // Element flag same as Elem of Ptr.
+ // Addressable, indirect, possibly read-only.
+ fl := flagAddr | flagIndir | v.flag&flagRO
+ s := (*SliceHeader)(v.val)
+ if i < 0 || i >= s.Len {
+ panic("reflect: slice index out of range")
+ }
+ tt := (*sliceType)(unsafe.Pointer(v.typ))
+ typ := toCommonType(tt.elem)
+ fl |= flag(typ.Kind()) << flagKindShift
+ val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
+ return Value{typ, val, fl}
+ }
+ panic(&ValueError{"reflect.Value.Index", k})
+}
+
+// Int returns v's underlying value, as an int64.
+// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
+func (v Value) Int() int64 {
+ k := v.kind()
+ var p unsafe.Pointer
+ if v.flag&flagIndir != 0 {
+ p = v.val
+ } else {
+ // The escape analysis is good enough that &v.val
+ // does not trigger a heap allocation.
+ p = unsafe.Pointer(&v.val)
+ }
+ switch k {
case Int:
- *(*int)(v.addr) = int(x)
+ return int64(*(*int)(p))
case Int8:
- *(*int8)(v.addr) = int8(x)
+ return int64(*(*int8)(p))
case Int16:
- *(*int16)(v.addr) = int16(x)
+ return int64(*(*int16)(p))
case Int32:
- *(*int32)(v.addr) = int32(x)
+ return int64(*(*int32)(p))
case Int64:
- *(*int64)(v.addr) = x
+ return int64(*(*int64)(p))
}
+ panic(&ValueError{"reflect.Value.Int", k})
}
-// Set sets v to the value x.
-func (v *IntValue) SetValue(x Value) { v.Set(x.(*IntValue).Get()) }
-
-// Overflow returns true if x cannot be represented by the type of v.
-func (v *IntValue) Overflow(x int64) bool {
- bitSize := uint(v.typ.Bits())
- trunc := (x << (64 - bitSize)) >> (64 - bitSize)
- return x != trunc
+// CanInterface returns true if Interface can be used without panicking.
+func (v Value) CanInterface() bool {
+ if v.flag == 0 {
+ panic(&ValueError{"reflect.Value.CanInterface", Invalid})
+ }
+ return v.flag&(flagMethod|flagRO) == 0
}
-// StringHeader is the runtime representation of a string.
-type StringHeader struct {
- Data uintptr
- Len int
+// Interface returns v's current value as an interface{}.
+// It is equivalent to:
+// var i interface{} = (v's underlying value)
+// If v is a method obtained by invoking Value.Method
+// (as opposed to Type.Method), Interface cannot return an
+// interface value, so it panics.
+// It also panics if the Value was obtained by accessing
+// unexported struct fields.
+func (v Value) Interface() (i interface{}) {
+ return valueInterface(v, true)
}
-// StringValue represents a string value.
-type StringValue struct {
- value "string"
-}
+func valueInterface(v Value, safe bool) interface{} {
+ if v.flag == 0 {
+ panic(&ValueError{"reflect.Value.Interface", 0})
+ }
+ if v.flag&flagMethod != 0 {
+ panic("reflect.Value.Interface: cannot create interface value for method with bound receiver")
+ }
-// Get returns the underlying string value.
-func (v *StringValue) Get() string { return *(*string)(v.addr) }
+ if safe && v.flag&flagRO != 0 {
+ // Do not allow access to unexported values via Interface,
+ // because they might be pointers that should not be
+ // writable or methods or function that should not be callable.
+ panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
+ }
-// Set sets v to the value x.
-func (v *StringValue) Set(x string) {
- if !v.canSet {
- panic(cannotSet)
+ k := v.kind()
+ if k == Interface {
+ // Special case: return the element inside the interface.
+ // Empty interface has one layout, all interfaces with
+ // methods have a second layout.
+ if v.NumMethod() == 0 {
+ return *(*interface{})(v.val)
+ }
+ return *(*interface {
+ M()
+ })(v.val)
+ }
+
+ // Non-interface value.
+ var eface emptyInterface
+ eface.typ = v.typ.runtimeType()
+ eface.word = v.iword()
+
+ if v.flag&flagIndir != 0 && v.kind() != Ptr && v.kind() != UnsafePointer {
+ // eface.word is a pointer to the actual data,
+ // which might be changed. We need to return
+ // a pointer to unchanging data, so make a copy.
+ ptr := unsafe_New(v.typ)
+ memmove(ptr, unsafe.Pointer(eface.word), v.typ.size)
+ eface.word = iword(ptr)
+ }
+
+ return *(*interface{})(unsafe.Pointer(&eface))
+}
+
+// InterfaceData returns the interface v's value as a uintptr pair.
+// It panics if v's Kind is not Interface.
+func (v Value) InterfaceData() [2]uintptr {
+ v.mustBe(Interface)
+ // We treat this as a read operation, so we allow
+ // it even for unexported data, because the caller
+ // has to import "unsafe" to turn it into something
+ // that can be abused.
+ // Interface value is always bigger than a word; assume flagIndir.
+ return *(*[2]uintptr)(v.val)
+}
+
+// IsNil returns true if v is a nil value.
+// It panics if v's Kind is not Chan, Func, Interface, Map, Ptr, or Slice.
+func (v Value) IsNil() bool {
+ k := v.kind()
+ switch k {
+ case Chan, Func, Map, Ptr:
+ if v.flag&flagMethod != 0 {
+ panic("reflect: IsNil of method Value")
+ }
+ ptr := v.val
+ if v.flag&flagIndir != 0 {
+ ptr = *(*unsafe.Pointer)(ptr)
+ }
+ return ptr == nil
+ case Interface, Slice:
+ // Both interface and slice are nil if first word is 0.
+ // Both are always bigger than a word; assume flagIndir.
+ return *(*unsafe.Pointer)(v.val) == nil
+ }
+ panic(&ValueError{"reflect.Value.IsNil", k})
+}
+
+// IsValid returns true if v represents a value.
+// It returns false if v is the zero Value.
+// If IsValid returns false, all other methods except String panic.
+// Most functions and methods never return an invalid value.
+// If one does, its documentation states the conditions explicitly.
+func (v Value) IsValid() bool {
+ return v.flag != 0
+}
+
+// Kind returns v's Kind.
+// If v is the zero Value (IsValid returns false), Kind returns Invalid.
+func (v Value) Kind() Kind {
+ return v.kind()
+}
+
+// Len returns v's length.
+// It panics if v's Kind is not Array, Chan, Map, Slice, or String.
+func (v Value) Len() int {
+ k := v.kind()
+ switch k {
+ case Array:
+ tt := (*arrayType)(unsafe.Pointer(v.typ))
+ return int(tt.len)
+ case Chan:
+ return int(chanlen(*(*iword)(v.iword())))
+ case Map:
+ return int(maplen(*(*iword)(v.iword())))
+ case Slice:
+ // Slice is bigger than a word; assume flagIndir.
+ return (*SliceHeader)(v.val).Len
+ case String:
+ // String is bigger than a word; assume flagIndir.
+ return (*StringHeader)(v.val).Len
+ }
+ panic(&ValueError{"reflect.Value.Len", k})
+}
+
+// MapIndex returns the value associated with key in the map v.
+// It panics if v's Kind is not Map.
+// It returns the zero Value if key is not found in the map or if v represents a nil map.
+// As in Go, the key's value must be assignable to the map's key type.
+func (v Value) MapIndex(key Value) Value {
+ v.mustBe(Map)
+ tt := (*mapType)(unsafe.Pointer(v.typ))
+
+ // Do not require key to be exported, so that DeepEqual
+ // and other programs can use all the keys returned by
+ // MapKeys as arguments to MapIndex. If either the map
+ // or the key is unexported, though, the result will be
+ // considered unexported. This is consistent with the
+ // behavior for structs, which allow read but not write
+ // of unexported fields.
+ key = key.assignTo("reflect.Value.MapIndex", toCommonType(tt.key), nil)
+
+ word, ok := mapaccess(v.typ.runtimeType(), *(*iword)(v.iword()), key.iword())
+ if !ok {
+ return Value{}
+ }
+ typ := toCommonType(tt.elem)
+ fl := (v.flag | key.flag) & flagRO
+ if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+ fl |= flagIndir
}
- *(*string)(v.addr) = x
+ fl |= flag(typ.Kind()) << flagKindShift
+ return Value{typ, unsafe.Pointer(word), fl}
}
-// Set sets v to the value x.
-func (v *StringValue) SetValue(x Value) { v.Set(x.(*StringValue).Get()) }
-
-// UintValue represents a uint value.
-type UintValue struct {
- value "uint"
-}
+// MapKeys returns a slice containing all the keys present in the map,
+// in unspecified order.
+// It panics if v's Kind is not Map.
+// It returns an empty slice if v represents a nil map.
+func (v Value) MapKeys() []Value {
+ v.mustBe(Map)
+ tt := (*mapType)(unsafe.Pointer(v.typ))
+ keyType := toCommonType(tt.key)
-// Get returns the underlying uuint value.
-func (v *UintValue) Get() uint64 {
- switch v.typ.Kind() {
- case Uint:
- return uint64(*(*uint)(v.addr))
- case Uint8:
- return uint64(*(*uint8)(v.addr))
- case Uint16:
- return uint64(*(*uint16)(v.addr))
- case Uint32:
- return uint64(*(*uint32)(v.addr))
- case Uint64:
- return *(*uint64)(v.addr)
- case Uintptr:
- return uint64(*(*uintptr)(v.addr))
+ fl := v.flag & flagRO
+ fl |= flag(keyType.Kind()) << flagKindShift
+ if keyType.Kind() != Ptr && keyType.Kind() != UnsafePointer {
+ fl |= flagIndir
}
- panic("reflect: invalid uint kind")
-}
-// Set sets v to the value x.
-func (v *UintValue) Set(x uint64) {
- if !v.canSet {
- panic(cannotSet)
+ m := *(*iword)(v.iword())
+ mlen := int32(0)
+ if m != nil {
+ mlen = maplen(m)
}
- switch v.typ.Kind() {
- default:
- panic("reflect: invalid uint kind")
- case Uint:
- *(*uint)(v.addr) = uint(x)
- case Uint8:
- *(*uint8)(v.addr) = uint8(x)
- case Uint16:
- *(*uint16)(v.addr) = uint16(x)
- case Uint32:
- *(*uint32)(v.addr) = uint32(x)
- case Uint64:
- *(*uint64)(v.addr) = x
- case Uintptr:
- *(*uintptr)(v.addr) = uintptr(x)
+ it := mapiterinit(v.typ.runtimeType(), m)
+ a := make([]Value, mlen)
+ var i int
+ for i = 0; i < len(a); i++ {
+ keyWord, ok := mapiterkey(it)
+ if !ok {
+ break
+ }
+ a[i] = Value{keyType, unsafe.Pointer(keyWord), fl}
+ mapiternext(it)
}
+ return a[:i]
}
-// Overflow returns true if x cannot be represented by the type of v.
-func (v *UintValue) Overflow(x uint64) bool {
- bitSize := uint(v.typ.Bits())
- trunc := (x << (64 - bitSize)) >> (64 - bitSize)
- return x != trunc
+// Method returns a function value corresponding to v's i'th method.
+// The arguments to a Call on the returned function should not include
+// a receiver; the returned function will always use v as the receiver.
+// Method panics if i is out of range.
+func (v Value) Method(i int) Value {
+ if v.typ == nil {
+ panic(&ValueError{"reflect.Value.Method", Invalid})
+ }
+ if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
+ panic("reflect: Method index out of range")
+ }
+ fl := v.flag & (flagRO | flagAddr | flagIndir)
+ fl |= flag(Func) << flagKindShift
+ fl |= flag(i)<<flagMethodShift | flagMethod
+ return Value{v.typ, v.val, fl}
}
-// Set sets v to the value x.
-func (v *UintValue) SetValue(x Value) { v.Set(x.(*UintValue).Get()) }
-
-// UnsafePointerValue represents an unsafe.Pointer value.
-type UnsafePointerValue struct {
- value "unsafe.Pointer"
+// NumMethod returns the number of methods in the value's method set.
+func (v Value) NumMethod() int {
+ if v.typ == nil {
+ panic(&ValueError{"reflect.Value.NumMethod", Invalid})
+ }
+ if v.flag&flagMethod != 0 {
+ return 0
+ }
+ return v.typ.NumMethod()
}
-// Get returns the underlying uintptr value.
-// Get returns uintptr, not unsafe.Pointer, so that
-// programs that do not import "unsafe" cannot
-// obtain a value of unsafe.Pointer type from "reflect".
-func (v *UnsafePointerValue) Get() uintptr { return uintptr(*(*unsafe.Pointer)(v.addr)) }
-
-// Set sets v to the value x.
-func (v *UnsafePointerValue) Set(x unsafe.Pointer) {
- if !v.canSet {
- panic(cannotSet)
+// MethodByName returns a function value corresponding to the method
+// of v with the given name.
+// The arguments to a Call on the returned function should not include
+// a receiver; the returned function will always use v as the receiver.
+// It returns the zero Value if no method was found.
+func (v Value) MethodByName(name string) Value {
+ if v.typ == nil {
+ panic(&ValueError{"reflect.Value.MethodByName", Invalid})
}
- *(*unsafe.Pointer)(v.addr) = x
+ if v.flag&flagMethod != 0 {
+ return Value{}
+ }
+ m, ok := v.typ.MethodByName(name)
+ if !ok {
+ return Value{}
+ }
+ return v.Method(m.Index)
}
-// Set sets v to the value x.
-func (v *UnsafePointerValue) SetValue(x Value) {
- v.Set(unsafe.Pointer(x.(*UnsafePointerValue).Get()))
+// NumField returns the number of fields in the struct v.
+// It panics if v's Kind is not Struct.
+func (v Value) NumField() int {
+ v.mustBe(Struct)
+ tt := (*structType)(unsafe.Pointer(v.typ))
+ return len(tt.fields)
}
-func typesMustMatch(t1, t2 Type) {
- if t1 != t2 {
- panic("type mismatch: " + t1.String() + " != " + t2.String())
+// OverflowComplex returns true if the complex128 x cannot be represented by v's type.
+// It panics if v's Kind is not Complex64 or Complex128.
+func (v Value) OverflowComplex(x complex128) bool {
+ k := v.kind()
+ switch k {
+ case Complex64:
+ return overflowFloat32(real(x)) || overflowFloat32(imag(x))
+ case Complex128:
+ return false
}
+ panic(&ValueError{"reflect.Value.OverflowComplex", k})
}
-/*
- * array
- */
-
-// ArrayOrSliceValue is the common interface
-// implemented by both ArrayValue and SliceValue.
-type ArrayOrSliceValue interface {
- Value
- Len() int
- Cap() int
- Elem(i int) Value
- addr() addr
+// OverflowFloat returns true if the float64 x cannot be represented by v's type.
+// It panics if v's Kind is not Float32 or Float64.
+func (v Value) OverflowFloat(x float64) bool {
+ k := v.kind()
+ switch k {
+ case Float32:
+ return overflowFloat32(x)
+ case Float64:
+ return false
+ }
+ panic(&ValueError{"reflect.Value.OverflowFloat", k})
}
-// grow grows the slice s so that it can hold extra more values, allocating
-// more capacity if needed. It also returns the old and new slice lengths.
-func grow(s *SliceValue, extra int) (*SliceValue, int, int) {
- i0 := s.Len()
- i1 := i0 + extra
- if i1 < i0 {
- panic("append: slice overflow")
- }
- m := s.Cap()
- if i1 <= m {
- return s.Slice(0, i1), i0, i1
+func overflowFloat32(x float64) bool {
+ if x < 0 {
+ x = -x
}
- if m == 0 {
- m = extra
- } else {
- for m < i1 {
- if i0 < 1024 {
- m += m
- } else {
- m += m / 4
- }
+ return math.MaxFloat32 <= x && x <= math.MaxFloat64
+}
+
+// OverflowInt returns true if the int64 x cannot be represented by v's type.
+// It panics if v's Kind is not Int, Int8, int16, Int32, or Int64.
+func (v Value) OverflowInt(x int64) bool {
+ k := v.kind()
+ switch k {
+ case Int, Int8, Int16, Int32, Int64:
+ bitSize := v.typ.size * 8
+ trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+ return x != trunc
+ }
+ panic(&ValueError{"reflect.Value.OverflowInt", k})
+}
+
+// OverflowUint returns true if the uint64 x cannot be represented by v's type.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
+func (v Value) OverflowUint(x uint64) bool {
+ k := v.kind()
+ switch k {
+ case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
+ bitSize := v.typ.size * 8
+ trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+ return x != trunc
+ }
+ panic(&ValueError{"reflect.Value.OverflowUint", k})
+}
+
+// Pointer returns v's value as a uintptr.
+// It returns uintptr instead of unsafe.Pointer so that
+// code using reflect cannot obtain unsafe.Pointers
+// without importing the unsafe package explicitly.
+// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
+func (v Value) Pointer() uintptr {
+ k := v.kind()
+ switch k {
+ case Chan, Func, Map, Ptr, UnsafePointer:
+ if k == Func && v.flag&flagMethod != 0 {
+ panic("reflect.Value.Pointer of method Value")
+ }
+ p := v.val
+ if v.flag&flagIndir != 0 {
+ p = *(*unsafe.Pointer)(p)
}
+ return uintptr(p)
+ case Slice:
+ return (*SliceHeader)(v.val).Data
}
- t := MakeSlice(s.Type().(*SliceType), i1, m)
- Copy(t, s)
- return t, i0, i1
+ panic(&ValueError{"reflect.Value.Pointer", k})
}
-// Append appends the values x to a slice s and returns the resulting slice.
-// Each x must have the same type as s' element type.
-func Append(s *SliceValue, x ...Value) *SliceValue {
- s, i0, i1 := grow(s, len(x))
- for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
- s.Elem(i).SetValue(x[j])
+// Recv receives and returns a value from the channel v.
+// It panics if v's Kind is not Chan.
+// The receive blocks until a value is ready.
+// The boolean value ok is true if the value x corresponds to a send
+// on the channel, false if it is a zero value received because the channel is closed.
+func (v Value) Recv() (x Value, ok bool) {
+ v.mustBe(Chan)
+ v.mustBeExported()
+ return v.recv(false)
+}
+
+// internal recv, possibly non-blocking (nb).
+// v is known to be a channel.
+func (v Value) recv(nb bool) (val Value, ok bool) {
+ tt := (*chanType)(unsafe.Pointer(v.typ))
+ if ChanDir(tt.dir)&RecvDir == 0 {
+ panic("recv on send-only channel")
}
- return s
+ word, selected, ok := chanrecv(v.typ.runtimeType(), *(*iword)(v.iword()), nb)
+ if selected {
+ typ := toCommonType(tt.elem)
+ fl := flag(typ.Kind()) << flagKindShift
+ if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+ fl |= flagIndir
+ }
+ val = Value{typ, unsafe.Pointer(word), fl}
+ }
+ return
}
-// AppendSlice appends a slice t to a slice s and returns the resulting slice.
-// The slices s and t must have the same element type.
-func AppendSlice(s, t *SliceValue) *SliceValue {
- s, i0, i1 := grow(s, t.Len())
- Copy(s.Slice(i0, i1), t)
- return s
+// Send sends x on the channel v.
+// It panics if v's kind is not Chan or if x's type is not the same type as v's element type.
+// As in Go, x's value must be assignable to the channel's element type.
+func (v Value) Send(x Value) {
+ v.mustBe(Chan)
+ v.mustBeExported()
+ v.send(x, false)
+}
+
+// internal send, possibly non-blocking.
+// v is known to be a channel.
+func (v Value) send(x Value, nb bool) (selected bool) {
+ tt := (*chanType)(unsafe.Pointer(v.typ))
+ if ChanDir(tt.dir)&SendDir == 0 {
+ panic("send on recv-only channel")
+ }
+ x.mustBeExported()
+ x = x.assignTo("reflect.Value.Send", toCommonType(tt.elem), nil)
+ return chansend(v.typ.runtimeType(), *(*iword)(v.iword()), x.iword(), nb)
}
-// Copy copies the contents of src into dst until either
-// dst has been filled or src has been exhausted.
-// It returns the number of elements copied.
-// The arrays dst and src must have the same element type.
-func Copy(dst, src ArrayOrSliceValue) int {
- // TODO: This will have to move into the runtime
- // once the real gc goes in.
- de := dst.Type().(ArrayOrSliceType).Elem()
- se := src.Type().(ArrayOrSliceType).Elem()
- typesMustMatch(de, se)
- n := dst.Len()
- if xn := src.Len(); n > xn {
- n = xn
+// Set assigns x to the value v.
+// It panics if CanSet returns false.
+// As in Go, x's value must be assignable to v's type.
+func (v Value) Set(x Value) {
+ v.mustBeAssignable()
+ x.mustBeExported() // do not let unexported x leak
+ var target *interface{}
+ if v.kind() == Interface {
+ target = (*interface{})(v.val)
+ }
+ x = x.assignTo("reflect.Set", v.typ, target)
+ if x.flag&flagIndir != 0 {
+ memmove(v.val, x.val, v.typ.size)
+ } else {
+ storeIword(v.val, iword(x.val), v.typ.size)
}
- memmove(dst.addr(), src.addr(), uintptr(n)*de.Size())
- return n
}
-// An ArrayValue represents an array.
-type ArrayValue struct {
- value "array"
+// SetBool sets v's underlying value.
+// It panics if v's Kind is not Bool or if CanSet() is false.
+func (v Value) SetBool(x bool) {
+ v.mustBeAssignable()
+ v.mustBe(Bool)
+ *(*bool)(v.val) = x
}
-// Len returns the length of the array.
-func (v *ArrayValue) Len() int { return v.typ.(*ArrayType).Len() }
-
-// Cap returns the capacity of the array (equal to Len()).
-func (v *ArrayValue) Cap() int { return v.typ.(*ArrayType).Len() }
-
-// addr returns the base address of the data in the array.
-func (v *ArrayValue) addr() addr { return v.value.addr }
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *ArrayValue) Set(x *ArrayValue) {
- if !v.canSet {
- panic(cannotSet)
+// SetBytes sets v's underlying value.
+// It panics if v's underlying value is not a slice of bytes.
+func (v Value) SetBytes(x []byte) {
+ v.mustBeAssignable()
+ v.mustBe(Slice)
+ if v.typ.Elem().Kind() != Uint8 {
+ panic("reflect.Value.SetBytes of non-byte slice")
}
- typesMustMatch(v.typ, x.typ)
- Copy(v, x)
+ *(*[]byte)(v.val) = x
}
-// Set sets v to the value x.
-func (v *ArrayValue) SetValue(x Value) { v.Set(x.(*ArrayValue)) }
-
-// Elem returns the i'th element of v.
-func (v *ArrayValue) Elem(i int) Value {
- typ := v.typ.(*ArrayType).Elem()
- n := v.Len()
- if i < 0 || i >= n {
- panic("array index out of bounds")
+// SetComplex sets v's underlying value to x.
+// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
+func (v Value) SetComplex(x complex128) {
+ v.mustBeAssignable()
+ switch k := v.kind(); k {
+ default:
+ panic(&ValueError{"reflect.Value.SetComplex", k})
+ case Complex64:
+ *(*complex64)(v.val) = complex64(x)
+ case Complex128:
+ *(*complex128)(v.val) = x
}
- p := addr(uintptr(v.addr()) + uintptr(i)*typ.Size())
- return newValue(typ, p, v.canSet)
}
-/*
- * slice
- */
-
-// runtime representation of slice
-type SliceHeader struct {
- Data uintptr
- Len int
- Cap int
+// SetFloat sets v's underlying value to x.
+// It panics if v's Kind is not Float32 or Float64, or if CanSet() is false.
+func (v Value) SetFloat(x float64) {
+ v.mustBeAssignable()
+ switch k := v.kind(); k {
+ default:
+ panic(&ValueError{"reflect.Value.SetFloat", k})
+ case Float32:
+ *(*float32)(v.val) = float32(x)
+ case Float64:
+ *(*float64)(v.val) = x
+ }
}
-// A SliceValue represents a slice.
-type SliceValue struct {
- value "slice"
+// SetInt sets v's underlying value to x.
+// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64, or if CanSet() is false.
+func (v Value) SetInt(x int64) {
+ v.mustBeAssignable()
+ switch k := v.kind(); k {
+ default:
+ panic(&ValueError{"reflect.Value.SetInt", k})
+ case Int:
+ *(*int)(v.val) = int(x)
+ case Int8:
+ *(*int8)(v.val) = int8(x)
+ case Int16:
+ *(*int16)(v.val) = int16(x)
+ case Int32:
+ *(*int32)(v.val) = int32(x)
+ case Int64:
+ *(*int64)(v.val) = x
+ }
}
-func (v *SliceValue) slice() *SliceHeader { return (*SliceHeader)(v.value.addr) }
-
-// IsNil returns whether v is a nil slice.
-func (v *SliceValue) IsNil() bool { return v.slice().Data == 0 }
-
-// Len returns the length of the slice.
-func (v *SliceValue) Len() int { return int(v.slice().Len) }
-
-// Cap returns the capacity of the slice.
-func (v *SliceValue) Cap() int { return int(v.slice().Cap) }
-
-// addr returns the base address of the data in the slice.
-func (v *SliceValue) addr() addr { return addr(v.slice().Data) }
-
-// SetLen changes the length of v.
-// The new length n must be between 0 and the capacity, inclusive.
-func (v *SliceValue) SetLen(n int) {
- s := v.slice()
+// SetLen sets v's length to n.
+// It panics if v's Kind is not Slice or if n is negative or
+// greater than the capacity of the slice.
+func (v Value) SetLen(n int) {
+ v.mustBeAssignable()
+ v.mustBe(Slice)
+ s := (*SliceHeader)(v.val)
if n < 0 || n > int(s.Cap) {
panic("reflect: slice length out of range in SetLen")
}
s.Len = n
}
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *SliceValue) Set(x *SliceValue) {
- if !v.canSet {
- panic(cannotSet)
+// SetMapIndex sets the value associated with key in the map v to val.
+// It panics if v's Kind is not Map.
+// If val is the zero Value, SetMapIndex deletes the key from the map.
+// As in Go, key's value must be assignable to the map's key type,
+// and val's value must be assignable to the map's value type.
+func (v Value) SetMapIndex(key, val Value) {
+ v.mustBe(Map)
+ v.mustBeExported()
+ key.mustBeExported()
+ tt := (*mapType)(unsafe.Pointer(v.typ))
+ key = key.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.key), nil)
+ if val.typ != nil {
+ val.mustBeExported()
+ val = val.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.elem), nil)
+ }
+ mapassign(v.typ.runtimeType(), *(*iword)(v.iword()), key.iword(), val.iword(), val.typ != nil)
+}
+
+// SetUint sets v's underlying value to x.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false.
+func (v Value) SetUint(x uint64) {
+ v.mustBeAssignable()
+ switch k := v.kind(); k {
+ default:
+ panic(&ValueError{"reflect.Value.SetUint", k})
+ case Uint:
+ *(*uint)(v.val) = uint(x)
+ case Uint8:
+ *(*uint8)(v.val) = uint8(x)
+ case Uint16:
+ *(*uint16)(v.val) = uint16(x)
+ case Uint32:
+ *(*uint32)(v.val) = uint32(x)
+ case Uint64:
+ *(*uint64)(v.val) = x
+ case Uintptr:
+ *(*uintptr)(v.val) = uintptr(x)
}
- typesMustMatch(v.typ, x.typ)
- *v.slice() = *x.slice()
}
-// Set sets v to the value x.
-func (v *SliceValue) SetValue(x Value) { v.Set(x.(*SliceValue)) }
-
-// Get returns the uintptr address of the v.Cap()'th element. This gives
-// the same result for all slices of the same array.
-// It is mainly useful for printing.
-func (v *SliceValue) Get() uintptr {
- typ := v.typ.(*SliceType)
- return uintptr(v.addr()) + uintptr(v.Cap())*typ.Elem().Size()
+// SetPointer sets the unsafe.Pointer value v to x.
+// It panics if v's Kind is not UnsafePointer.
+func (v Value) SetPointer(x unsafe.Pointer) {
+ v.mustBeAssignable()
+ v.mustBe(UnsafePointer)
+ *(*unsafe.Pointer)(v.val) = x
}
-// Slice returns a sub-slice of the slice v.
-func (v *SliceValue) Slice(beg, end int) *SliceValue {
- cap := v.Cap()
- if beg < 0 || end < beg || end > cap {
- panic("slice index out of bounds")
- }
- typ := v.typ.(*SliceType)
- s := new(SliceHeader)
- s.Data = uintptr(v.addr()) + uintptr(beg)*typ.Elem().Size()
- s.Len = end - beg
- s.Cap = cap - beg
- return newValue(typ, addr(s), v.canSet).(*SliceValue)
+// SetString sets v's underlying value to x.
+// It panics if v's Kind is not String or if CanSet() is false.
+func (v Value) SetString(x string) {
+ v.mustBeAssignable()
+ v.mustBe(String)
+ *(*string)(v.val) = x
}
-// Elem returns the i'th element of v.
-func (v *SliceValue) Elem(i int) Value {
- typ := v.typ.(*SliceType).Elem()
- n := v.Len()
- if i < 0 || i >= n {
- panic("reflect: slice index out of range")
- }
- p := addr(uintptr(v.addr()) + uintptr(i)*typ.Size())
- return newValue(typ, p, v.canSet)
-}
+// Slice returns a slice of v.
+// It panics if v's Kind is not Array or Slice.
+func (v Value) Slice(beg, end int) Value {
+ var (
+ cap int
+ typ *sliceType
+ base unsafe.Pointer
+ )
+ switch k := v.kind(); k {
+ default:
+ panic(&ValueError{"reflect.Value.Slice", k})
+ case Array:
+ if v.flag&flagAddr == 0 {
+ panic("reflect.Value.Slice: slice of unaddressable array")
+ }
+ tt := (*arrayType)(unsafe.Pointer(v.typ))
+ cap = int(tt.len)
+ typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
+ base = v.val
+ case Slice:
+ typ = (*sliceType)(unsafe.Pointer(v.typ))
+ s := (*SliceHeader)(v.val)
+ base = unsafe.Pointer(s.Data)
+ cap = s.Cap
-// MakeSlice creates a new zero-initialized slice value
-// for the specified slice type, length, and capacity.
-func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
- s := &SliceHeader{
- Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
- Len: len,
- Cap: cap,
}
- return newValue(typ, addr(s), true).(*SliceValue)
-}
-
-/*
- * chan
- */
-
-// A ChanValue represents a chan.
-type ChanValue struct {
- value "chan"
-}
-
-// IsNil returns whether v is a nil channel.
-func (v *ChanValue) IsNil() bool { return *(*uintptr)(v.addr) == 0 }
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *ChanValue) Set(x *ChanValue) {
- if !v.canSet {
- panic(cannotSet)
+ if beg < 0 || end < beg || end > cap {
+ panic("reflect.Value.Slice: slice index out of bounds")
}
- typesMustMatch(v.typ, x.typ)
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr)
-}
-// Set sets v to the value x.
-func (v *ChanValue) SetValue(x Value) { v.Set(x.(*ChanValue)) }
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *ChanValue) Get() uintptr { return *(*uintptr)(v.addr) }
-
-// implemented in ../pkg/runtime/reflect.cgo
-func makechan(typ *runtime.ChanType, size uint32) (ch *byte)
-func chansend(ch, val *byte, pres *bool)
-func chanrecv(ch, val *byte, pres *bool)
-func chanclosed(ch *byte) bool
-func chanclose(ch *byte)
-func chanlen(ch *byte) int32
-func chancap(ch *byte) int32
-
-// Closed returns the result of closed(c) on the underlying channel.
-func (v *ChanValue) Closed() bool {
- ch := *(**byte)(v.addr)
- return chanclosed(ch)
-}
+ // Declare slice so that gc can see the base pointer in it.
+ var x []byte
-// Close closes the channel.
-func (v *ChanValue) Close() {
- ch := *(**byte)(v.addr)
- chanclose(ch)
-}
-
-func (v *ChanValue) Len() int {
- ch := *(**byte)(v.addr)
- return int(chanlen(ch))
-}
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
+ s.Data = uintptr(base) + uintptr(beg)*toCommonType(typ.elem).Size()
+ s.Len = end - beg
+ s.Cap = cap - beg
-func (v *ChanValue) Cap() int {
- ch := *(**byte)(v.addr)
- return int(chancap(ch))
+ fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
+ return Value{typ.common(), unsafe.Pointer(&x), fl}
}
-// internal send; non-blocking if b != nil
-func (v *ChanValue) send(x Value, b *bool) {
- t := v.Type().(*ChanType)
- if t.Dir()&SendDir == 0 {
- panic("send on recv-only channel")
+// String returns the string v's underlying value, as a string.
+// String is a special case because of Go's String method convention.
+// Unlike the other getters, it does not panic if v's Kind is not String.
+// Instead, it returns a string of the form "<T value>" where T is v's type.
+func (v Value) String() string {
+ switch k := v.kind(); k {
+ case Invalid:
+ return "<invalid Value>"
+ case String:
+ return *(*string)(v.val)
}
- typesMustMatch(t.Elem(), x.Type())
- ch := *(**byte)(v.addr)
- chansend(ch, (*byte)(x.getAddr()), b)
+ // If you call String on a reflect.Value of other type, it's better to
+ // print something than to panic. Useful in debugging.
+ return "<" + v.typ.String() + " Value>"
}
-// internal recv; non-blocking if b != nil
-func (v *ChanValue) recv(b *bool) Value {
- t := v.Type().(*ChanType)
- if t.Dir()&RecvDir == 0 {
- panic("recv on send-only channel")
- }
- ch := *(**byte)(v.addr)
- x := MakeZero(t.Elem())
- chanrecv(ch, (*byte)(x.getAddr()), b)
- return x
-}
-
-// Send sends x on the channel v.
-func (v *ChanValue) Send(x Value) { v.send(x, nil) }
-
-// Recv receives and returns a value from the channel v.
-func (v *ChanValue) Recv() Value { return v.recv(nil) }
-
-// TrySend attempts to sends x on the channel v but will not block.
+// TryRecv attempts to receive a value from the channel v but will not block.
+// It panics if v's Kind is not Chan.
+// If the receive cannot finish without blocking, x is the zero Value.
+// The boolean ok is true if the value x corresponds to a send
+// on the channel, false if it is a zero value received because the channel is closed.
+func (v Value) TryRecv() (x Value, ok bool) {
+ v.mustBe(Chan)
+ v.mustBeExported()
+ return v.recv(true)
+}
+
+// TrySend attempts to send x on the channel v but will not block.
+// It panics if v's Kind is not Chan.
// It returns true if the value was sent, false otherwise.
-func (v *ChanValue) TrySend(x Value) bool {
- var ok bool
- v.send(x, &ok)
- return ok
+// As in Go, x's value must be assignable to the channel's element type.
+func (v Value) TrySend(x Value) bool {
+ v.mustBe(Chan)
+ v.mustBeExported()
+ return v.send(x, true)
+}
+
+// Type returns v's type.
+func (v Value) Type() Type {
+ f := v.flag
+ if f == 0 {
+ panic(&ValueError{"reflect.Value.Type", Invalid})
+ }
+ if f&flagMethod == 0 {
+ // Easy case
+ return v.typ.toType()
+ }
+
+ // Method value.
+ // v.typ describes the receiver, not the method type.
+ i := int(v.flag) >> flagMethodShift
+ if v.typ.Kind() == Interface {
+ // Method on interface.
+ tt := (*interfaceType)(unsafe.Pointer(v.typ))
+ if i < 0 || i >= len(tt.methods) {
+ panic("reflect: broken Value")
+ }
+ m := &tt.methods[i]
+ return toCommonType(m.typ).toType()
+ }
+ // Method on concrete type.
+ ut := v.typ.uncommon()
+ if ut == nil || i < 0 || i >= len(ut.methods) {
+ panic("reflect: broken Value")
+ }
+ m := &ut.methods[i]
+ return toCommonType(m.mtyp).toType()
}
-// TryRecv attempts to receive a value from the channel v but will not block.
-// It returns the value if one is received, nil otherwise.
-func (v *ChanValue) TryRecv() Value {
- var ok bool
- x := v.recv(&ok)
- if !ok {
- return nil
+// Uint returns v's underlying value, as a uint64.
+// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
+func (v Value) Uint() uint64 {
+ k := v.kind()
+ var p unsafe.Pointer
+ if v.flag&flagIndir != 0 {
+ p = v.val
+ } else {
+ // The escape analysis is good enough that &v.val
+ // does not trigger a heap allocation.
+ p = unsafe.Pointer(&v.val)
+ }
+ switch k {
+ case Uint:
+ return uint64(*(*uint)(p))
+ case Uint8:
+ return uint64(*(*uint8)(p))
+ case Uint16:
+ return uint64(*(*uint16)(p))
+ case Uint32:
+ return uint64(*(*uint32)(p))
+ case Uint64:
+ return uint64(*(*uint64)(p))
+ case Uintptr:
+ return uint64(*(*uintptr)(p))
}
- return x
+ panic(&ValueError{"reflect.Value.Uint", k})
}
-// MakeChan creates a new channel with the specified type and buffer size.
-func MakeChan(typ *ChanType, buffer int) *ChanValue {
- if buffer < 0 {
- panic("MakeChan: negative buffer size")
+// UnsafeAddr returns a pointer to v's data.
+// It is for advanced clients that also import the "unsafe" package.
+// It panics if v is not addressable.
+func (v Value) UnsafeAddr() uintptr {
+ if v.typ == nil {
+ panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
}
- if typ.Dir() != BothDir {
- panic("MakeChan: unidirectional channel type")
+ if v.flag&flagAddr == 0 {
+ panic("reflect.Value.UnsafeAddr of unaddressable value")
}
- v := MakeZero(typ).(*ChanValue)
- *(**byte)(v.addr) = makechan((*runtime.ChanType)(unsafe.Pointer(typ)), uint32(buffer))
- return v
+ return uintptr(v.val)
}
-/*
- * func
- */
-
-// A FuncValue represents a function value.
-type FuncValue struct {
- value "func"
- first *value
- isInterface bool
+// StringHeader is the runtime representation of a string.
+// It cannot be used safely or portably.
+type StringHeader struct {
+ Data uintptr
+ Len int
}
-// IsNil returns whether v is a nil function.
-func (v *FuncValue) IsNil() bool { return *(*uintptr)(v.addr) == 0 }
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *FuncValue) Get() uintptr { return *(*uintptr)(v.addr) }
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *FuncValue) Set(x *FuncValue) {
- if !v.canSet {
- panic(cannotSet)
- }
- typesMustMatch(v.typ, x.typ)
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr)
+// SliceHeader is the runtime representation of a slice.
+// It cannot be used safely or portably.
+type SliceHeader struct {
+ Data uintptr
+ Len int
+ Cap int
}
-// Set sets v to the value x.
-func (v *FuncValue) SetValue(x Value) { v.Set(x.(*FuncValue)) }
-
-// Method returns a FuncValue corresponding to v's i'th method.
-// The arguments to a Call on the returned FuncValue
-// should not include a receiver; the FuncValue will use v
-// as the receiver.
-func (v *value) Method(i int) *FuncValue {
- t := v.Type().uncommon()
- if t == nil || i < 0 || i >= len(t.methods) {
- return nil
+func typesMustMatch(what string, t1, t2 Type) {
+ if t1 != t2 {
+ panic(what + ": " + t1.String() + " != " + t2.String())
}
- p := &t.methods[i]
- fn := p.tfn
- fv := &FuncValue{value: value{runtimeToType(p.typ), addr(&fn), true}, first: v, isInterface: false}
- return fv
}
-// implemented in ../pkg/runtime/*/asm.s
-func call(typ *FuncType, fnaddr *byte, isInterface bool, params *addr, results *addr)
-
-// Call calls the function fv with input parameters in.
-// It returns the function's output parameters as Values.
-func (fv *FuncValue) Call(in []Value) []Value {
- t := fv.Type().(*FuncType)
- nin := len(in)
- if fv.first != nil && !fv.isInterface {
- nin++
- }
- if nin != t.NumIn() {
- panic("FuncValue: wrong argument count")
+// grow grows the slice s so that it can hold extra more values, allocating
+// more capacity if needed. It also returns the old and new slice lengths.
+func grow(s Value, extra int) (Value, int, int) {
+ i0 := s.Len()
+ i1 := i0 + extra
+ if i1 < i0 {
+ panic("reflect.Append: slice overflow")
}
- if fv.first != nil && fv.isInterface {
- nin++
+ m := s.Cap()
+ if i1 <= m {
+ return s.Slice(0, i1), i0, i1
}
- nout := t.NumOut()
-
- params := make([]addr, nin)
- delta := 0
- off := 0
- if v := fv.first; v != nil {
- // Hard-wired first argument.
- if fv.isInterface {
- // v is a single uninterpreted word
- params[0] = v.getAddr()
- } else {
- // v is a real value
- tv := v.Type()
-
- // This is a method, so we need to always pass
- // a pointer.
- vAddr := v.getAddr()
- if ptv, ok := tv.(*PtrType); ok {
- typesMustMatch(t.In(0), tv)
+ if m == 0 {
+ m = extra
+ } else {
+ for m < i1 {
+ if i0 < 1024 {
+ m += m
} else {
- p := addr(new(addr))
- *(*addr)(p) = vAddr
- vAddr = p
- typesMustMatch(t.In(0).(*PtrType).Elem(), tv)
- }
-
- params[0] = vAddr
- delta = 1
- }
- off = 1
- }
- for i, v := range in {
- tv := v.Type()
- tf := t.In(i + delta)
-
- // If this is really a method, and we are explicitly
- // passing the object, then we need to pass the address
- // of the object instead. Unfortunately, we don't
- // have any way to know that this is a method, so we just
- // check the type. FIXME: This is ugly.
- vAddr := v.getAddr()
- if i == 0 && tf != tv {
- if ptf, ok := tf.(*PtrType); ok {
- p := addr(new(addr))
- *(*addr)(p) = vAddr
- vAddr = p
- tf = ptf.Elem()
+ m += m / 4
}
}
-
- typesMustMatch(tf, tv)
- params[i+off] = vAddr
- }
-
- ret := make([]Value, nout)
- results := make([]addr, nout)
- for i := 0; i < nout; i++ {
- tv := t.Out(i)
- v := MakeZero(tv)
- results[i] = v.getAddr()
- ret[i] = v
}
-
- call(t, *(**byte)(fv.addr), fv.isInterface, ¶ms[0], &results[0])
-
- return ret
+ t := MakeSlice(s.Type(), i1, m)
+ Copy(t, s)
+ return t, i0, i1
}
-/*
- * interface
- */
-
-// An InterfaceValue represents an interface value.
-type InterfaceValue struct {
- value "interface"
+// Append appends the values x to a slice s and returns the resulting slice.
+// As in Go, each x's value must be assignable to the slice's element type.
+func Append(s Value, x ...Value) Value {
+ s.mustBe(Slice)
+ s, i0, i1 := grow(s, len(x))
+ for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
+ s.Index(i).Set(x[j])
+ }
+ return s
}
-// IsNil returns whether v is a nil interface value.
-func (v *InterfaceValue) IsNil() bool { return v.Interface() == nil }
-
-// No single uinptr Get because v.Interface() is available.
-
-// Get returns the two words that represent an interface in the runtime.
-// Those words are useful only when playing unsafe games.
-func (v *InterfaceValue) Get() [2]uintptr {
- return *(*[2]uintptr)(v.addr)
+// AppendSlice appends a slice t to a slice s and returns the resulting slice.
+// The slices s and t must have the same element type.
+func AppendSlice(s, t Value) Value {
+ s.mustBe(Slice)
+ t.mustBe(Slice)
+ typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
+ s, i0, i1 := grow(s, t.Len())
+ Copy(s.Slice(i0, i1), t)
+ return s
}
-// Elem returns the concrete value stored in the interface value v.
-func (v *InterfaceValue) Elem() Value { return NewValue(v.Interface()) }
-
-// ../runtime/reflect.cgo
-func setiface(typ *InterfaceType, x *interface{}, addr addr)
-
-// Set assigns x to v.
-func (v *InterfaceValue) Set(x Value) {
- var i interface{}
- if x != nil {
- i = x.Interface()
- }
- if !v.canSet {
- panic(cannotSet)
+// Copy copies the contents of src into dst until either
+// dst has been filled or src has been exhausted.
+// It returns the number of elements copied.
+// Dst and src each must have kind Slice or Array, and
+// dst and src must have the same element type.
+func Copy(dst, src Value) int {
+ dk := dst.kind()
+ if dk != Array && dk != Slice {
+ panic(&ValueError{"reflect.Copy", dk})
}
- // Two different representations; see comment in Get.
- // Empty interface is easy.
- t := v.typ.(*InterfaceType)
- if t.NumMethod() == 0 {
- *(*interface{})(v.addr) = i
- return
+ if dk == Array {
+ dst.mustBeAssignable()
}
+ dst.mustBeExported()
- // Non-empty interface requires a runtime check.
- setiface(t, &i, v.addr)
-}
+ sk := src.kind()
+ if sk != Array && sk != Slice {
+ panic(&ValueError{"reflect.Copy", sk})
+ }
+ src.mustBeExported()
-// Set sets v to the value x.
-func (v *InterfaceValue) SetValue(x Value) { v.Set(x) }
+ de := dst.typ.Elem()
+ se := src.typ.Elem()
+ typesMustMatch("reflect.Copy", de, se)
-// Method returns a FuncValue corresponding to v's i'th method.
-// The arguments to a Call on the returned FuncValue
-// should not include a receiver; the FuncValue will use v
-// as the receiver.
-func (v *InterfaceValue) Method(i int) *FuncValue {
- t := v.Type().(*InterfaceType)
- if t == nil || i < 0 || i >= len(t.methods) {
- return nil
+ n := dst.Len()
+ if sn := src.Len(); n > sn {
+ n = sn
}
- p := &t.methods[i]
- // Interface is two words: itable, data.
- tab := *(**[10000]addr)(v.addr)
- data := &value{Typeof((*byte)(nil)), addr(uintptr(v.addr) + ptrSize), true}
+ // If sk is an in-line array, cannot take its address.
+ // Instead, copy element by element.
+ if src.flag&flagIndir == 0 {
+ for i := 0; i < n; i++ {
+ dst.Index(i).Set(src.Index(i))
+ }
+ return n
+ }
- fn := tab[i+1]
- fv := &FuncValue{value: value{runtimeToType(p.typ), addr(&fn), true}, first: data, isInterface: true}
- return fv
+ // Copy via memmove.
+ var da, sa unsafe.Pointer
+ if dk == Array {
+ da = dst.val
+ } else {
+ da = unsafe.Pointer((*SliceHeader)(dst.val).Data)
+ }
+ if sk == Array {
+ sa = src.val
+ } else {
+ sa = unsafe.Pointer((*SliceHeader)(src.val).Data)
+ }
+ memmove(da, sa, uintptr(n)*de.Size())
+ return n
}
/*
- * map
+ * constructors
*/
-// A MapValue represents a map value.
-type MapValue struct {
- value "map"
-}
-
-// IsNil returns whether v is a nil map value.
-func (v *MapValue) IsNil() bool { return *(*uintptr)(v.addr) == 0 }
+// implemented in package runtime
+func unsafe_New(Type) unsafe.Pointer
+func unsafe_NewArray(Type, int) unsafe.Pointer
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *MapValue) Set(x *MapValue) {
- if !v.canSet {
- panic(cannotSet)
- }
- if x == nil {
- *(**uintptr)(v.addr) = nil
- return
+// MakeSlice creates a new zero-initialized slice value
+// for the specified slice type, length, and capacity.
+func MakeSlice(typ Type, len, cap int) Value {
+ if typ.Kind() != Slice {
+ panic("reflect.MakeSlice of non-slice type")
}
- typesMustMatch(v.typ, x.typ)
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr)
-}
-
-// Set sets v to the value x.
-func (v *MapValue) SetValue(x Value) {
- if x == nil {
- v.Set(nil)
- return
+ if len < 0 {
+ panic("reflect.MakeSlice: negative len")
}
- v.Set(x.(*MapValue))
-}
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *MapValue) Get() uintptr { return *(*uintptr)(v.addr) }
-
-// implemented in ../pkg/runtime/reflect.cgo
-func mapaccess(m, key, val *byte) bool
-func mapassign(m, key, val *byte)
-func maplen(m *byte) int32
-func mapiterinit(m *byte) *byte
-func mapiternext(it *byte)
-func mapiterkey(it *byte, key *byte) bool
-func makemap(t *runtime.MapType) *byte
-
-// Elem returns the value associated with key in the map v.
-// It returns nil if key is not found in the map.
-func (v *MapValue) Elem(key Value) Value {
- t := v.Type().(*MapType)
- typesMustMatch(t.Key(), key.Type())
- m := *(**byte)(v.addr)
- if m == nil {
- return nil
- }
- newval := MakeZero(t.Elem())
- if !mapaccess(m, (*byte)(key.getAddr()), (*byte)(newval.getAddr())) {
- return nil
- }
- return newval
-}
-
-// SetElem sets the value associated with key in the map v to val.
-// If val is nil, Put deletes the key from map.
-func (v *MapValue) SetElem(key, val Value) {
- t := v.Type().(*MapType)
- typesMustMatch(t.Key(), key.Type())
- var vaddr *byte
- if val != nil {
- typesMustMatch(t.Elem(), val.Type())
- vaddr = (*byte)(val.getAddr())
- }
- m := *(**byte)(v.addr)
- mapassign(m, (*byte)(key.getAddr()), vaddr)
-}
-
-// Len returns the number of keys in the map v.
-func (v *MapValue) Len() int {
- m := *(**byte)(v.addr)
- if m == nil {
- return 0
- }
- return int(maplen(m))
-}
-
-// Keys returns a slice containing all the keys present in the map,
-// in unspecified order.
-func (v *MapValue) Keys() []Value {
- tk := v.Type().(*MapType).Key()
- m := *(**byte)(v.addr)
- mlen := int32(0)
- if m != nil {
- mlen = maplen(m)
+ if cap < 0 {
+ panic("reflect.MakeSlice: negative cap")
}
- it := mapiterinit(m)
- a := make([]Value, mlen)
- var i int
- for i = 0; i < len(a); i++ {
- k := MakeZero(tk)
- if !mapiterkey(it, (*byte)(k.getAddr())) {
- break
- }
- a[i] = k
- mapiternext(it)
+ if len > cap {
+ panic("reflect.MakeSlice: len > cap")
}
- return a[0:i]
-}
-// MakeMap creates a new map of the specified type.
-func MakeMap(typ *MapType) *MapValue {
- v := MakeZero(typ).(*MapValue)
- *(**byte)(v.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ)))
- return v
-}
+ // Declare slice so that gc can see the base pointer in it.
+ var x []byte
-/*
- * ptr
- */
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
+ s.Data = uintptr(unsafe_NewArray(typ.Elem(), cap))
+ s.Len = len
+ s.Cap = cap
-// A PtrValue represents a pointer.
-type PtrValue struct {
- value "ptr"
+ return Value{typ.common(), unsafe.Pointer(&x), flagIndir | flag(Slice)<<flagKindShift}
}
-// IsNil returns whether v is a nil pointer.
-func (v *PtrValue) IsNil() bool { return *(*uintptr)(v.addr) == 0 }
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *PtrValue) Get() uintptr { return *(*uintptr)(v.addr) }
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *PtrValue) Set(x *PtrValue) {
- if x == nil {
- *(**uintptr)(v.addr) = nil
- return
- }
- if !v.canSet {
- panic(cannotSet)
- }
- typesMustMatch(v.typ, x.typ)
- // TODO: This will have to move into the runtime
- // once the new gc goes in
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr)
-}
-
-// Set sets v to the value x.
-func (v *PtrValue) SetValue(x Value) {
- if x == nil {
- v.Set(nil)
- return
+// MakeChan creates a new channel with the specified type and buffer size.
+func MakeChan(typ Type, buffer int) Value {
+ if typ.Kind() != Chan {
+ panic("reflect.MakeChan of non-chan type")
}
- v.Set(x.(*PtrValue))
-}
-
-// PointTo changes v to point to x.
-// If x is a nil Value, PointTo sets v to nil.
-func (v *PtrValue) PointTo(x Value) {
- if x == nil {
- *(**uintptr)(v.addr) = nil
- return
+ if buffer < 0 {
+ panic("reflect.MakeChan: negative buffer size")
}
- if !x.CanSet() {
- panic("cannot set x; cannot point to x")
+ if typ.ChanDir() != BothDir {
+ panic("reflect.MakeChan: unidirectional channel type")
}
- typesMustMatch(v.typ.(*PtrType).Elem(), x.Type())
- // TODO: This will have to move into the runtime
- // once the new gc goes in.
- *(*uintptr)(v.addr) = x.Addr()
+ ch := makechan(typ.runtimeType(), uint32(buffer))
+ return Value{typ.common(), unsafe.Pointer(ch), flagIndir | (flag(Chan) << flagKindShift)}
}
-// Elem returns the value that v points to.
-// If v is a nil pointer, Elem returns a nil Value.
-func (v *PtrValue) Elem() Value {
- if v.IsNil() {
- return nil
+// MakeMap creates a new map of the specified type.
+func MakeMap(typ Type) Value {
+ if typ.Kind() != Map {
+ panic("reflect.MakeMap of non-map type")
}
- return newValue(v.typ.(*PtrType).Elem(), *(*addr)(v.addr), v.canSet)
+ m := makemap(typ.runtimeType())
+ return Value{typ.common(), unsafe.Pointer(m), flagIndir | (flag(Map) << flagKindShift)}
}
// Indirect returns the value that v points to.
-// If v is a nil pointer, Indirect returns a nil Value.
+// If v is a nil pointer, Indirect returns a zero Value.
// If v is not a pointer, Indirect returns v.
func Indirect(v Value) Value {
- if pv, ok := v.(*PtrValue); ok {
- return pv.Elem()
+ if v.Kind() != Ptr {
+ return v
}
- return v
+ return v.Elem()
}
-/*
- * struct
- */
+// ValueOf returns a new Value initialized to the concrete value
+// stored in the interface i. ValueOf(nil) returns the zero Value.
+func ValueOf(i interface{}) Value {
+ if i == nil {
+ return Value{}
+ }
-// A StructValue represents a struct value.
-type StructValue struct {
- value "struct"
-}
+ // TODO(rsc): Eliminate this terrible hack.
+ // In the call to packValue, eface.typ doesn't escape,
+ // and eface.word is an integer. So it looks like
+ // i (= eface) doesn't escape. But really it does,
+ // because eface.word is actually a pointer.
+ escapes(i)
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *StructValue) Set(x *StructValue) {
- // TODO: This will have to move into the runtime
- // once the gc goes in.
- if !v.canSet {
- panic(cannotSet)
+ // For an interface value with the noAddr bit set,
+ // the representation is identical to an empty interface.
+ eface := *(*emptyInterface)(unsafe.Pointer(&i))
+ typ := toCommonType(eface.typ)
+ fl := flag(typ.Kind()) << flagKindShift
+ if typ.Kind() != Ptr && typ.Kind() != UnsafePointer {
+ fl |= flagIndir
}
- typesMustMatch(v.typ, x.typ)
- memmove(v.addr, x.addr, v.typ.Size())
+ return Value{typ, unsafe.Pointer(eface.word), fl}
}
-// Set sets v to the value x.
-func (v *StructValue) SetValue(x Value) { v.Set(x.(*StructValue)) }
-
-// Field returns the i'th field of the struct.
-func (v *StructValue) Field(i int) Value {
- t := v.typ.(*StructType)
- if i < 0 || i >= t.NumField() {
- return nil
+// Zero returns a Value representing the zero value for the specified type.
+// The result is different from the zero value of the Value struct,
+// which represents no value at all.
+// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
+// The returned value is neither addressable nor settable.
+func Zero(typ Type) Value {
+ if typ == nil {
+ panic("reflect: Zero(nil)")
}
- f := t.Field(i)
- return newValue(f.Type, addr(uintptr(v.addr)+f.Offset), v.canSet && f.PkgPath == "")
+ t := typ.common()
+ fl := flag(t.Kind()) << flagKindShift
+ if t.Kind() == Ptr || t.Kind() == UnsafePointer {
+ return Value{t, nil, fl}
+ }
+ return Value{t, unsafe_New(typ), fl | flagIndir}
}
-// FieldByIndex returns the nested field corresponding to index.
-func (t *StructValue) FieldByIndex(index []int) (v Value) {
- v = t
- for i, x := range index {
- if i > 0 {
- if p, ok := v.(*PtrValue); ok {
- v = p.Elem()
- }
- if s, ok := v.(*StructValue); ok {
- t = s
- } else {
- v = nil
- return
- }
- }
- v = t.Field(x)
+// New returns a Value representing a pointer to a new zero value
+// for the specified type. That is, the returned Value's Type is PtrTo(t).
+func New(typ Type) Value {
+ if typ == nil {
+ panic("reflect: New(nil)")
}
- return
+ ptr := unsafe_New(typ)
+ fl := flag(Ptr) << flagKindShift
+ return Value{typ.common().ptrTo(), ptr, fl}
}
-// FieldByName returns the struct field with the given name.
-// The result is nil if no field was found.
-func (t *StructValue) FieldByName(name string) Value {
- if f, ok := t.Type().(*StructType).FieldByName(name); ok {
- return t.FieldByIndex(f.Index)
- }
- return nil
+// NewAt returns a Value representing a pointer to a value of the
+// specified type, using p as that pointer.
+func NewAt(typ Type, p unsafe.Pointer) Value {
+ fl := flag(Ptr) << flagKindShift
+ return Value{typ.common().ptrTo(), p, fl}
}
-// FieldByNameFunc returns the struct field with a name that satisfies the
-// match function.
-// The result is nil if no field was found.
-func (t *StructValue) FieldByNameFunc(match func(string) bool) Value {
- if f, ok := t.Type().(*StructType).FieldByNameFunc(match); ok {
- return t.FieldByIndex(f.Index)
+// assignTo returns a value v that can be assigned directly to typ.
+// It panics if v is not assignable to typ.
+// For a conversion to an interface type, target is a suggested scratch space to use.
+func (v Value) assignTo(context string, dst *commonType, target *interface{}) Value {
+ if v.flag&flagMethod != 0 {
+ panic(context + ": cannot assign method value to type " + dst.String())
+ }
+
+ switch {
+ case directlyAssignable(dst, v.typ):
+ // Overwrite type so that they match.
+ // Same memory layout, so no harm done.
+ v.typ = dst
+ fl := v.flag & (flagRO | flagAddr | flagIndir)
+ fl |= flag(dst.Kind()) << flagKindShift
+ return Value{dst, v.val, fl}
+
+ case implements(dst, v.typ):
+ if target == nil {
+ target = new(interface{})
+ }
+ x := valueInterface(v, false)
+ if dst.NumMethod() == 0 {
+ *target = x
+ } else {
+ ifaceE2I(dst.runtimeType(), x, unsafe.Pointer(target))
+ }
+ return Value{dst, unsafe.Pointer(target), flagIndir | flag(Interface)<<flagKindShift}
}
- return nil
+
+ // Failed.
+ panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
}
-// NumField returns the number of fields in the struct.
-func (v *StructValue) NumField() int { return v.typ.(*StructType).NumField() }
+// implemented in ../pkg/runtime
+func chancap(ch iword) int32
+func chanclose(ch iword)
+func chanlen(ch iword) int32
+func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received bool)
+func chansend(t *runtimeType, ch iword, val iword, nb bool) bool
-/*
- * constructors
- */
+func makechan(typ *runtimeType, size uint32) (ch iword)
+func makemap(t *runtimeType) (m iword)
+func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool)
+func mapassign(t *runtimeType, m iword, key, val iword, ok bool)
+func mapiterinit(t *runtimeType, m iword) *byte
+func mapiterkey(it *byte) (key iword, ok bool)
+func mapiternext(it *byte)
+func maplen(m iword) int32
-// NewValue returns a new Value initialized to the concrete value
-// stored in the interface i. NewValue(nil) returns nil.
-func NewValue(i interface{}) Value {
- if i == nil {
- return nil
- }
- t, a := unsafe.Reflect(i)
- return newValue(canonicalize(toType(t)), addr(a), true)
-}
-
-func newValue(typ Type, addr addr, canSet bool) Value {
- v := value{typ, addr, canSet}
- switch typ.(type) {
- case *ArrayType:
- return &ArrayValue{v}
- case *BoolType:
- return &BoolValue{v}
- case *ChanType:
- return &ChanValue{v}
- case *FloatType:
- return &FloatValue{v}
- case *FuncType:
- return &FuncValue{value: v}
- case *ComplexType:
- return &ComplexValue{v}
- case *IntType:
- return &IntValue{v}
- case *InterfaceType:
- return &InterfaceValue{v}
- case *MapType:
- return &MapValue{v}
- case *PtrType:
- return &PtrValue{v}
- case *SliceType:
- return &SliceValue{v}
- case *StringType:
- return &StringValue{v}
- case *StructType:
- return &StructValue{v}
- case *UintType:
- return &UintValue{v}
- case *UnsafePointerType:
- return &UnsafePointerValue{v}
- }
- panic("newValue" + typ.String())
-}
-
-// MakeZero returns a zero Value for the specified Type.
-func MakeZero(typ Type) Value {
- if typ == nil {
- return nil
+func call(typ *commonType, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
+func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer)
+
+// Dummy annotation marking that the value x escapes,
+// for use in cases where the reflect code is so clever that
+// the compiler cannot follow.
+func escapes(x interface{}) {
+ if dummy.b {
+ dummy.x = x
}
- return newValue(typ, addr(unsafe.New(typ)), true)
+}
+
+var dummy struct {
+ b bool
+ x interface{}
}