mirror of
https://github.com/golang/go
synced 2024-10-03 04:21:22 -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.printField(key);
|
||||||
p.addstr(":");
|
p.addstr(":");
|
||||||
p.printField(f.Get(key));
|
p.printField(f.Elem(key));
|
||||||
}
|
}
|
||||||
p.addstr("]");
|
p.addstr("]");
|
||||||
case *reflect.StructValue:
|
case *reflect.StructValue:
|
||||||
|
@ -626,15 +626,15 @@ func TestMap(t *testing.T) {
|
|||||||
i++;
|
i++;
|
||||||
|
|
||||||
// Check that value lookup is correct.
|
// Check that value lookup is correct.
|
||||||
vv := mv.Get(NewValue(k));
|
vv := mv.Elem(NewValue(k));
|
||||||
if vi := vv.(*IntValue).Get(); vi != v {
|
if vi := vv.(*IntValue).Get(); vi != v {
|
||||||
t.Errorf("Key %q: have value %d, want %d", vi, v);
|
t.Errorf("Key %q: have value %d, want %d", vi, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy into new map.
|
// 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 {
|
if vv != nil {
|
||||||
t.Errorf("Invalid key: got non-nil value %s", valueToString(vv));
|
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"];
|
v, ok := newm["a"];
|
||||||
if ok {
|
if ok {
|
||||||
t.Errorf("newm[\"a\"] = %d after delete", v);
|
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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
for i, k := range map1.Keys() {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -889,20 +889,25 @@ func (v *InterfaceValue) Elem() Value {
|
|||||||
return NewValue(v.Interface());
|
return NewValue(v.Interface());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ../runtime/reflect.cgo
|
||||||
|
func setiface(typ *InterfaceType, x *interface{}, addr addr)
|
||||||
|
|
||||||
// Set assigns x to v.
|
// Set assigns x to v.
|
||||||
func (v *InterfaceValue) Set(x interface{}) {
|
func (v *InterfaceValue) Set(x Value) {
|
||||||
|
i := x.Interface();
|
||||||
if !v.canSet {
|
if !v.canSet {
|
||||||
panic(cannotSet);
|
panic(cannotSet);
|
||||||
}
|
}
|
||||||
// Two different representations; see comment in Get.
|
// Two different representations; see comment in Get.
|
||||||
// Empty interface is easy.
|
// Empty interface is easy.
|
||||||
if v.typ.(*InterfaceType).NumMethod() == 0 {
|
t := v.typ.(*InterfaceType);
|
||||||
*(*interface{})(v.addr) = x;
|
if t.NumMethod() == 0 {
|
||||||
|
*(*interface{})(v.addr) = i;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-empty interface requires a runtime check.
|
// Non-empty interface requires a runtime check.
|
||||||
panic("unimplemented: interface Set");
|
setiface(t, &i, v.addr);
|
||||||
// unsafe.SetInterface(v.typ, v.addr, x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method returns a FuncValue corresponding to v's i'th method.
|
// 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 mapiterkey(it *byte, key *byte) bool
|
||||||
func makemap(t *runtime.MapType) *byte
|
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.
|
// 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);
|
t := v.Type().(*MapType);
|
||||||
typesMustMatch(t.Key(), key.Type());
|
typesMustMatch(t.Key(), key.Type());
|
||||||
m := *(**byte)(v.addr);
|
m := *(**byte)(v.addr);
|
||||||
@ -975,9 +980,9 @@ func (v *MapValue) Get(key Value) Value {
|
|||||||
return newval;
|
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.
|
// 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);
|
t := v.Type().(*MapType);
|
||||||
typesMustMatch(t.Key(), key.Type());
|
typesMustMatch(t.Key(), key.Type());
|
||||||
var vaddr *byte;
|
var vaddr *byte;
|
||||||
|
@ -379,7 +379,7 @@ sys·ifaceI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok)
|
|||||||
// ifaceE2I(sigi *byte, iface any) (ret any);
|
// ifaceE2I(sigi *byte, iface any) (ret any);
|
||||||
// Called only for explicit conversions (with type assertion).
|
// Called only for explicit conversions (with type assertion).
|
||||||
void
|
void
|
||||||
sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
|
ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
|
||||||
{
|
{
|
||||||
Type *t;
|
Type *t;
|
||||||
|
|
||||||
@ -389,10 +389,17 @@ sys·ifaceE2I(InterfaceType *inter, Eface e, Iface ret)
|
|||||||
printf("interface is nil, not %S\n", *inter->string);
|
printf("interface is nil, not %S\n", *inter->string);
|
||||||
throw("interface conversion");
|
throw("interface conversion");
|
||||||
} else {
|
} else {
|
||||||
ret.data = e.data;
|
ret->data = e.data;
|
||||||
ret.tab = itab(inter, t, 0);
|
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);
|
// ifaceE2I2(sigi *byte, iface any) (ret any, ok bool);
|
||||||
@ -618,4 +625,3 @@ unsafe·Unreflect(Iface typ, void *addr, Eface e)
|
|||||||
|
|
||||||
FLUSH(&e);
|
FLUSH(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,16 @@ package reflect
|
|||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "type.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
|
* Go wrappers around the C functions near the bottom of hashmap.c
|
||||||
* There's no recursion here even though it looks like there is:
|
* 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) {
|
func makemap(typ *byte) (map *byte) {
|
||||||
MapType *t;
|
MapType *t;
|
||||||
|
|
||||||
// typ is a *runtime.MapType, but the MapType
|
t = (MapType*)gettype(typ);
|
||||||
// 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);
|
|
||||||
|
|
||||||
map = (byte*)makemap(t->key->size, t->elem->size, t->key->alg, t->elem->alg, 0);
|
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
|
// defined in type.h includes an interface value header
|
||||||
// in front of the raw ChanType. the -2 below backs up
|
// in front of the raw ChanType. the -2 below backs up
|
||||||
// to the interface value header.
|
// to the interface value header.
|
||||||
t = (ChanType*)((void**)typ - 2);
|
t = (ChanType*)gettype(typ);
|
||||||
ch = (byte*)makechan(t->elem->size, t->elem->alg, size);
|
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);
|
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);
|
Hchan* makechan(uint32, uint32, uint32);
|
||||||
void chansend(Hchan*, void*, bool*);
|
void chansend(Hchan*, void*, bool*);
|
||||||
void chanrecv(Hchan*, void*, bool*);
|
void chanrecv(Hchan*, void*, bool*);
|
||||||
|
|
||||||
|
void ifaceE2I(struct InterfaceType*, Eface, Iface*);
|
||||||
|
Loading…
Reference in New Issue
Block a user