Commit bdbb9588 authored by Rob Pike's avatar Rob Pike

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
parent a45f947c
...@@ -88,7 +88,6 @@ export type empty interface {} ...@@ -88,7 +88,6 @@ export type empty interface {}
export type T struct { a int; b float64; c string; d *int } export type T struct { a int; b float64; c string; d *int }
func main() { func main() {
//NOTE: INTERFACES PARSE INCORRECTLY: parser's Fields() stops at '('
var s string; var s string;
var t reflect.Type; var t reflect.Type;
...@@ -224,13 +223,18 @@ func main() { ...@@ -224,13 +223,18 @@ func main() {
name, typ, tag, offset = st.Field(1); name, typ, tag, offset = st.Field(1);
assert(typ.String(), "float32"); assert(typ.String(), "float32");
//TODO! this is bad - can't put a method in an interface! 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("", "*(a int8, b int32)");
assert(t.String(), "*(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"); t = reflect.ParseTypeString("", "[32]int32");
assert(t.String(), "[32]int32"); assert(t.String(), "[32]int32");
at = t.(reflect.ArrayType); at = t.(reflect.ArrayType);
......
...@@ -671,10 +671,10 @@ func (p *Parser) Chan(name string, tokstart, dir int) *StubType { ...@@ -671,10 +671,10 @@ func (p *Parser) Chan(name string, tokstart, dir int) *StubType {
} }
// Parse array of fields for struct, interface, and func arguments // 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); a := new([]Field, 10);
nf := 0; nf := 0;
for p.token != "" && !special(p.token[0]) { for p.token != "" && p.token != term {
if nf == len(a) { if nf == len(a) {
a1 := new([]Field, 2*nf); a1 := new([]Field, 2*nf);
for i := 0; i < nf; i++ { for i := 0; i < nf; i++ {
...@@ -698,8 +698,16 @@ func (p *Parser) Fields(sep string) *[]Field { ...@@ -698,8 +698,16 @@ func (p *Parser) Fields(sep string) *[]Field {
return a[0:nf]; 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 { func (p *Parser) Struct(name string, tokstart int) *StubType {
f := p.Fields(";"); f := p.Fields(";", "}");
if p.token != "}" { if p.token != "}" {
return MissingStub; return MissingStub;
} }
...@@ -709,7 +717,7 @@ func (p *Parser) Struct(name string, tokstart int) *StubType { ...@@ -709,7 +717,7 @@ func (p *Parser) Struct(name string, tokstart int) *StubType {
} }
func (p *Parser) Interface(name string, tokstart int) *StubType { func (p *Parser) Interface(name string, tokstart int) *StubType {
f := p.Fields(";"); f := p.Fields(";", "}");
if p.token != "}" { if p.token != "}" {
return MissingStub; return MissingStub;
} }
...@@ -720,18 +728,24 @@ func (p *Parser) Interface(name string, tokstart int) *StubType { ...@@ -720,18 +728,24 @@ func (p *Parser) Interface(name string, tokstart int) *StubType {
func (p *Parser) Func(name string, tokstart int) *StubType { func (p *Parser) Func(name string, tokstart int) *StubType {
// may be 1 or 2 parenthesized lists // may be 1 or 2 parenthesized lists
f1 := NewStructTypeStruct("", "", p.Fields(",")); f1 := NewStructTypeStruct("", "", p.Fields(",", ")"));
if p.token != ")" { if p.token != ")" {
return MissingStub; return MissingStub;
} }
end := p.index; end := p.index;
p.Next(); p.Next();
if p.token != "(" { if p.token != "(" {
// 1 list: the in parameters only // 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)); 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 != ")" { if p.token != ")" {
return MissingStub; return MissingStub;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment