1
0
mirror of https://github.com/golang/go synced 2024-09-25 13:20:13 -06:00

beginnings of reflection values.

R=rsc
DELTA=421  (357 added, 17 deleted, 47 changed)
OCL=17388
CL=17401
This commit is contained in:
Rob Pike 2008-10-17 18:06:29 -07:00
parent 35eebcacc8
commit 265e73ee14
6 changed files with 408 additions and 65 deletions

View 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

133
usr/r/reflect/cast_amd64.s Normal file
View File

@ -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

36
usr/r/reflect/gencast.sh Executable file
View File

@ -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
!

View 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");
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}");
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");
valuedump("int8");
valuedump("int16");
valuedump("int32");
valuedump("int64");
valuedump("uint8");
valuedump("uint16");
valuedump("uint32");
valuedump("uint64");
valuedump("string");
}

View 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";
}

View 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;
@ -200,6 +237,11 @@ 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
return t.dir
@ -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.