summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2008-11-05 08:17:01 -0800
committerRob Pike <r@golang.org>2008-11-05 08:17:01 -0800
commit945927fae51c931691be47a2415ddc0061e66463 (patch)
treef7b7935ba85ebd18722671cd221d1db2696ea910
parentae7fb0d662b80be982de11939c8243313d63cd85 (diff)
downloadgolang-945927fae51c931691be47a2415ddc0061e66463.tar.gz
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
-rw-r--r--src/lib/reflect/test.go12
-rw-r--r--src/lib/reflect/type.go32
2 files changed, 31 insertions, 13 deletions
diff --git a/src/lib/reflect/test.go b/src/lib/reflect/test.go
index 54fd5ac4d..13be64cc0 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 64405765b..09ecbc067 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;
}