diff options
author | Rob Pike <r@golang.org> | 2008-10-16 18:09:38 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2008-10-16 18:09:38 -0700 |
commit | 599c9b2ea35113570eab0ae41c83845cc8b1af1f (patch) | |
tree | be2c943d8e2a2da55b276b796376ec6a4e35e118 | |
parent | 354cf33a45af21df29c1acb059c65a989cbf0b59 (diff) | |
download | golang-599c9b2ea35113570eab0ae41c83845cc8b1af1f.tar.gz |
type string parser; now handles all types
R=rsc
DELTA=253 (153 added, 81 deleted, 19 changed)
OCL=17331
CL=17331
-rw-r--r-- | usr/r/reflect/main.go | 35 | ||||
-rw-r--r-- | usr/r/reflect/tostring.go | 15 | ||||
-rw-r--r-- | usr/r/reflect/type.go | 210 |
3 files changed, 166 insertions, 94 deletions
diff --git a/usr/r/reflect/main.go b/usr/r/reflect/main.go index 9e8897ad3..f46b6d81e 100644 --- a/usr/r/reflect/main.go +++ b/usr/r/reflect/main.go @@ -10,29 +10,6 @@ import ( func main() { var s string; - - if false { - s = reflect.ToString(reflect.Int8); print(s, "\n"); - s = reflect.ToString(reflect.Int16); print(s, "\n"); - s = reflect.ToString(reflect.Int32); print(s, "\n"); - s = reflect.ToString(reflect.Int64); print(s, "\n"); - s = reflect.ToString(reflect.Uint8); print(s, "\n"); - s = reflect.ToString(reflect.Uint16); print(s, "\n"); - s = reflect.ToString(reflect.Uint32); print(s, "\n"); - s = reflect.ToString(reflect.Uint64); print(s, "\n"); - s = reflect.ToString(reflect.Float32); print(s, "\n"); - s = reflect.ToString(reflect.Float64); print(s, "\n"); - s = reflect.ToString(reflect.Float80); print(s, "\n"); - s = reflect.ToString(reflect.String); print(s, "\n"); - - s = reflect.ToString(reflect.PtrInt8); print(s, "\n"); - s = reflect.ToString(reflect.PtrPtrInt8); print(s, "\n"); - s = reflect.ToString(reflect.ArrayFloat32); print(s, "\n"); - s = reflect.ToString(reflect.MapStringInt16); print(s, "\n"); - s = reflect.ToString(reflect.ChanArray); print(s, "\n"); - s = reflect.ToString(reflect.Structure); print(s, "\n"); - s = reflect.ToString(reflect.Function); print(s, "\n"); - } var t reflect.Type; t = reflect.ParseTypeString("int8"); @@ -52,4 +29,16 @@ func main() { 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 *int32, ? *int8)}"); + s = reflect.ToString(t); print(s, "\n"); } diff --git a/usr/r/reflect/tostring.go b/usr/r/reflect/tostring.go index 60fb9f6f8..09b6945a2 100644 --- a/usr/r/reflect/tostring.go +++ b/usr/r/reflect/tostring.go @@ -14,14 +14,14 @@ import ( export func ToString(typ Type) string -func FieldsToString(t Type) string { +func FieldsToString(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); if i < s.Len() - 1 { - str1 += "; "; + str1 += sep + " "; } str += str1; } @@ -86,16 +86,15 @@ func ToString(typ Type) string { } return str + ToString(c.Elem()); case StructKind: - return "struct{" + FieldsToString(typ) + "}"; + return "struct{" + FieldsToString(typ, ";") + "}"; + case InterfaceKind: + return "interface{" + FieldsToString(typ, ";") + "}"; case FuncKind: f := typ.(FuncType); str = "func"; - if f.Receiver() != nil { - str += "(" + FieldsToString(f.Receiver()) + ")"; - } - str += "(" + FieldsToString(f.In()) + ")"; + str += "(" + FieldsToString(f.In(), ",") + ")"; if f.Out() != nil { - str += "(" + FieldsToString(f.Out()) + ")"; + str += "(" + FieldsToString(f.Out(), ",") + ")"; } return str; default: diff --git a/usr/r/reflect/type.go b/usr/r/reflect/type.go index abec5c11e..4eda9f407 100644 --- a/usr/r/reflect/type.go +++ b/usr/r/reflect/type.go @@ -25,6 +25,7 @@ export const ( Int32Kind; Int64Kind; Int8Kind; + InterfaceKind; MapKind; PtrKind; StringKind; @@ -241,26 +242,45 @@ func (t *StructTypeStruct) Len() int { return len(t.field) } -func Struct(field *[]Field) *StructTypeStruct { +func NewStructTypeStruct(field *[]Field) *StructTypeStruct { t := new(StructTypeStruct); t.field = field; return t; } -func NewStructTypeStruct(field *[]Field) *StructTypeStruct { - t := new(StructTypeStruct); +export type InterfaceType interface { + Field(int) (name string, typ Type); + Len() int; +} + +type InterfaceTypeStruct struct { + field *[]Field; +} + +func (t *InterfaceTypeStruct) Field(i int) (name string, typ Type) { + return t.field[i].name, t.field[i].typ.Get() +} + +func (t *InterfaceTypeStruct) Len() int { + return len(t.field) +} + +func NewInterfaceTypeStruct(field *[]Field) *InterfaceTypeStruct { + t := new(InterfaceTypeStruct); t.field = field; return t; } +func (t *InterfaceTypeStruct) Kind() int { + return InterfaceKind +} + export type FuncType interface { - Receiver() StructType; In() StructType; Out() StructType; } type FuncTypeStruct struct { - receiver *StructTypeStruct; in *StructTypeStruct; out *StructTypeStruct; } @@ -269,45 +289,24 @@ func (t *FuncTypeStruct) Kind() int { return FuncKind } -func (t *FuncTypeStruct) Receiver() StructType { - return t.receiver -} - func (t *FuncTypeStruct) In() StructType { return t.in } func (t *FuncTypeStruct) Out() StructType { + if t.out == nil { // nil.(StructType) != nil so make sure caller sees real nil + return nil + } return t.out } -func NewFuncTypeStruct(receiver, in, out *StructTypeStruct) *FuncTypeStruct { +func NewFuncTypeStruct(in, out *StructTypeStruct) *FuncTypeStruct { t := new(FuncTypeStruct); - t.receiver = receiver; t.in = in; t.out = out; return t; } -//////////////////////// -//helpers for early bootstrap and debugging -func Stub(n string, t Type) *StubType { - s := new(StubType); - s.name = n; - s.typ = t; - return s; -} -export var PtrInt8 Type = NewPtrTypeStruct(Stub("i", Int8)); -export var PtrPtrInt8 Type = NewPtrTypeStruct(Stub("i", PtrInt8)); -export var ArrayFloat32 Type = NewArrayTypeStruct(100, Stub("f", Float32)); -export var MapStringInt16 Type = NewMapTypeStruct(Stub("s", String), Stub("i", Int16)); -export var ChanArray Type = NewChanTypeStruct(RecvDir, Stub("a", ArrayFloat32)); -var F1 = Field{"i", Stub("i", Int64)}; -var Fields = []Field{F1}; -export var Structure = NewStructTypeStruct(&Fields); -export var Function Type = NewFuncTypeStruct(Structure, Structure, Structure); -//////////////////////// - // Cache of expanded types keyed by type name. var types *map[string] *Type // BUG TODO: should be Type not *Type // List of typename, typestring pairs @@ -380,7 +379,7 @@ func init() { typename = name '.' name fieldlist = - [ field { ',' field } ] + [ field { [ ',' | ';' ] field } ] field = identifier stubtype arraytype = @@ -402,12 +401,13 @@ func init() { */ +// Helper functions for token scanning func isdigit(c uint8) bool { return '0' <= c && c <= '9' } func special(c uint8) bool { - s := "*[](){}<"; // Note: '.' is not in this list. "P.T" is an identifer, as is "?". + s := "*[](){}<;,"; // Note: '.' is not in this list. "P.T" is an identifer, as is "?". for i := 0; i < len(s); i++ { if c == s[i] { return true @@ -416,12 +416,14 @@ func special(c uint8) bool { return false; } +// Simple parser for type strings type Parser struct { - str string; - index int; - token string; + str string; // string being parsed + token string; // the token being parsed now + index int; // next character position in str } +// Load next token into p.token func (p *Parser) Next() { token := ""; for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ { @@ -434,28 +436,15 @@ func (p *Parser) Next() { c, w := sys.stringtorune(p.str, p.index); p.index += w; switch { - case c == '*': - p.token = "*"; - return; - case c == '[': - p.token = "["; - return; - case c == ']': - p.token = "]"; - return; - case c == '(': - p.token = "("; - return; - case c == ')': - p.token = ")"; - return; case c == '<': - if p.index < len(p.str) && p.str[p.index+1] == '-' { + if p.index < len(p.str) && p.str[p.index] == '-' { p.index++; p.token = "<-"; return; } - p.token = "<"; // shouldn't happen but let the parser figure it out + fallthrough; // shouldn't happen but let the parser figure it out + case special(uint8(c)): + p.token = string(c); return; case isdigit(uint8(c)): for p.index < len(p.str) && isdigit(p.str[p.index]) { @@ -464,7 +453,7 @@ func (p *Parser) Next() { p.token = p.str[start : p.index]; return; } - for p.index < len(p.str) && !special(p.str[p.index]) { + for p.index < len(p.str) && p.str[p.index] != ' ' && !special(p.str[p.index]) { p.index++ } p.token = p.str[start : p.index]; @@ -507,27 +496,127 @@ func (p *Parser) Map() *StubType { return NewStubType(NewMapTypeStruct(keytype, elemtype)); } -func (p *Parser) Simple() *StubType { +func (p *Parser) Chan(dir int) *StubType { + if p.token == "<-" { + if dir != BothDir { + return MissingStub + } + p.Next(); + dir = SendDir; + } + elemtype := p.Type(); + return NewStubType(NewChanTypeStruct(dir, elemtype)); +} + +// Parse array of fields for struct, interface, and func arguments +func (p *Parser) Fields(sep string) *[]Field { + a := new([]Field, 10); + nf := 0; + for p.token != "" && !special(p.token[0]) { + if nf == len(a) { + a1 := new([]Field, 2*nf); + for i := 0; i < nf; i++ { + a1[i] = a[i]; + } + a = a1; + } + a[nf].name = p.token; + p.Next(); + a[nf].typ = p.Type(); + nf++; + if p.token != sep { + break; + } + p.Next(); // skip separator + } + return a[0:nf]; +} + +func (p *Parser) Struct() *StubType { + f := p.Fields(";"); + if p.token != "}" { + return MissingStub; + } + p.Next(); + return NewStubType(NewStructTypeStruct(f)); +} + +func (p *Parser) Interface() *StubType { + f := p.Fields(";"); + if p.token != "}" { + return MissingStub; + } + p.Next(); + return NewStubType(NewInterfaceTypeStruct(f)); +} + +func (p *Parser) Func() *StubType { + // may be 1 or 2 parenthesized lists + f1 := NewStructTypeStruct(p.Fields(",")); + if p.token != ")" { + return MissingStub; + } + p.Next(); + if p.token != "(" { + // 1 list: the in parameters only + return NewStubType(NewFuncTypeStruct(f1, nil)); + } + p.Next(); + f2 := NewStructTypeStruct(p.Fields(",")); + if p.token != ")" { + return MissingStub; + } + p.Next(); + // 2 lists: the in and out parameters are present + return NewStubType(NewFuncTypeStruct(f1, f2)); +} + +func (p *Parser) Type() *StubType { + dir := BothDir; switch { case p.token == "": return nil; case p.token == "*": p.Next(); - return NewStubType(NewPtrTypeStruct(p.Simple())); + return NewStubType(NewPtrTypeStruct(p.Type())); case p.token == "[": p.Next(); return p.Array(); case p.token == "map": p.Next(); return p.Map(); + case p.token == "<-": + p.Next(); + dir = RecvDir; + if p.token != "chan" { + return MissingStub; + } + fallthrough; + case p.token == "chan": + p.Next(); + return p.Chan(dir); + case p.token == "struct": + p.Next(); + if p.token != "{" { + return MissingStub + } + p.Next(); + return p.Struct(); + case p.token == "interface": + p.Next(); + if p.token != "{" { + return MissingStub + } + p.Next(); + return p.Interface(); + case p.token == "(": + p.Next(); + return p.Func(); case isdigit(p.token[0]): p.Next(); - print("reflect.Simple: number encountered\n"); // TODO: remove return MissingStub; case special(p.token[0]): - // TODO: get chans right p.Next(); - print("reflect.Simple: special character encountered\n"); // TODO: remove return MissingStub; } // must be an identifier. is it basic? if so, we have a stub @@ -543,7 +632,6 @@ func (p *Parser) Simple() *StubType { } } if ndot != 1 { - print("reflect.Simple: illegal identifier ", p.token, "\n"); // TODO: remove p.Next(); return MissingStub; } @@ -553,10 +641,6 @@ func (p *Parser) Simple() *StubType { return s; } -func (p *Parser) Type() *StubType { - return p.Simple(); -} - export func ParseTypeString(str string) Type { p := new(Parser); p.str = str; |