summaryrefslogtreecommitdiff
path: root/src/pkg/reflect/tostring.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/reflect/tostring.go')
-rw-r--r--src/pkg/reflect/tostring.go234
1 files changed, 234 insertions, 0 deletions
diff --git a/src/pkg/reflect/tostring.go b/src/pkg/reflect/tostring.go
new file mode 100644
index 000000000..43be4b9e8
--- /dev/null
+++ b/src/pkg/reflect/tostring.go
@@ -0,0 +1,234 @@
+// 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.
+
+// Reflection library.
+// 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
+
+import (
+ "reflect";
+ "strconv";
+)
+
+func typeToString(typ Type, expand bool) string
+func valueToString(val Value) string
+
+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':
+ out += `\x00`;
+ case '"':
+ out += `\"`;
+ case '\\':
+ out += `\\`;
+ default:
+ out += string(c);
+ }
+ }
+ out += "\"";
+ return out;
+}
+
+type hasFields interface {
+ Field(i int) (name string, typ Type, tag string, offset int);
+ Len() int;
+}
+
+func typeFieldsToString(t hasFields, sep string, iface bool) string {
+ var str string;
+ for i := 0; i < t.Len(); i++ {
+ str1, typ, tag, offset := t.Field(i);
+ if str1 != "" {
+ str1 += " "
+ }
+ str2 := typeToString(typ, false);
+ if iface && str2[0:4] == "func" {
+ str2 = str2[4:len(str2)]
+ }
+ str1 += str2;
+ if tag != "" {
+ str1 += " " + doubleQuote(tag);
+ }
+ if i < t.Len() - 1 {
+ str1 += sep + " ";
+ }
+ str += str1;
+ }
+ return str;
+}
+
+// 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;
+ if name := typ.Name(); !expand && name != "" {
+ return name
+ }
+ switch(typ.Kind()) {
+ case MissingKind:
+ return "$missing$";
+ case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind,
+ UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind,
+ FloatKind, Float32Kind, Float64Kind,
+ StringKind,
+ DotDotDotKind:
+ return typ.Name();
+ case PtrKind:
+ p := typ.(PtrType);
+ return "*" + typeToString(p.Sub(), false);
+ case ArrayKind:
+ a := typ.(ArrayType);
+ if a.IsSlice() {
+ str = "[]"
+ } else {
+ str = "[" + strconv.Itoa64(int64(a.Len())) + "]"
+ }
+ return str + typeToString(a.Elem(), false);
+ case MapKind:
+ m := typ.(MapType);
+ str = "map[" + typeToString(m.Key(), false) + "]";
+ return str + typeToString(m.Elem(), false);
+ case ChanKind:
+ c := typ.(ChanType);
+ switch c.Dir() {
+ case RecvDir:
+ str = "<-chan";
+ case SendDir:
+ str = "chan<-";
+ case BothDir:
+ str = "chan";
+ default:
+ panicln("reflect.typeToString: unknown chan direction");
+ }
+ return str + typeToString(c.Elem(), false);
+ case StructKind:
+ return "struct{" + typeFieldsToString(typ.(StructType), ";", false) + "}";
+ case InterfaceKind:
+ return "interface{" + typeFieldsToString(typ.(InterfaceType), ";", true) + "}";
+ case FuncKind:
+ f := typ.(FuncType);
+ str = "func(" + typeFieldsToString(f.In(), ",", false) + ")";
+ if f.Out() != nil {
+ str += "(" + typeFieldsToString(f.Out(), ",", false) + ")";
+ }
+ return str;
+ default:
+ panicln("reflect.typeToString: can't print type ", typ.Kind());
+ }
+ return "reflect.typeToString: can't happen";
+}
+
+// TODO: want an unsigned one too
+func integer(v int64) string {
+ return strconv.Itoa64(v);
+}
+
+// valueToString returns a textual representation of the reflection value val.
+// For debugging only.
+func valueToString(val Value) string {
+ var str string;
+ typ := val.Type();
+ switch(val.Kind()) {
+ case MissingKind:
+ return "missing";
+ case IntKind:
+ return integer(int64(val.(IntValue).Get()));
+ 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()));
+ case UintKind:
+ return integer(int64(val.(UintValue).Get()));
+ 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()));
+ case FloatKind:
+ if strconv.FloatSize == 32 {
+ return strconv.Ftoa32(float32(val.(FloatValue).Get()), 'g', -1);
+ } else {
+ return strconv.Ftoa64(float64(val.(FloatValue).Get()), 'g', -1);
+ }
+ case Float32Kind:
+ return strconv.Ftoa32(val.(Float32Value).Get(), 'g', -1);
+ case Float64Kind:
+ return strconv.Ftoa64(val.(Float64Value).Get(), 'g', -1);
+ case StringKind:
+ return val.(StringValue).Get();
+ case BoolKind:
+ if val.(BoolValue).Get() {
+ return "true"
+ } else {
+ return "false"
+ }
+ case PtrKind:
+ v := val.(PtrValue);
+ return typeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")";
+ case ArrayKind:
+ t := typ.(ArrayType);
+ v := val.(ArrayValue);
+ str += typeToString(t, false);
+ str += "{";
+ for i := 0; i < v.Len(); i++ {
+ if i > 0 {
+ str += ", "
+ }
+ str += valueToString(v.Elem(i));
+ }
+ str += "}";
+ return str;
+ case MapKind:
+ t := typ.(MapType);
+ v := val.(MapValue);
+ str = typeToString(t, false);
+ str += "{";
+ str += "<can't iterate on maps>";
+ str += "}";
+ return str;
+ case ChanKind:
+ str = typeToString(typ, false);
+ return str;
+ case StructKind:
+ t := typ.(StructType);
+ v := val.(StructValue);
+ str += typeToString(t, false);
+ 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:
+ v := val.(FuncValue);
+ return typeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")";
+ default:
+ panicln("reflect.valueToString: can't print type ", val.Kind());
+ }
+ return "reflect.valueToString: can't happen";
+}