reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 01a40ec..eeae6cc 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -41,10 +41,482 @@
}
}
-// Value is the common interface to reflection values.
-// The implementations of Value (e.g., ArrayValue, StructValue)
+// 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.
+type Value struct {
+ Internal valueInterface
+}
+
+// TODO(rsc): This implementation of Value is a just a façade
+// in front of the old implementation, now called valueInterface.
+// A future CL will change it to a real implementation.
+// Changing the API is already a big enough step for one CL.
+
+// 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 (e *ValueError) String() 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"
+}
+
+// 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) internal() valueInterface {
+ vi := v.Internal
+ if vi == nil {
+ panic(&ValueError{methodName(), 0})
+ }
+ return vi
+}
+
+func (v Value) panicIfNot(want Kind) valueInterface {
+ vi := v.Internal
+ if vi == nil {
+ panic(&ValueError{methodName(), 0})
+ }
+ if k := vi.Kind(); k != want {
+ panic(&ValueError{methodName(), k})
+ }
+ return vi
+}
+
+func (v Value) panicIfNots(wants []Kind) valueInterface {
+ vi := v.Internal
+ if vi == nil {
+ panic(&ValueError{methodName(), 0})
+ }
+ k := vi.Kind()
+ for _, want := range wants {
+ if k == want {
+ return vi
+ }
+ }
+ panic(&ValueError{methodName(), k})
+}
+
+// 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 {
+ return v.internal().Addr()
+}
+
+// Bool returns v's underlying value.
+// It panics if v's kind is not Bool.
+func (v Value) Bool() bool {
+ u := v.panicIfNot(Bool).(*boolValue)
+ return u.Get()
+}
+
+// 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, the result of dereferencing a pointer,
+// or the result of a call to NewValue, MakeChan, MakeMap, or Zero.
+// If CanAddr returns false, calling Addr will panic.
+func (v Value) CanAddr() bool {
+ return v.internal().CanAddr()
+}
+
+// CanSet returns true if the value of v can be changed.
+// Values obtained by the use of unexported struct fields
+// can be read but not set.
+// If CanSet returns false, calling Set or any type-specific
+// setter (e.g., SetBool, SetInt64) will panic.
+func (v Value) CanSet() bool {
+ return v.internal().CanSet()
+}
+
+// Call calls the function v with the input parameters in.
+// It panics if v's Kind is not Func.
+// It returns the output parameters as Values.
+func (v Value) Call(in []Value) []Value {
+ return v.panicIfNot(Func).(*funcValue).Call(in)
+}
+
+var capKinds = []Kind{Array, Chan, Slice}
+
+type capper interface {
+ Cap() int
+}
+
+// Cap returns v's capacity.
+// It panics if v's Kind is not Array, Chan, or Slice.
+func (v Value) Cap() int {
+ return v.panicIfNots(capKinds).(capper).Cap()
+}
+
+// Close closes the channel v.
+// It panics if v's Kind is not Chan.
+func (v Value) Close() {
+ v.panicIfNot(Chan).(*chanValue).Close()
+}
+
+var complexKinds = []Kind{Complex64, Complex128}
+
+// 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 {
+ return v.panicIfNots(complexKinds).(*complexValue).Get()
+}
+
+var interfaceOrPtr = []Kind{Interface, Ptr}
+
+type elemer interface {
+ Elem() Value
+}
+
+// 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 {
+ return v.panicIfNots(interfaceOrPtr).(elemer).Elem()
+}
+
+// Field returns the i'th field of the struct v.
+// It panics if v's Kind is not Struct.
+func (v Value) Field(i int) Value {
+ return v.panicIfNot(Struct).(*structValue).Field(i)
+}
+
+// FieldByIndex returns the nested field corresponding to index.
+// It panics if v's Kind is not struct.
+func (v Value) FieldByIndex(index []int) Value {
+ return v.panicIfNot(Struct).(*structValue).FieldByIndex(index)
+}
+
+// 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 {
+ return v.panicIfNot(Struct).(*structValue).FieldByName(name)
+}
+
+// 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 {
+ return v.panicIfNot(Struct).(*structValue).FieldByNameFunc(match)
+}
+
+var floatKinds = []Kind{Float32, Float64}
+
+// Float returns v's underlying value, as an float64.
+// It panics if v's Kind is not Float32 or Float64
+func (v Value) Float() float64 {
+ return v.panicIfNots(floatKinds).(*floatValue).Get()
+}
+
+var arrayOrSlice = []Kind{Array, Slice}
+
+// Index returns v's i'th element.
+// It panics if v's Kind is not Array or Slice.
+func (v Value) Index(i int) Value {
+ return v.panicIfNots(arrayOrSlice).(arrayOrSliceValue).Elem(i)
+}
+
+var intKinds = []Kind{Int, Int8, Int16, Int32, Int64}
+
+// Int returns v's underlying value, as an int64.
+// It panics if v's Kind is not a sized or unsized Int kind.
+func (v Value) Int() int64 {
+ return v.panicIfNots(intKinds).(*intValue).Get()
+}
+
+// Interface returns v's value as an interface{}.
+// If v is a method obtained by invoking Value.Method
+// (as opposed to Type.Method), Interface cannot return an
+// interface value, so it panics.
+func (v Value) Interface() interface{} {
+ return v.internal().Interface()
+}
+
+// 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 {
+ return v.panicIfNot(Interface).(*interfaceValue).Get()
+}
+
+var nilKinds = []Kind{Chan, Func, Interface, Map, Ptr, Slice}
+
+type isNiller interface {
+ IsNil() bool
+}
+
+// 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 {
+ return v.panicIfNots(nilKinds).(isNiller).IsNil()
+}
+
+// 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.Internal != nil
+}
+
+// Kind returns v's Kind.
+// If v is the zero Value (IsValid returns false), Kind returns Invalid.
+func (v Value) Kind() Kind {
+ if v.Internal == nil {
+ return Invalid
+ }
+ return v.internal().Kind()
+}
+
+var lenKinds = []Kind{Array, Chan, Map, Slice}
+
+type lenner interface {
+ Len() int
+}
+
+// Len returns v's length.
+// It panics if v's Kind is not Array, Chan, Map, or Slice.
+func (v Value) Len() int {
+ return v.panicIfNots(lenKinds).(lenner).Len()
+}
+
+// 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.
+func (v Value) MapIndex(key Value) Value {
+ return v.panicIfNot(Map).(*mapValue).Elem(key)
+}
+
+// MapKeys returns a slice containing all the keys present in the map,
+// in unspecified order.
+// It panics if v's Kind is not Map.
+func (v Value) MapKeys() []Value {
+ return v.panicIfNot(Map).(*mapValue).Keys()
+}
+
+// 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.
+func (v Value) Method(i int) Value {
+ return v.internal().Method(i)
+}
+
+// NumField returns the number of fields in the struct v.
+// It panics if v's Kind is not Struct.
+func (v Value) NumField() int {
+ return v.panicIfNot(Struct).(*structValue).NumField()
+}
+
+// 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 {
+ return v.panicIfNots(complexKinds).(*complexValue).Overflow(x)
+}
+
+// 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 {
+ return v.panicIfNots(floatKinds).(*floatValue).Overflow(x)
+}
+
+// OverflowInt returns true if the int64 x cannot be represented by v's type.
+// It panics if v's Kind is not a sized or unsized Int kind.
+func (v Value) OverflowInt(x int64) bool {
+ return v.panicIfNots(intKinds).(*intValue).Overflow(x)
+}
+
+// OverflowUint returns true if the uint64 x cannot be represented by v's type.
+// It panics if v's Kind is not a sized or unsized Uint kind.
+func (v Value) OverflowUint(x uint64) bool {
+ return v.panicIfNots(uintKinds).(*uintValue).Overflow(x)
+}
+
+var pointerKinds = []Kind{Chan, Func, Map, Ptr, Slice, UnsafePointer}
+
+type uintptrGetter interface {
+ Get() uintptr
+}
+
+// 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 {
+ return v.panicIfNots(pointerKinds).(uintptrGetter).Get()
+}
+
+
+// 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) {
+ return v.panicIfNot(Chan).(*chanValue).Recv()
+}
+
+// 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.
+func (v Value) Send(x Value) {
+ v.panicIfNot(Chan).(*chanValue).Send(x)
+}
+
+// Set assigns x to the value v; x must have the same type as v.
+// It panics if CanSet() returns false or if x is the zero Value.
+func (v Value) Set(x Value) {
+ x.internal()
+ v.internal().SetValue(x)
+}
+
+// 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.panicIfNot(Bool).(*boolValue).Set(x)
+}
+
+// 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.panicIfNots(complexKinds).(*complexValue).Set(x)
+}
+
+// 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.panicIfNots(floatKinds).(*floatValue).Set(x)
+}
+
+// SetInt sets v's underlying value to x.
+// It panics if v's Kind is not a sized or unsized Int kind, or if CanSet() is false.
+func (v Value) SetInt(x int64) {
+ v.panicIfNots(intKinds).(*intValue).Set(x)
+}
+
+// SetLen sets v's length to n.
+// It panics if v's Kind is not Slice.
+func (v Value) SetLen(n int) {
+ v.panicIfNot(Slice).(*sliceValue).SetLen(n)
+}
+
+// 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.
+func (v Value) SetMapIndex(key, val Value) {
+ v.panicIfNot(Map).(*mapValue).SetElem(key, val)
+}
+
+// SetUint sets v's underlying value to x.
+// It panics if v's Kind is not a sized or unsized Uint kind, or if CanSet() is false.
+func (v Value) SetUint(x uint64) {
+ v.panicIfNots(uintKinds).(*uintValue).Set(x)
+}
+
+// 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.panicIfNot(UnsafePointer).(*unsafePointerValue).Set(x)
+}
+
+// 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.panicIfNot(String).(*stringValue).Set(x)
+}
+
+// BUG(rsc): Value.Slice should allow slicing arrays.
+
+// Slice returns a slice of v.
+// It panics if v's Kind is not Slice.
+func (v Value) Slice(beg, end int) Value {
+ return v.panicIfNot(Slice).(*sliceValue).Slice(beg, end)
+}
+
+// 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 {
+ vi := v.Internal
+ if vi == nil {
+ return "<invalid Value>"
+ }
+ if vi.Kind() == String {
+ return vi.(*stringValue).Get()
+ }
+ return "<" + vi.Type().String() + " Value>"
+}
+
+// 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) {
+ return v.panicIfNot(Chan).(*chanValue).TryRecv()
+}
+
+// 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 Value) TrySend(x Value) bool {
+ return v.panicIfNot(Chan).(*chanValue).TrySend(x)
+}
+
+// Type returns v's type.
+func (v Value) Type() Type {
+ return v.internal().Type()
+}
+
+var uintKinds = []Kind{Uint, Uint8, Uint16, Uint32, Uint64, Uintptr}
+
+// Uint returns v's underlying value, as a uint64.
+// It panics if v's Kind is not a sized or unsized Uint kind.
+func (v Value) Uint() uint64 {
+ return v.panicIfNots(uintKinds).(*uintValue).Get()
+}
+
+// UnsafeAddr returns a pointer to v's data.
+// It is for advanced clients that also import the "unsafe" package.
+func (v Value) UnsafeAddr() uintptr {
+ return v.internal().UnsafeAddr()
+}
+
+// valueInterface is the common interface to reflection values.
+// The implementations of Value (e.g., arrayValue, structValue)
// have additional type-specific methods.
-type Value interface {
+type valueInterface interface {
// Type returns the value's type.
Type() Type
@@ -64,7 +536,7 @@
// 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, the result of dereferencing a pointer,
- // or the result of a call to NewValue, MakeChan, MakeMap, or MakeZero.
+ // or the result of a call to NewValue, MakeChan, MakeMap, or Zero.
// If CanAddr returns false, calling Addr will panic.
CanAddr() bool
@@ -72,17 +544,19 @@
// If the value is not addressable, Addr panics.
// 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.
- Addr() *PtrValue
+ Addr() Value
// UnsafeAddr returns a pointer to the underlying data.
// It is for advanced clients that also import the "unsafe" package.
UnsafeAddr() 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
+ // 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
+ Method(i int) Value
+
+ Kind() Kind
getAddr() addr
}
@@ -97,7 +571,7 @@
// 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.
+// convert from, say, *uintValue to *floatValue.
type value struct {
typ Type
addr addr
@@ -106,7 +580,9 @@
func (v *value) Type() Type { return v.typ }
-func (v *value) Addr() *PtrValue {
+func (v *value) Kind() Kind { return v.typ.Kind() }
+
+func (v *value) Addr() Value {
if !v.CanAddr() {
panic("reflect: cannot take address of value")
}
@@ -119,7 +595,7 @@
// the caller would get the address of a -
// but it doesn't match the Go model.
// The language doesn't let you say &&v.
- return newValue(PtrTo(v.typ), addr(&a), flag).(*PtrValue)
+ return newValue(PtrTo(v.typ), addr(&a), flag)
}
func (v *value) UnsafeAddr() uintptr { return uintptr(v.addr) }
@@ -127,7 +603,8 @@
func (v *value) getAddr() addr { return v.addr }
func (v *value) Interface() interface{} {
- if typ, ok := v.typ.(*InterfaceType); ok {
+ typ := v.typ
+ if typ.Kind() == Interface {
// 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
@@ -153,16 +630,16 @@
* basic types
*/
-// BoolValue represents a bool value.
-type BoolValue struct {
+// boolValue represents a bool value.
+type boolValue struct {
value "bool"
}
// Get returns the underlying bool value.
-func (v *BoolValue) Get() bool { return *(*bool)(v.addr) }
+func (v *boolValue) Get() bool { return *(*bool)(v.addr) }
// Set sets v to the value x.
-func (v *BoolValue) Set(x bool) {
+func (v *boolValue) Set(x bool) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -170,15 +647,15 @@
}
// Set sets v to the value x.
-func (v *BoolValue) SetValue(x Value) { v.Set(x.(*BoolValue).Get()) }
+func (v *boolValue) SetValue(x Value) { v.Set(x.Bool()) }
-// FloatValue represents a float value.
-type FloatValue struct {
+// floatValue represents a float value.
+type floatValue struct {
value "float"
}
// Get returns the underlying int value.
-func (v *FloatValue) Get() float64 {
+func (v *floatValue) Get() float64 {
switch v.typ.Kind() {
case Float32:
return float64(*(*float32)(v.addr))
@@ -189,7 +666,7 @@
}
// Set sets v to the value x.
-func (v *FloatValue) Set(x float64) {
+func (v *floatValue) Set(x float64) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -204,7 +681,7 @@
}
// Overflow returns true if x cannot be represented by the type of v.
-func (v *FloatValue) Overflow(x float64) bool {
+func (v *floatValue) Overflow(x float64) bool {
if v.typ.Size() == 8 {
return false
}
@@ -215,15 +692,15 @@
}
// Set sets v to the value x.
-func (v *FloatValue) SetValue(x Value) { v.Set(x.(*FloatValue).Get()) }
+func (v *floatValue) SetValue(x Value) { v.Set(x.Float()) }
-// ComplexValue represents a complex value.
-type ComplexValue struct {
+// complexValue represents a complex value.
+type complexValue struct {
value "complex"
}
// Get returns the underlying complex value.
-func (v *ComplexValue) Get() complex128 {
+func (v *complexValue) Get() complex128 {
switch v.typ.Kind() {
case Complex64:
return complex128(*(*complex64)(v.addr))
@@ -234,7 +711,7 @@
}
// Set sets v to the value x.
-func (v *ComplexValue) Set(x complex128) {
+func (v *complexValue) Set(x complex128) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -248,16 +725,33 @@
}
}
-// Set sets v to the value x.
-func (v *ComplexValue) SetValue(x Value) { v.Set(x.(*ComplexValue).Get()) }
+// How did we forget this one?
+func (v *complexValue) Overflow(x complex128) bool {
+ if v.typ.Size() == 16 {
+ return false
+ }
+ r := real(x)
+ i := imag(x)
+ if r < 0 {
+ r = -r
+ }
+ if i < 0 {
+ i = -i
+ }
+ return math.MaxFloat32 <= r && r <= math.MaxFloat64 ||
+ math.MaxFloat32 <= i && i <= math.MaxFloat64
+}
-// IntValue represents an int value.
-type IntValue struct {
+// Set sets v to the value x.
+func (v *complexValue) SetValue(x Value) { v.Set(x.Complex()) }
+
+// intValue represents an int value.
+type intValue struct {
value "int"
}
// Get returns the underlying int value.
-func (v *IntValue) Get() int64 {
+func (v *intValue) Get() int64 {
switch v.typ.Kind() {
case Int:
return int64(*(*int)(v.addr))
@@ -274,7 +768,7 @@
}
// Set sets v to the value x.
-func (v *IntValue) Set(x int64) {
+func (v *intValue) Set(x int64) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -295,10 +789,10 @@
}
// Set sets v to the value x.
-func (v *IntValue) SetValue(x Value) { v.Set(x.(*IntValue).Get()) }
+func (v *intValue) SetValue(x Value) { v.Set(x.Int()) }
// Overflow returns true if x cannot be represented by the type of v.
-func (v *IntValue) Overflow(x int64) bool {
+func (v *intValue) Overflow(x int64) bool {
bitSize := uint(v.typ.Bits())
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
@@ -310,16 +804,16 @@
Len int
}
-// StringValue represents a string value.
-type StringValue struct {
+// stringValue represents a string value.
+type stringValue struct {
value "string"
}
// Get returns the underlying string value.
-func (v *StringValue) Get() string { return *(*string)(v.addr) }
+func (v *stringValue) Get() string { return *(*string)(v.addr) }
// Set sets v to the value x.
-func (v *StringValue) Set(x string) {
+func (v *stringValue) Set(x string) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -327,15 +821,18 @@
}
// Set sets v to the value x.
-func (v *StringValue) SetValue(x Value) { v.Set(x.(*StringValue).Get()) }
+func (v *stringValue) SetValue(x Value) {
+ // Do the kind check explicitly, because x.String() does not.
+ v.Set(x.panicIfNot(String).(*stringValue).Get())
+}
-// UintValue represents a uint value.
-type UintValue struct {
+// uintValue represents a uint value.
+type uintValue struct {
value "uint"
}
// Get returns the underlying uuint value.
-func (v *UintValue) Get() uint64 {
+func (v *uintValue) Get() uint64 {
switch v.typ.Kind() {
case Uint:
return uint64(*(*uint)(v.addr))
@@ -354,7 +851,7 @@
}
// Set sets v to the value x.
-func (v *UintValue) Set(x uint64) {
+func (v *uintValue) Set(x uint64) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -377,17 +874,17 @@
}
// Overflow returns true if x cannot be represented by the type of v.
-func (v *UintValue) Overflow(x uint64) bool {
+func (v *uintValue) Overflow(x uint64) bool {
bitSize := uint(v.typ.Bits())
trunc := (x << (64 - bitSize)) >> (64 - bitSize)
return x != trunc
}
// Set sets v to the value x.
-func (v *UintValue) SetValue(x Value) { v.Set(x.(*UintValue).Get()) }
+func (v *uintValue) SetValue(x Value) { v.Set(x.Uint()) }
-// UnsafePointerValue represents an unsafe.Pointer value.
-type UnsafePointerValue struct {
+// unsafePointerValue represents an unsafe.Pointer value.
+type unsafePointerValue struct {
value "unsafe.Pointer"
}
@@ -395,10 +892,10 @@
// 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)) }
+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) {
+func (v *unsafePointerValue) Set(x unsafe.Pointer) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -406,8 +903,10 @@
}
// Set sets v to the value x.
-func (v *UnsafePointerValue) SetValue(x Value) {
- v.Set(unsafe.Pointer(x.(*UnsafePointerValue).Get()))
+func (v *unsafePointerValue) SetValue(x Value) {
+ // Do the kind check explicitly, because x.UnsafePointer
+ // applies to more than just the UnsafePointer Kind.
+ v.Set(unsafe.Pointer(x.panicIfNot(UnsafePointer).(*unsafePointerValue).Get()))
}
func typesMustMatch(t1, t2 Type) {
@@ -421,9 +920,9 @@
*/
// ArrayOrSliceValue is the common interface
-// implemented by both ArrayValue and SliceValue.
-type ArrayOrSliceValue interface {
- Value
+// implemented by both arrayValue and sliceValue.
+type arrayOrSliceValue interface {
+ valueInterface
Len() int
Cap() int
Elem(i int) Value
@@ -432,7 +931,7 @@
// 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) {
+func grow(s Value, extra int) (Value, int, int) {
i0 := s.Len()
i1 := i0 + extra
if i1 < i0 {
@@ -453,24 +952,25 @@
}
}
}
- t := MakeSlice(s.Type().(*SliceType), i1, m)
+ t := MakeSlice(s.Type(), i1, m)
Copy(t, s)
return t, i0, i1
}
// 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 {
+func Append(s Value, x ...Value) Value {
s, i0, i1 := grow(s, len(x))
+ sa := s.panicIfNot(Slice).(*sliceValue)
for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
- s.Elem(i).SetValue(x[j])
+ sa.Elem(i).Set(x[j])
}
return s
}
// 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 {
+func AppendSlice(s, t Value) Value {
s, i0, i1 := grow(s, t.Len())
Copy(s.Slice(i0, i1), t)
return s
@@ -479,51 +979,56 @@
// 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 {
+// Dst and src each must be a slice or array, and they
+// must have the same element type.
+func Copy(dst, src Value) 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()
+ de := dst.Type().Elem()
+ se := src.Type().Elem()
typesMustMatch(de, se)
n := dst.Len()
if xn := src.Len(); n > xn {
n = xn
}
- memmove(dst.addr(), src.addr(), uintptr(n)*de.Size())
+ memmove(dst.panicIfNots(arrayOrSlice).(arrayOrSliceValue).addr(),
+ src.panicIfNots(arrayOrSlice).(arrayOrSliceValue).addr(),
+ uintptr(n)*de.Size())
return n
}
-// An ArrayValue represents an array.
-type ArrayValue struct {
+// An arrayValue represents an array.
+type arrayValue struct {
value "array"
}
// Len returns the length of the array.
-func (v *ArrayValue) Len() int { return v.typ.(*ArrayType).Len() }
+func (v *arrayValue) Len() int { return v.typ.Len() }
// Cap returns the capacity of the array (equal to Len()).
-func (v *ArrayValue) Cap() int { return v.typ.(*ArrayType).Len() }
+func (v *arrayValue) Cap() int { return v.typ.Len() }
// addr returns the base address of the data in the array.
-func (v *ArrayValue) addr() addr { return v.value.addr }
+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) {
+func (v *arrayValue) Set(x *arrayValue) {
if !v.CanSet() {
panic(cannotSet)
}
typesMustMatch(v.typ, x.typ)
- Copy(v, x)
+ Copy(Value{v}, Value{x})
}
// Set sets v to the value x.
-func (v *ArrayValue) SetValue(x Value) { v.Set(x.(*ArrayValue)) }
+func (v *arrayValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Array).(*arrayValue))
+}
// Elem returns the i'th element of v.
-func (v *ArrayValue) Elem(i int) Value {
- typ := v.typ.(*ArrayType).Elem()
+func (v *arrayValue) Elem(i int) Value {
+ typ := v.typ.Elem()
n := v.Len()
if i < 0 || i >= n {
panic("array index out of bounds")
@@ -543,28 +1048,28 @@
Cap int
}
-// A SliceValue represents a slice.
-type SliceValue struct {
+// A sliceValue represents a slice.
+type sliceValue struct {
value "slice"
}
-func (v *SliceValue) slice() *SliceHeader { return (*SliceHeader)(v.value.addr) }
+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 }
+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) }
+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) }
+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) }
+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) {
+func (v *sliceValue) SetLen(n int) {
s := v.slice()
if n < 0 || n > int(s.Cap) {
panic("reflect: slice length out of range in SetLen")
@@ -574,7 +1079,7 @@
// Set assigns x to v.
// The new value x must have the same type as v.
-func (v *SliceValue) Set(x *SliceValue) {
+func (v *sliceValue) Set(x *sliceValue) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -583,23 +1088,25 @@
}
// Set sets v to the value x.
-func (v *SliceValue) SetValue(x Value) { v.Set(x.(*SliceValue)) }
+func (v *sliceValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Slice).(*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)
+func (v *sliceValue) Get() uintptr {
+ typ := v.typ
return uintptr(v.addr()) + uintptr(v.Cap())*typ.Elem().Size()
}
// Slice returns a sub-slice of the slice v.
-func (v *SliceValue) Slice(beg, end int) *SliceValue {
+func (v *sliceValue) Slice(beg, end int) Value {
cap := v.Cap()
if beg < 0 || end < beg || end > cap {
panic("slice index out of bounds")
}
- typ := v.typ.(*SliceType)
+ typ := v.typ
s := new(SliceHeader)
s.Data = uintptr(v.addr()) + uintptr(beg)*typ.Elem().Size()
s.Len = end - beg
@@ -611,12 +1118,12 @@
if v.flag&canStore != 0 {
flag |= canStore
}
- return newValue(typ, addr(s), flag).(*SliceValue)
+ return newValue(typ, addr(s), flag)
}
// Elem returns the i'th element of v.
-func (v *SliceValue) Elem(i int) Value {
- typ := v.typ.(*SliceType).Elem()
+func (v *sliceValue) Elem(i int) Value {
+ typ := v.typ.Elem()
n := v.Len()
if i < 0 || i >= n {
panic("reflect: slice index out of range")
@@ -631,30 +1138,33 @@
// MakeSlice creates a new zero-initialized slice value
// for the specified slice type, length, and capacity.
-func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
+func MakeSlice(typ Type, len, cap int) Value {
+ if typ.Kind() != Slice {
+ panic("reflect: MakeSlice of non-slice type")
+ }
s := &SliceHeader{
Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
Len: len,
Cap: cap,
}
- return newValue(typ, addr(s), canAddr|canSet|canStore).(*SliceValue)
+ return newValue(typ, addr(s), canAddr|canSet|canStore)
}
/*
* chan
*/
-// A ChanValue represents a chan.
-type ChanValue struct {
+// 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 }
+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) {
+func (v *chanValue) Set(x *chanValue) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -663,11 +1173,13 @@
}
// Set sets v to the value x.
-func (v *ChanValue) SetValue(x Value) { v.Set(x.(*ChanValue)) }
+func (v *chanValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Chan).(*chanValue))
+}
// Get returns the uintptr value of v.
// It is mainly useful for printing.
-func (v *ChanValue) Get() uintptr { return *(*uintptr)(v.addr) }
+func (v *chanValue) Get() uintptr { return *(*uintptr)(v.addr) }
// implemented in ../pkg/runtime/reflect.cgo
func makechan(typ *runtime.ChanType, size uint32) (ch *byte)
@@ -678,59 +1190,59 @@
func chancap(ch *byte) int32
// Close closes the channel.
-func (v *ChanValue) Close() {
+func (v *chanValue) Close() {
ch := *(**byte)(v.addr)
chanclose(ch)
}
-func (v *ChanValue) Len() int {
+func (v *chanValue) Len() int {
ch := *(**byte)(v.addr)
return int(chanlen(ch))
}
-func (v *ChanValue) Cap() int {
+func (v *chanValue) Cap() int {
ch := *(**byte)(v.addr)
return int(chancap(ch))
}
// internal send; non-blocking if selected != nil
-func (v *ChanValue) send(x Value, selected *bool) {
- t := v.Type().(*ChanType)
- if t.Dir()&SendDir == 0 {
+func (v *chanValue) send(x Value, selected *bool) {
+ t := v.Type()
+ if t.ChanDir()&SendDir == 0 {
panic("send on recv-only channel")
}
typesMustMatch(t.Elem(), x.Type())
ch := *(**byte)(v.addr)
- chansend(ch, (*byte)(x.getAddr()), selected)
+ chansend(ch, (*byte)(x.internal().getAddr()), selected)
}
// internal recv; non-blocking if selected != nil
-func (v *ChanValue) recv(selected *bool) (Value, bool) {
- t := v.Type().(*ChanType)
- if t.Dir()&RecvDir == 0 {
+func (v *chanValue) recv(selected *bool) (Value, bool) {
+ t := v.Type()
+ if t.ChanDir()&RecvDir == 0 {
panic("recv on send-only channel")
}
ch := *(**byte)(v.addr)
- x := MakeZero(t.Elem())
+ x := Zero(t.Elem())
var ok bool
- chanrecv(ch, (*byte)(x.getAddr()), selected, &ok)
+ chanrecv(ch, (*byte)(x.internal().getAddr()), selected, &ok)
return x, ok
}
// Send sends x on the channel v.
-func (v *ChanValue) Send(x Value) { v.send(x, nil) }
+func (v *chanValue) Send(x Value) { v.send(x, nil) }
// Recv receives and returns a value from the channel v.
// 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 *ChanValue) Recv() (x Value, ok bool) {
+func (v *chanValue) Recv() (x Value, ok bool) {
return v.recv(nil)
}
// TrySend attempts to sends x on the channel v but will not block.
// It returns true if the value was sent, false otherwise.
-func (v *ChanValue) TrySend(x Value) bool {
+func (v *chanValue) TrySend(x Value) bool {
var selected bool
v.send(x, &selected)
return selected
@@ -741,25 +1253,29 @@
// If the receive can finish without blocking, TryRecv returns x != nil.
// 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 *ChanValue) TryRecv() (x Value, ok bool) {
+func (v *chanValue) TryRecv() (x Value, ok bool) {
var selected bool
x, ok = v.recv(&selected)
if !selected {
- return nil, false
+ return Value{}, false
}
return x, ok
}
// MakeChan creates a new channel with the specified type and buffer size.
-func MakeChan(typ *ChanType, buffer int) *ChanValue {
+func MakeChan(typ Type, buffer int) Value {
+ if typ.Kind() != Chan {
+ panic("reflect: MakeChan of non-chan type")
+ }
if buffer < 0 {
panic("MakeChan: negative buffer size")
}
- if typ.Dir() != BothDir {
+ if typ.ChanDir() != BothDir {
panic("MakeChan: unidirectional channel type")
}
- v := MakeZero(typ).(*ChanValue)
- *(**byte)(v.addr) = makechan((*runtime.ChanType)(unsafe.Pointer(typ)), uint32(buffer))
+ v := Zero(typ)
+ ch := v.panicIfNot(Chan).(*chanValue)
+ *(**byte)(ch.addr) = makechan((*runtime.ChanType)(unsafe.Pointer(typ.(*commonType))), uint32(buffer))
return v
}
@@ -767,23 +1283,23 @@
* func
*/
-// A FuncValue represents a function value.
-type FuncValue struct {
+// A funcValue represents a function value.
+type funcValue struct {
value "func"
first *value
isInterface bool
}
// IsNil returns whether v is a nil function.
-func (v *FuncValue) IsNil() bool { return *(*uintptr)(v.addr) == 0 }
+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) }
+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) {
+func (v *funcValue) Set(x *funcValue) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -792,21 +1308,23 @@
}
// Set sets v to the value x.
-func (v *FuncValue) SetValue(x Value) { v.Set(x.(*FuncValue)) }
+func (v *funcValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Func).(*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
+// 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 {
+func (v *value) Method(i int) Value {
t := v.Type().uncommon()
if t == nil || i < 0 || i >= len(t.methods) {
- return nil
+ panic("reflect: Method index out of range")
}
p := &t.methods[i]
fn := p.tfn
- fv := &FuncValue{value: value{toType(*p.typ), addr(&fn), 0}, first: v, isInterface: false}
- return fv
+ fv := &funcValue{value: value{toType(p.typ), addr(&fn), 0}, first: v, isInterface: false}
+ return Value{fv}
}
// implemented in ../pkg/runtime/*/asm.s
@@ -820,23 +1338,23 @@
// If fv is a method obtained by invoking Value.Method
// (as opposed to Type.Method), Interface cannot return an
// interface value, so it panics.
-func (fv *FuncValue) Interface() interface{} {
+func (fv *funcValue) Interface() interface{} {
if fv.first != nil {
- panic("FuncValue: cannot create interface value for method with bound receiver")
+ panic("funcValue: cannot create interface value for method with bound receiver")
}
return fv.value.Interface()
}
// 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)
+func (fv *funcValue) Call(in []Value) []Value {
+ t := fv.Type()
nin := len(in)
if fv.first != nil && !fv.isInterface {
nin++
}
if nin != t.NumIn() {
- panic("FuncValue: wrong argument count")
+ panic("funcValue: wrong argument count")
}
nout := t.NumOut()
@@ -906,7 +1424,7 @@
a := uintptr(tv.Align())
off = (off + a - 1) &^ (a - 1)
n := tv.Size()
- memmove(addr(ptr+off), v.getAddr(), n)
+ memmove(addr(ptr+off), v.internal().getAddr(), n)
off += n
}
off = (off + ptrSize - 1) &^ (ptrSize - 1)
@@ -922,9 +1440,9 @@
tv := t.Out(i)
a := uintptr(tv.Align())
off = (off + a - 1) &^ (a - 1)
- v := MakeZero(tv)
+ v := Zero(tv)
n := tv.Size()
- memmove(v.getAddr(), addr(ptr+off), n)
+ memmove(v.internal().getAddr(), addr(ptr+off), n)
ret[i] = v
off += n
}
@@ -936,40 +1454,37 @@
* interface
*/
-// An InterfaceValue represents an interface value.
-type InterfaceValue struct {
+// An interfaceValue represents an interface value.
+type interfaceValue struct {
value "interface"
}
// IsNil returns whether v is a nil interface value.
-func (v *InterfaceValue) IsNil() bool { return v.Interface() == nil }
+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 {
+func (v *interfaceValue) Get() [2]uintptr {
return *(*[2]uintptr)(v.addr)
}
// Elem returns the concrete value stored in the interface value v.
-func (v *InterfaceValue) Elem() Value { return NewValue(v.Interface()) }
+func (v *interfaceValue) Elem() Value { return NewValue(v.Interface()) }
// ../runtime/reflect.cgo
-func setiface(typ *InterfaceType, x *interface{}, addr addr)
+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()
- }
+func (v *interfaceValue) Set(x Value) {
+ i := x.Interface()
if !v.CanSet() {
panic(cannotSet)
}
// Two different representations; see comment in Get.
// Empty interface is easy.
- t := v.typ.(*InterfaceType)
+ t := (*interfaceType)(unsafe.Pointer(v.typ.(*commonType)))
if t.NumMethod() == 0 {
*(*interface{})(v.addr) = i
return
@@ -980,16 +1495,16 @@
}
// Set sets v to the value x.
-func (v *InterfaceValue) SetValue(x Value) { v.Set(x) }
+func (v *interfaceValue) SetValue(x Value) { v.Set(x) }
-// 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
+// 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)
+func (v *interfaceValue) Method(i int) Value {
+ t := (*interfaceType)(unsafe.Pointer(v.Type().(*commonType)))
if t == nil || i < 0 || i >= len(t.methods) {
- return nil
+ panic("reflect: Method index out of range")
}
p := &t.methods[i]
@@ -999,25 +1514,25 @@
// Function pointer is at p.perm in the table.
fn := tab.Fn[i]
- fv := &FuncValue{value: value{toType(*p.typ), addr(&fn), 0}, first: data, isInterface: true}
- return fv
+ fv := &funcValue{value: value{toType(p.typ), addr(&fn), 0}, first: data, isInterface: true}
+ return Value{fv}
}
/*
* map
*/
-// A MapValue represents a map value.
-type MapValue struct {
+// 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 }
+func (v *mapValue) 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 *MapValue) Set(x *MapValue) {
+func (v *mapValue) Set(x *mapValue) {
if !v.CanSet() {
panic(cannotSet)
}
@@ -1030,17 +1545,13 @@
}
// Set sets v to the value x.
-func (v *MapValue) SetValue(x Value) {
- if x == nil {
- v.Set(nil)
- return
- }
- v.Set(x.(*MapValue))
+func (v *mapValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Map).(*mapValue))
}
// Get returns the uintptr value of v.
// It is mainly useful for printing.
-func (v *MapValue) Get() uintptr { return *(*uintptr)(v.addr) }
+func (v *mapValue) Get() uintptr { return *(*uintptr)(v.addr) }
// implemented in ../pkg/runtime/reflect.cgo
func mapaccess(m, key, val *byte) bool
@@ -1053,36 +1564,36 @@
// 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)
+func (v *mapValue) Elem(key Value) Value {
+ t := v.Type()
typesMustMatch(t.Key(), key.Type())
m := *(**byte)(v.addr)
if m == nil {
- return nil
+ return Value{}
}
- newval := MakeZero(t.Elem())
- if !mapaccess(m, (*byte)(key.getAddr()), (*byte)(newval.getAddr())) {
- return nil
+ newval := Zero(t.Elem())
+ if !mapaccess(m, (*byte)(key.internal().getAddr()), (*byte)(newval.internal().getAddr())) {
+ return Value{}
}
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)
+func (v *mapValue) SetElem(key, val Value) {
+ t := v.Type()
typesMustMatch(t.Key(), key.Type())
var vaddr *byte
- if val != nil {
+ if val.IsValid() {
typesMustMatch(t.Elem(), val.Type())
- vaddr = (*byte)(val.getAddr())
+ vaddr = (*byte)(val.internal().getAddr())
}
m := *(**byte)(v.addr)
- mapassign(m, (*byte)(key.getAddr()), vaddr)
+ mapassign(m, (*byte)(key.internal().getAddr()), vaddr)
}
// Len returns the number of keys in the map v.
-func (v *MapValue) Len() int {
+func (v *mapValue) Len() int {
m := *(**byte)(v.addr)
if m == nil {
return 0
@@ -1092,8 +1603,8 @@
// 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()
+func (v *mapValue) Keys() []Value {
+ tk := v.Type().Key()
m := *(**byte)(v.addr)
mlen := int32(0)
if m != nil {
@@ -1103,8 +1614,8 @@
a := make([]Value, mlen)
var i int
for i = 0; i < len(a); i++ {
- k := MakeZero(tk)
- if !mapiterkey(it, (*byte)(k.getAddr())) {
+ k := Zero(tk)
+ if !mapiterkey(it, (*byte)(k.internal().getAddr())) {
break
}
a[i] = k
@@ -1114,9 +1625,13 @@
}
// 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)))
+func MakeMap(typ Type) Value {
+ if typ.Kind() != Map {
+ panic("reflect: MakeMap of non-map type")
+ }
+ v := Zero(typ)
+ m := v.panicIfNot(Map).(*mapValue)
+ *(**byte)(m.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ.(*commonType))))
return v
}
@@ -1124,21 +1639,21 @@
* ptr
*/
-// A PtrValue represents a pointer.
-type PtrValue struct {
+// A ptrValue represents a pointer.
+type ptrValue struct {
value "ptr"
}
// IsNil returns whether v is a nil pointer.
-func (v *PtrValue) IsNil() bool { return *(*uintptr)(v.addr) == 0 }
+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) }
+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, and x.Elem().CanSet() must be true.
-func (v *PtrValue) Set(x *PtrValue) {
+func (v *ptrValue) Set(x *ptrValue) {
if x == nil {
*(**uintptr)(v.addr) = nil
return
@@ -1156,25 +1671,21 @@
}
// Set sets v to the value x.
-func (v *PtrValue) SetValue(x Value) {
- if x == nil {
- v.Set(nil)
- return
- }
- v.Set(x.(*PtrValue))
+func (v *ptrValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Ptr).(*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 {
+func (v *ptrValue) PointTo(x Value) {
+ if !x.IsValid() {
*(**uintptr)(v.addr) = nil
return
}
if !x.CanSet() {
panic("cannot set x; cannot point to x")
}
- typesMustMatch(v.typ.(*PtrType).Elem(), x.Type())
+ typesMustMatch(v.typ.Elem(), x.Type())
// TODO: This will have to move into the runtime
// once the new gc goes in.
*(*uintptr)(v.addr) = x.UnsafeAddr()
@@ -1182,39 +1693,39 @@
// Elem returns the value that v points to.
// If v is a nil pointer, Elem returns a nil Value.
-func (v *PtrValue) Elem() Value {
+func (v *ptrValue) Elem() Value {
if v.IsNil() {
- return nil
+ return Value{}
}
flag := canAddr
if v.flag&canStore != 0 {
flag |= canSet | canStore
}
- return newValue(v.typ.(*PtrType).Elem(), *(*addr)(v.addr), flag)
+ return newValue(v.typ.Elem(), *(*addr)(v.addr), flag)
}
// Indirect returns the value that v points to.
// If v is a nil pointer, Indirect returns a nil 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.panicIfNot(Ptr).(*ptrValue).Elem()
}
/*
* struct
*/
-// A StructValue represents a struct value.
-type StructValue struct {
+// A structValue represents a struct value.
+type structValue struct {
value "struct"
}
// Set assigns x to v.
// The new value x must have the same type as v.
-func (v *StructValue) Set(x *StructValue) {
+func (v *structValue) Set(x *structValue) {
// TODO: This will have to move into the runtime
// once the gc goes in.
if !v.CanSet() {
@@ -1225,13 +1736,15 @@
}
// Set sets v to the value x.
-func (v *StructValue) SetValue(x Value) { v.Set(x.(*StructValue)) }
+func (v *structValue) SetValue(x Value) {
+ v.Set(x.panicIfNot(Struct).(*structValue))
+}
// Field returns the i'th field of the struct.
-func (v *StructValue) Field(i int) Value {
- t := v.typ.(*StructType)
+func (v *structValue) Field(i int) Value {
+ t := v.typ
if i < 0 || i >= t.NumField() {
- return nil
+ panic("reflect: Field index out of range")
}
f := t.Field(i)
flag := v.flag
@@ -1243,102 +1756,102 @@
}
// FieldByIndex returns the nested field corresponding to index.
-func (t *StructValue) FieldByIndex(index []int) (v Value) {
- v = t
+func (t *structValue) FieldByIndex(index []int) (v Value) {
+ v = Value{t}
for i, x := range index {
if i > 0 {
- if p, ok := v.(*PtrValue); ok {
- v = p.Elem()
+ if v.Kind() == Ptr {
+ v = v.Elem()
}
- if s, ok := v.(*StructValue); ok {
- t = s
- } else {
- v = nil
- return
+ if v.Kind() != Struct {
+ return Value{}
}
}
- v = t.Field(x)
+ v = v.Field(x)
}
return
}
// 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 {
+func (t *structValue) FieldByName(name string) Value {
+ if f, ok := t.Type().FieldByName(name); ok {
return t.FieldByIndex(f.Index)
}
- return nil
+ return Value{}
}
// 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 {
+func (t *structValue) FieldByNameFunc(match func(string) bool) Value {
+ if f, ok := t.Type().FieldByNameFunc(match); ok {
return t.FieldByIndex(f.Index)
}
- return nil
+ return Value{}
}
// NumField returns the number of fields in the struct.
-func (v *StructValue) NumField() int { return v.typ.(*StructType).NumField() }
+func (v *structValue) NumField() int { return v.typ.NumField() }
/*
* constructors
*/
// NewValue returns a new Value initialized to the concrete value
-// stored in the interface i. NewValue(nil) returns nil.
+// stored in the interface i. NewValue(nil) returns the zero Value.
func NewValue(i interface{}) Value {
if i == nil {
- return nil
+ return Value{}
}
- t, a := unsafe.Reflect(i)
- return newValue(toType(t), addr(a), canSet|canAddr|canStore)
+ _, a := unsafe.Reflect(i)
+ return newValue(Typeof(i), addr(a), canSet|canAddr|canStore)
}
func newValue(typ Type, addr addr, flag uint32) Value {
v := value{typ, addr, flag}
- 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}
+ switch typ.Kind() {
+ case Array:
+ return Value{&arrayValue{v}}
+ case Bool:
+ return Value{&boolValue{v}}
+ case Chan:
+ return Value{&chanValue{v}}
+ case Float32, Float64:
+ return Value{&floatValue{v}}
+ case Func:
+ return Value{&funcValue{value: v}}
+ case Complex64, Complex128:
+ return Value{&complexValue{v}}
+ case Int, Int8, Int16, Int32, Int64:
+ return Value{&intValue{v}}
+ case Interface:
+ return Value{&interfaceValue{v}}
+ case Map:
+ return Value{&mapValue{v}}
+ case Ptr:
+ return Value{&ptrValue{v}}
+ case Slice:
+ return Value{&sliceValue{v}}
+ case String:
+ return Value{&stringValue{v}}
+ case Struct:
+ return Value{&structValue{v}}
+ case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+ return Value{&uintValue{v}}
+ case UnsafePointer:
+ return Value{&unsafePointerValue{v}}
}
panic("newValue" + typ.String())
}
-// MakeZero returns a zero Value for the specified Type.
-func MakeZero(typ Type) Value {
+// Zero returns a Value representing a 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.
+func Zero(typ Type) Value {
if typ == nil {
- return nil
+ panic("reflect: Zero(nil)")
}
return newValue(typ, addr(unsafe.New(typ)), canSet|canAddr|canStore)
}