X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=libgo%2Fgo%2Freflect%2Fvalue.go;h=5d0890016ed7459997344a464e169395acbdadd8;hp=8ef402bbc795caf10dac88b67745520985412a2d;hb=c0ce9d8ac93395bdae88d31d20ad4eafec207b30;hpb=48080209fa53b6ea88c86e9f445c431b4cd1e47b diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go index 8ef402bbc79..5d0890016ed 100644 --- a/libgo/go/reflect/value.go +++ b/libgo/go/reflect/value.go @@ -7,17 +7,17 @@ package reflect 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 { @@ -26,1217 +26,1783 @@ func memmove(adst, asrc addr, n uintptr) { // 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 "", 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<> 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)<> 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)<> (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)<" where T is v's type. +func (v Value) String() string { + switch k := v.kind(); k { + case Invalid: + return "" + 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)<= 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)<