2008-10-15 18:11:51 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2008-10-16 17:38:33 -06:00
|
|
|
// Reflection library.
|
2008-10-22 12:02:56 -06:00
|
|
|
// Formatting of types and values for debugging.
|
2008-10-16 17:38:33 -06:00
|
|
|
|
2008-10-15 18:11:51 -06:00
|
|
|
package reflect
|
|
|
|
|
|
|
|
import (
|
2008-10-16 12:12:02 -06:00
|
|
|
"reflect";
|
|
|
|
"strings";
|
2008-10-15 18:11:51 -06:00
|
|
|
)
|
|
|
|
|
2008-10-22 17:48:17 -06:00
|
|
|
export func TypeToString(typ Type, expand bool) string
|
2008-10-17 19:06:29 -06:00
|
|
|
export func ValueToString(val Value) string
|
2008-10-16 12:12:02 -06:00
|
|
|
|
2008-10-30 18:29:53 -06:00
|
|
|
func DoubleQuote(s string) string {
|
|
|
|
out := "\"";
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
c := s[i];
|
|
|
|
switch c {
|
|
|
|
case '\n':
|
|
|
|
out += `\n`;
|
|
|
|
case '\t':
|
|
|
|
out += `\t`;
|
|
|
|
case '\x00':
|
2008-10-31 16:26:14 -06:00
|
|
|
out += `\x00`;
|
2008-10-30 18:29:53 -06:00
|
|
|
case '"':
|
|
|
|
out += `\"`;
|
|
|
|
case '\\':
|
|
|
|
out += `\\`;
|
|
|
|
default:
|
|
|
|
out += string(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out += "\"";
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2008-10-22 12:02:56 -06:00
|
|
|
type HasFields interface {
|
2008-10-30 18:29:53 -06:00
|
|
|
Field(i int) (name string, typ Type, tag string, offset uint64);
|
2008-10-22 12:02:56 -06:00
|
|
|
Len() int;
|
|
|
|
}
|
|
|
|
|
|
|
|
func TypeFieldsToString(t HasFields, sep string) string {
|
2008-10-16 12:12:02 -06:00
|
|
|
var str string;
|
2008-10-22 12:02:56 -06:00
|
|
|
for i := 0; i < t.Len(); i++ {
|
2008-10-30 18:29:53 -06:00
|
|
|
str1, typ, tag, offset := t.Field(i);
|
2008-10-22 17:48:17 -06:00
|
|
|
str1 += " " + TypeToString(typ, false);
|
2008-10-30 18:29:53 -06:00
|
|
|
if tag != "" {
|
|
|
|
str1 += " " + DoubleQuote(tag);
|
|
|
|
}
|
2008-10-22 12:02:56 -06:00
|
|
|
if i < t.Len() - 1 {
|
2008-10-16 19:09:38 -06:00
|
|
|
str1 += sep + " ";
|
2008-10-16 12:12:02 -06:00
|
|
|
}
|
|
|
|
str += str1;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2008-10-22 17:48:17 -06:00
|
|
|
func TypeToString(typ Type, expand bool) string {
|
2008-10-16 12:12:02 -06:00
|
|
|
var str string;
|
2008-10-22 17:48:17 -06:00
|
|
|
if name := typ.Name(); !expand && name != "" {
|
2008-10-22 14:02:43 -06:00
|
|
|
return name
|
|
|
|
}
|
2008-10-15 18:11:51 -06:00
|
|
|
switch(typ.Kind()) {
|
2008-10-16 17:38:33 -06:00
|
|
|
case MissingKind:
|
2008-10-22 12:02:56 -06:00
|
|
|
return "$missing$";
|
2008-11-03 16:50:11 -07:00
|
|
|
case DotDotDotKind:
|
|
|
|
return "...";
|
2008-10-29 16:31:02 -06:00
|
|
|
case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind,
|
|
|
|
UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind,
|
|
|
|
FloatKind, Float32Kind, Float64Kind, Float80Kind:
|
|
|
|
StringKind:
|
|
|
|
return typ.Name();
|
2008-10-15 18:11:51 -06:00
|
|
|
case PtrKind:
|
|
|
|
p := typ.(PtrType);
|
2008-10-22 17:48:17 -06:00
|
|
|
return "*" + TypeToString(p.Sub(), false);
|
2008-10-15 18:11:51 -06:00
|
|
|
case ArrayKind:
|
|
|
|
a := typ.(ArrayType);
|
2008-10-22 12:02:56 -06:00
|
|
|
if a.Open() {
|
2008-10-16 12:12:02 -06:00
|
|
|
str = "[]"
|
2008-10-15 18:11:51 -06:00
|
|
|
} else {
|
2008-10-22 12:02:56 -06:00
|
|
|
str = "[" + strings.ltoa(int64(a.Len())) + "]"
|
2008-10-15 18:11:51 -06:00
|
|
|
}
|
2008-10-22 17:48:17 -06:00
|
|
|
return str + TypeToString(a.Elem(), false);
|
2008-10-15 18:11:51 -06:00
|
|
|
case MapKind:
|
|
|
|
m := typ.(MapType);
|
2008-10-22 17:48:17 -06:00
|
|
|
str = "map[" + TypeToString(m.Key(), false) + "]";
|
|
|
|
return str + TypeToString(m.Elem(), false);
|
2008-10-15 18:11:51 -06:00
|
|
|
case ChanKind:
|
|
|
|
c := typ.(ChanType);
|
|
|
|
switch c.Dir() {
|
|
|
|
case RecvDir:
|
2008-10-16 12:12:02 -06:00
|
|
|
str = "<-chan";
|
2008-10-15 18:11:51 -06:00
|
|
|
case SendDir:
|
2008-10-16 12:12:02 -06:00
|
|
|
str = "chan<-";
|
2008-10-15 18:11:51 -06:00
|
|
|
case BothDir:
|
2008-10-16 12:12:02 -06:00
|
|
|
str = "chan";
|
2008-10-15 18:11:51 -06:00
|
|
|
default:
|
2008-10-17 19:06:29 -06:00
|
|
|
panicln("reflect.TypeToString: unknown chan direction");
|
2008-10-15 18:11:51 -06:00
|
|
|
}
|
2008-10-22 17:48:17 -06:00
|
|
|
return str + TypeToString(c.Elem(), false);
|
2008-10-15 18:11:51 -06:00
|
|
|
case StructKind:
|
2008-10-17 19:06:29 -06:00
|
|
|
return "struct{" + TypeFieldsToString(typ, ";") + "}";
|
2008-10-16 19:09:38 -06:00
|
|
|
case InterfaceKind:
|
2008-10-17 19:06:29 -06:00
|
|
|
return "interface{" + TypeFieldsToString(typ, ";") + "}";
|
2008-10-15 18:11:51 -06:00
|
|
|
case FuncKind:
|
|
|
|
f := typ.(FuncType);
|
2008-10-22 12:02:56 -06:00
|
|
|
str = "(" + TypeFieldsToString(f.In(), ",") + ")";
|
2008-10-15 18:11:51 -06:00
|
|
|
if f.Out() != nil {
|
2008-10-17 19:06:29 -06:00
|
|
|
str += "(" + TypeFieldsToString(f.Out(), ",") + ")";
|
2008-10-15 18:11:51 -06:00
|
|
|
}
|
2008-10-16 12:12:02 -06:00
|
|
|
return str;
|
2008-10-15 18:11:51 -06:00
|
|
|
default:
|
2008-10-17 19:06:29 -06:00
|
|
|
panicln("reflect.TypeToString: can't print type ", typ.Kind());
|
2008-10-15 18:11:51 -06:00
|
|
|
}
|
2008-10-17 19:06:29 -06:00
|
|
|
return "reflect.TypeToString: can't happen";
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: want an unsigned one too
|
|
|
|
func integer(v int64) string {
|
2008-10-22 12:02:56 -06:00
|
|
|
return strings.ltoa(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
func floatingpoint(v float64) string {
|
|
|
|
return strings.dtoa(v);
|
2008-10-17 19:06:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func ValueToString(val Value) string {
|
|
|
|
var str string;
|
|
|
|
typ := val.Type();
|
|
|
|
switch(val.Kind()) {
|
|
|
|
case MissingKind:
|
|
|
|
return "missing";
|
2008-10-29 16:31:02 -06:00
|
|
|
case IntKind:
|
|
|
|
return integer(int64(val.(IntValue).Get()));
|
2008-10-17 19:06:29 -06:00
|
|
|
case Int8Kind:
|
|
|
|
return integer(int64(val.(Int8Value).Get()));
|
|
|
|
case Int16Kind:
|
|
|
|
return integer(int64(val.(Int16Value).Get()));
|
|
|
|
case Int32Kind:
|
|
|
|
return integer(int64(val.(Int32Value).Get()));
|
|
|
|
case Int64Kind:
|
|
|
|
return integer(int64(val.(Int64Value).Get()));
|
2008-10-29 16:31:02 -06:00
|
|
|
case UintKind:
|
|
|
|
return integer(int64(val.(UintValue).Get()));
|
2008-10-17 19:06:29 -06:00
|
|
|
case Uint8Kind:
|
|
|
|
return integer(int64(val.(Uint8Value).Get()));
|
|
|
|
case Uint16Kind:
|
|
|
|
return integer(int64(val.(Uint16Value).Get()));
|
|
|
|
case Uint32Kind:
|
|
|
|
return integer(int64(val.(Uint32Value).Get()));
|
|
|
|
case Uint64Kind:
|
|
|
|
return integer(int64(val.(Uint64Value).Get()));
|
2008-10-29 16:31:02 -06:00
|
|
|
case FloatKind:
|
|
|
|
return floatingpoint(float64(val.(FloatValue).Get()));
|
2008-10-17 19:06:29 -06:00
|
|
|
case Float32Kind:
|
2008-10-22 12:02:56 -06:00
|
|
|
return floatingpoint(float64(val.(Float32Value).Get()));
|
2008-10-17 19:06:29 -06:00
|
|
|
case Float64Kind:
|
2008-10-22 12:02:56 -06:00
|
|
|
return floatingpoint(float64(val.(Float64Value).Get()));
|
2008-10-17 19:06:29 -06:00
|
|
|
case Float80Kind:
|
|
|
|
return "float80";
|
|
|
|
case StringKind:
|
|
|
|
return val.(StringValue).Get();
|
2008-10-31 17:34:47 -06:00
|
|
|
case BoolKind:
|
|
|
|
if val.(BoolValue).Get() {
|
|
|
|
return "true"
|
|
|
|
} else {
|
|
|
|
return "false"
|
|
|
|
}
|
2008-10-17 19:06:29 -06:00
|
|
|
case PtrKind:
|
2008-10-22 12:02:56 -06:00
|
|
|
v := val.(PtrValue);
|
2008-10-24 17:33:29 -06:00
|
|
|
return TypeToString(typ, false) + "(" + integer(int64(v.Get())) + ")";
|
2008-10-22 12:02:56 -06:00
|
|
|
case ArrayKind:
|
|
|
|
t := typ.(ArrayType);
|
|
|
|
v := val.(ArrayValue);
|
2008-10-22 17:48:17 -06:00
|
|
|
str += TypeToString(t, false);
|
2008-10-22 12:02:56 -06:00
|
|
|
str += "{";
|
2008-10-22 17:48:17 -06:00
|
|
|
for i := uint64(0); i < v.Len(); i++ {
|
2008-10-22 12:02:56 -06:00
|
|
|
if i > 0 {
|
|
|
|
str += ", "
|
|
|
|
}
|
|
|
|
str += ValueToString(v.Elem(i));
|
|
|
|
}
|
|
|
|
str += "}";
|
|
|
|
return str;
|
|
|
|
case MapKind:
|
|
|
|
t := typ.(MapType);
|
|
|
|
v := val.(ArrayValue);
|
2008-10-22 17:48:17 -06:00
|
|
|
str = TypeToString(t, false);
|
2008-10-22 12:02:56 -06:00
|
|
|
str += "{";
|
|
|
|
str += "<can't iterate on maps>";
|
|
|
|
str += "}";
|
|
|
|
return str;
|
|
|
|
case ChanKind:
|
|
|
|
return "can't print chans yet";
|
|
|
|
case StructKind:
|
|
|
|
t := typ.(StructType);
|
|
|
|
v := val.(StructValue);
|
2008-10-22 17:48:17 -06:00
|
|
|
str += TypeToString(t, false);
|
2008-10-22 12:02:56 -06:00
|
|
|
str += "{";
|
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
if i > 0 {
|
|
|
|
str += ", "
|
|
|
|
}
|
|
|
|
str += ValueToString(v.Field(i));
|
|
|
|
}
|
|
|
|
str += "}";
|
|
|
|
return str;
|
|
|
|
case InterfaceKind:
|
|
|
|
return "can't print interfaces yet";
|
|
|
|
case FuncKind:
|
|
|
|
return "can't print funcs yet";
|
2008-10-17 19:06:29 -06:00
|
|
|
default:
|
|
|
|
panicln("reflect.ValueToString: can't print type ", val.Kind());
|
|
|
|
}
|
|
|
|
return "reflect.ValueToString: can't happen";
|
2008-10-15 18:11:51 -06:00
|
|
|
}
|