diff options
Diffstat (limited to 'src/pkg/reflect')
-rw-r--r-- | src/pkg/reflect/Makefile | 2 | ||||
-rw-r--r-- | src/pkg/reflect/all_test.go | 375 | ||||
-rw-r--r-- | src/pkg/reflect/type.go | 2 | ||||
-rw-r--r-- | src/pkg/reflect/value.go | 95 |
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") } |