mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
document reflect.
R=rsc DELTA=201 (90 added, 0 deleted, 111 changed) OCL=25904 CL=25966
This commit is contained in:
parent
5bd5242bcc
commit
3bc6fd63fe
4 changed files with 192 additions and 102 deletions
|
|
@ -43,7 +43,7 @@ func assert(s, t string) {
|
||||||
|
|
||||||
func typedump(s, t string) {
|
func typedump(s, t string) {
|
||||||
typ := reflect.ParseTypeString("", s);
|
typ := reflect.ParseTypeString("", s);
|
||||||
assert(reflect.TypeToString(typ, true), t);
|
assert(reflect.typeToString(typ, true), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
func valuedump(s, t string) {
|
func valuedump(s, t string) {
|
||||||
|
|
@ -84,7 +84,7 @@ func valuedump(s, t string) {
|
||||||
case reflect.BoolKind:
|
case reflect.BoolKind:
|
||||||
v.(reflect.BoolValue).Set(true);
|
v.(reflect.BoolValue).Set(true);
|
||||||
}
|
}
|
||||||
assert(reflect.ValueToString(v), t);
|
assert(reflect.valueToString(v), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
type T struct { a int; b float64; c string; d *int }
|
type T struct { a int; b float64; c string; d *int }
|
||||||
|
|
@ -156,43 +156,43 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
|
||||||
|
|
||||||
{ var tmp = 123;
|
{ var tmp = 123;
|
||||||
value := reflect.NewValue(tmp);
|
value := reflect.NewValue(tmp);
|
||||||
assert(reflect.ValueToString(value), "123");
|
assert(reflect.valueToString(value), "123");
|
||||||
}
|
}
|
||||||
{ var tmp = 123.4;
|
{ var tmp = 123.4;
|
||||||
value := reflect.NewValue(tmp);
|
value := reflect.NewValue(tmp);
|
||||||
assert(reflect.ValueToString(value), "123.4");
|
assert(reflect.valueToString(value), "123.4");
|
||||||
}
|
}
|
||||||
{ var tmp = "abc";
|
{ var tmp = "abc";
|
||||||
value := reflect.NewValue(tmp);
|
value := reflect.NewValue(tmp);
|
||||||
assert(reflect.ValueToString(value), "abc");
|
assert(reflect.valueToString(value), "abc");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var i int = 7;
|
var i int = 7;
|
||||||
var tmp = &T{123, 456.75, "hello", &i};
|
var tmp = &T{123, 456.75, "hello", &i};
|
||||||
value := reflect.NewValue(tmp);
|
value := reflect.NewValue(tmp);
|
||||||
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "reflect.T{123, 456.75, hello, *int(@)}");
|
assert(reflect.valueToString(value.(reflect.PtrValue).Sub()), "reflect.T{123, 456.75, hello, *int(@)}");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
type C chan *T; // TODO: should not be necessary
|
type C chan *T; // TODO: should not be necessary
|
||||||
var tmp = new(C);
|
var tmp = new(C);
|
||||||
value := reflect.NewValue(tmp);
|
value := reflect.NewValue(tmp);
|
||||||
assert(reflect.ValueToString(value), "*reflect.C·all_test(@)");
|
assert(reflect.valueToString(value), "*reflect.C·all_test(@)");
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
// type A [10]int;
|
// type A [10]int;
|
||||||
// var tmp A = A{1,2,3,4,5,6,7,8,9,10};
|
// var tmp A = A{1,2,3,4,5,6,7,8,9,10};
|
||||||
// value := reflect.NewValue(&tmp);
|
// value := reflect.NewValue(&tmp);
|
||||||
// assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "reflect.A·all_test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
|
// assert(reflect.valueToString(value.(reflect.PtrValue).Sub()), "reflect.A·all_test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
|
||||||
// value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.IntValue).Set(123);
|
// value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.IntValue).Set(123);
|
||||||
// assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "reflect.A·all_test{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}");
|
// assert(reflect.valueToString(value.(reflect.PtrValue).Sub()), "reflect.A·all_test{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}");
|
||||||
// }
|
// }
|
||||||
{
|
{
|
||||||
type AA []int;
|
type AA []int;
|
||||||
var tmp = AA{1,2,3,4,5,6,7,8,9,10};
|
var tmp = AA{1,2,3,4,5,6,7,8,9,10};
|
||||||
value := reflect.NewValue(&tmp); // TODO: NewValue(tmp) too
|
value := reflect.NewValue(&tmp); // TODO: NewValue(tmp) too
|
||||||
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "reflect.AA·all_test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
|
assert(reflect.valueToString(value.(reflect.PtrValue).Sub()), "reflect.AA·all_test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}");
|
||||||
value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.IntValue).Set(123);
|
value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.IntValue).Set(123);
|
||||||
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "reflect.AA·all_test{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}");
|
assert(reflect.valueToString(value.(reflect.PtrValue).Sub()), "reflect.AA·all_test{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Reflection library.
|
// Reflection library.
|
||||||
// Formatting of types and values for debugging.
|
// Formatting of reflection types and values for debugging.
|
||||||
|
// Not defined as methods so they do not need to be linked into most binaries;
|
||||||
|
// the functions are not used by the library itself, only in tests.
|
||||||
|
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
|
|
@ -12,8 +14,8 @@ import (
|
||||||
"strconv";
|
"strconv";
|
||||||
)
|
)
|
||||||
|
|
||||||
func TypeToString(typ Type, expand bool) string
|
func typeToString(typ Type, expand bool) string
|
||||||
func ValueToString(val Value) string
|
func valueToString(val Value) string
|
||||||
|
|
||||||
func doubleQuote(s string) string {
|
func doubleQuote(s string) string {
|
||||||
out := "\"";
|
out := "\"";
|
||||||
|
|
@ -50,7 +52,7 @@ func typeFieldsToString(t hasFields, sep string) string {
|
||||||
if str1 != "" {
|
if str1 != "" {
|
||||||
str1 += " "
|
str1 += " "
|
||||||
}
|
}
|
||||||
str1 += TypeToString(typ, false);
|
str1 += typeToString(typ, false);
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
str1 += " " + doubleQuote(tag);
|
str1 += " " + doubleQuote(tag);
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +64,11 @@ func typeFieldsToString(t hasFields, sep string) string {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
func TypeToString(typ Type, expand bool) string {
|
// typeToString returns a textual representation of typ. The expand
|
||||||
|
// flag specifies whether to expand the contents of type names; if false,
|
||||||
|
// the name itself is used as the representation.
|
||||||
|
// Meant for debugging only; typ.String() serves for most purposes.
|
||||||
|
func typeToString(typ Type, expand bool) string {
|
||||||
var str string;
|
var str string;
|
||||||
if name := typ.Name(); !expand && name != "" {
|
if name := typ.Name(); !expand && name != "" {
|
||||||
return name
|
return name
|
||||||
|
|
@ -78,7 +84,7 @@ func TypeToString(typ Type, expand bool) string {
|
||||||
return typ.Name();
|
return typ.Name();
|
||||||
case PtrKind:
|
case PtrKind:
|
||||||
p := typ.(PtrType);
|
p := typ.(PtrType);
|
||||||
return "*" + TypeToString(p.Sub(), false);
|
return "*" + typeToString(p.Sub(), false);
|
||||||
case ArrayKind:
|
case ArrayKind:
|
||||||
a := typ.(ArrayType);
|
a := typ.(ArrayType);
|
||||||
if a.IsSlice() {
|
if a.IsSlice() {
|
||||||
|
|
@ -86,11 +92,11 @@ func TypeToString(typ Type, expand bool) string {
|
||||||
} else {
|
} else {
|
||||||
str = "[" + strconv.Itoa64(int64(a.Len())) + "]"
|
str = "[" + strconv.Itoa64(int64(a.Len())) + "]"
|
||||||
}
|
}
|
||||||
return str + TypeToString(a.Elem(), false);
|
return str + typeToString(a.Elem(), false);
|
||||||
case MapKind:
|
case MapKind:
|
||||||
m := typ.(MapType);
|
m := typ.(MapType);
|
||||||
str = "map[" + TypeToString(m.Key(), false) + "]";
|
str = "map[" + typeToString(m.Key(), false) + "]";
|
||||||
return str + TypeToString(m.Elem(), false);
|
return str + typeToString(m.Elem(), false);
|
||||||
case ChanKind:
|
case ChanKind:
|
||||||
c := typ.(ChanType);
|
c := typ.(ChanType);
|
||||||
switch c.Dir() {
|
switch c.Dir() {
|
||||||
|
|
@ -101,9 +107,9 @@ func TypeToString(typ Type, expand bool) string {
|
||||||
case BothDir:
|
case BothDir:
|
||||||
str = "chan";
|
str = "chan";
|
||||||
default:
|
default:
|
||||||
panicln("reflect.TypeToString: unknown chan direction");
|
panicln("reflect.typeToString: unknown chan direction");
|
||||||
}
|
}
|
||||||
return str + TypeToString(c.Elem(), false);
|
return str + typeToString(c.Elem(), false);
|
||||||
case StructKind:
|
case StructKind:
|
||||||
return "struct{" + typeFieldsToString(typ.(StructType), ";") + "}";
|
return "struct{" + typeFieldsToString(typ.(StructType), ";") + "}";
|
||||||
case InterfaceKind:
|
case InterfaceKind:
|
||||||
|
|
@ -116,9 +122,9 @@ func TypeToString(typ Type, expand bool) string {
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
default:
|
default:
|
||||||
panicln("reflect.TypeToString: can't print type ", typ.Kind());
|
panicln("reflect.typeToString: can't print type ", typ.Kind());
|
||||||
}
|
}
|
||||||
return "reflect.TypeToString: can't happen";
|
return "reflect.typeToString: can't happen";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: want an unsigned one too
|
// TODO: want an unsigned one too
|
||||||
|
|
@ -126,7 +132,9 @@ func integer(v int64) string {
|
||||||
return strconv.Itoa64(v);
|
return strconv.Itoa64(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValueToString(val Value) string {
|
// valueToString returns a textual representation of the reflection value val.
|
||||||
|
// For debugging only.
|
||||||
|
func valueToString(val Value) string {
|
||||||
var str string;
|
var str string;
|
||||||
typ := val.Type();
|
typ := val.Type();
|
||||||
switch(val.Kind()) {
|
switch(val.Kind()) {
|
||||||
|
|
@ -174,41 +182,41 @@ func ValueToString(val Value) string {
|
||||||
}
|
}
|
||||||
case PtrKind:
|
case PtrKind:
|
||||||
v := val.(PtrValue);
|
v := val.(PtrValue);
|
||||||
return TypeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")";
|
return typeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")";
|
||||||
case ArrayKind:
|
case ArrayKind:
|
||||||
t := typ.(ArrayType);
|
t := typ.(ArrayType);
|
||||||
v := val.(ArrayValue);
|
v := val.(ArrayValue);
|
||||||
str += TypeToString(t, false);
|
str += typeToString(t, false);
|
||||||
str += "{";
|
str += "{";
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
str += ", "
|
str += ", "
|
||||||
}
|
}
|
||||||
str += ValueToString(v.Elem(i));
|
str += valueToString(v.Elem(i));
|
||||||
}
|
}
|
||||||
str += "}";
|
str += "}";
|
||||||
return str;
|
return str;
|
||||||
case MapKind:
|
case MapKind:
|
||||||
t := typ.(MapType);
|
t := typ.(MapType);
|
||||||
v := val.(MapValue);
|
v := val.(MapValue);
|
||||||
str = TypeToString(t, false);
|
str = typeToString(t, false);
|
||||||
str += "{";
|
str += "{";
|
||||||
str += "<can't iterate on maps>";
|
str += "<can't iterate on maps>";
|
||||||
str += "}";
|
str += "}";
|
||||||
return str;
|
return str;
|
||||||
case ChanKind:
|
case ChanKind:
|
||||||
str = TypeToString(typ, false);
|
str = typeToString(typ, false);
|
||||||
return str;
|
return str;
|
||||||
case StructKind:
|
case StructKind:
|
||||||
t := typ.(StructType);
|
t := typ.(StructType);
|
||||||
v := val.(StructValue);
|
v := val.(StructValue);
|
||||||
str += TypeToString(t, false);
|
str += typeToString(t, false);
|
||||||
str += "{";
|
str += "{";
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
str += ", "
|
str += ", "
|
||||||
}
|
}
|
||||||
str += ValueToString(v.Field(i));
|
str += valueToString(v.Field(i));
|
||||||
}
|
}
|
||||||
str += "}";
|
str += "}";
|
||||||
return str;
|
return str;
|
||||||
|
|
@ -217,7 +225,7 @@ func ValueToString(val Value) string {
|
||||||
case FuncKind:
|
case FuncKind:
|
||||||
return "can't print funcs yet";
|
return "can't print funcs yet";
|
||||||
default:
|
default:
|
||||||
panicln("reflect.ValueToString: can't print type ", val.Kind());
|
panicln("reflect.valueToString: can't print type ", val.Kind());
|
||||||
}
|
}
|
||||||
return "reflect.ValueToString: can't happen";
|
return "reflect.valueToString: can't happen";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@
|
||||||
// Reflection library.
|
// Reflection library.
|
||||||
// Types and parsing of type strings.
|
// Types and parsing of type strings.
|
||||||
|
|
||||||
|
// This package implements data ``reflection''. A program can use it to analyze types
|
||||||
|
// and values it does not know at compile time, such as the values passed in a call
|
||||||
|
// to a function with a ... parameter. This is achieved by extracting the dynamic
|
||||||
|
// contents of an interface value.
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -19,6 +23,7 @@ func ExpandType(name string) Type
|
||||||
|
|
||||||
func typestrings() string // implemented in C; declared here
|
func typestrings() string // implemented in C; declared here
|
||||||
|
|
||||||
|
// These constants identify what kind of thing a Type represents: an int, struct, etc.
|
||||||
const (
|
const (
|
||||||
MissingKind = iota;
|
MissingKind = iota;
|
||||||
ArrayKind;
|
ArrayKind;
|
||||||
|
|
@ -57,10 +62,18 @@ const (
|
||||||
var missingString = "$missing$" // syntactic name for undefined type names
|
var missingString = "$missing$" // syntactic name for undefined type names
|
||||||
var dotDotDotString = "..."
|
var dotDotDotString = "..."
|
||||||
|
|
||||||
|
// Type is the generic interface to reflection types. Once its Kind is known,
|
||||||
|
// such as BoolKind, the Type can be narrowed to the appropriate, more
|
||||||
|
// specific interface, such as BoolType. Such narrowed types still implement
|
||||||
|
// the Type interface.
|
||||||
type Type interface {
|
type Type interface {
|
||||||
|
// The kind of thing described: ArrayKind, BoolKind, etc.
|
||||||
Kind() int;
|
Kind() int;
|
||||||
|
// The name declared for the type ("int", "BoolArray", etc.).
|
||||||
Name() string;
|
Name() string;
|
||||||
|
// For a named type, same as Name(); otherwise a representation of the type such as "[]int".
|
||||||
String() string;
|
String() string;
|
||||||
|
// The number of bytes needed to store a value; analogous to unsafe.Sizeof().
|
||||||
Size() int;
|
Size() int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +117,10 @@ func newBasicType(name string, kind int, size int) Type {
|
||||||
return &basicType{ commonType{kind, name, name, size} }
|
return &basicType{ commonType{kind, name, name, size} }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prebuilt basic types
|
// Prebuilt basic Type objects representing the predeclared basic types.
|
||||||
|
// Most are self-evident except:
|
||||||
|
// Missing represents types whose representation cannot be discovered; usually an error.
|
||||||
|
// DotDotDot represents the pseudo-type of a ... parameter.
|
||||||
var (
|
var (
|
||||||
Missing = newBasicType(missingString, MissingKind, 1);
|
Missing = newBasicType(missingString, MissingKind, 1);
|
||||||
empty interface{};
|
empty interface{};
|
||||||
|
|
@ -149,9 +165,10 @@ func (t *stubType) Get() Type {
|
||||||
|
|
||||||
// -- Pointer
|
// -- Pointer
|
||||||
|
|
||||||
|
// PtrType represents a pointer.
|
||||||
type PtrType interface {
|
type PtrType interface {
|
||||||
Type;
|
Type;
|
||||||
Sub() Type
|
Sub() Type // The type of the pointed-to item; for "*int", it will be "int".
|
||||||
}
|
}
|
||||||
|
|
||||||
type ptrTypeStruct struct {
|
type ptrTypeStruct struct {
|
||||||
|
|
@ -169,11 +186,12 @@ func (t *ptrTypeStruct) Sub() Type {
|
||||||
|
|
||||||
// -- Array
|
// -- Array
|
||||||
|
|
||||||
|
// ArrayType represents an array or slice type.
|
||||||
type ArrayType interface {
|
type ArrayType interface {
|
||||||
Type;
|
Type;
|
||||||
IsSlice() bool;
|
IsSlice() bool; // True for slices, false for arrays.
|
||||||
Len() int;
|
Len() int; // 0 for slices, the length for array types.
|
||||||
Elem() Type;
|
Elem() Type; // The type of the elements.
|
||||||
}
|
}
|
||||||
|
|
||||||
type arrayTypeStruct struct {
|
type arrayTypeStruct struct {
|
||||||
|
|
@ -184,7 +202,7 @@ type arrayTypeStruct struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayTypeStruct(name, typestring string, open bool, len int, elem *stubType) *arrayTypeStruct {
|
func newArrayTypeStruct(name, typestring string, open bool, len int, elem *stubType) *arrayTypeStruct {
|
||||||
return &arrayTypeStruct{ commonType{ArrayKind, typestring, name, 0}, elem, open, len}
|
return &arrayTypeStruct{ commonType{ArrayKind, typestring, name, 0 }, elem, open, len}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *arrayTypeStruct) Size() int {
|
func (t *arrayTypeStruct) Size() int {
|
||||||
|
|
@ -199,7 +217,9 @@ func (t *arrayTypeStruct) IsSlice() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *arrayTypeStruct) Len() int {
|
func (t *arrayTypeStruct) Len() int {
|
||||||
// what about open array? TODO
|
if t.isslice {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return t.len
|
return t.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,10 +229,11 @@ func (t *arrayTypeStruct) Elem() Type {
|
||||||
|
|
||||||
// -- Map
|
// -- Map
|
||||||
|
|
||||||
|
// MapType represents a map type.
|
||||||
type MapType interface {
|
type MapType interface {
|
||||||
Type;
|
Type;
|
||||||
Key() Type;
|
Key() Type; // The type of the keys.
|
||||||
Elem() Type;
|
Elem() Type; // The type of the elements/values.
|
||||||
}
|
}
|
||||||
|
|
||||||
type mapTypeStruct struct {
|
type mapTypeStruct struct {
|
||||||
|
|
@ -235,13 +256,15 @@ func (t *mapTypeStruct) Elem() Type {
|
||||||
|
|
||||||
// -- Chan
|
// -- Chan
|
||||||
|
|
||||||
|
// ChanType represents a chan type.
|
||||||
type ChanType interface {
|
type ChanType interface {
|
||||||
Type;
|
Type;
|
||||||
Dir() int;
|
Dir() int; // The direction of the channel.
|
||||||
Elem() Type;
|
Elem() Type; // The type of the elements.
|
||||||
}
|
}
|
||||||
|
|
||||||
const ( // channel direction
|
// Channel direction.
|
||||||
|
const (
|
||||||
SendDir = 1 << iota;
|
SendDir = 1 << iota;
|
||||||
RecvDir;
|
RecvDir;
|
||||||
BothDir = SendDir | RecvDir;
|
BothDir = SendDir | RecvDir;
|
||||||
|
|
@ -267,9 +290,13 @@ func (t *chanTypeStruct) Elem() Type {
|
||||||
|
|
||||||
// -- Struct
|
// -- Struct
|
||||||
|
|
||||||
|
// StructType represents a struct type.
|
||||||
type StructType interface {
|
type StructType interface {
|
||||||
Type;
|
Type;
|
||||||
Field(int) (name string, typ Type, tag string, offset int);
|
// Field returns, for field i, its name, Type, tag information, and byte offset.
|
||||||
|
// The indices are in declaration order starting at 0.
|
||||||
|
Field(i int) (name string, typ Type, tag string, offset int);
|
||||||
|
// Len is the number of fields.
|
||||||
Len() int;
|
Len() int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,8 +355,12 @@ func (t *structTypeStruct) Len() int {
|
||||||
|
|
||||||
// -- Interface
|
// -- Interface
|
||||||
|
|
||||||
|
// InterfaceType represents an interface type.
|
||||||
|
// It behaves much like a StructType, treating the methods as fields.
|
||||||
type InterfaceType interface {
|
type InterfaceType interface {
|
||||||
Type;
|
Type;
|
||||||
|
// Field returns, for method i, its name, Type, the empty string, and 0.
|
||||||
|
// The indices are in declaration order starting at 0. TODO: is this true?
|
||||||
Field(int) (name string, typ Type, tag string, offset int);
|
Field(int) (name string, typ Type, tag string, offset int);
|
||||||
Len() int;
|
Len() int;
|
||||||
}
|
}
|
||||||
|
|
@ -355,10 +386,11 @@ var nilInterface = newInterfaceTypeStruct("nil", "", make([]structField, 0));
|
||||||
|
|
||||||
// -- Func
|
// -- Func
|
||||||
|
|
||||||
|
// FuncType represents a function type.
|
||||||
type FuncType interface {
|
type FuncType interface {
|
||||||
Type;
|
Type;
|
||||||
In() StructType;
|
In() StructType; // The parameters in the form of a StructType.
|
||||||
Out() StructType;
|
Out() StructType; // The results in the form of a StructType.
|
||||||
}
|
}
|
||||||
|
|
||||||
type funcTypeStruct struct {
|
type funcTypeStruct struct {
|
||||||
|
|
@ -466,6 +498,9 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Parsing of type strings. These strings are how the run-time recovers type
|
||||||
|
information dynamically.
|
||||||
|
|
||||||
Grammar
|
Grammar
|
||||||
|
|
||||||
stubtype = - represent as StubType when possible
|
stubtype = - represent as StubType when possible
|
||||||
|
|
@ -850,6 +885,9 @@ func (p *typeParser) Type(name string) *stubType {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseTypeString takes a type name and type string (such as "[]int") and
|
||||||
|
// returns the Type structure representing a type name specifying the corresponding
|
||||||
|
// type. An empty typestring represents (the type of) a nil interface value.
|
||||||
func ParseTypeString(name, typestring string) Type {
|
func ParseTypeString(name, typestring string) Type {
|
||||||
if typestring == "" {
|
if typestring == "" {
|
||||||
// If the typestring is empty, it represents (the type of) a nil interface value
|
// If the typestring is empty, it represents (the type of) a nil interface value
|
||||||
|
|
@ -909,7 +947,8 @@ func typeNameToTypeString(name string) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type is known by name. Find (and create if necessary) its real type.
|
// ExpandType takes the name of a type and returns its Type structure,
|
||||||
|
// unpacking the associated type string if necessary.
|
||||||
func ExpandType(name string) Type {
|
func ExpandType(name string) Type {
|
||||||
lock();
|
lock();
|
||||||
t, ok := types[name];
|
t, ok := types[name];
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,25 @@ import (
|
||||||
"unsafe";
|
"unsafe";
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Addr is shorthand for unsafe.Pointer and is used to represent the address of Values.
|
||||||
type Addr unsafe.Pointer
|
type Addr unsafe.Pointer
|
||||||
|
|
||||||
func equalType(a, b Type) bool {
|
func equalType(a, b Type) bool {
|
||||||
return a.String() == b.String()
|
return a.String() == b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value is the generic interface to reflection values. Once its Kind is known,
|
||||||
|
// such as BoolKind, the Value can be narrowed to the appropriate, more
|
||||||
|
// specific interface, such as BoolValue. Such narrowed values still implement
|
||||||
|
// the Value interface.
|
||||||
type Value interface {
|
type Value interface {
|
||||||
|
// The kind of thing described: ArrayKind, BoolKind, etc.
|
||||||
Kind() int;
|
Kind() int;
|
||||||
|
// The reflection Type of the value.
|
||||||
Type() Type;
|
Type() Type;
|
||||||
|
// The address of the value.
|
||||||
Addr() Addr;
|
Addr() Addr;
|
||||||
|
// The value itself is the dynamic value of an empty interface.
|
||||||
Interface() interface {};
|
Interface() interface {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,6 +74,8 @@ type creatorFn func(typ Type, addr Addr) Value
|
||||||
|
|
||||||
// -- Missing
|
// -- Missing
|
||||||
|
|
||||||
|
// MissingValue represents a value whose type is not known. It usually
|
||||||
|
// indicates an error.
|
||||||
type MissingValue interface {
|
type MissingValue interface {
|
||||||
Value;
|
Value;
|
||||||
}
|
}
|
||||||
|
|
@ -79,10 +90,11 @@ func missingCreator(typ Type, addr Addr) Value {
|
||||||
|
|
||||||
// -- Int
|
// -- Int
|
||||||
|
|
||||||
|
// IntValue represents an int value.
|
||||||
type IntValue interface {
|
type IntValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() int;
|
Get() int; // Get the underlying int.
|
||||||
Set(int);
|
Set(int); // Set the underlying int.
|
||||||
}
|
}
|
||||||
|
|
||||||
type intValueStruct struct {
|
type intValueStruct struct {
|
||||||
|
|
@ -103,10 +115,11 @@ func (v *intValueStruct) Set(i int) {
|
||||||
|
|
||||||
// -- Int8
|
// -- Int8
|
||||||
|
|
||||||
|
// Int8Value represents an int8 value.
|
||||||
type Int8Value interface {
|
type Int8Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() int8;
|
Get() int8; // Get the underlying int8.
|
||||||
Set(int8);
|
Set(int8); // Set the underlying int8.
|
||||||
}
|
}
|
||||||
|
|
||||||
type int8ValueStruct struct {
|
type int8ValueStruct struct {
|
||||||
|
|
@ -127,10 +140,11 @@ func (v *int8ValueStruct) Set(i int8) {
|
||||||
|
|
||||||
// -- Int16
|
// -- Int16
|
||||||
|
|
||||||
|
// Int16Value represents an int16 value.
|
||||||
type Int16Value interface {
|
type Int16Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() int16;
|
Get() int16; // Get the underlying int16.
|
||||||
Set(int16);
|
Set(int16); // Set the underlying int16.
|
||||||
}
|
}
|
||||||
|
|
||||||
type int16ValueStruct struct {
|
type int16ValueStruct struct {
|
||||||
|
|
@ -151,10 +165,11 @@ func (v *int16ValueStruct) Set(i int16) {
|
||||||
|
|
||||||
// -- Int32
|
// -- Int32
|
||||||
|
|
||||||
|
// Int32Value represents an int32 value.
|
||||||
type Int32Value interface {
|
type Int32Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() int32;
|
Get() int32; // Get the underlying int32.
|
||||||
Set(int32);
|
Set(int32); // Set the underlying int32.
|
||||||
}
|
}
|
||||||
|
|
||||||
type int32ValueStruct struct {
|
type int32ValueStruct struct {
|
||||||
|
|
@ -175,10 +190,11 @@ func (v *int32ValueStruct) Set(i int32) {
|
||||||
|
|
||||||
// -- Int64
|
// -- Int64
|
||||||
|
|
||||||
|
// Int64Value represents an int64 value.
|
||||||
type Int64Value interface {
|
type Int64Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() int64;
|
Get() int64; // Get the underlying int64.
|
||||||
Set(int64);
|
Set(int64); // Set the underlying int64.
|
||||||
}
|
}
|
||||||
|
|
||||||
type int64ValueStruct struct {
|
type int64ValueStruct struct {
|
||||||
|
|
@ -199,10 +215,11 @@ func (v *int64ValueStruct) Set(i int64) {
|
||||||
|
|
||||||
// -- Uint
|
// -- Uint
|
||||||
|
|
||||||
|
// UintValue represents a uint value.
|
||||||
type UintValue interface {
|
type UintValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() uint;
|
Get() uint; // Get the underlying uint.
|
||||||
Set(uint);
|
Set(uint); // Set the underlying uint.
|
||||||
}
|
}
|
||||||
|
|
||||||
type uintValueStruct struct {
|
type uintValueStruct struct {
|
||||||
|
|
@ -223,10 +240,11 @@ func (v *uintValueStruct) Set(i uint) {
|
||||||
|
|
||||||
// -- Uint8
|
// -- Uint8
|
||||||
|
|
||||||
|
// Uint8Value represents a uint8 value.
|
||||||
type Uint8Value interface {
|
type Uint8Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() uint8;
|
Get() uint8; // Get the underlying uint8.
|
||||||
Set(uint8);
|
Set(uint8); // Set the underlying uint8.
|
||||||
}
|
}
|
||||||
|
|
||||||
type uint8ValueStruct struct {
|
type uint8ValueStruct struct {
|
||||||
|
|
@ -247,10 +265,11 @@ func (v *uint8ValueStruct) Set(i uint8) {
|
||||||
|
|
||||||
// -- Uint16
|
// -- Uint16
|
||||||
|
|
||||||
|
// Uint16Value represents a uint16 value.
|
||||||
type Uint16Value interface {
|
type Uint16Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() uint16;
|
Get() uint16; // Get the underlying uint16.
|
||||||
Set(uint16);
|
Set(uint16); // Set the underlying uint16.
|
||||||
}
|
}
|
||||||
|
|
||||||
type uint16ValueStruct struct {
|
type uint16ValueStruct struct {
|
||||||
|
|
@ -271,10 +290,11 @@ func (v *uint16ValueStruct) Set(i uint16) {
|
||||||
|
|
||||||
// -- Uint32
|
// -- Uint32
|
||||||
|
|
||||||
|
// Uint32Value represents a uint32 value.
|
||||||
type Uint32Value interface {
|
type Uint32Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() uint32;
|
Get() uint32; // Get the underlying uint32.
|
||||||
Set(uint32);
|
Set(uint32); // Set the underlying uint32.
|
||||||
}
|
}
|
||||||
|
|
||||||
type uint32ValueStruct struct {
|
type uint32ValueStruct struct {
|
||||||
|
|
@ -295,10 +315,11 @@ func (v *uint32ValueStruct) Set(i uint32) {
|
||||||
|
|
||||||
// -- Uint64
|
// -- Uint64
|
||||||
|
|
||||||
|
// Uint64Value represents a uint64 value.
|
||||||
type Uint64Value interface {
|
type Uint64Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() uint64;
|
Get() uint64; // Get the underlying uint64.
|
||||||
Set(uint64);
|
Set(uint64); // Set the underlying uint64.
|
||||||
}
|
}
|
||||||
|
|
||||||
type uint64ValueStruct struct {
|
type uint64ValueStruct struct {
|
||||||
|
|
@ -319,10 +340,11 @@ func (v *uint64ValueStruct) Set(i uint64) {
|
||||||
|
|
||||||
// -- Uintptr
|
// -- Uintptr
|
||||||
|
|
||||||
|
// UintptrValue represents a uintptr value.
|
||||||
type UintptrValue interface {
|
type UintptrValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() uintptr;
|
Get() uintptr; // Get the underlying uintptr.
|
||||||
Set(uintptr);
|
Set(uintptr); // Set the underlying uintptr.
|
||||||
}
|
}
|
||||||
|
|
||||||
type uintptrValueStruct struct {
|
type uintptrValueStruct struct {
|
||||||
|
|
@ -343,10 +365,11 @@ func (v *uintptrValueStruct) Set(i uintptr) {
|
||||||
|
|
||||||
// -- Float
|
// -- Float
|
||||||
|
|
||||||
|
// FloatValue represents a float value.
|
||||||
type FloatValue interface {
|
type FloatValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() float;
|
Get() float; // Get the underlying float.
|
||||||
Set(float);
|
Set(float); // Get the underlying float.
|
||||||
}
|
}
|
||||||
|
|
||||||
type floatValueStruct struct {
|
type floatValueStruct struct {
|
||||||
|
|
@ -367,10 +390,11 @@ func (v *floatValueStruct) Set(f float) {
|
||||||
|
|
||||||
// -- Float32
|
// -- Float32
|
||||||
|
|
||||||
|
// Float32Value represents a float32 value.
|
||||||
type Float32Value interface {
|
type Float32Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() float32;
|
Get() float32; // Get the underlying float32.
|
||||||
Set(float32);
|
Set(float32); // Get the underlying float32.
|
||||||
}
|
}
|
||||||
|
|
||||||
type float32ValueStruct struct {
|
type float32ValueStruct struct {
|
||||||
|
|
@ -391,10 +415,11 @@ func (v *float32ValueStruct) Set(f float32) {
|
||||||
|
|
||||||
// -- Float64
|
// -- Float64
|
||||||
|
|
||||||
|
// Float64Value represents a float64 value.
|
||||||
type Float64Value interface {
|
type Float64Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() float64;
|
Get() float64; // Get the underlying float64.
|
||||||
Set(float64);
|
Set(float64); // Get the underlying float64.
|
||||||
}
|
}
|
||||||
|
|
||||||
type float64ValueStruct struct {
|
type float64ValueStruct struct {
|
||||||
|
|
@ -415,10 +440,11 @@ func (v *float64ValueStruct) Set(f float64) {
|
||||||
|
|
||||||
// -- Float80
|
// -- Float80
|
||||||
|
|
||||||
|
// Float80Value represents a float80 value.
|
||||||
type Float80Value interface {
|
type Float80Value interface {
|
||||||
Value;
|
Value;
|
||||||
Get() float80;
|
Get() float80; // Get the underlying float80.
|
||||||
Set(float80);
|
Set(float80); // Get the underlying float80.
|
||||||
}
|
}
|
||||||
|
|
||||||
type float80ValueStruct struct {
|
type float80ValueStruct struct {
|
||||||
|
|
@ -442,10 +468,11 @@ func (v *Float80ValueStruct) Set(f float80) {
|
||||||
|
|
||||||
// -- String
|
// -- String
|
||||||
|
|
||||||
|
// StringValue represents a string value.
|
||||||
type StringValue interface {
|
type StringValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() string;
|
Get() string; // Get the underlying string value.
|
||||||
Set(string);
|
Set(string); // Set the underlying string value.
|
||||||
}
|
}
|
||||||
|
|
||||||
type stringValueStruct struct {
|
type stringValueStruct struct {
|
||||||
|
|
@ -466,10 +493,11 @@ func (v *stringValueStruct) Set(s string) {
|
||||||
|
|
||||||
// -- Bool
|
// -- Bool
|
||||||
|
|
||||||
|
// BoolValue represents a bool value.
|
||||||
type BoolValue interface {
|
type BoolValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() bool;
|
Get() bool; // Get the underlying bool value.
|
||||||
Set(bool);
|
Set(bool); // Set the underlying bool value.
|
||||||
}
|
}
|
||||||
|
|
||||||
type boolValueStruct struct {
|
type boolValueStruct struct {
|
||||||
|
|
@ -490,11 +518,12 @@ func (v *boolValueStruct) Set(b bool) {
|
||||||
|
|
||||||
// -- Pointer
|
// -- Pointer
|
||||||
|
|
||||||
|
// PtrValue represents a pointer value.
|
||||||
type PtrValue interface {
|
type PtrValue interface {
|
||||||
Value;
|
Value;
|
||||||
Sub() Value;
|
Sub() Value; // The Value pointed to.
|
||||||
Get() Addr;
|
Get() Addr; // Get the address stored in the pointer.
|
||||||
SetSub(Value);
|
SetSub(Value); // Set the the pointed-to Value.
|
||||||
}
|
}
|
||||||
|
|
||||||
type ptrValueStruct struct {
|
type ptrValueStruct struct {
|
||||||
|
|
@ -526,15 +555,16 @@ func ptrCreator(typ Type, addr Addr) Value {
|
||||||
// -- Array
|
// -- Array
|
||||||
// Slices and arrays are represented by the same interface.
|
// Slices and arrays are represented by the same interface.
|
||||||
|
|
||||||
|
// ArrayValue represents an array or slice value.
|
||||||
type ArrayValue interface {
|
type ArrayValue interface {
|
||||||
Value;
|
Value;
|
||||||
IsSlice() bool;
|
IsSlice() bool; // Is this a slice (true) or array (false)?
|
||||||
Len() int;
|
Len() int; // The length of the array/slice.
|
||||||
Cap() int;
|
Cap() int; // The capacity of the array/slice (==Len() for arrays).
|
||||||
Elem(i int) Value;
|
Elem(i int) Value; // The Value of the i'th element.
|
||||||
SetLen(len int);
|
SetLen(len int); // Set the length; slice only.
|
||||||
Set(src ArrayValue);
|
Set(src ArrayValue); // Set the underlying Value; slice only for src and dest both.
|
||||||
CopyFrom(src ArrayValue, n int)
|
CopyFrom(src ArrayValue, n int) // Copy the elements from src; lengths must match.
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyArray(dst ArrayValue, src ArrayValue, n int);
|
func copyArray(dst ArrayValue, src ArrayValue, n int);
|
||||||
|
|
@ -581,7 +611,7 @@ func (v *sliceValueStruct) SetLen(len int) {
|
||||||
|
|
||||||
func (v *sliceValueStruct) Set(src ArrayValue) {
|
func (v *sliceValueStruct) Set(src ArrayValue) {
|
||||||
if !src.IsSlice() {
|
if !src.IsSlice() {
|
||||||
panic("can't set from fixed array");
|
panic("can't set slice from array");
|
||||||
}
|
}
|
||||||
s := src.(*sliceValueStruct);
|
s := src.(*sliceValueStruct);
|
||||||
if !equalType(v.typ, s.typ) {
|
if !equalType(v.typ, s.typ) {
|
||||||
|
|
@ -619,10 +649,11 @@ func (v *arrayValueStruct) Cap() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *arrayValueStruct) SetLen(len int) {
|
func (v *arrayValueStruct) SetLen(len int) {
|
||||||
|
panicln("can't set len of array");
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *arrayValueStruct) Set(src ArrayValue) {
|
func (v *arrayValueStruct) Set(src ArrayValue) {
|
||||||
panicln("can't set fixed array");
|
panicln("can't set array");
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *arrayValueStruct) Elem(i int) Value {
|
func (v *arrayValueStruct) Elem(i int) Value {
|
||||||
|
|
@ -659,10 +690,12 @@ func arrayCreator(typ Type, addr Addr) Value {
|
||||||
|
|
||||||
// -- Map TODO: finish and test
|
// -- Map TODO: finish and test
|
||||||
|
|
||||||
|
// MapValue represents a map value.
|
||||||
|
// Its implementation is incomplete.
|
||||||
type MapValue interface {
|
type MapValue interface {
|
||||||
Value;
|
Value;
|
||||||
Len() int;
|
Len() int; // The number of elements; currently always returns 0.
|
||||||
Elem(key Value) Value;
|
Elem(key Value) Value; // The value indexed by key; unimplemented.
|
||||||
}
|
}
|
||||||
|
|
||||||
type mapValueStruct struct {
|
type mapValueStruct struct {
|
||||||
|
|
@ -684,6 +717,8 @@ func (v *mapValueStruct) Elem(key Value) Value {
|
||||||
|
|
||||||
// -- Chan
|
// -- Chan
|
||||||
|
|
||||||
|
// ChanValue represents a chan value.
|
||||||
|
// Its implementation is incomplete.
|
||||||
type ChanValue interface {
|
type ChanValue interface {
|
||||||
Value;
|
Value;
|
||||||
}
|
}
|
||||||
|
|
@ -698,10 +733,11 @@ func chanCreator(typ Type, addr Addr) Value {
|
||||||
|
|
||||||
// -- Struct
|
// -- Struct
|
||||||
|
|
||||||
|
// StructValue represents a struct value.
|
||||||
type StructValue interface {
|
type StructValue interface {
|
||||||
Value;
|
Value;
|
||||||
Len() int;
|
Len() int; // The number of fields.
|
||||||
Field(i int) Value;
|
Field(i int) Value; // The Value of field i.
|
||||||
}
|
}
|
||||||
|
|
||||||
type structValueStruct struct {
|
type structValueStruct struct {
|
||||||
|
|
@ -732,9 +768,10 @@ func structCreator(typ Type, addr Addr) Value {
|
||||||
|
|
||||||
// -- Interface
|
// -- Interface
|
||||||
|
|
||||||
|
// InterfaceValue represents an interface value.
|
||||||
type InterfaceValue interface {
|
type InterfaceValue interface {
|
||||||
Value;
|
Value;
|
||||||
Get() interface {};
|
Get() interface {}; // Get the underlying interface{} value.
|
||||||
}
|
}
|
||||||
|
|
||||||
type interfaceValueStruct struct {
|
type interfaceValueStruct struct {
|
||||||
|
|
@ -751,6 +788,9 @@ func interfaceCreator(typ Type, addr Addr) Value {
|
||||||
|
|
||||||
// -- Func
|
// -- Func
|
||||||
|
|
||||||
|
|
||||||
|
// FuncValue represents a func value.
|
||||||
|
// Its implementation is incomplete.
|
||||||
type FuncValue interface {
|
type FuncValue interface {
|
||||||
Value;
|
Value;
|
||||||
}
|
}
|
||||||
|
|
@ -801,6 +841,7 @@ func newValueAddr(typ Type, addr Addr) Value {
|
||||||
return c(typ, addr);
|
return c(typ, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewInitValue creates a new, zero-initialized Value for the specified Type.
|
||||||
func NewInitValue(typ Type) Value {
|
func NewInitValue(typ Type) Value {
|
||||||
// Some values cannot be made this way.
|
// Some values cannot be made this way.
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
|
|
@ -819,6 +860,8 @@ func NewInitValue(typ Type) Value {
|
||||||
return newValueAddr(typ, Addr(&data[0]));
|
return newValueAddr(typ, Addr(&data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSliceValue creates a new, zero-initialized slice value (ArrayValue) for the specified
|
||||||
|
// slice type (ArrayType), length, and capacity.
|
||||||
func NewSliceValue(typ ArrayType, len, cap int) ArrayValue {
|
func NewSliceValue(typ ArrayType, len, cap int) ArrayValue {
|
||||||
if !typ.IsSlice() {
|
if !typ.IsSlice() {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -869,7 +912,7 @@ func copyArray(dst ArrayValue, src ArrayValue, n int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewValue creates a new Value from the interface{} object provided.
|
||||||
func NewValue(e interface {}) Value {
|
func NewValue(e interface {}) Value {
|
||||||
value, typestring, indir := sys.Reflect(e);
|
value, typestring, indir := sys.Reflect(e);
|
||||||
typ, ok := typecache[typestring];
|
typ, ok := typecache[typestring];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue