mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Make the reflection library match the reflection string which
6g generates for functions: expect the keyword "func". The older reflection syntax, without the "func", is still recognized for simplicity in parsing interface reflection strings. R=r,rsc DELTA=66 (31 added, 8 deleted, 27 changed) OCL=27396 CL=27422
This commit is contained in:
parent
e21d981a2f
commit
ca9765d83a
4 changed files with 56 additions and 33 deletions
|
|
@ -117,8 +117,8 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
|
||||||
typedump("map[string]int32", "map[string]int32");
|
typedump("map[string]int32", "map[string]int32");
|
||||||
typedump("chan<-string", "chan<-string");
|
typedump("chan<-string", "chan<-string");
|
||||||
typedump("struct {c chan *int32; d float32}", "struct{c chan*int32; d float32}");
|
typedump("struct {c chan *int32; d float32}", "struct{c chan*int32; d float32}");
|
||||||
typedump("*(a int8, b int32)", "*(a int8, b int32)");
|
typedump("func(a int8, b int32)", "func(a int8, b int32)");
|
||||||
typedump("struct {c *(? chan *P.integer, ? *int8)}", "struct{c *(chan*P.integer, *int8)}");
|
typedump("struct {c func(? chan *P.integer, ? *int8)}", "struct{c func(chan*P.integer, *int8)}");
|
||||||
typedump("struct {a int8; b int32}", "struct{a int8; b int32}");
|
typedump("struct {a int8; b int32}", "struct{a int8; b int32}");
|
||||||
typedump("struct {a int8; b int8; b int32}", "struct{a int8; b int8; b int32}");
|
typedump("struct {a int8; b int8; b int32}", "struct{a int8; b int8; b int32}");
|
||||||
typedump("struct {a int8; b int8; c int8; b int32}", "struct{a int8; b int8; c int8; b int32}");
|
typedump("struct {a int8; b int8; c int8; b int32}", "struct{a int8; b int8; c int8; b int32}");
|
||||||
|
|
@ -126,7 +126,8 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
|
||||||
typedump("struct {a int8; b int8; c int8; d int8; e int8; b int32}", "struct{a int8; b int8; c int8; d int8; e int8; b int32}");
|
typedump("struct {a int8; b int8; c int8; d int8; e int8; b int32}", "struct{a int8; b int8; c int8; d int8; e int8; b int32}");
|
||||||
typedump("struct {a int8 \"hi there\"; }", "struct{a int8 \"hi there\"}");
|
typedump("struct {a int8 \"hi there\"; }", "struct{a int8 \"hi there\"}");
|
||||||
typedump("struct {a int8 \"hi \\x00there\\t\\n\\\"\\\\\"; }", "struct{a int8 \"hi \\x00there\\t\\n\\\"\\\\\"}");
|
typedump("struct {a int8 \"hi \\x00there\\t\\n\\\"\\\\\"; }", "struct{a int8 \"hi \\x00there\\t\\n\\\"\\\\\"}");
|
||||||
typedump("struct {f *(args ...)}", "struct{f *(args ...)}");
|
typedump("struct {f func(args ...)}", "struct{f func(args ...)}");
|
||||||
|
typedump("interface { a(? func(? func(? int) int) func(? func(? int)) int); b() }", "interface{a (func(func(int)(int))(func(func(int))(int))); b ()}");
|
||||||
|
|
||||||
// Values
|
// Values
|
||||||
valuedump("int8", "8");
|
valuedump("int8", "8");
|
||||||
|
|
@ -148,8 +149,8 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
|
||||||
valuedump("map[string]int32", "map[string]int32{<can't iterate on maps>}");
|
valuedump("map[string]int32", "map[string]int32{<can't iterate on maps>}");
|
||||||
valuedump("chan<-string", "chan<-string");
|
valuedump("chan<-string", "chan<-string");
|
||||||
valuedump("struct {c chan *int32; d float32}", "struct{c chan*int32; d float32}{chan*int32, 0}");
|
valuedump("struct {c chan *int32; d float32}", "struct{c chan*int32; d float32}{chan*int32, 0}");
|
||||||
valuedump("*(a int8, b int32)", "*(a int8, b int32)(0)");
|
valuedump("func(a int8, b int32)", "func(a int8, b int32)(0)");
|
||||||
valuedump("struct {c *(? chan *P.integer, ? *int8)}", "struct{c *(chan*P.integer, *int8)}{*(chan*P.integer, *int8)(0)}");
|
valuedump("struct {c func(? chan *P.integer, ? *int8)}", "struct{c func(chan*P.integer, *int8)}{func(chan*P.integer, *int8)(0)}");
|
||||||
valuedump("struct {a int8; b int32}", "struct{a int8; b int32}{0, 0}");
|
valuedump("struct {a int8; b int32}", "struct{a int8; b int32}{0, 0}");
|
||||||
valuedump("struct {a int8; b int8; b int32}", "struct{a int8; b int8; b int32}{0, 0, 0}");
|
valuedump("struct {a int8; b int8; b int32}", "struct{a int8; b int8; b int32}{0, 0, 0}");
|
||||||
|
|
||||||
|
|
@ -243,14 +244,14 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
|
||||||
t = reflect.ParseTypeString("", "interface {a() *int}");
|
t = reflect.ParseTypeString("", "interface {a() *int}");
|
||||||
assert(t.String(), "interface {a() *int}");
|
assert(t.String(), "interface {a() *int}");
|
||||||
|
|
||||||
t = reflect.ParseTypeString("", "*(a int8, b int32)");
|
t = reflect.ParseTypeString("", "func(a int8, b int32)");
|
||||||
assert(t.String(), "*(a int8, b int32)");
|
assert(t.String(), "func(a int8, b int32)");
|
||||||
|
|
||||||
t = reflect.ParseTypeString("", "*(a int8, b int32) float");
|
t = reflect.ParseTypeString("", "func(a int8, b int32) float");
|
||||||
assert(t.String(), "*(a int8, b int32) float");
|
assert(t.String(), "func(a int8, b int32) float");
|
||||||
|
|
||||||
t = reflect.ParseTypeString("", "*(a int8, b int32) (a float, b float)");
|
t = reflect.ParseTypeString("", "func(a int8, b int32) (a float, b float)");
|
||||||
assert(t.String(), "*(a int8, b int32) (a float, b float)");
|
assert(t.String(), "func(a int8, b int32) (a float, b float)");
|
||||||
|
|
||||||
t = reflect.ParseTypeString("", "[32]int32");
|
t = reflect.ParseTypeString("", "[32]int32");
|
||||||
assert(t.String(), "[32]int32");
|
assert(t.String(), "[32]int32");
|
||||||
|
|
@ -311,6 +312,14 @@ func TestInterfaceValue(t *testing.T) {
|
||||||
assert(v3.Type().String(), "float");
|
assert(v3.Type().String(), "float");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFunctionValue(t *testing.T) {
|
||||||
|
v := reflect.NewValue(func() {});
|
||||||
|
if v.Interface() != v.Interface() {
|
||||||
|
t.Fatalf("TestFunction != itself");
|
||||||
|
}
|
||||||
|
assert(v.Type().String(), "func()");
|
||||||
|
}
|
||||||
|
|
||||||
func TestCopyArray(t *testing.T) {
|
func TestCopyArray(t *testing.T) {
|
||||||
a := []int{ 1, 2, 3, 4, 10, 9, 8, 7 };
|
a := []int{ 1, 2, 3, 4, 10, 9, 8, 7 };
|
||||||
b := []int{ 11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44 };
|
b := []int{ 11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44 };
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,18 @@ type hasFields interface {
|
||||||
Len() int;
|
Len() int;
|
||||||
}
|
}
|
||||||
|
|
||||||
func typeFieldsToString(t hasFields, sep string) string {
|
func typeFieldsToString(t hasFields, sep string, iface bool) string {
|
||||||
var str string;
|
var str string;
|
||||||
for i := 0; i < t.Len(); i++ {
|
for i := 0; i < t.Len(); i++ {
|
||||||
str1, typ, tag, offset := t.Field(i);
|
str1, typ, tag, offset := t.Field(i);
|
||||||
if str1 != "" {
|
if str1 != "" {
|
||||||
str1 += " "
|
str1 += " "
|
||||||
}
|
}
|
||||||
str1 += typeToString(typ, false);
|
str2 := typeToString(typ, false);
|
||||||
|
if iface && str2[0:4] == "func" {
|
||||||
|
str2 = str2[4:len(str2)]
|
||||||
|
}
|
||||||
|
str1 += str2;
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
str1 += " " + doubleQuote(tag);
|
str1 += " " + doubleQuote(tag);
|
||||||
}
|
}
|
||||||
|
|
@ -111,14 +115,14 @@ func typeToString(typ Type, expand bool) string {
|
||||||
}
|
}
|
||||||
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), ";", false) + "}";
|
||||||
case InterfaceKind:
|
case InterfaceKind:
|
||||||
return "interface{" + typeFieldsToString(typ.(InterfaceType), ";") + "}";
|
return "interface{" + typeFieldsToString(typ.(InterfaceType), ";", true) + "}";
|
||||||
case FuncKind:
|
case FuncKind:
|
||||||
f := typ.(FuncType);
|
f := typ.(FuncType);
|
||||||
str = "(" + typeFieldsToString(f.In(), ",") + ")";
|
str = "func(" + typeFieldsToString(f.In(), ",", false) + ")";
|
||||||
if f.Out() != nil {
|
if f.Out() != nil {
|
||||||
str += "(" + typeFieldsToString(f.Out(), ",") + ")";
|
str += "(" + typeFieldsToString(f.Out(), ",", false) + ")";
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
default:
|
default:
|
||||||
|
|
@ -221,7 +225,8 @@ func valueToString(val Value) string {
|
||||||
case InterfaceKind:
|
case InterfaceKind:
|
||||||
return "can't print interfaces yet";
|
return "can't print interfaces yet";
|
||||||
case FuncKind:
|
case FuncKind:
|
||||||
return "can't print funcs yet";
|
v := val.(FuncValue);
|
||||||
|
return typeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")";
|
||||||
default:
|
default:
|
||||||
panicln("reflect.valueToString: can't print type ", val.Kind());
|
panicln("reflect.valueToString: can't print type ", val.Kind());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ type allTypes struct {
|
||||||
xfloat float;
|
xfloat float;
|
||||||
xfloat32 float32;
|
xfloat32 float32;
|
||||||
xfloat64 float64;
|
xfloat64 float64;
|
||||||
|
xfunc func();
|
||||||
xint int;
|
xint int;
|
||||||
xint16 int16;
|
xint16 int16;
|
||||||
xint32 int32;
|
xint32 int32;
|
||||||
|
|
@ -466,17 +467,11 @@ type funcTypeStruct struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFuncTypeStruct(name, typestring string, in, out *structTypeStruct) *funcTypeStruct {
|
func newFuncTypeStruct(name, typestring string, in, out *structTypeStruct) *funcTypeStruct {
|
||||||
return &funcTypeStruct{ commonType{FuncKind, typestring, name, 0}, in, out }
|
return &funcTypeStruct{ commonType{FuncKind, typestring, name, ptrsize}, in, out }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *funcTypeStruct) FieldAlign() int {
|
func (t *funcTypeStruct) FieldAlign() int {
|
||||||
panic("reflect.type: func.FieldAlign(): cannot happen");
|
return unsafe.Alignof(x.xfunc);
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *funcTypeStruct) Size() int {
|
|
||||||
panic("reflect.type: func.Size(): cannot happen");
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *funcTypeStruct) In() StructType {
|
func (t *funcTypeStruct) In() StructType {
|
||||||
|
|
@ -602,15 +597,18 @@ func init() {
|
||||||
interfacetype =
|
interfacetype =
|
||||||
'interface' '{' fieldlist '}'
|
'interface' '{' fieldlist '}'
|
||||||
chantype =
|
chantype =
|
||||||
'<-' chan stubtype
|
'<-' 'chan' stubtype
|
||||||
chan '<-' stubtype
|
'chan' '<-' stubtype
|
||||||
chan stubtype
|
'chan' stubtype
|
||||||
maptype =
|
maptype =
|
||||||
'map' '[' stubtype ']' stubtype
|
'map' '[' stubtype ']' stubtype
|
||||||
pointertype =
|
pointertype =
|
||||||
'*' stubtype
|
'*' stubtype
|
||||||
functiontype =
|
functiontype =
|
||||||
'(' fieldlist ')'
|
[ 'func' ] '(' fieldlist ')' [ '(' fieldlist ')' | stubtype ]
|
||||||
|
|
||||||
|
In functiontype 'func' is optional because it is omitted in
|
||||||
|
the reflection string for interface types.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -860,7 +858,8 @@ func (p *typeParser) Func(name string, tokstart int) *stubType {
|
||||||
p.Next();
|
p.Next();
|
||||||
if p.token != "(" {
|
if p.token != "(" {
|
||||||
// 1 list: the in parameters are a list. Is there a single out parameter?
|
// 1 list: the in parameters are a list. Is there a single out parameter?
|
||||||
if p.token == "" || p.token == "}" || p.token == "," || p.token == ";" {
|
switch p.token {
|
||||||
|
case "", "}", ")", ",", ";":
|
||||||
return newStubType(name, newFuncTypeStruct(name, p.TypeString(tokstart), f1, nil));
|
return newStubType(name, newFuncTypeStruct(name, p.TypeString(tokstart), f1, nil));
|
||||||
}
|
}
|
||||||
// A single out parameter.
|
// A single out parameter.
|
||||||
|
|
@ -918,6 +917,13 @@ func (p *typeParser) Type(name string) *stubType {
|
||||||
}
|
}
|
||||||
p.Next();
|
p.Next();
|
||||||
return p.Interface(name, tokstart);
|
return p.Interface(name, tokstart);
|
||||||
|
case p.token == "func":
|
||||||
|
p.Next();
|
||||||
|
if p.token != "(" {
|
||||||
|
return missingStub
|
||||||
|
}
|
||||||
|
p.Next();
|
||||||
|
return p.Func(name, tokstart);
|
||||||
case p.token == "(":
|
case p.token == "(":
|
||||||
p.Next();
|
p.Next();
|
||||||
return p.Func(name, tokstart);
|
return p.Func(name, tokstart);
|
||||||
|
|
|
||||||
|
|
@ -776,12 +776,17 @@ func interfaceCreator(typ Type, addr Addr) Value {
|
||||||
// Its implementation is incomplete.
|
// Its implementation is incomplete.
|
||||||
type FuncValue interface {
|
type FuncValue interface {
|
||||||
Value;
|
Value;
|
||||||
|
Get() Addr; // The address of the function.
|
||||||
}
|
}
|
||||||
|
|
||||||
type funcValueStruct struct {
|
type funcValueStruct struct {
|
||||||
commonValue
|
commonValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *funcValueStruct) Get() Addr {
|
||||||
|
return *(*Addr)(v.addr)
|
||||||
|
}
|
||||||
|
|
||||||
func funcCreator(typ Type, addr Addr) Value {
|
func funcCreator(typ Type, addr Addr) Value {
|
||||||
return &funcValueStruct{ commonValue{FuncKind, typ, addr} }
|
return &funcValueStruct{ commonValue{FuncKind, typ, addr} }
|
||||||
}
|
}
|
||||||
|
|
@ -827,8 +832,6 @@ func newValueAddr(typ Type, addr Addr) Value {
|
||||||
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() {
|
||||||
case FuncKind: // must be pointers, at least for now (TODO?)
|
|
||||||
return nil;
|
|
||||||
case ArrayKind:
|
case ArrayKind:
|
||||||
if typ.(ArrayType).IsSlice() {
|
if typ.(ArrayType).IsSlice() {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue