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
This commit is contained in:
Russ Cox 2011-04-08 12:26:51 -04:00
parent 846a368b88
commit fb175cf77e
5 changed files with 1437 additions and 888 deletions

View file

@ -207,58 +207,46 @@ func testType(t *testing.T, i int, typ Type, want string) {
func TestTypes(t *testing.T) {
for i, tt := range typeTests {
testType(t, i, NewValue(tt.i).(*StructValue).Field(0).Type(), tt.s)
testType(t, i, NewValue(tt.i).Field(0).Type(), tt.s)
}
}
func TestSet(t *testing.T) {
for i, tt := range valueTests {
v := NewValue(tt.i)
switch v := v.(type) {
case *IntValue:
switch v.Type().Kind() {
case Int:
v.Set(132)
case Int8:
v.Set(8)
case Int16:
v.Set(16)
case Int32:
v.Set(32)
case Int64:
v.Set(64)
}
case *UintValue:
switch v.Type().Kind() {
case Uint:
v.Set(132)
case Uint8:
v.Set(8)
case Uint16:
v.Set(16)
case Uint32:
v.Set(32)
case Uint64:
v.Set(64)
}
case *FloatValue:
switch v.Type().Kind() {
case Float32:
v.Set(256.25)
case Float64:
v.Set(512.125)
}
case *ComplexValue:
switch v.Type().Kind() {
case Complex64:
v.Set(532.125 + 10i)
case Complex128:
v.Set(564.25 + 1i)
}
case *StringValue:
v.Set("stringy cheese")
case *BoolValue:
v.Set(true)
switch v.Kind() {
case Int:
v.SetInt(132)
case Int8:
v.SetInt(8)
case Int16:
v.SetInt(16)
case Int32:
v.SetInt(32)
case Int64:
v.SetInt(64)
case Uint:
v.SetUint(132)
case Uint8:
v.SetUint(8)
case Uint16:
v.SetUint(16)
case Uint32:
v.SetUint(32)
case Uint64:
v.SetUint(64)
case Float32:
v.SetFloat(256.25)
case Float64:
v.SetFloat(512.125)
case Complex64:
v.SetComplex(532.125 + 10i)
case Complex128:
v.SetComplex(564.25 + 1i)
case String:
v.SetString("stringy cheese")
case Bool:
v.SetBool(true)
}
s := valueToString(v)
if s != tt.s {
@ -270,52 +258,39 @@ func TestSet(t *testing.T) {
func TestSetValue(t *testing.T) {
for i, tt := range valueTests {
v := NewValue(tt.i)
switch v := v.(type) {
case *IntValue:
switch v.Type().Kind() {
case Int:
v.SetValue(NewValue(int(132)))
case Int8:
v.SetValue(NewValue(int8(8)))
case Int16:
v.SetValue(NewValue(int16(16)))
case Int32:
v.SetValue(NewValue(int32(32)))
case Int64:
v.SetValue(NewValue(int64(64)))
}
case *UintValue:
switch v.Type().Kind() {
case Uint:
v.SetValue(NewValue(uint(132)))
case Uint8:
v.SetValue(NewValue(uint8(8)))
case Uint16:
v.SetValue(NewValue(uint16(16)))
case Uint32:
v.SetValue(NewValue(uint32(32)))
case Uint64:
v.SetValue(NewValue(uint64(64)))
}
case *FloatValue:
switch v.Type().Kind() {
case Float32:
v.SetValue(NewValue(float32(256.25)))
case Float64:
v.SetValue(NewValue(512.125))
}
case *ComplexValue:
switch v.Type().Kind() {
case Complex64:
v.SetValue(NewValue(complex64(532.125 + 10i)))
case Complex128:
v.SetValue(NewValue(complex128(564.25 + 1i)))
}
case *StringValue:
v.SetValue(NewValue("stringy cheese"))
case *BoolValue:
v.SetValue(NewValue(true))
switch v.Kind() {
case Int:
v.Set(NewValue(int(132)))
case Int8:
v.Set(NewValue(int8(8)))
case Int16:
v.Set(NewValue(int16(16)))
case Int32:
v.Set(NewValue(int32(32)))
case Int64:
v.Set(NewValue(int64(64)))
case Uint:
v.Set(NewValue(uint(132)))
case Uint8:
v.Set(NewValue(uint8(8)))
case Uint16:
v.Set(NewValue(uint16(16)))
case Uint32:
v.Set(NewValue(uint32(32)))
case Uint64:
v.Set(NewValue(uint64(64)))
case Float32:
v.Set(NewValue(float32(256.25)))
case Float64:
v.Set(NewValue(512.125))
case Complex64:
v.Set(NewValue(complex64(532.125 + 10i)))
case Complex128:
v.Set(NewValue(complex128(564.25 + 1i)))
case String:
v.Set(NewValue("stringy cheese"))
case Bool:
v.Set(NewValue(true))
}
s := valueToString(v)
if s != tt.s {
@ -350,7 +325,7 @@ func TestValueToString(t *testing.T) {
func TestArrayElemSet(t *testing.T) {
v := NewValue([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
v.(*ArrayValue).Elem(4).(*IntValue).Set(123)
v.Index(4).SetInt(123)
s := valueToString(v)
const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
if s != want {
@ -358,7 +333,7 @@ func TestArrayElemSet(t *testing.T) {
}
v = NewValue([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
v.(*SliceValue).Elem(4).(*IntValue).Set(123)
v.Index(4).SetInt(123)
s = valueToString(v)
const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
if s != want1 {
@ -371,14 +346,14 @@ func TestPtrPointTo(t *testing.T) {
var i int32 = 1234
vip := NewValue(&ip)
vi := NewValue(i)
vip.(*PtrValue).Elem().(*PtrValue).PointTo(vi)
vip.Elem().Set(vi.Addr())
if *ip != 1234 {
t.Errorf("got %d, want 1234", *ip)
}
ip = nil
vp := NewValue(ip).(*PtrValue)
vp.PointTo(vp.Elem())
vp := NewValue(ip)
vp.Set(Zero(vp.Type()))
if ip != nil {
t.Errorf("got non-nil (%p), want nil", ip)
}
@ -388,7 +363,7 @@ func TestPtrSetNil(t *testing.T) {
var i int32 = 1234
ip := &i
vip := NewValue(&ip)
vip.(*PtrValue).Elem().(*PtrValue).Set(nil)
vip.Elem().Set(Zero(vip.Elem().Type()))
if ip != nil {
t.Errorf("got non-nil (%d), want nil", *ip)
}
@ -397,7 +372,7 @@ func TestPtrSetNil(t *testing.T) {
func TestMapSetNil(t *testing.T) {
m := make(map[string]int)
vm := NewValue(&m)
vm.(*PtrValue).Elem().(*MapValue).Set(nil)
vm.Elem().Set(Zero(vm.Elem().Type()))
if m != nil {
t.Errorf("got non-nil (%p), want nil", m)
}
@ -406,16 +381,16 @@ func TestMapSetNil(t *testing.T) {
func TestAll(t *testing.T) {
testType(t, 1, Typeof((int8)(0)), "int8")
testType(t, 2, Typeof((*int8)(nil)).(*PtrType).Elem(), "int8")
testType(t, 2, Typeof((*int8)(nil)).Elem(), "int8")
typ := Typeof((*struct {
c chan *int32
d float32
})(nil))
testType(t, 3, typ, "*struct { c chan *int32; d float32 }")
etyp := typ.(*PtrType).Elem()
etyp := typ.Elem()
testType(t, 4, etyp, "struct { c chan *int32; d float32 }")
styp := etyp.(*StructType)
styp := etyp
f := styp.Field(0)
testType(t, 5, f.Type, "chan *int32")
@ -432,22 +407,22 @@ func TestAll(t *testing.T) {
typ = Typeof([32]int32{})
testType(t, 7, typ, "[32]int32")
testType(t, 8, typ.(*ArrayType).Elem(), "int32")
testType(t, 8, typ.Elem(), "int32")
typ = Typeof((map[string]*int32)(nil))
testType(t, 9, typ, "map[string] *int32")
mtyp := typ.(*MapType)
mtyp := typ
testType(t, 10, mtyp.Key(), "string")
testType(t, 11, mtyp.Elem(), "*int32")
typ = Typeof((chan<- string)(nil))
testType(t, 12, typ, "chan<- string")
testType(t, 13, typ.(*ChanType).Elem(), "string")
testType(t, 13, typ.Elem(), "string")
// make sure tag strings are not part of element type
typ = Typeof(struct {
d []uint32 "TAG"
}{}).(*StructType).Field(0).Type
}{}).Field(0).Type
testType(t, 14, typ, "[]uint32")
}
@ -457,9 +432,9 @@ func TestInterfaceGet(t *testing.T) {
}
inter.e = 123.456
v1 := NewValue(&inter)
v2 := v1.(*PtrValue).Elem().(*StructValue).Field(0)
v2 := v1.Elem().Field(0)
assert(t, v2.Type().String(), "interface { }")
i2 := v2.(*InterfaceValue).Interface()
i2 := v2.Interface()
v3 := NewValue(i2)
assert(t, v3.Type().String(), "float64")
}
@ -470,9 +445,9 @@ func TestInterfaceValue(t *testing.T) {
}
inter.e = 123.456
v1 := NewValue(&inter)
v2 := v1.(*PtrValue).Elem().(*StructValue).Field(0)
v2 := v1.Elem().Field(0)
assert(t, v2.Type().String(), "interface { }")
v3 := v2.(*InterfaceValue).Elem()
v3 := v2.Elem()
assert(t, v3.Type().String(), "float64")
i3 := v2.Interface()
@ -506,9 +481,9 @@ func TestAppend(t *testing.T) {
e0[j] = NewValue(e)
}
// Convert extra from []int to *SliceValue.
e1 := NewValue(test.extra).(*SliceValue)
e1 := NewValue(test.extra)
// Test Append.
a0 := NewValue(test.orig).(*SliceValue)
a0 := NewValue(test.orig)
have0 := Append(a0, e0...).Interface().([]int)
if !DeepEqual(have0, want) {
t.Errorf("Append #%d: have %v, want %v", i, have0, want)
@ -521,7 +496,7 @@ func TestAppend(t *testing.T) {
t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
}
// Test AppendSlice.
a1 := NewValue(test.orig).(*SliceValue)
a1 := NewValue(test.orig)
have1 := AppendSlice(a1, e1).Interface().([]int)
if !DeepEqual(have1, want) {
t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
@ -545,8 +520,8 @@ func TestCopy(t *testing.T) {
t.Fatalf("b != c before test")
}
}
aa := NewValue(a).(*SliceValue)
ab := NewValue(b).(*SliceValue)
aa := NewValue(a)
ab := NewValue(b)
for tocopy := 1; tocopy <= 7; tocopy++ {
aa.SetLen(tocopy)
Copy(ab, aa)
@ -660,7 +635,7 @@ func TestDeepEqual(t *testing.T) {
func TestTypeof(t *testing.T) {
for _, test := range deepEqualTests {
v := NewValue(test.a)
if v == nil {
if !v.IsValid() {
continue
}
typ := Typeof(test.a)
@ -715,8 +690,8 @@ func TestDeepEqualComplexStructInequality(t *testing.T) {
func check2ndField(x interface{}, offs uintptr, t *testing.T) {
s := NewValue(x).(*StructValue)
f := s.Type().(*StructType).Field(1)
s := NewValue(x)
f := s.Type().Field(1)
if f.Offset != offs {
t.Error("mismatched offsets in structure alignment:", f.Offset, offs)
}
@ -747,36 +722,22 @@ func TestAlignment(t *testing.T) {
check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t)
}
type IsNiller interface {
IsNil() bool
}
func Nil(a interface{}, t *testing.T) {
n := NewValue(a).(*StructValue).Field(0).(IsNiller)
n := NewValue(a).Field(0)
if !n.IsNil() {
t.Errorf("%v should be nil", a)
}
}
func NotNil(a interface{}, t *testing.T) {
n := NewValue(a).(*StructValue).Field(0).(IsNiller)
n := NewValue(a).Field(0)
if n.IsNil() {
t.Errorf("value of type %v should not be nil", NewValue(a).Type().String())
}
}
func TestIsNil(t *testing.T) {
// These do not implement IsNil
doNotNil := []interface{}{int(0), float32(0), struct{ a int }{}}
for _, ts := range doNotNil {
ty := Typeof(ts)
v := MakeZero(ty)
if _, ok := v.(IsNiller); ok {
t.Errorf("%s is nilable; should not be", ts)
}
}
// These do implement IsNil.
// These implement IsNil.
// Wrap in extra struct to hide interface type.
doNil := []interface{}{
struct{ x *int }{},
@ -787,11 +748,9 @@ func TestIsNil(t *testing.T) {
struct{ x []string }{},
}
for _, ts := range doNil {
ty := Typeof(ts).(*StructType).Field(0).Type
v := MakeZero(ty)
if _, ok := v.(IsNiller); !ok {
t.Errorf("%s %T is not nilable; should be", ts, v)
}
ty := Typeof(ts).Field(0).Type
v := Zero(ty)
v.IsNil() // panics if not okay to call
}
// Check the implementations
@ -844,7 +803,7 @@ func TestInterfaceExtraction(t *testing.T) {
}
s.w = os.Stdout
v := Indirect(NewValue(&s)).(*StructValue).Field(0).Interface()
v := Indirect(NewValue(&s)).Field(0).Interface()
if v != s.w.(interface{}) {
t.Error("Interface() on interface: ", v, s.w)
}
@ -864,7 +823,7 @@ func TestInterfaceEditing(t *testing.T) {
// and setting that copy to "bye" should
// not change the value stored in i.
v.(*StringValue).Set("bye")
v.SetString("bye")
if i.(string) != "hello" {
t.Errorf(`Set("bye") changed i to %s`, i.(string))
}
@ -872,7 +831,7 @@ func TestInterfaceEditing(t *testing.T) {
// the same should be true of smaller items.
i = 123
v = NewValue(i)
v.(*IntValue).Set(234)
v.SetInt(234)
if i.(int) != 123 {
t.Errorf("Set(234) changed i to %d", i.(int))
}
@ -880,20 +839,20 @@ func TestInterfaceEditing(t *testing.T) {
func TestNilPtrValueSub(t *testing.T) {
var pi *int
if pv := NewValue(pi).(*PtrValue); pv.Elem() != nil {
t.Error("NewValue((*int)(nil)).(*PtrValue).Elem() != nil")
if pv := NewValue(pi); pv.Elem().IsValid() {
t.Error("NewValue((*int)(nil)).Elem().IsValid()")
}
}
func TestMap(t *testing.T) {
m := map[string]int{"a": 1, "b": 2}
mv := NewValue(m).(*MapValue)
mv := NewValue(m)
if n := mv.Len(); n != len(m) {
t.Errorf("Len = %d, want %d", n, len(m))
}
keys := mv.Keys()
keys := mv.MapKeys()
i := 0
newmap := MakeMap(mv.Type().(*MapType))
newmap := MakeMap(mv.Type())
for k, v := range m {
// Check that returned Keys match keys in range.
// These aren't required to be in the same order,
@ -901,22 +860,22 @@ func TestMap(t *testing.T) {
// the test easier.
if i >= len(keys) {
t.Errorf("Missing key #%d %q", i, k)
} else if kv := keys[i].(*StringValue); kv.Get() != k {
t.Errorf("Keys[%d] = %q, want %q", i, kv.Get(), k)
} else if kv := keys[i]; kv.String() != k {
t.Errorf("Keys[%q] = %d, want %d", i, kv.Int(), k)
}
i++
// Check that value lookup is correct.
vv := mv.Elem(NewValue(k))
if vi := vv.(*IntValue).Get(); vi != int64(v) {
vv := mv.MapIndex(NewValue(k))
if vi := vv.Int(); vi != int64(v) {
t.Errorf("Key %q: have value %d, want %d", k, vi, v)
}
// Copy into new map.
newmap.SetElem(NewValue(k), NewValue(v))
newmap.SetMapIndex(NewValue(k), NewValue(v))
}
vv := mv.Elem(NewValue("not-present"))
if vv != nil {
vv := mv.MapIndex(NewValue("not-present"))
if vv.IsValid() {
t.Errorf("Invalid key: got non-nil value %s", valueToString(vv))
}
@ -932,14 +891,14 @@ func TestMap(t *testing.T) {
}
}
newmap.SetElem(NewValue("a"), nil)
newmap.SetMapIndex(NewValue("a"), Value{})
v, ok := newm["a"]
if ok {
t.Errorf("newm[\"a\"] = %d after delete", v)
}
mv = NewValue(&m).(*PtrValue).Elem().(*MapValue)
mv.Set(nil)
mv = NewValue(&m).Elem()
mv.Set(Zero(mv.Type()))
if m != nil {
t.Errorf("mv.Set(nil) failed")
}
@ -948,15 +907,15 @@ func TestMap(t *testing.T) {
func TestChan(t *testing.T) {
for loop := 0; loop < 2; loop++ {
var c chan int
var cv *ChanValue
var cv Value
// check both ways to allocate channels
switch loop {
case 1:
c = make(chan int, 1)
cv = NewValue(c).(*ChanValue)
cv = NewValue(c)
case 0:
cv = MakeChan(Typeof(c).(*ChanType), 1)
cv = MakeChan(Typeof(c), 1)
c = cv.Interface().(chan int)
}
@ -968,22 +927,22 @@ func TestChan(t *testing.T) {
// Recv
c <- 3
if i, ok := cv.Recv(); i.(*IntValue).Get() != 3 || !ok {
t.Errorf("native send 3, reflect Recv %d, %t", i.(*IntValue).Get(), ok)
if i, ok := cv.Recv(); i.Int() != 3 || !ok {
t.Errorf("native send 3, reflect Recv %d, %t", i.Int(), ok)
}
// TryRecv fail
val, ok := cv.TryRecv()
if val != nil || ok {
if val.IsValid() || ok {
t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok)
}
// TryRecv success
c <- 4
val, ok = cv.TryRecv()
if val == nil {
if !val.IsValid() {
t.Errorf("TryRecv on ready chan got nil")
} else if i := val.(*IntValue).Get(); i != 4 || !ok {
} else if i := val.Int(); i != 4 || !ok {
t.Errorf("native send 4, TryRecv %d, %t", i, ok)
}
@ -1008,27 +967,27 @@ func TestChan(t *testing.T) {
// Close
c <- 123
cv.Close()
if i, ok := cv.Recv(); i.(*IntValue).Get() != 123 || !ok {
t.Errorf("send 123 then close; Recv %d, %t", i.(*IntValue).Get(), ok)
if i, ok := cv.Recv(); i.Int() != 123 || !ok {
t.Errorf("send 123 then close; Recv %d, %t", i.Int(), ok)
}
if i, ok := cv.Recv(); i.(*IntValue).Get() != 0 || ok {
t.Errorf("after close Recv %d, %t", i.(*IntValue).Get(), ok)
if i, ok := cv.Recv(); i.Int() != 0 || ok {
t.Errorf("after close Recv %d, %t", i.Int(), ok)
}
}
// check creation of unbuffered channel
var c chan int
cv := MakeChan(Typeof(c).(*ChanType), 0)
cv := MakeChan(Typeof(c), 0)
c = cv.Interface().(chan int)
if cv.TrySend(NewValue(7)) {
t.Errorf("TrySend on sync chan succeeded")
}
if v, ok := cv.TryRecv(); v != nil || ok {
if v, ok := cv.TryRecv(); v.IsValid() || ok {
t.Errorf("TryRecv on sync chan succeeded")
}
// len/cap
cv = MakeChan(Typeof(c).(*ChanType), 10)
cv = MakeChan(Typeof(c), 10)
c = cv.Interface().(chan int)
for i := 0; i < 3; i++ {
c <- i
@ -1046,14 +1005,14 @@ func dummy(b byte, c int, d byte) (i byte, j int, k byte) {
}
func TestFunc(t *testing.T) {
ret := NewValue(dummy).(*FuncValue).Call([]Value{NewValue(byte(10)), NewValue(20), NewValue(byte(30))})
ret := NewValue(dummy).Call([]Value{NewValue(byte(10)), NewValue(20), NewValue(byte(30))})
if len(ret) != 3 {
t.Fatalf("Call returned %d values, want 3", len(ret))
}
i := ret[0].(*UintValue).Get()
j := ret[1].(*IntValue).Get()
k := ret[2].(*UintValue).Get()
i := byte(ret[0].Uint())
j := int(ret[1].Int())
k := byte(ret[2].Uint())
if i != 10 || j != 20 || k != 30 {
t.Errorf("Call returned %d, %d, %d; want 10, 20, 30", i, j, k)
}
@ -1068,30 +1027,30 @@ func (p Point) Dist(scale int) int { return p.x*p.x*scale + p.y*p.y*scale }
func TestMethod(t *testing.T) {
// Non-curried method of type.
p := Point{3, 4}
i := Typeof(p).Method(0).Func.Call([]Value{NewValue(p), NewValue(10)})[0].(*IntValue).Get()
i := Typeof(p).Method(0).Func.Call([]Value{NewValue(p), NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Type Method returned %d; want 250", i)
}
i = Typeof(&p).Method(0).Func.Call([]Value{NewValue(&p), NewValue(10)})[0].(*IntValue).Get()
i = Typeof(&p).Method(0).Func.Call([]Value{NewValue(&p), NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Pointer Type Method returned %d; want 250", i)
}
// Curried method of value.
i = NewValue(p).Method(0).Call([]Value{NewValue(10)})[0].(*IntValue).Get()
i = NewValue(p).Method(0).Call([]Value{NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Value Method returned %d; want 250", i)
}
// Curried method of pointer.
i = NewValue(&p).Method(0).Call([]Value{NewValue(10)})[0].(*IntValue).Get()
i = NewValue(&p).Method(0).Call([]Value{NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Value Method returned %d; want 250", i)
}
// Curried method of pointer to value.
i = NewValue(p).Addr().Method(0).Call([]Value{NewValue(10)})[0].(*IntValue).Get()
i = NewValue(p).Addr().Method(0).Call([]Value{NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Value Method returned %d; want 250", i)
}
@ -1105,8 +1064,8 @@ func TestMethod(t *testing.T) {
Dist(int) int
}
}{p}
pv := NewValue(s).(*StructValue).Field(0)
i = pv.Method(0).Call([]Value{NewValue(10)})[0].(*IntValue).Get()
pv := NewValue(s).Field(0)
i = pv.Method(0).Call([]Value{NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Interface Method returned %d; want 250", i)
}
@ -1121,19 +1080,19 @@ func TestInterfaceSet(t *testing.T) {
Dist(int) int
}
}
sv := NewValue(&s).(*PtrValue).Elem().(*StructValue)
sv.Field(0).(*InterfaceValue).Set(NewValue(p))
sv := NewValue(&s).Elem()
sv.Field(0).Set(NewValue(p))
if q := s.I.(*Point); q != p {
t.Errorf("i: have %p want %p", q, p)
}
pv := sv.Field(1).(*InterfaceValue)
pv := sv.Field(1)
pv.Set(NewValue(p))
if q := s.P.(*Point); q != p {
t.Errorf("i: have %p want %p", q, p)
}
i := pv.Method(0).Call([]Value{NewValue(10)})[0].(*IntValue).Get()
i := pv.Method(0).Call([]Value{NewValue(10)})[0].Int()
if i != 250 {
t.Errorf("Interface Method returned %d; want 250", i)
}
@ -1148,7 +1107,7 @@ func TestAnonymousFields(t *testing.T) {
var field StructField
var ok bool
var t1 T1
type1 := Typeof(t1).(*StructType)
type1 := Typeof(t1)
if field, ok = type1.FieldByName("int"); !ok {
t.Error("no field 'int'")
}
@ -1232,7 +1191,7 @@ var fieldTests = []FTest{
func TestFieldByIndex(t *testing.T) {
for _, test := range fieldTests {
s := Typeof(test.s).(*StructType)
s := Typeof(test.s)
f := s.FieldByIndex(test.index)
if f.Name != "" {
if test.index != nil {
@ -1247,8 +1206,8 @@ func TestFieldByIndex(t *testing.T) {
}
if test.value != 0 {
v := NewValue(test.s).(*StructValue).FieldByIndex(test.index)
if v != nil {
v := NewValue(test.s).FieldByIndex(test.index)
if v.IsValid() {
if x, ok := v.Interface().(int); ok {
if x != test.value {
t.Errorf("%s%v is %d; want %d", s.Name(), test.index, x, test.value)
@ -1265,7 +1224,7 @@ func TestFieldByIndex(t *testing.T) {
func TestFieldByName(t *testing.T) {
for _, test := range fieldTests {
s := Typeof(test.s).(*StructType)
s := Typeof(test.s)
f, found := s.FieldByName(test.name)
if found {
if test.index != nil {
@ -1287,8 +1246,8 @@ func TestFieldByName(t *testing.T) {
}
if test.value != 0 {
v := NewValue(test.s).(*StructValue).FieldByName(test.name)
if v != nil {
v := NewValue(test.s).FieldByName(test.name)
if v.IsValid() {
if x, ok := v.Interface().(int); ok {
if x != test.value {
t.Errorf("%s.%s is %d; want %d", s.Name(), test.name, x, test.value)
@ -1312,10 +1271,10 @@ func TestImportPath(t *testing.T) {
func TestDotDotDot(t *testing.T) {
// Test example from FuncType.DotDotDot documentation.
var f func(x int, y ...float64)
typ := Typeof(f).(*FuncType)
typ := Typeof(f)
if typ.NumIn() == 2 && typ.In(0) == Typeof(int(0)) {
sl, ok := typ.In(1).(*SliceType)
if ok {
sl := typ.In(1)
if sl.Kind() == Slice {
if sl.Elem() == Typeof(0.0) {
// ok
return
@ -1346,11 +1305,11 @@ func (*outer) m() {}
func TestNestedMethods(t *testing.T) {
typ := Typeof((*outer)(nil))
if typ.NumMethod() != 1 || typ.Method(0).Func.Get() != NewValue((*outer).m).(*FuncValue).Get() {
if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != NewValue((*outer).m).Pointer() {
t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
for i := 0; i < typ.NumMethod(); i++ {
m := typ.Method(i)
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Get())
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
}
}
}
@ -1370,21 +1329,21 @@ func (i *innerInt) m() int {
func TestEmbeddedMethods(t *testing.T) {
typ := Typeof((*outerInt)(nil))
if typ.NumMethod() != 1 || typ.Method(0).Func.Get() != NewValue((*outerInt).m).(*FuncValue).Get() {
if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != NewValue((*outerInt).m).Pointer() {
t.Errorf("Wrong method table for outerInt: (m=%p)", (*outerInt).m)
for i := 0; i < typ.NumMethod(); i++ {
m := typ.Method(i)
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Get())
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
}
}
i := &innerInt{3}
if v := NewValue(i).Method(0).Call(nil)[0].(*IntValue).Get(); v != 3 {
if v := NewValue(i).Method(0).Call(nil)[0].Int(); v != 3 {
t.Errorf("i.m() = %d, want 3", v)
}
o := &outerInt{1, innerInt{2}}
if v := NewValue(o).Method(0).Call(nil)[0].(*IntValue).Get(); v != 2 {
if v := NewValue(o).Method(0).Call(nil)[0].Int(); v != 2 {
t.Errorf("i.m() = %d, want 2", v)
}
@ -1402,7 +1361,7 @@ func TestPtrTo(t *testing.T) {
typ = PtrTo(typ)
}
for i = 0; i < 100; i++ {
typ = typ.(*PtrType).Elem()
typ = typ.Elem()
}
if typ != Typeof(i) {
t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, Typeof(i))
@ -1415,11 +1374,11 @@ func TestAddr(t *testing.T) {
}
v := NewValue(&p)
v = v.(*PtrValue).Elem()
v = v.Elem()
v = v.Addr()
v = v.(*PtrValue).Elem()
v = v.(*StructValue).Field(0)
v.(*IntValue).Set(2)
v = v.Elem()
v = v.Field(0)
v.SetInt(2)
if p.X != 2 {
t.Errorf("Addr.Elem.Set failed to set value")
}
@ -1428,12 +1387,12 @@ func TestAddr(t *testing.T) {
// Exercises generation of PtrTypes not present in the binary.
v = NewValue(&p)
v = v.Addr()
v = v.(*PtrValue).Elem()
v = v.(*PtrValue).Elem()
v = v.Elem()
v = v.Elem()
v = v.Addr()
v = v.(*PtrValue).Elem()
v = v.(*StructValue).Field(0)
v.(*IntValue).Set(3)
v = v.Elem()
v = v.Field(0)
v.SetInt(3)
if p.X != 3 {
t.Errorf("Addr.Elem.Set failed to set value")
}
@ -1443,9 +1402,9 @@ func TestAddr(t *testing.T) {
v = NewValue(p)
v0 := v
v = v.Addr()
v = v.(*PtrValue).Elem()
v = v.(*StructValue).Field(0)
v.(*IntValue).Set(4)
v = v.Elem()
v = v.Field(0)
v.SetInt(4)
if p.X != 3 { // should be unchanged from last time
t.Errorf("somehow value Set changed original p")
}