Commit 3bc6fd63 authored by Rob Pike's avatar Rob Pike

document reflect.

R=rsc
DELTA=201  (90 added, 0 deleted, 111 changed)
OCL=25904
CL=25966
parent 5bd5242b
...@@ -43,7 +43,7 @@ func assert(s, t string) { ...@@ -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) { ...@@ -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 ...@@ -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 @@ ...@@ -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 ( ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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 ...@@ -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 ( ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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)); ...@@ -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() { ...@@ -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 { ...@@ -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 { ...@@ -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 ( ...@@ -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 ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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];
......
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