Commit a8f6e38b authored by Rob Pike's avatar Rob Pike

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
parent c6da3e5a
...@@ -507,3 +507,65 @@ func TestAlignment(t *testing.T) { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment