]> Cypherpunks repositories - gostls13.git/commitdiff
beginnings of reflection values.
authorRob Pike <r@golang.org>
Sat, 18 Oct 2008 01:06:29 +0000 (18:06 -0700)
committerRob Pike <r@golang.org>
Sat, 18 Oct 2008 01:06:29 +0000 (18:06 -0700)
R=rsc
DELTA=421  (357 added, 17 deleted, 47 changed)
OCL=17388
CL=17401

usr/r/reflect/Makefile
usr/r/reflect/cast_amd64.s [new file with mode: 0644]
usr/r/reflect/gencast.sh [new file with mode: 0755]
usr/r/reflect/main.go
usr/r/reflect/tostring.go
usr/r/reflect/type.go

index ffd1f14bcc8479c28f10261aff352cfd742c62a2..1d999f4e0a1f6d7e9c55afcab46284c8a5f8062a 100644 (file)
@@ -3,7 +3,7 @@
 # license that can be found in the LICENSE file.
 
 # DO NOT EDIT.  Automatically generated by gobuild.
-# gobuild -m reflect tostring.go type.go
+# gobuild -m reflect tostring.go type.go value.go cast_amd64.s
 O=6
 GC=$(O)g
 CC=$(O)c -w
@@ -32,16 +32,23 @@ clean:
 
 O1=\
        type.$O\
+       cast_amd64.$O\
 
 O2=\
+       value.$O\
+
+O3=\
        tostring.$O\
 
-$(PKG): a1 a2
+$(PKG): a1 a2 a3
 a1:    $(O1)
        $(AR) grc $(PKG) $(O1)
 a2:    $(O2)
        $(AR) grc $(PKG) $(O2)
+a3:    $(O3)
+       $(AR) grc $(PKG) $(O3)
 
 $(O1): nuke
 $(O2): a1
+$(O3): a2
 
diff --git a/usr/r/reflect/cast_amd64.s b/usr/r/reflect/cast_amd64.s
new file mode 100644 (file)
index 0000000..1de31dd
--- /dev/null
@@ -0,0 +1,133 @@
+// Conversion operators - really just casts
+// *** Created by gencast.sh - Do Not Edit ***
+
+TEXT reflect·AddrToPtrAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrAddrToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrInt8(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrInt8ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrInt16(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrInt16ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrInt32(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrInt32ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrInt64(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrInt64ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrUint8(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrUint8ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrUint16(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrUint16ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrUint32(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrUint32ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrUint64(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrUint64ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrFloat32(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrFloat32ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrFloat64(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrFloat64ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrFloat80(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrFloat80ToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·AddrToPtrString(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
+TEXT reflect·PtrStringToAddr(SB),7,$-8
+       MOVQ    8(SP), AX
+       MOVQ    AX, 16(SP)
+       RET
+
diff --git a/usr/r/reflect/gencast.sh b/usr/r/reflect/gencast.sh
new file mode 100755 (executable)
index 0000000..e3871a5
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+# 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.
+
+awk '
+BEGIN {
+       print("// Conversion operators - really just casts")
+       print("// *** Created by gencast.sh - Do Not Edit ***\n")}
+{
+       print("TEXT reflect·AddrToPtr" $0 "(SB),7,$-8")
+       print("\tMOVQ   8(SP), AX")
+       print("\tMOVQ   AX, 16(SP)")
+       print("\tRET")
+       print("")
+       print("TEXT reflect·Ptr" $0 "ToAddr(SB),7,$-8")
+       print("\tMOVQ   8(SP), AX")
+       print("\tMOVQ   AX, 16(SP)")
+       print("\tRET")
+       print("")
+}
+' > cast_$GOARCH.s << '!'
+Addr
+Int8
+Int16
+Int32
+Int64
+Uint8
+Uint16
+Uint32
+Uint64
+Float32
+Float64
+Float80
+String
+!
index 0348cef9fef78e79eb0e09a877de2811432ca67c..1967ed7c3901840127c69a84aebb692689e7b822 100644 (file)
@@ -8,37 +8,79 @@ import (
        "reflect"
 )
 
+func typedump(s string) {
+       t := reflect.ParseTypeString(s);
+       print(reflect.TypeToString(t),"; size = ", t.Size(), "\n");
+}
+
+func valuedump(s string) {
+       t := reflect.ParseTypeString(s);
+       v := reflect.NewInitValue(t);
+       switch v.Kind() {
+       case reflect.Int8Kind:
+               v.(reflect.Int8Value).Put(8);
+       case reflect.Int16Kind:
+               v.(reflect.Int16Value).Put(16);
+       case reflect.Int32Kind:
+               v.(reflect.Int32Value).Put(32);
+       case reflect.Int64Kind:
+               v.(reflect.Int64Value).Put(64);
+       case reflect.Uint8Kind:
+               v.(reflect.Uint8Value).Put(8);
+       case reflect.Uint16Kind:
+               v.(reflect.Uint16Value).Put(16);
+       case reflect.Uint32Kind:
+               v.(reflect.Uint32Value).Put(32);
+       case reflect.Uint64Kind:
+               v.(reflect.Uint64Value).Put(64);
+       case reflect.Float32Kind:
+               v.(reflect.Float32Value).Put(320.0);
+       case reflect.Float64Kind:
+               v.(reflect.Float32Value).Put(640.0);
+       case reflect.StringKind:
+               v.(reflect.StringValue).Put("stringy cheese");
+       }
+       print(s, " value = ", reflect.ValueToString(v), "\n");
+}
+
 func main() {
        var s string;
        var t reflect.Type;
-
-       t = reflect.ParseTypeString("int8");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("**int8");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("**P.integer");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("[32]int32");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("[]int8");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("map[string]int32");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("*chan<-string");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("struct {c *chan *int32; d float32}");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("*(a int8, b int32)");
-       s = reflect.ToString(t); print(s, "\n");
-
-       t = reflect.ParseTypeString("struct {c *(? *chan *P.integer, ? *int8)}");
-       s = reflect.ToString(t); print(s, "\n");
+       
+       typedump("int8");
+       typedump("int16");
+       typedump("int32");
+       typedump("int64");
+       typedump("uint8");
+       typedump("uint16");
+       typedump("uint32");
+       typedump("uint64");
+       typedump("float32");
+       typedump("float64");
+       typedump("float80");
+       typedump("int8");
+       typedump("**int8");
+       typedump("**P.integer");
+       typedump("[32]int32");
+       typedump("[]int8");
+       typedump("*map[string]int32");
+       typedump("*chan<-string");
+       typedump("struct {c *chan *int32; d float32}");
+       typedump("*(a int8, b int32)");
+       typedump("struct {c *(? *chan *P.integer, ? *int8)}");
+       typedump("struct {a int8; b int32}");
+       typedump("struct {a int8; b int8; b int32}");
+       typedump("struct {a int8; b int8; c int8; b int32}");
+       typedump("struct {a int8; b int8; c int8; d int8; b int32}");
+       typedump("struct {a int8; b int8; c int8; d int8; e int8; b int32}");
+       
+       valuedump("int8");
+       valuedump("int16");
+       valuedump("int32");
+       valuedump("int64");
+       valuedump("uint8");
+       valuedump("uint16");
+       valuedump("uint32");
+       valuedump("uint64");
+       valuedump("string");
 }
index 09b6945a2a31b31c07852abfd0dbfd49caa60bde..0449a6e9e0fc6481739264ecae197972ce42d26a 100644 (file)
@@ -12,14 +12,15 @@ import (
        "strings";
 )
 
-export func ToString(typ Type) string
+export func TypeToString(typ Type) string
+export func ValueToString(val Value) string
 
-func FieldsToString(t Type, sep string) string {
+func TypeFieldsToString(t Type, sep string) string {
        s := t.(StructType);
        var str string;
        for i := 0; i < s.Len(); i++ {
                str1, t := s.Field(i);
-               str1 +=  " " + ToString(t);
+               str1 +=  " " + TypeToString(t);
                if i < s.Len() - 1 {
                        str1 += sep + " ";
                }
@@ -28,7 +29,7 @@ func FieldsToString(t Type, sep string) string {
        return str;
 }
 
-func ToString(typ Type) string {
+func TypeToString(typ Type) string {
        var str string;
        switch(typ.Kind()) {
        case MissingKind:
@@ -59,7 +60,7 @@ func ToString(typ Type) string {
                return "string";
        case PtrKind:
                p := typ.(PtrType);
-               return "*" + ToString(p.Sub());
+               return "*" + TypeToString(p.Sub());
        case ArrayKind:
                a := typ.(ArrayType);
                if a.Len() < 0 {
@@ -67,11 +68,11 @@ func ToString(typ Type) string {
                } else {
                        str = "[" + strings.itoa(a.Len()) +  "]"
                }
-               return str + ToString(a.Elem());
+               return str + TypeToString(a.Elem());
        case MapKind:
                m := typ.(MapType);
-               str = "map[" + ToString(m.Key()) + "]";
-               return str + ToString(m.Elem());
+               str = "map[" + TypeToString(m.Key()) + "]";
+               return str + TypeToString(m.Elem());
        case ChanKind:
                c := typ.(ChanType);
                switch c.Dir() {
@@ -82,23 +83,67 @@ func ToString(typ Type) string {
                case BothDir:
                        str = "chan";
                default:
-                       panicln("reflect.ToString: unknown chan direction");
+                       panicln("reflect.TypeToString: unknown chan direction");
                }
-               return str + ToString(c.Elem());
+               return str + TypeToString(c.Elem());
        case StructKind:
-               return "struct{" + FieldsToString(typ, ";") + "}";
+               return "struct{" + TypeFieldsToString(typ, ";") + "}";
        case InterfaceKind:
-               return "interface{" + FieldsToString(typ, ";") + "}";
+               return "interface{" + TypeFieldsToString(typ, ";") + "}";
        case FuncKind:
                f := typ.(FuncType);
                str = "func";
-               str += "(" + FieldsToString(f.In(), ",") + ")";
+               str += "(" + TypeFieldsToString(f.In(), ",") + ")";
                if f.Out() != nil {
-                       str += "(" + FieldsToString(f.Out(), ",") + ")";
+                       str += "(" + TypeFieldsToString(f.Out(), ",") + ")";
                }
                return str;
        default:
-               panicln("reflect.ToString: can't print type ", typ.Kind());
+               panicln("reflect.TypeToString: can't print type ", typ.Kind());
        }
-       return "reflect.ToString: can't happen";
+       return "reflect.TypeToString: can't happen";
+}
+
+// TODO: want an unsigned one too
+func integer(v int64) string {
+       return strings.itol(v);
+}
+
+func ValueToString(val Value) string {
+       var str string;
+       typ := val.Type();
+       switch(val.Kind()) {
+       case MissingKind:
+               return "missing";
+       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 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 Float32Kind:
+               return "float32";
+       case Float64Kind:
+               return "float64";
+       case Float80Kind:
+               return "float80";
+       case StringKind:
+               return val.(StringValue).Get();
+       case PtrKind:
+               p := typ.(PtrType);
+               return ValueToString(p.Sub());
+       default:
+               panicln("reflect.ValueToString: can't print type ", val.Kind());
+       }
+       return "reflect.ValueToString: can't happen";
 }
index 965a3177b329702e69ae229e1b38f6a773f79d21..9ed6c75e9eab6a76a7d4086e63615f9cb16610c3 100644 (file)
@@ -36,45 +36,58 @@ export const (
        Uint8Kind;
 )
 
+var ptrsize int
+var interfacesize int
+
 var MissingString = "missing"  // syntactic name for undefined type names
 
-type Type interface {
+export type Type interface {
        Kind()  int;
+       Size()  int;
 }
 
+// -- Basic
+
 type BasicType struct{
-       kind    int
+       kind    int;
+       size    int;
 }
 
 func (t *BasicType) Kind() int {
        return t.kind
 }
 
-func NewBasicType(k int) Type {
+func (t *BasicType) Size() int {
+       return t.size
+}
+
+func NewBasicType(k, size int) Type {
        t := new(BasicType);
        t.kind = k;
+       t.size = size;
        return t;
 }
 
-// Basic types
+// Prebuilt basic types
 export var (
-       Missing = NewBasicType(MissingKind);
-       Int8 = NewBasicType(Int8Kind);
-       Int16 = NewBasicType(Int16Kind);
-       Int32 = NewBasicType(Int32Kind);
-       Int64 = NewBasicType(Int64Kind);
-       Uint8 = NewBasicType(Uint8Kind);
-       Uint16 = NewBasicType(Uint16Kind);
-       Uint32 = NewBasicType(Uint32Kind);
-       Uint64 = NewBasicType(Uint64Kind);
-       Float32 = NewBasicType(Float32Kind);
-       Float64 = NewBasicType(Float64Kind);
-       Float80 = NewBasicType(Float80Kind);
-       String = NewBasicType(StringKind);
+       Missing = NewBasicType(MissingKind, 1);
+       Int8 = NewBasicType(Int8Kind, 1);
+       Int16 = NewBasicType(Int16Kind, 2);
+       Int32 = NewBasicType(Int32Kind, 4);
+       Int64 = NewBasicType(Int64Kind, 8);
+       Uint8 = NewBasicType(Uint8Kind, 1);
+       Uint16 = NewBasicType(Uint16Kind, 2);
+       Uint32 = NewBasicType(Uint32Kind, 4);
+       Uint64 = NewBasicType(Uint64Kind, 8);
+       Float32 = NewBasicType(Float32Kind, 4);
+       Float64 = NewBasicType(Float64Kind, 8);
+       Float80 = NewBasicType(Float80Kind, 10);        // TODO: strange size?
+       String = NewBasicType(StringKind, 8);   // implemented as a pointer
 )
 
 // Stub types allow us to defer evaluating type names until needed.
 // If the name is empty, the type must be non-nil.
+
 type StubType struct {
        name    string;
        typ             Type;
@@ -99,6 +112,8 @@ func NewNamedStubType(n string) *StubType {
        return s;
 }
 
+// -- Pointer
+
 export type PtrType interface {
        Sub()   Type
 }
@@ -111,6 +126,10 @@ func (t *PtrTypeStruct) Kind() int {
        return PtrKind
 }
 
+func (t *PtrTypeStruct) Size() int {
+       return ptrsize
+}
+
 func (t *PtrTypeStruct) Sub() Type {
        return t.sub.Get()
 }
@@ -121,6 +140,8 @@ func NewPtrTypeStruct(sub *StubType) *PtrTypeStruct {
        return t;
 }
 
+// -- Array
+
 export type ArrayType interface {
        Len()   int;
        Elem()  Type;
@@ -135,6 +156,13 @@ func (t *ArrayTypeStruct) Kind() int {
        return ArrayKind
 }
 
+func (t *ArrayTypeStruct) Size() int {
+       if t.len < 0 {
+               return ptrsize  // open arrays are pointers to structures
+       }
+       return t.len * t.elem.Get().Size();
+}
+
 func (t *ArrayTypeStruct) Len() int {
        // -1 is open array?  TODO
        return t.len
@@ -151,6 +179,8 @@ func NewArrayTypeStruct(len int, elem *StubType) *ArrayTypeStruct {
        return t;
 }
 
+// -- Map
+
 export type MapType interface {
        Key()   Type;
        Elem()  Type;
@@ -165,6 +195,11 @@ func (t *MapTypeStruct) Kind() int {
        return MapKind
 }
 
+func (t *MapTypeStruct) Size() int {
+       panic("reflect.type: map.Size(): cannot happen");
+       return 0
+}
+
 func (t *MapTypeStruct) Key() Type {
        return t.key.Get()
 }
@@ -180,6 +215,8 @@ func NewMapTypeStruct(key, elem *StubType) *MapTypeStruct {
        return t;
 }
 
+// -- Chan
+
 export type ChanType interface {
        Dir()   int;
        Elem()  Type;
@@ -199,6 +236,11 @@ type ChanTypeStruct struct {
 func (t *ChanTypeStruct) Kind() int {
        return ChanKind
 }
+       
+func (t *ChanTypeStruct) Size() int {
+       panic("reflect.type: chan.Size(): cannot happen");
+       return 0
+}
 
 func (t *ChanTypeStruct) Dir() int {
        // -1 is open array?  TODO
@@ -216,6 +258,8 @@ func NewChanTypeStruct(dir int, elem *StubType) *ChanTypeStruct {
        return t;
 }
 
+// -- Struct
+
 export type StructType interface {
        Field(int)      (name string, typ Type);
        Len()   int;
@@ -224,6 +268,7 @@ export type StructType interface {
 type Field struct {
        name    string;
        typ     *StubType;
+       size    int;
 }
 
 type StructTypeStruct struct {
@@ -234,6 +279,25 @@ func (t *StructTypeStruct) Kind() int {
        return StructKind
 }
 
+// TODO: not portable; depends on 6g
+func (t *StructTypeStruct) Size() int {
+       size := 0;
+       for i := 0; i < len(t.field); i++ {
+               elemsize := t.field[i].typ.Get().Size();
+               // pad until at (elemsize mod 8) boundary
+               align := elemsize - 1;
+               if align > 7 {  // BUG: we know structs are at 8-aligned
+                       align = 7
+               }
+               if align > 0 {
+                       size = (size + align) & ^align;
+               }
+               size += elemsize;
+       }
+       size = (size + 7) & ^7;
+       return size;
+}
+
 func (t *StructTypeStruct) Field(i int) (name string, typ Type) {
        return t.field[i].name, t.field[i].typ.Get()
 }
@@ -248,6 +312,8 @@ func NewStructTypeStruct(field *[]Field) *StructTypeStruct {
        return t;
 }
 
+// -- Interface
+
 export type InterfaceType interface {
        Field(int)      (name string, typ Type);
        Len()   int;
@@ -275,6 +341,12 @@ func (t *InterfaceTypeStruct) Kind() int {
        return InterfaceKind
 }
 
+func (t *InterfaceTypeStruct) Size() int {
+       return interfacesize
+}
+
+// -- Func
+
 export type FuncType interface {
        In()    StructType;
        Out()   StructType;
@@ -289,6 +361,11 @@ func (t *FuncTypeStruct) Kind() int {
        return FuncKind
 }
 
+func (t *FuncTypeStruct) Size() int {
+       panic("reflect.type: func.Size(): cannot happen");
+       return 0
+}
+
 func (t *FuncTypeStruct) In() StructType {
        return t.in
 }
@@ -330,6 +407,9 @@ func Unlock() {
 }
 
 func init() {
+       ptrsize = 8;    // TODO: compute this
+       interfacesize = 2*ptrsize;      // TODO: compute this
+
        lockchan = new(chan bool, 1);   // unlocked at creation - buffer is empty
        Lock(); // not necessary because of init ordering but be safe.