mirror of
https://github.com/golang/go
synced 2024-10-03 02:31:21 -06:00
reflection for interface set
rename map access methods to Elem, SetElem. R=r DELTA=95 (66 added, 7 deleted, 22 changed) OCL=31456 CL=31469
This commit is contained in:
parent
0dadc4fe4f
commit
92e925778e
@ -453,7 +453,7 @@ func (p *pp) printField(field reflect.Value) (was_string bool) {
|
||||
}
|
||||
p.printField(key);
|
||||
p.addstr(":");
|
||||
p.printField(f.Get(key));
|
||||
p.printField(f.Elem(key));
|
||||
}
|
||||
p.addstr("]");
|
||||
case *reflect.StructValue:
|
||||
|
@ -626,15 +626,15 @@ func TestMap(t *testing.T) {
|
||||
i++;
|
||||
|
||||
// Check that value lookup is correct.
|
||||
vv := mv.Get(NewValue(k));
|
||||
vv := mv.Elem(NewValue(k));
|
||||
if vi := vv.(*IntValue).Get(); vi != v {
|
||||
t.Errorf("Key %q: have value %d, want %d", vi, v);
|
||||
}
|
||||
|
||||
// Copy into new map.
|
||||
newmap.Put(NewValue(k), NewValue(v));
|
||||
newmap.SetElem(NewValue(k), NewValue(v));
|
||||
}
|
||||
vv := mv.Get(NewValue("not-present"));
|
||||
vv := mv.Elem(NewValue("not-present"));
|
||||
if vv != nil {
|
||||
t.Errorf("Invalid key: got non-nil value %s", valueToString(vv));
|
||||
}
|
||||
@ -651,7 +651,7 @@ func TestMap(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
newmap.Put(NewValue("a"), nil);
|
||||
newmap.SetElem(NewValue("a"), nil);
|
||||
v, ok := newm["a"];
|
||||
if ok {
|
||||
t.Errorf("newm[\"a\"] = %d after delete", v);
|
||||
@ -784,3 +784,28 @@ func TestMethod(t *testing.T) {
|
||||
t.Errorf("Interface Method returned %d; want 250", i);
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterfaceSet(t *testing.T) {
|
||||
p := &Point{3, 4};
|
||||
|
||||
var s struct {
|
||||
I interface {};
|
||||
P interface { Dist(int)int };
|
||||
}
|
||||
sv := NewValue(&s).(*PtrValue).Elem().(*StructValue);
|
||||
sv.Field(0).(*InterfaceValue).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.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();
|
||||
if i != 250 {
|
||||
t.Errorf("Interface Method returned %d; want 250", i);
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
||||
return false;
|
||||
}
|
||||
for i, k := range map1.Keys() {
|
||||
if !deepValueEqual(map1.Get(k), map2.Get(k), visited, depth+1) {
|
||||
if !deepValueEqual(map1.Elem(k), map2.Elem(k), visited, depth+1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -889,20 +889,25 @@ func (v *InterfaceValue) Elem() Value {
|
||||
return NewValue(v.Interface());
|
||||
}
|
||||
|
||||
// ../runtime/reflect.cgo
|
||||
func setiface(typ *InterfaceType, x *interface{}, addr addr)
|
||||
|
||||
// Set assigns x to v.
|
||||
func (v *InterfaceValue) Set(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.
|
||||
if v.typ.(*InterfaceType).NumMethod() == 0 {
|
||||
*(*interface{})(v.addr) = x;
|
||||
t := v.typ.(*InterfaceType);
|
||||
if t.NumMethod() == 0 {
|
||||
*(*interface{})(v.addr) = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-empty interface requires a runtime check.
|
||||
panic("unimplemented: interface Set");
|
||||
// unsafe.SetInterface(v.typ, v.addr, x);
|
||||
setiface(t, &i, v.addr);
|
||||
}
|
||||
|
||||
// Method returns a FuncValue corresponding to v's i'th method.
|
||||
@ -959,9 +964,9 @@ func mapiternext(it *byte)
|
||||
func mapiterkey(it *byte, key *byte) bool
|
||||
func makemap(t *runtime.MapType) *byte
|
||||
|
||||
// Get returns the value associated with key in the map v.
|
||||
// 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) Get(key Value) Value {
|
||||
func (v *MapValue) Elem(key Value) Value {
|
||||
t := v.Type().(*MapType);
|
||||
typesMustMatch(t.Key(), key.Type());
|
||||
m := *(**byte)(v.addr);
|
||||
@ -975,9 +980,9 @@ func (v *MapValue) Get(key Value) Value {
|
||||
return newval;
|
||||
}
|
||||
|
||||
// Put sets the value associated with key in the map v to val.
|
||||
// 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) Put(key, val Value) {
|
||||
func (v *MapValue) SetElem(key, val Value) {
|
||||
t := v.Type().(*MapType);
|
||||
typesMustMatch(t.Key(), key.Type());
|
||||
var vaddr *byte;
|
||||
|
@ -379,7 +379,7 @@ sys·ifaceI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok)
|
||||
// ifaceE2I(sigi *byte, iface any) (ret any);
|
||||
// Called only for explicit conversions (with type assertion).
|
||||
void
|
||||
sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
|
||||
ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
@ -389,10 +389,17 @@ sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
|
||||
printf("interface is nil, not %S\n", *inter->string);
|
||||
throw("interface conversion");
|
||||
} else {
|
||||
ret.data = e.data;
|
||||
ret.tab = itab(inter, t, 0);
|
||||
ret->data = e.data;
|
||||
ret->tab = itab(inter, t, 0);
|
||||
}
|
||||
FLUSH(&ret);
|
||||
}
|
||||
|
||||
// ifaceE2I(sigi *byte, iface any) (ret any);
|
||||
// Called only for explicit conversions (with type assertion).
|
||||
void
|
||||
sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
|
||||
{
|
||||
ifaceE2I(inter, e, &ret);
|
||||
}
|
||||
|
||||
// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
|
||||
@ -618,4 +625,3 @@ unsafe·Unreflect(Iface typ, void *addr, Eface e)
|
||||
|
||||
FLUSH(&e);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,16 @@ package reflect
|
||||
#include "runtime.h"
|
||||
#include "type.h"
|
||||
|
||||
static Type*
|
||||
gettype(void *typ)
|
||||
{
|
||||
// typ is a *runtime.Type (or *runtime.MapType, etc), but the Type
|
||||
// defined in type.h includes an interface value header
|
||||
// in front of the raw structure. the -2 below backs up
|
||||
// to the interface value header.
|
||||
return (Type*)((void**)typ - 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Go wrappers around the C functions near the bottom of hashmap.c
|
||||
* There's no recursion here even though it looks like there is:
|
||||
@ -41,12 +51,7 @@ func mapiterkey(it *byte, key *byte) (ok bool) {
|
||||
func makemap(typ *byte) (map *byte) {
|
||||
MapType *t;
|
||||
|
||||
// typ is a *runtime.MapType, but the MapType
|
||||
// defined in type.h includes an interface value header
|
||||
// in front of the raw MapType. the -2 below backs up
|
||||
// to the interface value header.
|
||||
t = (MapType*)((void**)typ - 2);
|
||||
|
||||
t = (MapType*)gettype(typ);
|
||||
map = (byte*)makemap(t->key->size, t->elem->size, t->key->alg, t->elem->alg, 0);
|
||||
}
|
||||
|
||||
@ -61,7 +66,7 @@ func makechan(typ *byte, size uint32) (ch *byte) {
|
||||
// defined in type.h includes an interface value header
|
||||
// in front of the raw ChanType. the -2 below backs up
|
||||
// to the interface value header.
|
||||
t = (ChanType*)((void**)typ - 2);
|
||||
t = (ChanType*)gettype(typ);
|
||||
ch = (byte*)makechan(t->elem->size, t->elem->alg, size);
|
||||
}
|
||||
|
||||
@ -73,3 +78,19 @@ func chanrecv(ch *byte, val *byte, pres *bool) {
|
||||
chanrecv((Hchan*)ch, val, pres);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Go wrappers around the functions in iface.c
|
||||
*/
|
||||
|
||||
func setiface(typ *byte, x *byte, ret *byte) {
|
||||
InterfaceType *t;
|
||||
|
||||
t = (InterfaceType*)gettype(typ);
|
||||
if(t->mhdr.nel == 0) {
|
||||
// already an empty interface
|
||||
*(Eface*)ret = *(Eface*)x;
|
||||
return;
|
||||
}
|
||||
ifaceE2I((InterfaceType*)gettype(typ), *(Eface*)x, (Iface*)ret);
|
||||
}
|
||||
|
@ -477,3 +477,5 @@ Hmap* makemap(uint32, uint32, uint32, uint32, uint32);
|
||||
Hchan* makechan(uint32, uint32, uint32);
|
||||
void chansend(Hchan*, void*, bool*);
|
||||
void chanrecv(Hchan*, void*, bool*);
|
||||
|
||||
void ifaceE2I(struct InterfaceType*, Eface, Iface*);
|
||||
|
Loading…
Reference in New Issue
Block a user