]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: allow Slice of arrays
authorRuss Cox <rsc@golang.org>
Tue, 19 Apr 2011 00:00:42 +0000 (20:00 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 19 Apr 2011 00:00:42 +0000 (20:00 -0400)
R=r
CC=golang-dev
https://golang.org/cl/4444049

src/cmd/gc/reflect.c
src/pkg/reflect/all_test.go
src/pkg/reflect/type.go
src/pkg/reflect/value.go
src/pkg/runtime/type.go

index fe9c6ac9fd6a35a2521f01cd813cc3b5c441cb1d..4b0de95c26e4f28fcd7a70586c717f4ee8ebf28c 100644 (file)
@@ -690,7 +690,7 @@ dtypesym(Type *t)
        int ot, xt, n, isddd, dupok;
        Sym *s, *s1, *s2;
        Sig *a, *m;
-       Type *t1, *tbase;
+       Type *t1, *tbase, *t2;
 
        if(isideal(t))
                fatal("dtypesym %T", t);
@@ -727,15 +727,25 @@ ok:
                break;
 
        case TARRAY:
-               // ../../pkg/runtime/type.go:/ArrayType
-               s1 = dtypesym(t->type);
-               ot = dcommontype(s, ot, t);
-               xt = ot - 2*widthptr;
-               ot = dsymptr(s, ot, s1, 0);
-               if(t->bound < 0)
-                       ot = duintptr(s, ot, -1);
-               else
+               if(t->bound >= 0) {
+                       // ../../pkg/runtime/type.go:/ArrayType
+                       s1 = dtypesym(t->type);
+                       t2 = typ(TARRAY);
+                       t2->type = t->type;
+                       t2->bound = -1;  // slice
+                       s2 = dtypesym(t2);
+                       ot = dcommontype(s, ot, t);
+                       xt = ot - 2*widthptr;
+                       ot = dsymptr(s, ot, s1, 0);
+                       ot = dsymptr(s, ot, s2, 0);
                        ot = duintptr(s, ot, t->bound);
+               } else {
+                       // ../../pkg/runtime/type.go:/SliceType
+                       s1 = dtypesym(t->type);
+                       ot = dcommontype(s, ot, t);
+                       xt = ot - 2*widthptr;
+                       ot = dsymptr(s, ot, s1, 0);
+               }
                break;
 
        case TCHAN:
index 8529c62ae537f701c47cc45a2e00accecc7dac83..79fef902a008f975de4a36b6bb6f2f9d87612cfe 100644 (file)
@@ -1435,3 +1435,17 @@ func TestSmallNegativeInt(t *testing.T) {
                t.Errorf("int16(-1).Int() returned %v", v.Int())
        }
 }
+
+func TestSlice(t *testing.T) {
+       xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+       v := NewValue(xs).Slice(3, 5).Interface().([]int)
+       if len(v) != 2 || v[0] != 4 || v[1] != 5 {
+               t.Errorf("xs.Slice(3, 5) = %v", v)
+       }
+
+       xa := [7]int{10, 20, 30, 40, 50, 60, 70}
+       v = NewValue(&xa).Elem().Slice(2, 5).Interface().([]int)
+       if len(v) != 3 || v[0] != 30 || v[1] != 40 || v[2] != 50 {
+               t.Errorf("xa.Slice(2, 5) = %v", v)
+       }
+}
index 4801731bbe274aeaed775ca123c424f36c89fc70..5e3051cab51c8feb7e22835a32253f4c09abff59 100644 (file)
@@ -260,6 +260,7 @@ const (
 type arrayType struct {
        commonType "array"
        elem       *runtime.Type
+       slice      *runtime.Type
        len        uintptr
 }
 
index b31aa5a211e08fb16d0f6487d86b46260a21763b..44aaebd50a0a6f79555efd3c4948527ba0d45951 100644 (file)
@@ -1244,20 +1244,32 @@ func (v Value) SetString(x string) {
        *(*string)(iv.addr) = x
 }
 
-// BUG(rsc): Value.Slice should allow slicing arrays.
-
 // Slice returns a slice of v.
-// It panics if v's Kind is not Slice.
+// It panics if v's Kind is not Array or Slice.
 func (v Value) Slice(beg, end int) Value {
        iv := v.internal()
-       iv.mustBe(Slice)
+       if iv.kind != Array && iv.kind != Slice {
+               panic(&ValueError{"reflect.Value.Slice", iv.kind})
+       }
        cap := v.Cap()
        if beg < 0 || end < beg || end > cap {
                panic("reflect.Value.Slice: slice index out of bounds")
        }
-       typ := iv.typ.toType()
+       var typ Type
+       var base uintptr
+       switch iv.kind {
+       case Array:
+               if iv.flag&flagAddr == 0 {
+                       panic("reflect.Value.Slice: slice of unaddressable array")
+               }
+               typ = toType((*arrayType)(unsafe.Pointer(iv.typ)).slice)
+               base = uintptr(iv.addr)
+       case Slice:
+               typ = iv.typ.toType()
+               base = (*SliceHeader)(iv.addr).Data
+       }
        s := new(SliceHeader)
-       s.Data = uintptr((*SliceHeader)(iv.addr).Data) + uintptr(beg)*typ.Elem().Size()
+       s.Data = base + uintptr(beg)*typ.Elem().Size()
        s.Len = end - beg
        s.Cap = cap - beg
        return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
index 71ad4e7a54648d562848c416a925f5ecde9cb31c..30f3ec6423dd550712832d4443ff6b44c741fa87 100644 (file)
@@ -117,8 +117,9 @@ type UnsafePointerType commonType
 // ArrayType represents a fixed array type.
 type ArrayType struct {
        commonType
-       elem *Type // array element type
-       len  uintptr
+       elem  *Type // array element type
+       slice *Type // slice type
+       len   uintptr
 }
 
 // SliceType represents a slice type.