summaryrefslogtreecommitdiff
path: root/src/pkg/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/reflect')
-rw-r--r--src/pkg/reflect/Makefile2
-rw-r--r--src/pkg/reflect/all_test.go375
-rw-r--r--src/pkg/reflect/type.go2
-rw-r--r--src/pkg/reflect/value.go95
4 files changed, 323 insertions, 151 deletions
diff --git a/src/pkg/reflect/Makefile b/src/pkg/reflect/Makefile
index b72d3873f..b946449a3 100644
--- a/src/pkg/reflect/Makefile
+++ b/src/pkg/reflect/Makefile
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
-include ../../Make.$(GOARCH)
+include ../../Make.inc
TARG=reflect
GOFILES=\
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index e2c57dadb..7d34e5ca3 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -38,27 +38,27 @@ func assert(t *testing.T, s, want string) {
func typestring(i interface{}) string { return Typeof(i).String() }
var typeTests = []pair{
- pair{struct{ x int }{}, "int"},
- pair{struct{ x int8 }{}, "int8"},
- pair{struct{ x int16 }{}, "int16"},
- pair{struct{ x int32 }{}, "int32"},
- pair{struct{ x int64 }{}, "int64"},
- pair{struct{ x uint }{}, "uint"},
- pair{struct{ x uint8 }{}, "uint8"},
- pair{struct{ x uint16 }{}, "uint16"},
- pair{struct{ x uint32 }{}, "uint32"},
- pair{struct{ x uint64 }{}, "uint64"},
- pair{struct{ x float }{}, "float"},
- pair{struct{ x float32 }{}, "float32"},
- pair{struct{ x float64 }{}, "float64"},
- pair{struct{ x int8 }{}, "int8"},
- pair{struct{ x (**int8) }{}, "**int8"},
- pair{struct{ x (**integer) }{}, "**reflect_test.integer"},
- pair{struct{ x ([32]int32) }{}, "[32]int32"},
- pair{struct{ x ([]int8) }{}, "[]int8"},
- pair{struct{ x (map[string]int32) }{}, "map[string] int32"},
- pair{struct{ x (chan<- string) }{}, "chan<- string"},
- pair{struct {
+ {struct{ x int }{}, "int"},
+ {struct{ x int8 }{}, "int8"},
+ {struct{ x int16 }{}, "int16"},
+ {struct{ x int32 }{}, "int32"},
+ {struct{ x int64 }{}, "int64"},
+ {struct{ x uint }{}, "uint"},
+ {struct{ x uint8 }{}, "uint8"},
+ {struct{ x uint16 }{}, "uint16"},
+ {struct{ x uint32 }{}, "uint32"},
+ {struct{ x uint64 }{}, "uint64"},
+ {struct{ x float }{}, "float"},
+ {struct{ x float32 }{}, "float32"},
+ {struct{ x float64 }{}, "float64"},
+ {struct{ x int8 }{}, "int8"},
+ {struct{ x (**int8) }{}, "**int8"},
+ {struct{ x (**integer) }{}, "**reflect_test.integer"},
+ {struct{ x ([32]int32) }{}, "[32]int32"},
+ {struct{ x ([]int8) }{}, "[]int8"},
+ {struct{ x (map[string]int32) }{}, "map[string] int32"},
+ {struct{ x (chan<- string) }{}, "chan<- string"},
+ {struct {
x struct {
c chan *int32
d float32
@@ -66,15 +66,15 @@ var typeTests = []pair{
}{},
"struct { c chan *int32; d float32 }",
},
- pair{struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"},
- pair{struct {
+ {struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"},
+ {struct {
x struct {
c func(chan *integer, *int8)
}
}{},
"struct { c func(chan *reflect_test.integer, *int8) }",
},
- pair{struct {
+ {struct {
x struct {
a int8
b int32
@@ -82,7 +82,7 @@ var typeTests = []pair{
}{},
"struct { a int8; b int32 }",
},
- pair{struct {
+ {struct {
x struct {
a int8
b int8
@@ -91,7 +91,7 @@ var typeTests = []pair{
}{},
"struct { a int8; b int8; c int32 }",
},
- pair{struct {
+ {struct {
x struct {
a int8
b int8
@@ -101,7 +101,7 @@ var typeTests = []pair{
}{},
"struct { a int8; b int8; c int8; d int32 }",
},
- pair{struct {
+ {struct {
x struct {
a int8
b int8
@@ -112,7 +112,7 @@ var typeTests = []pair{
}{},
"struct { a int8; b int8; c int8; d int8; e int32 }",
},
- pair{struct {
+ {struct {
x struct {
a int8
b int8
@@ -124,28 +124,28 @@ var typeTests = []pair{
}{},
"struct { a int8; b int8; c int8; d int8; e int8; f int32 }",
},
- pair{struct {
+ {struct {
x struct {
a int8 "hi there"
}
}{},
`struct { a int8 "hi there" }`,
},
- pair{struct {
+ {struct {
x struct {
a int8 "hi \x00there\t\n\"\\"
}
}{},
`struct { a int8 "hi \x00there\t\n\"\\" }`,
},
- pair{struct {
+ {struct {
x struct {
f func(args ...int)
}
}{},
"struct { f func(...int) }",
},
- pair{struct {
+ {struct {
x (interface {
a(func(func(int) int) func(func(int)) int)
b()
@@ -156,47 +156,45 @@ var typeTests = []pair{
}
var valueTests = []pair{
- pair{(int8)(0), "8"},
- pair{(int16)(0), "16"},
- pair{(int32)(0), "32"},
- pair{(int64)(0), "64"},
- pair{(uint8)(0), "8"},
- pair{(uint16)(0), "16"},
- pair{(uint32)(0), "32"},
- pair{(uint64)(0), "64"},
- pair{(float32)(0), "256.25"},
- pair{(float64)(0), "512.125"},
- pair{(string)(""), "stringy cheese"},
- pair{(bool)(false), "true"},
- pair{(*int8)(nil), "*int8(0)"},
- pair{(**int8)(nil), "**int8(0)"},
- pair{([5]int32){}, "[5]int32{0, 0, 0, 0, 0}"},
- pair{(**integer)(nil), "**reflect_test.integer(0)"},
- pair{(map[string]int32)(nil), "map[string] int32{<can't iterate on maps>}"},
- pair{(chan<- string)(nil), "chan<- string"},
- pair{(struct {
+ {(int8)(0), "8"},
+ {(int16)(0), "16"},
+ {(int32)(0), "32"},
+ {(int64)(0), "64"},
+ {(uint8)(0), "8"},
+ {(uint16)(0), "16"},
+ {(uint32)(0), "32"},
+ {(uint64)(0), "64"},
+ {(float32)(0), "256.25"},
+ {(float64)(0), "512.125"},
+ {(string)(""), "stringy cheese"},
+ {(bool)(false), "true"},
+ {(*int8)(nil), "*int8(0)"},
+ {(**int8)(nil), "**int8(0)"},
+ {[5]int32{}, "[5]int32{0, 0, 0, 0, 0}"},
+ {(**integer)(nil), "**reflect_test.integer(0)"},
+ {(map[string]int32)(nil), "map[string] int32{<can't iterate on maps>}"},
+ {(chan<- string)(nil), "chan<- string"},
+ {struct {
c chan *int32
d float32
- }){},
+ }{},
"struct { c chan *int32; d float32 }{chan *int32, 0}",
},
- pair{(func(a int8, b int32))(nil), "func(int8, int32)(0)"},
- pair{(struct {
- c func(chan *integer, *int8)
- }){},
+ {(func(a int8, b int32))(nil), "func(int8, int32)(0)"},
+ {struct{ c func(chan *integer, *int8) }{},
"struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}",
},
- pair{(struct {
+ {struct {
a int8
b int32
- }){},
+ }{},
"struct { a int8; b int32 }{0, 0}",
},
- pair{(struct {
+ {struct {
a int8
b int8
c int32
- }){},
+ }{},
"struct { a int8; b int8; c int32 }{0, 0, 0}",
},
}
@@ -338,16 +336,16 @@ func TestSetValue(t *testing.T) {
var _i = 7
var valueToStringTests = []pair{
- pair{123, "123"},
- pair{123.5, "123.5"},
- pair{byte(123), "123"},
- pair{"abc", "abc"},
- pair{T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"},
- pair{new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"},
- pair{[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
- pair{&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
- pair{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
- pair{&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
+ {123, "123"},
+ {123.5, "123.5"},
+ {byte(123), "123"},
+ {"abc", "abc"},
+ {T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"},
+ {new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"},
+ {[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
+ {&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
+ {[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
+ {&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
}
func TestValueToString(t *testing.T) {
@@ -386,6 +384,13 @@ func TestPtrPointTo(t *testing.T) {
if *ip != 1234 {
t.Errorf("got %d, want 1234", *ip)
}
+
+ ip = nil
+ vp := NewValue(ip).(*PtrValue)
+ vp.PointTo(vp.Elem())
+ if ip != nil {
+ t.Errorf("got non-nil (%p), want nil", ip)
+ }
}
func TestPtrSetNil(t *testing.T) {
@@ -493,22 +498,67 @@ func TestFunctionValue(t *testing.T) {
assert(t, v.Type().String(), "func()")
}
-func TestCopyArray(t *testing.T) {
+var appendTests = []struct {
+ orig, extra []int
+}{
+ {make([]int, 2, 4), []int{22}},
+ {make([]int, 2, 4), []int{22, 33, 44}},
+}
+
+func TestAppend(t *testing.T) {
+ for i, test := range appendTests {
+ origLen, extraLen := len(test.orig), len(test.extra)
+ want := append(test.orig, test.extra...)
+ // Convert extra from []int to []Value.
+ e0 := make([]Value, len(test.extra))
+ for j, e := range test.extra {
+ e0[j] = NewValue(e)
+ }
+ // Convert extra from []int to *SliceValue.
+ e1 := NewValue(test.extra).(*SliceValue)
+ // Test Append.
+ a0 := NewValue(test.orig).(*SliceValue)
+ have0 := Append(a0, e0...).Interface().([]int)
+ if !DeepEqual(have0, want) {
+ t.Errorf("Append #%d: have %v, want %v", i, have0, want)
+ }
+ // Check that the orig and extra slices were not modified.
+ if len(test.orig) != origLen {
+ t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+ }
+ if len(test.extra) != extraLen {
+ t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+ }
+ // Test AppendSlice.
+ a1 := NewValue(test.orig).(*SliceValue)
+ have1 := AppendSlice(a1, e1).Interface().([]int)
+ if !DeepEqual(have1, want) {
+ t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
+ }
+ // Check that the orig and extra slices were not modified.
+ if len(test.orig) != origLen {
+ t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen)
+ }
+ if len(test.extra) != extraLen {
+ t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
+ }
+ }
+}
+
+func TestCopy(t *testing.T) {
a := []int{1, 2, 3, 4, 10, 9, 8, 7}
b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
- va := NewValue(&a)
- vb := NewValue(&b)
for i := 0; i < len(b); i++ {
if b[i] != c[i] {
t.Fatalf("b != c before test")
}
}
- aa := va.(*PtrValue).Elem().(*SliceValue)
- ab := vb.(*PtrValue).Elem().(*SliceValue)
+ aa := NewValue(a).(*SliceValue)
+ ab := NewValue(b).(*SliceValue)
for tocopy := 1; tocopy <= 7; tocopy++ {
aa.SetLen(tocopy)
- ArrayCopy(ab, aa)
+ Copy(ab, aa)
aa.SetLen(8)
for i := 0; i < tocopy; i++ {
if a[i] != b[i] {
@@ -570,42 +620,42 @@ type DeepEqualTest struct {
var deepEqualTests = []DeepEqualTest{
// Equalities
- DeepEqualTest{1, 1, true},
- DeepEqualTest{int32(1), int32(1), true},
- DeepEqualTest{0.5, 0.5, true},
- DeepEqualTest{float32(0.5), float32(0.5), true},
- DeepEqualTest{"hello", "hello", true},
- DeepEqualTest{make([]int, 10), make([]int, 10), true},
- DeepEqualTest{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
- DeepEqualTest{Basic{1, 0.5}, Basic{1, 0.5}, true},
- DeepEqualTest{os.Error(nil), os.Error(nil), true},
- DeepEqualTest{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
+ {1, 1, true},
+ {int32(1), int32(1), true},
+ {0.5, 0.5, true},
+ {float32(0.5), float32(0.5), true},
+ {"hello", "hello", true},
+ {make([]int, 10), make([]int, 10), true},
+ {&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
+ {Basic{1, 0.5}, Basic{1, 0.5}, true},
+ {os.Error(nil), os.Error(nil), true},
+ {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
// Inequalities
- DeepEqualTest{1, 2, false},
- DeepEqualTest{int32(1), int32(2), false},
- DeepEqualTest{0.5, 0.6, false},
- DeepEqualTest{float32(0.5), float32(0.6), false},
- DeepEqualTest{"hello", "hey", false},
- DeepEqualTest{make([]int, 10), make([]int, 11), false},
- DeepEqualTest{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
- DeepEqualTest{Basic{1, 0.5}, Basic{1, 0.6}, false},
- DeepEqualTest{Basic{1, 0}, Basic{2, 0}, false},
- DeepEqualTest{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
- DeepEqualTest{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
- DeepEqualTest{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
- DeepEqualTest{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
- DeepEqualTest{nil, 1, false},
- DeepEqualTest{1, nil, false},
+ {1, 2, false},
+ {int32(1), int32(2), false},
+ {0.5, 0.6, false},
+ {float32(0.5), float32(0.6), false},
+ {"hello", "hey", false},
+ {make([]int, 10), make([]int, 11), false},
+ {&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
+ {Basic{1, 0.5}, Basic{1, 0.6}, false},
+ {Basic{1, 0}, Basic{2, 0}, false},
+ {map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
+ {map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
+ {map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
+ {map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
+ {nil, 1, false},
+ {1, nil, false},
// Mismatched types
- DeepEqualTest{1, 1.0, false},
- DeepEqualTest{int32(1), int64(1), false},
- DeepEqualTest{0.5, "hello", false},
- DeepEqualTest{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
- DeepEqualTest{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
- DeepEqualTest{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
- DeepEqualTest{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
+ {1, 1.0, false},
+ {int32(1), int64(1), false},
+ {0.5, "hello", false},
+ {[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
+ {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
+ {Basic{1, 0.5}, NotBasic{1, 0.5}, false},
+ {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
}
func TestDeepEqual(t *testing.T) {
@@ -868,7 +918,7 @@ func TestMap(t *testing.T) {
// Check that value lookup is correct.
vv := mv.Elem(NewValue(k))
if vi := vv.(*IntValue).Get(); vi != int64(v) {
- t.Errorf("Key %q: have value %d, want %d", vi, v)
+ t.Errorf("Key %q: have value %d, want %d", k, vi, v)
}
// Copy into new map.
@@ -1041,6 +1091,11 @@ func TestMethod(t *testing.T) {
t.Errorf("Type Method returned %d; want 250", i)
}
+ i = Typeof(&p).Method(0).Func.Call([]Value{NewValue(&p), NewValue(10)})[0].(*IntValue).Get()
+ 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()
if i != 250 {
@@ -1159,26 +1214,26 @@ type S4 struct {
}
var fieldTests = []FTest{
- FTest{struct{}{}, "", nil, 0},
- FTest{struct{}{}, "foo", nil, 0},
- FTest{S0{a: 'a'}, "a", []int{0}, 'a'},
- FTest{S0{}, "d", nil, 0},
- FTest{S1{S0: S0{a: 'a'}}, "a", []int{1, 0}, 'a'},
- FTest{S1{b: 'b'}, "b", []int{0}, 'b'},
- FTest{S1{}, "S0", []int{1}, 0},
- FTest{S1{S0: S0{c: 'c'}}, "c", []int{1, 2}, 'c'},
- FTest{S2{a: 'a'}, "a", []int{0}, 'a'},
- FTest{S2{}, "S1", []int{1}, 0},
- FTest{S2{S1: &S1{b: 'b'}}, "b", []int{1, 0}, 'b'},
- FTest{S2{S1: &S1{S0: S0{c: 'c'}}}, "c", []int{1, 1, 2}, 'c'},
- FTest{S2{}, "d", nil, 0},
- FTest{S3{}, "S1", nil, 0},
- FTest{S3{S2: S2{a: 'a'}}, "a", []int{1, 0}, 'a'},
- FTest{S3{}, "b", nil, 0},
- FTest{S3{d: 'd'}, "d", []int{2}, 0},
- FTest{S3{e: 'e'}, "e", []int{3}, 'e'},
- FTest{S4{a: 'a'}, "a", []int{1}, 'a'},
- FTest{S4{}, "b", nil, 0},
+ {struct{}{}, "", nil, 0},
+ {struct{}{}, "foo", nil, 0},
+ {S0{a: 'a'}, "a", []int{0}, 'a'},
+ {S0{}, "d", nil, 0},
+ {S1{S0: S0{a: 'a'}}, "a", []int{1, 0}, 'a'},
+ {S1{b: 'b'}, "b", []int{0}, 'b'},
+ {S1{}, "S0", []int{1}, 0},
+ {S1{S0: S0{c: 'c'}}, "c", []int{1, 2}, 'c'},
+ {S2{a: 'a'}, "a", []int{0}, 'a'},
+ {S2{}, "S1", []int{1}, 0},
+ {S2{S1: &S1{b: 'b'}}, "b", []int{1, 0}, 'b'},
+ {S2{S1: &S1{S0: S0{c: 'c'}}}, "c", []int{1, 1, 2}, 'c'},
+ {S2{}, "d", nil, 0},
+ {S3{}, "S1", nil, 0},
+ {S3{S2: S2{a: 'a'}}, "a", []int{1, 0}, 'a'},
+ {S3{}, "b", nil, 0},
+ {S3{d: 'd'}, "d", []int{2}, 0},
+ {S3{e: 'e'}, "e", []int{3}, 'e'},
+ {S4{a: 'a'}, "a", []int{1}, 'a'},
+ {S4{}, "b", nil, 0},
}
func TestFieldByIndex(t *testing.T) {
@@ -1282,3 +1337,65 @@ func TestDotDotDot(t *testing.T) {
}
t.Error(s)
}
+
+type inner struct {
+ x int
+}
+
+type outer struct {
+ y int
+ inner
+}
+
+func (*inner) m() {}
+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() {
+ 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())
+ }
+ }
+}
+
+type innerInt struct {
+ x int
+}
+
+type outerInt struct {
+ y int
+ innerInt
+}
+
+func (i *innerInt) m() int {
+ return i.x
+}
+
+func TestEmbeddedMethods(t *testing.T) {
+ typ := Typeof((*outerInt)(nil))
+ if typ.NumMethod() != 1 || typ.Method(0).Func.Get() != NewValue((*outerInt).m).(*FuncValue).Get() {
+ 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())
+ }
+ }
+
+ i := &innerInt{3}
+ if v := NewValue(i).Method(0).Call(nil)[0].(*IntValue).Get(); 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 {
+ t.Errorf("i.m() = %d, want 2", v)
+ }
+
+ f := (*outerInt).m
+ if v := f(o); v != 2 {
+ t.Errorf("f(o) = %d, want 2", v)
+ }
+}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index d87ccc984..9a7467b32 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -550,7 +550,7 @@ func (t *StructType) fieldByNameFunc(match func(string) bool, mark map[*StructTy
var fi int // field index
n := 0 // number of matching fields at depth fd
L:
- for i, _ := range t.fields {
+ for i := range t.fields {
f := t.Field(i)
d := inf
switch {
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 56a5d69d8..e0bcb1a39 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -141,7 +141,7 @@ type FloatValue struct {
// Get returns the underlying int value.
func (v *FloatValue) Get() float64 {
- switch v.typ.(*FloatType).Kind() {
+ switch v.typ.Kind() {
case Float:
return float64(*(*float)(v.addr))
case Float32:
@@ -157,7 +157,7 @@ func (v *FloatValue) Set(x float64) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*FloatType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid float kind")
case Float:
@@ -190,7 +190,7 @@ type ComplexValue struct {
// Get returns the underlying complex value.
func (v *ComplexValue) Get() complex128 {
- switch v.typ.(*ComplexType).Kind() {
+ switch v.typ.Kind() {
case Complex:
return complex128(*(*complex)(v.addr))
case Complex64:
@@ -206,7 +206,7 @@ func (v *ComplexValue) Set(x complex128) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*ComplexType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid complex kind")
case Complex:
@@ -228,7 +228,7 @@ type IntValue struct {
// Get returns the underlying int value.
func (v *IntValue) Get() int64 {
- switch v.typ.(*IntType).Kind() {
+ switch v.typ.Kind() {
case Int:
return int64(*(*int)(v.addr))
case Int8:
@@ -248,7 +248,7 @@ func (v *IntValue) Set(x int64) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*IntType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid int kind")
case Int:
@@ -306,7 +306,7 @@ type UintValue struct {
// Get returns the underlying uuint value.
func (v *UintValue) Get() uint64 {
- switch v.typ.(*UintType).Kind() {
+ switch v.typ.Kind() {
case Uint:
return uint64(*(*uint)(v.addr))
case Uint8:
@@ -328,7 +328,7 @@ func (v *UintValue) Set(x uint64) {
if !v.canSet {
panic(cannotSet)
}
- switch v.typ.(*UintType).Kind() {
+ switch v.typ.Kind() {
default:
panic("reflect: invalid uint kind")
case Uint:
@@ -400,11 +400,57 @@ type ArrayOrSliceValue interface {
addr() addr
}
-// ArrayCopy copies the contents of src into dst until either
+// grow grows the slice s so that it can hold extra more values, allocating
+// more capacity if needed. It also returns the old and new slice lengths.
+func grow(s *SliceValue, extra int) (*SliceValue, int, int) {
+ i0 := s.Len()
+ i1 := i0 + extra
+ if i1 < i0 {
+ panic("append: slice overflow")
+ }
+ m := s.Cap()
+ if i1 <= m {
+ return s.Slice(0, i1), i0, i1
+ }
+ if m == 0 {
+ m = extra
+ } else {
+ for m < i1 {
+ if i0 < 1024 {
+ m += m
+ } else {
+ m += m / 4
+ }
+ }
+ }
+ t := MakeSlice(s.Type().(*SliceType), 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 {
+ 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])
+ }
+ 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 {
+ s, i0, i1 := grow(s, t.Len())
+ Copy(s.Slice(i0, i1), t)
+ return s
+}
+
+// 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 ArrayCopy(dst, src ArrayOrSliceValue) int {
+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()
@@ -439,7 +485,7 @@ func (v *ArrayValue) Set(x *ArrayValue) {
panic(cannotSet)
}
typesMustMatch(v.typ, x.typ)
- ArrayCopy(v, x)
+ Copy(v, x)
}
// Set sets v to the value x.
@@ -730,8 +776,6 @@ type tiny struct {
// 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 {
- var structAlign = Typeof((*tiny)(nil)).(*PtrType).Elem().Size()
-
t := fv.Type().(*FuncType)
nin := len(in)
if fv.first != nil && !fv.isInterface {
@@ -757,7 +801,7 @@ func (fv *FuncValue) Call(in []Value) []Value {
size = (size + a - 1) &^ (a - 1)
size += tv.Size()
}
- size = (size + structAlign - 1) &^ (structAlign - 1)
+ size = (size + ptrSize - 1) &^ (ptrSize - 1)
for i := 0; i < nout; i++ {
tv := t.Out(i)
a := uintptr(tv.Align())
@@ -767,9 +811,9 @@ func (fv *FuncValue) Call(in []Value) []Value {
// size must be > 0 in order for &args[0] to be valid.
// the argument copying is going to round it up to
- // a multiple of 8 anyway, so make it 8 to begin with.
- if size < 8 {
- size = 8
+ // a multiple of ptrSize anyway, so make it ptrSize to begin with.
+ if size < ptrSize {
+ size = ptrSize
}
// round to pointer size
@@ -811,7 +855,7 @@ func (fv *FuncValue) Call(in []Value) []Value {
memmove(addr(ptr+off), v.getAddr(), n)
off += n
}
- off = (off + structAlign - 1) &^ (structAlign - 1)
+ off = (off + ptrSize - 1) &^ (ptrSize - 1)
// Call
call(*(**byte)(fv.addr), (*byte)(addr(ptr)), uint32(size))
@@ -843,11 +887,17 @@ type InterfaceValue struct {
value "interface"
}
-// No Get because v.Interface() is available.
-
// 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)
+}
+
// Elem returns the concrete value stored in the interface value v.
func (v *InterfaceValue) Elem() Value { return NewValue(v.Interface()) }
@@ -1058,7 +1108,12 @@ func (v *PtrValue) SetValue(x Value) {
}
// PointTo changes v to point to x.
+// If x is a nil Value, PointTo sets v to nil.
func (v *PtrValue) PointTo(x Value) {
+ if x == nil {
+ *(**uintptr)(v.addr) = nil
+ return
+ }
if !x.CanSet() {
panic("cannot set x; cannot point to x")
}