Commit 060f157d authored by Rob Pike's avatar Rob Pike

type string parser; now handles all types

R=rsc
DELTA=253  (153 added, 81 deleted, 19 changed)
OCL=17331
CL=17331
parent 7cb6b678
...@@ -10,29 +10,6 @@ import ( ...@@ -10,29 +10,6 @@ import (
func main() { func main() {
var s string; 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; var t reflect.Type;
t = reflect.ParseTypeString("int8"); t = reflect.ParseTypeString("int8");
...@@ -52,4 +29,16 @@ func main() { ...@@ -52,4 +29,16 @@ func main() {
t = reflect.ParseTypeString("map[string]int32"); t = reflect.ParseTypeString("map[string]int32");
s = reflect.ToString(t); print(s, "\n"); 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");
} }
...@@ -14,14 +14,14 @@ import ( ...@@ -14,14 +14,14 @@ import (
export func ToString(typ Type) string export func ToString(typ Type) string
func FieldsToString(t Type) string { func FieldsToString(t Type, sep string) string {
s := t.(StructType); s := t.(StructType);
var str string; var str string;
for i := 0; i < s.Len(); i++ { for i := 0; i < s.Len(); i++ {
str1, t := s.Field(i); str1, t := s.Field(i);
str1 += " " + ToString(t); str1 += " " + ToString(t);
if i < s.Len() - 1 { if i < s.Len() - 1 {
str1 += "; "; str1 += sep + " ";
} }
str += str1; str += str1;
} }
...@@ -86,16 +86,15 @@ func ToString(typ Type) string { ...@@ -86,16 +86,15 @@ func ToString(typ Type) string {
} }
return str + ToString(c.Elem()); return str + ToString(c.Elem());
case StructKind: case StructKind:
return "struct{" + FieldsToString(typ) + "}"; return "struct{" + FieldsToString(typ, ";") + "}";
case InterfaceKind:
return "interface{" + FieldsToString(typ, ";") + "}";
case FuncKind: case FuncKind:
f := typ.(FuncType); f := typ.(FuncType);
str = "func"; str = "func";
if f.Receiver() != nil { str += "(" + FieldsToString(f.In(), ",") + ")";
str += "(" + FieldsToString(f.Receiver()) + ")";
}
str += "(" + FieldsToString(f.In()) + ")";
if f.Out() != nil { if f.Out() != nil {
str += "(" + FieldsToString(f.Out()) + ")"; str += "(" + FieldsToString(f.Out(), ",") + ")";
} }
return str; return str;
default: default:
......
...@@ -25,6 +25,7 @@ export const ( ...@@ -25,6 +25,7 @@ export const (
Int32Kind; Int32Kind;
Int64Kind; Int64Kind;
Int8Kind; Int8Kind;
InterfaceKind;
MapKind; MapKind;
PtrKind; PtrKind;
StringKind; StringKind;
...@@ -241,26 +242,45 @@ func (t *StructTypeStruct) Len() int { ...@@ -241,26 +242,45 @@ func (t *StructTypeStruct) Len() int {
return len(t.field) return len(t.field)
} }
func Struct(field *[]Field) *StructTypeStruct { func NewStructTypeStruct(field *[]Field) *StructTypeStruct {
t := new(StructTypeStruct); t := new(StructTypeStruct);
t.field = field; t.field = field;
return t; return t;
} }
func NewStructTypeStruct(field *[]Field) *StructTypeStruct { export type InterfaceType interface {
t := new(StructTypeStruct); 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; t.field = field;
return t; return t;
} }
func (t *InterfaceTypeStruct) Kind() int {
return InterfaceKind
}
export type FuncType interface { export type FuncType interface {
Receiver() StructType;
In() StructType; In() StructType;
Out() StructType; Out() StructType;
} }
type FuncTypeStruct struct { type FuncTypeStruct struct {
receiver *StructTypeStruct;
in *StructTypeStruct; in *StructTypeStruct;
out *StructTypeStruct; out *StructTypeStruct;
} }
...@@ -269,45 +289,24 @@ func (t *FuncTypeStruct) Kind() int { ...@@ -269,45 +289,24 @@ func (t *FuncTypeStruct) Kind() int {
return FuncKind return FuncKind
} }
func (t *FuncTypeStruct) Receiver() StructType {
return t.receiver
}
func (t *FuncTypeStruct) In() StructType { func (t *FuncTypeStruct) In() StructType {
return t.in return t.in
} }
func (t *FuncTypeStruct) Out() StructType { func (t *FuncTypeStruct) Out() StructType {
if t.out == nil { // nil.(StructType) != nil so make sure caller sees real nil
return nil
}
return t.out return t.out
} }
func NewFuncTypeStruct(receiver, in, out *StructTypeStruct) *FuncTypeStruct { func NewFuncTypeStruct(in, out *StructTypeStruct) *FuncTypeStruct {
t := new(FuncTypeStruct); t := new(FuncTypeStruct);
t.receiver = receiver;
t.in = in; t.in = in;
t.out = out; t.out = out;
return t; 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. // Cache of expanded types keyed by type name.
var types *map[string] *Type // BUG TODO: should be Type not *Type var types *map[string] *Type // BUG TODO: should be Type not *Type
// List of typename, typestring pairs // List of typename, typestring pairs
...@@ -380,7 +379,7 @@ func init() { ...@@ -380,7 +379,7 @@ func init() {
typename = typename =
name '.' name name '.' name
fieldlist = fieldlist =
[ field { ',' field } ] [ field { [ ',' | ';' ] field } ]
field = field =
identifier stubtype identifier stubtype
arraytype = arraytype =
...@@ -402,12 +401,13 @@ func init() { ...@@ -402,12 +401,13 @@ func init() {
*/ */
// Helper functions for token scanning
func isdigit(c uint8) bool { func isdigit(c uint8) bool {
return '0' <= c && c <= '9' return '0' <= c && c <= '9'
} }
func special(c uint8) bool { 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++ { for i := 0; i < len(s); i++ {
if c == s[i] { if c == s[i] {
return true return true
...@@ -416,12 +416,14 @@ func special(c uint8) bool { ...@@ -416,12 +416,14 @@ func special(c uint8) bool {
return false; return false;
} }
// Simple parser for type strings
type Parser struct { type Parser struct {
str string; str string; // string being parsed
index int; token string; // the token being parsed now
token string; index int; // next character position in str
} }
// Load next token into p.token
func (p *Parser) Next() { func (p *Parser) Next() {
token := ""; token := "";
for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ { for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ {
...@@ -434,28 +436,15 @@ func (p *Parser) Next() { ...@@ -434,28 +436,15 @@ func (p *Parser) Next() {
c, w := sys.stringtorune(p.str, p.index); c, w := sys.stringtorune(p.str, p.index);
p.index += w; p.index += w;
switch { 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 == '<': 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.index++;
p.token = "<-"; p.token = "<-";
return; 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; return;
case isdigit(uint8(c)): case isdigit(uint8(c)):
for p.index < len(p.str) && isdigit(p.str[p.index]) { for p.index < len(p.str) && isdigit(p.str[p.index]) {
...@@ -464,7 +453,7 @@ func (p *Parser) Next() { ...@@ -464,7 +453,7 @@ func (p *Parser) Next() {
p.token = p.str[start : p.index]; p.token = p.str[start : p.index];
return; 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.index++
} }
p.token = p.str[start : p.index]; p.token = p.str[start : p.index];
...@@ -507,27 +496,127 @@ func (p *Parser) Map() *StubType { ...@@ -507,27 +496,127 @@ func (p *Parser) Map() *StubType {
return NewStubType(NewMapTypeStruct(keytype, elemtype)); 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 { switch {
case p.token == "": case p.token == "":
return nil; return nil;
case p.token == "*": case p.token == "*":
p.Next(); p.Next();
return NewStubType(NewPtrTypeStruct(p.Simple())); return NewStubType(NewPtrTypeStruct(p.Type()));
case p.token == "[": case p.token == "[":
p.Next(); p.Next();
return p.Array(); return p.Array();
case p.token == "map": case p.token == "map":
p.Next(); p.Next();
return p.Map(); 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]): case isdigit(p.token[0]):
p.Next(); p.Next();
print("reflect.Simple: number encountered\n"); // TODO: remove
return MissingStub; return MissingStub;
case special(p.token[0]): case special(p.token[0]):
// TODO: get chans right
p.Next(); p.Next();
print("reflect.Simple: special character encountered\n"); // TODO: remove
return MissingStub; return MissingStub;
} }
// must be an identifier. is it basic? if so, we have a stub // must be an identifier. is it basic? if so, we have a stub
...@@ -543,7 +632,6 @@ func (p *Parser) Simple() *StubType { ...@@ -543,7 +632,6 @@ func (p *Parser) Simple() *StubType {
} }
} }
if ndot != 1 { if ndot != 1 {
print("reflect.Simple: illegal identifier ", p.token, "\n"); // TODO: remove
p.Next(); p.Next();
return MissingStub; return MissingStub;
} }
...@@ -553,10 +641,6 @@ func (p *Parser) Simple() *StubType { ...@@ -553,10 +641,6 @@ func (p *Parser) Simple() *StubType {
return s; return s;
} }
func (p *Parser) Type() *StubType {
return p.Simple();
}
export func ParseTypeString(str string) Type { export func ParseTypeString(str string) Type {
p := new(Parser); p := new(Parser);
p.str = str; p.str = str;
......
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