From bdbb958895e7055e3ecd3f9c75b3d453b0ab7fff Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Wed, 5 Nov 2008 08:17:01 -0800 Subject: [PATCH] fix bugs parsing functions in reflect library. parsed interfaces wrong. could not handle a function with a single type as a return value. R=rsc DELTA=34 (20 added, 2 deleted, 12 changed) OCL=18511 CL=18520 --- src/lib/reflect/test.go | 12 ++++++++---- src/lib/reflect/type.go | 32 +++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/lib/reflect/test.go b/src/lib/reflect/test.go index 54fd5ac4d6..13be64cc08 100644 --- a/src/lib/reflect/test.go +++ b/src/lib/reflect/test.go @@ -88,7 +88,6 @@ export type empty interface {} export type T struct { a int; b float64; c string; d *int } func main() { -//NOTE: INTERFACES PARSE INCORRECTLY: parser's Fields() stops at '(' var s string; var t reflect.Type; @@ -224,13 +223,18 @@ func main() { name, typ, tag, offset = st.Field(1); assert(typ.String(), "float32"); - //TODO! this is bad - can't put a method in an interface! - t = reflect.ParseTypeString("", "interface {a int}"); - assert(t.String(), "interface {a int}"); + t = reflect.ParseTypeString("", "interface {a() *int}"); + assert(t.String(), "interface {a() *int}"); t = reflect.ParseTypeString("", "*(a int8, b int32)"); assert(t.String(), "*(a int8, b int32)"); + t = reflect.ParseTypeString("", "*(a int8, b int32) float"); + assert(t.String(), "*(a int8, b int32) float"); + + t = reflect.ParseTypeString("", "*(a int8, b int32) (a float, b float)"); + assert(t.String(), "*(a int8, b int32) (a float, b float)"); + t = reflect.ParseTypeString("", "[32]int32"); assert(t.String(), "[32]int32"); at = t.(reflect.ArrayType); diff --git a/src/lib/reflect/type.go b/src/lib/reflect/type.go index 64405765b5..09ecbc0675 100644 --- a/src/lib/reflect/type.go +++ b/src/lib/reflect/type.go @@ -671,10 +671,10 @@ func (p *Parser) Chan(name string, tokstart, dir int) *StubType { } // Parse array of fields for struct, interface, and func arguments -func (p *Parser) Fields(sep string) *[]Field { +func (p *Parser) Fields(sep, term string) *[]Field { a := new([]Field, 10); nf := 0; - for p.token != "" && !special(p.token[0]) { + for p.token != "" && p.token != term { if nf == len(a) { a1 := new([]Field, 2*nf); for i := 0; i < nf; i++ { @@ -698,8 +698,16 @@ func (p *Parser) Fields(sep string) *[]Field { return a[0:nf]; } +// A single type packaged as a field for a function return +func (p *Parser) OneField() *[]Field { + a := new([]Field, 1); + a[0].name = ""; + a[0].typ = p.Type(""); + return a; +} + func (p *Parser) Struct(name string, tokstart int) *StubType { - f := p.Fields(";"); + f := p.Fields(";", "}"); if p.token != "}" { return MissingStub; } @@ -709,7 +717,7 @@ func (p *Parser) Struct(name string, tokstart int) *StubType { } func (p *Parser) Interface(name string, tokstart int) *StubType { - f := p.Fields(";"); + f := p.Fields(";", "}"); if p.token != "}" { return MissingStub; } @@ -720,18 +728,24 @@ func (p *Parser) Interface(name string, tokstart int) *StubType { func (p *Parser) Func(name string, tokstart int) *StubType { // may be 1 or 2 parenthesized lists - f1 := NewStructTypeStruct("", "", p.Fields(",")); + f1 := NewStructTypeStruct("", "", p.Fields(",", ")")); if p.token != ")" { return MissingStub; } end := p.index; p.Next(); if p.token != "(" { - // 1 list: the in parameters only - return NewStubType(name, NewFuncTypeStruct(name, p.str[tokstart:end], f1, nil)); + // 1 list: the in parameters are a list. Is there a single out parameter? + if p.token == "" || p.token == "}" || p.token == "," || p.token == ";" { + return NewStubType(name, NewFuncTypeStruct(name, p.str[tokstart:end], f1, nil)); + } + // A single out parameter. + f2 := NewStructTypeStruct("", "", p.OneField()); + return NewStubType(name, NewFuncTypeStruct(name, p.str[tokstart:end], f1, f2)); + } else { + p.Next(); } - p.Next(); - f2 := NewStructTypeStruct("", "", p.Fields(",")); + f2 := NewStructTypeStruct("", "", p.Fields(",", ")")); if p.token != ")" { return MissingStub; } -- 2.50.0