mirror of
https://github.com/golang/go
synced 2024-11-26 05:37:57 -07:00
implement IsNil() bool for those types that can be nil. most of them, anyway.
R=rsc DELTA=97 (96 added, 0 deleted, 1 changed) OCL=28596 CL=28702
This commit is contained in:
parent
c6da3e5a69
commit
a8f6e38bce
@ -507,3 +507,65 @@ func TestAlignment(t *testing.T) {
|
|||||||
x1 := T2{T2inner{2, 3}, 17};
|
x1 := T2{T2inner{2, 3}, 17};
|
||||||
check2ndField(x1, uintptr(unsafe.Pointer(&x1.f)) - uintptr(unsafe.Pointer(&x1)), t);
|
check2ndField(x1, uintptr(unsafe.Pointer(&x1.f)) - uintptr(unsafe.Pointer(&x1)), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Nillable interface {
|
||||||
|
IsNil() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func Nil(a interface{}, t *testing.T) {
|
||||||
|
n := NewValue(a).(Nillable);
|
||||||
|
if !n.IsNil() {
|
||||||
|
t.Errorf("%v should be nil", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotNil(a interface{}, t *testing.T) {
|
||||||
|
n := NewValue(a).(Nillable);
|
||||||
|
if n.IsNil() {
|
||||||
|
t.Errorf("value of type %v should not be nil", NewValue(a).Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsNil(t *testing.T) {
|
||||||
|
// These do not implement IsNil
|
||||||
|
doNotNil := []string{"int", "float32", "struct { a int }"};
|
||||||
|
// These do implement IsNil
|
||||||
|
doNil := []string{"*int", "interface{}", "map[string]int", "func() bool", "chan int", "[]string"};
|
||||||
|
for i, ts := range doNotNil {
|
||||||
|
ty := reflect.ParseTypeString("", ts);
|
||||||
|
v := reflect.NewInitValue(ty);
|
||||||
|
if nilable, ok := v.(Nillable); ok {
|
||||||
|
t.Errorf("%s is nilable; should not be", ts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ts := range doNil {
|
||||||
|
ty := reflect.ParseTypeString("", ts);
|
||||||
|
v := reflect.NewInitValue(ty);
|
||||||
|
if nilable, ok := v.(Nillable); !ok {
|
||||||
|
t.Errorf("%s is not nilable; should be", ts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check the implementations
|
||||||
|
var pi *int;
|
||||||
|
Nil(pi, t);
|
||||||
|
pi = new(int);
|
||||||
|
NotNil(pi, t);
|
||||||
|
|
||||||
|
var si []int;
|
||||||
|
Nil(si, t);
|
||||||
|
si = make([]int, 10);
|
||||||
|
NotNil(si, t);
|
||||||
|
|
||||||
|
// TODO: map and chan don't work yet
|
||||||
|
|
||||||
|
var ii interface {};
|
||||||
|
Nil(ii, t);
|
||||||
|
ii = pi;
|
||||||
|
NotNil(ii, t);
|
||||||
|
|
||||||
|
var fi func(t *testing.T);
|
||||||
|
Nil(fi, t);
|
||||||
|
fi = TestIsNil;
|
||||||
|
NotNil(fi, t);
|
||||||
|
}
|
||||||
|
@ -501,6 +501,7 @@ type PtrValue interface {
|
|||||||
Sub() Value; // The Value pointed to.
|
Sub() Value; // The Value pointed to.
|
||||||
Get() Addr; // Get the address stored in the pointer.
|
Get() Addr; // Get the address stored in the pointer.
|
||||||
SetSub(Value); // Set the the pointed-to Value.
|
SetSub(Value); // Set the the pointed-to Value.
|
||||||
|
IsNil() bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ptrValueStruct struct {
|
type ptrValueStruct struct {
|
||||||
@ -525,6 +526,10 @@ func (v *ptrValueStruct) SetSub(subv Value) {
|
|||||||
*(*Addr)(v.addr) = subv.Addr();
|
*(*Addr)(v.addr) = subv.Addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *ptrValueStruct) IsNil() bool {
|
||||||
|
return uintptr(*(*Addr)(v.addr)) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func ptrCreator(typ Type, addr Addr) Value {
|
func ptrCreator(typ Type, addr Addr) Value {
|
||||||
return &ptrValueStruct{ commonValue{PtrKind, typ, addr} };
|
return &ptrValueStruct{ commonValue{PtrKind, typ, addr} };
|
||||||
}
|
}
|
||||||
@ -541,7 +546,8 @@ type ArrayValue interface {
|
|||||||
Elem(i int) Value; // The Value of the i'th element.
|
Elem(i int) Value; // The Value of the i'th element.
|
||||||
SetLen(len int); // Set the length; slice only.
|
SetLen(len int); // Set the length; slice only.
|
||||||
Set(src ArrayValue); // Set the underlying Value; slice only for src and dest both.
|
Set(src ArrayValue); // Set the underlying Value; slice only for src and dest both.
|
||||||
CopyFrom(src ArrayValue, n int) // Copy the elements from src; lengths must match.
|
CopyFrom(src ArrayValue, n int); // Copy the elements from src; lengths must match.
|
||||||
|
IsNil() bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyArray(dst ArrayValue, src ArrayValue, n int);
|
func copyArray(dst ArrayValue, src ArrayValue, n int);
|
||||||
@ -606,6 +612,10 @@ func (v *sliceValueStruct) CopyFrom(src ArrayValue, n int) {
|
|||||||
copyArray(v, src, n);
|
copyArray(v, src, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *sliceValueStruct) IsNil() bool {
|
||||||
|
return uintptr(v.slice.data) == 0
|
||||||
|
}
|
||||||
|
|
||||||
type arrayValueStruct struct {
|
type arrayValueStruct struct {
|
||||||
commonValue;
|
commonValue;
|
||||||
elemtype Type;
|
elemtype Type;
|
||||||
@ -643,6 +653,10 @@ func (v *arrayValueStruct) CopyFrom(src ArrayValue, n int) {
|
|||||||
copyArray(v, src, n);
|
copyArray(v, src, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *arrayValueStruct) IsNil() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func arrayCreator(typ Type, addr Addr) Value {
|
func arrayCreator(typ Type, addr Addr) Value {
|
||||||
arraytype := typ.(ArrayType);
|
arraytype := typ.(ArrayType);
|
||||||
if arraytype.IsSlice() {
|
if arraytype.IsSlice() {
|
||||||
@ -673,6 +687,7 @@ type MapValue interface {
|
|||||||
Value;
|
Value;
|
||||||
Len() int; // The number of elements; currently always returns 0.
|
Len() int; // The number of elements; currently always returns 0.
|
||||||
Elem(key Value) Value; // The value indexed by key; unimplemented.
|
Elem(key Value) Value; // The value indexed by key; unimplemented.
|
||||||
|
IsNil() bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type mapValueStruct struct {
|
type mapValueStruct struct {
|
||||||
@ -687,6 +702,10 @@ func (v *mapValueStruct) Len() int {
|
|||||||
return 0 // TODO: probably want this to be dynamic
|
return 0 // TODO: probably want this to be dynamic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *mapValueStruct) IsNil() bool {
|
||||||
|
return false // TODO: implement this properly
|
||||||
|
}
|
||||||
|
|
||||||
func (v *mapValueStruct) Elem(key Value) Value {
|
func (v *mapValueStruct) Elem(key Value) Value {
|
||||||
panic("map value element");
|
panic("map value element");
|
||||||
return nil
|
return nil
|
||||||
@ -698,12 +717,17 @@ func (v *mapValueStruct) Elem(key Value) Value {
|
|||||||
// Its implementation is incomplete.
|
// Its implementation is incomplete.
|
||||||
type ChanValue interface {
|
type ChanValue interface {
|
||||||
Value;
|
Value;
|
||||||
|
IsNil() bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type chanValueStruct struct {
|
type chanValueStruct struct {
|
||||||
commonValue
|
commonValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *chanValueStruct) IsNil() bool {
|
||||||
|
return false // TODO: implement this properly
|
||||||
|
}
|
||||||
|
|
||||||
func chanCreator(typ Type, addr Addr) Value {
|
func chanCreator(typ Type, addr Addr) Value {
|
||||||
return &chanValueStruct{ commonValue{ChanKind, typ, addr} }
|
return &chanValueStruct{ commonValue{ChanKind, typ, addr} }
|
||||||
}
|
}
|
||||||
@ -750,6 +774,7 @@ type InterfaceValue interface {
|
|||||||
Value;
|
Value;
|
||||||
Get() interface {}; // Get the underlying interface{} value.
|
Get() interface {}; // Get the underlying interface{} value.
|
||||||
Value() Value;
|
Value() Value;
|
||||||
|
IsNil() bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type interfaceValueStruct struct {
|
type interfaceValueStruct struct {
|
||||||
@ -768,6 +793,10 @@ func (v *interfaceValueStruct) Value() Value {
|
|||||||
return NewValue(i);
|
return NewValue(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *interfaceValueStruct) IsNil() bool {
|
||||||
|
return *(*interface{})(v.addr) == nil
|
||||||
|
}
|
||||||
|
|
||||||
func interfaceCreator(typ Type, addr Addr) Value {
|
func interfaceCreator(typ Type, addr Addr) Value {
|
||||||
return &interfaceValueStruct{ commonValue{InterfaceKind, typ, addr} }
|
return &interfaceValueStruct{ commonValue{InterfaceKind, typ, addr} }
|
||||||
}
|
}
|
||||||
@ -780,6 +809,7 @@ func interfaceCreator(typ Type, addr Addr) Value {
|
|||||||
type FuncValue interface {
|
type FuncValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() Addr; // The address of the function.
|
Get() Addr; // The address of the function.
|
||||||
|
IsNil() bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type funcValueStruct struct {
|
type funcValueStruct struct {
|
||||||
@ -790,6 +820,10 @@ func (v *funcValueStruct) Get() Addr {
|
|||||||
return *(*Addr)(v.addr)
|
return *(*Addr)(v.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *funcValueStruct) IsNil() bool {
|
||||||
|
return *(*Addr)(v.addr) == nil
|
||||||
|
}
|
||||||
|
|
||||||
func funcCreator(typ Type, addr Addr) Value {
|
func funcCreator(typ Type, addr Addr) Value {
|
||||||
return &funcValueStruct{ commonValue{FuncKind, typ, addr} }
|
return &funcValueStruct{ commonValue{FuncKind, typ, addr} }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user