mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
parsing of type strings. still missing: func, struct, interface, chan
R=rsc DELTA=366 (337 added, 7 deleted, 22 changed) OCL=17321 CL=17324
This commit is contained in:
parent
1163b1db6f
commit
32b84d5a94
3 changed files with 352 additions and 28 deletions
|
|
@ -11,23 +11,45 @@ import (
|
||||||
func main() {
|
func main() {
|
||||||
var s string;
|
var s string;
|
||||||
|
|
||||||
s = reflect.ToString(reflect.Int8); print(s, "\n");
|
if false {
|
||||||
s = reflect.ToString(reflect.Int16); print(s, "\n");
|
s = reflect.ToString(reflect.Int8); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Int32); print(s, "\n");
|
s = reflect.ToString(reflect.Int16); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Int64); print(s, "\n");
|
s = reflect.ToString(reflect.Int32); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Uint8); print(s, "\n");
|
s = reflect.ToString(reflect.Int64); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Uint16); print(s, "\n");
|
s = reflect.ToString(reflect.Uint8); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Uint32); print(s, "\n");
|
s = reflect.ToString(reflect.Uint16); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Uint64); print(s, "\n");
|
s = reflect.ToString(reflect.Uint32); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Float32); print(s, "\n");
|
s = reflect.ToString(reflect.Uint64); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Float64); print(s, "\n");
|
s = reflect.ToString(reflect.Float32); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Float80); print(s, "\n");
|
s = reflect.ToString(reflect.Float64); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.String); 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.PtrInt8); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.ArrayFloat32); print(s, "\n");
|
s = reflect.ToString(reflect.PtrPtrInt8); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.MapStringInt16); print(s, "\n");
|
s = reflect.ToString(reflect.ArrayFloat32); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.ChanArray); print(s, "\n");
|
s = reflect.ToString(reflect.MapStringInt16); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Structure); print(s, "\n");
|
s = reflect.ToString(reflect.ChanArray); print(s, "\n");
|
||||||
s = reflect.ToString(reflect.Function); 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");
|
||||||
|
s = reflect.ToString(t); print(s, "\n");
|
||||||
|
|
||||||
|
t = reflect.ParseTypeString("**int8");
|
||||||
|
s = reflect.ToString(t); print(s, "\n");
|
||||||
|
|
||||||
|
t = reflect.ParseTypeString("**P.integer");
|
||||||
|
s = reflect.ToString(t); print(s, "\n");
|
||||||
|
|
||||||
|
t = reflect.ParseTypeString("[32]int32");
|
||||||
|
s = reflect.ToString(t); print(s, "\n");
|
||||||
|
|
||||||
|
t = reflect.ParseTypeString("[]int8");
|
||||||
|
s = reflect.ToString(t); print(s, "\n");
|
||||||
|
|
||||||
|
t = reflect.ParseTypeString("map[string]int32");
|
||||||
|
s = reflect.ToString(t); print(s, "\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Reflection library.
|
||||||
|
// Formatting of types for debugging.
|
||||||
|
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -28,6 +31,8 @@ func FieldsToString(t Type) string {
|
||||||
func ToString(typ Type) string {
|
func ToString(typ Type) string {
|
||||||
var str string;
|
var str string;
|
||||||
switch(typ.Kind()) {
|
switch(typ.Kind()) {
|
||||||
|
case MissingKind:
|
||||||
|
return "missing";
|
||||||
case Int8Kind:
|
case Int8Kind:
|
||||||
return "int8";
|
return "int8";
|
||||||
case Int16Kind:
|
case Int16Kind:
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,20 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Reflection library.
|
||||||
|
// Types and parsing of type strings.
|
||||||
|
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
export type Type interface
|
export type Type interface
|
||||||
export type Value interface{} // TODO: define this
|
|
||||||
|
|
||||||
export func LookupTypeName(name string) Type
|
export func ExpandType(name string) Type
|
||||||
|
|
||||||
//export var GlobalTypeStrings = sys.typestrings;
|
//export var GlobalTypeStrings = sys.typestrings;
|
||||||
|
|
||||||
// Cache of types keyed by type name
|
|
||||||
var types = new(map[string] *Type) // BUG TODO: should be Type not *Type
|
|
||||||
// Cache of type strings keyed by type name
|
|
||||||
var strings = new(map[string] string)
|
|
||||||
|
|
||||||
export const (
|
export const (
|
||||||
ArrayKind = iota;
|
MissingKind = iota;
|
||||||
|
ArrayKind;
|
||||||
ChanKind;
|
ChanKind;
|
||||||
Float32Kind;
|
Float32Kind;
|
||||||
Float64Kind;
|
Float64Kind;
|
||||||
|
|
@ -37,6 +35,8 @@ export const (
|
||||||
Uint8Kind;
|
Uint8Kind;
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var MissingString = "missing" // syntactic name for undefined type names
|
||||||
|
|
||||||
type Type interface {
|
type Type interface {
|
||||||
Kind() int;
|
Kind() int;
|
||||||
}
|
}
|
||||||
|
|
@ -57,6 +57,7 @@ func NewBasicType(k int) Type {
|
||||||
|
|
||||||
// Basic types
|
// Basic types
|
||||||
export var (
|
export var (
|
||||||
|
Missing = NewBasicType(MissingKind);
|
||||||
Int8 = NewBasicType(Int8Kind);
|
Int8 = NewBasicType(Int8Kind);
|
||||||
Int16 = NewBasicType(Int16Kind);
|
Int16 = NewBasicType(Int16Kind);
|
||||||
Int32 = NewBasicType(Int32Kind);
|
Int32 = NewBasicType(Int32Kind);
|
||||||
|
|
@ -71,6 +72,8 @@ export var (
|
||||||
String = NewBasicType(StringKind);
|
String = NewBasicType(StringKind);
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Stub types allow us to defer evaluating type names until needed.
|
||||||
|
// If the name is empty, the type must be non-nil.
|
||||||
type StubType struct {
|
type StubType struct {
|
||||||
name string;
|
name string;
|
||||||
typ Type;
|
typ Type;
|
||||||
|
|
@ -78,11 +81,23 @@ type StubType struct {
|
||||||
|
|
||||||
func (t *StubType) Get() Type {
|
func (t *StubType) Get() Type {
|
||||||
if t.typ == nil {
|
if t.typ == nil {
|
||||||
t.typ = LookupTypeName(t.name)
|
t.typ = ExpandType(t.name)
|
||||||
}
|
}
|
||||||
return t.typ
|
return t.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStubType(t Type) *StubType {
|
||||||
|
s := new(StubType);
|
||||||
|
s.typ = t;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNamedStubType(n string) *StubType {
|
||||||
|
s := new(StubType);
|
||||||
|
s.name = n;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
export type PtrType interface {
|
export type PtrType interface {
|
||||||
Sub() Type
|
Sub() Type
|
||||||
}
|
}
|
||||||
|
|
@ -274,8 +289,8 @@ func NewFuncTypeStruct(receiver, in, out *StructTypeStruct) *FuncTypeStruct {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
//helpers for early bootstrap and debugging
|
//helpers for early bootstrap and debugging
|
||||||
export func LookupTypeName(name string) Type { return Int8 }
|
|
||||||
func Stub(n string, t Type) *StubType {
|
func Stub(n string, t Type) *StubType {
|
||||||
s := new(StubType);
|
s := new(StubType);
|
||||||
s.name = n;
|
s.name = n;
|
||||||
|
|
@ -283,6 +298,7 @@ func Stub(n string, t Type) *StubType {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
export var PtrInt8 Type = NewPtrTypeStruct(Stub("i", Int8));
|
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 ArrayFloat32 Type = NewArrayTypeStruct(100, Stub("f", Float32));
|
||||||
export var MapStringInt16 Type = NewMapTypeStruct(Stub("s", String), Stub("i", Int16));
|
export var MapStringInt16 Type = NewMapTypeStruct(Stub("s", String), Stub("i", Int16));
|
||||||
export var ChanArray Type = NewChanTypeStruct(RecvDir, Stub("a", ArrayFloat32));
|
export var ChanArray Type = NewChanTypeStruct(RecvDir, Stub("a", ArrayFloat32));
|
||||||
|
|
@ -290,3 +306,284 @@ var F1 = Field{"i", Stub("i", Int64)};
|
||||||
var Fields = []Field{F1};
|
var Fields = []Field{F1};
|
||||||
export var Structure = NewStructTypeStruct(&Fields);
|
export var Structure = NewStructTypeStruct(&Fields);
|
||||||
export var Function Type = NewFuncTypeStruct(Structure, Structure, Structure);
|
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
|
||||||
|
var typestrings *map[string] string
|
||||||
|
// Map of basic types to prebuilt StubTypes
|
||||||
|
var basicstubs *map[string] *StubType
|
||||||
|
|
||||||
|
var MissingStub *StubType;
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
types = new(map[string] *Type);
|
||||||
|
typestrings = new(map[string] string);
|
||||||
|
basicstubs = new(map[string] *StubType);
|
||||||
|
|
||||||
|
// Basics go into types table
|
||||||
|
types["missing"] = &Missing;
|
||||||
|
types["int8"] = &Int8;
|
||||||
|
types["int16"] = &Int16;
|
||||||
|
types["int32"] = &Int32;
|
||||||
|
types["int64"] = &Int64;
|
||||||
|
types["uint8"] = &Uint8;
|
||||||
|
types["uint16"] = &Uint16;
|
||||||
|
types["uint32"] = &Uint32;
|
||||||
|
types["uint64"] = &Uint64;
|
||||||
|
types["float32"] = &Float32;
|
||||||
|
types["float64"] = &Float64;
|
||||||
|
types["float80"] = &Float80;
|
||||||
|
types["string"] = &String;
|
||||||
|
|
||||||
|
// Basics get prebuilt stubs
|
||||||
|
MissingStub = NewStubType(Missing);
|
||||||
|
basicstubs["missing"] = MissingStub;
|
||||||
|
basicstubs["int8"] = NewStubType(Int8);
|
||||||
|
basicstubs["int16"] = NewStubType(Int16);
|
||||||
|
basicstubs["int32"] = NewStubType(Int32);
|
||||||
|
basicstubs["int64"] = NewStubType(Int64);
|
||||||
|
basicstubs["uint8"] = NewStubType(Uint8);
|
||||||
|
basicstubs["uint16"] = NewStubType(Uint16);
|
||||||
|
basicstubs["uint32"] = NewStubType(Uint32);
|
||||||
|
basicstubs["uint64"] = NewStubType(Uint64);
|
||||||
|
basicstubs["float32"] = NewStubType(Float32);
|
||||||
|
basicstubs["float64"] = NewStubType(Float64);
|
||||||
|
basicstubs["float80"] = NewStubType(Float80);
|
||||||
|
basicstubs["string"] = NewStubType(String);
|
||||||
|
|
||||||
|
typestrings["P.integer"] = "int32";
|
||||||
|
return;
|
||||||
|
typestrings["P.S"] = "struct {t *P.T}";
|
||||||
|
typestrings["P.T"] = "struct {c *(? *chan P.S, *int)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Grammar
|
||||||
|
|
||||||
|
stubtype = - represent as StubType when possible
|
||||||
|
type
|
||||||
|
identifier =
|
||||||
|
name
|
||||||
|
'?'
|
||||||
|
type =
|
||||||
|
basictypename - int8, string, etc.
|
||||||
|
typename
|
||||||
|
arraytype
|
||||||
|
structtype
|
||||||
|
interfacetype
|
||||||
|
chantype
|
||||||
|
maptype
|
||||||
|
pointertype
|
||||||
|
functiontype
|
||||||
|
typename =
|
||||||
|
name '.' name
|
||||||
|
fieldlist =
|
||||||
|
[ field { ',' field } ]
|
||||||
|
field =
|
||||||
|
identifier stubtype
|
||||||
|
arraytype =
|
||||||
|
'[' [ number ] ']' stubtype
|
||||||
|
structtype =
|
||||||
|
'struct' '{' fieldlist '}'
|
||||||
|
interfacetype =
|
||||||
|
'interface' '{' fieldlist '}'
|
||||||
|
chantype =
|
||||||
|
'<-' chan stubtype
|
||||||
|
chan '<-' stubtype
|
||||||
|
chan stubtype
|
||||||
|
maptype =
|
||||||
|
'map' '[' stubtype ']' stubtype
|
||||||
|
pointertype =
|
||||||
|
'*' stubtype
|
||||||
|
functiontype =
|
||||||
|
'(' fieldlist ')'
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 "?".
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if c == s[i] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Parser struct {
|
||||||
|
str string;
|
||||||
|
index int;
|
||||||
|
token string;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) Next() {
|
||||||
|
token := "";
|
||||||
|
for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ {
|
||||||
|
}
|
||||||
|
if p.index >= len(p.str) {
|
||||||
|
p.token = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
start := p.index;
|
||||||
|
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] == '-' {
|
||||||
|
p.index++;
|
||||||
|
p.token = "<-";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.token = "<"; // shouldn't happen but let the parser figure it out
|
||||||
|
return;
|
||||||
|
case isdigit(uint8(c)):
|
||||||
|
for p.index < len(p.str) && isdigit(p.str[p.index]) {
|
||||||
|
p.index++
|
||||||
|
}
|
||||||
|
p.token = p.str[start : p.index];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for p.index < len(p.str) && !special(p.str[p.index]) {
|
||||||
|
p.index++
|
||||||
|
}
|
||||||
|
p.token = p.str[start : p.index];
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) Type() *StubType
|
||||||
|
|
||||||
|
func (p *Parser) Array() *StubType {
|
||||||
|
size := -1;
|
||||||
|
if p.token != "]" {
|
||||||
|
if len(p.token) == 0 || !isdigit(p.token[0]) {
|
||||||
|
return MissingStub
|
||||||
|
}
|
||||||
|
// write our own (trivial and simpleminded) atoi to avoid dependency
|
||||||
|
size = 0;
|
||||||
|
for i := 0; i < len(p.token); i++ {
|
||||||
|
size = size * 10 + int(p.token[i]) - '0'
|
||||||
|
}
|
||||||
|
p.Next();
|
||||||
|
}
|
||||||
|
if p.token != "]" {
|
||||||
|
return MissingStub
|
||||||
|
}
|
||||||
|
p.Next();
|
||||||
|
elemtype := p.Type();
|
||||||
|
return NewStubType(NewArrayTypeStruct(size, elemtype));
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) Map() *StubType {
|
||||||
|
if p.token != "[" {
|
||||||
|
return MissingStub
|
||||||
|
}
|
||||||
|
p.Next();
|
||||||
|
keytype := p.Type();
|
||||||
|
if p.token != "]" {
|
||||||
|
return MissingStub
|
||||||
|
}
|
||||||
|
p.Next();
|
||||||
|
elemtype := p.Type();
|
||||||
|
return NewStubType(NewMapTypeStruct(keytype, elemtype));
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) Simple() *StubType {
|
||||||
|
switch {
|
||||||
|
case p.token == "":
|
||||||
|
return nil;
|
||||||
|
case p.token == "*":
|
||||||
|
p.Next();
|
||||||
|
return NewStubType(NewPtrTypeStruct(p.Simple()));
|
||||||
|
case p.token == "[":
|
||||||
|
p.Next();
|
||||||
|
return p.Array();
|
||||||
|
case p.token == "map":
|
||||||
|
p.Next();
|
||||||
|
return p.Map();
|
||||||
|
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
|
||||||
|
if s, ok := basicstubs[p.token]; ok {
|
||||||
|
p.Next();
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
// not a basic - must be of the form "P.T"
|
||||||
|
ndot := 0;
|
||||||
|
for i := 0; i < len(p.token); i++ {
|
||||||
|
if p.token[i] == '.' {
|
||||||
|
ndot++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ndot != 1 {
|
||||||
|
print("reflect.Simple: illegal identifier ", p.token, "\n"); // TODO: remove
|
||||||
|
p.Next();
|
||||||
|
return MissingStub;
|
||||||
|
}
|
||||||
|
s := new(StubType);
|
||||||
|
s.name = p.token;
|
||||||
|
p.Next();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) Type() *StubType {
|
||||||
|
return p.Simple();
|
||||||
|
}
|
||||||
|
|
||||||
|
export func ParseTypeString(str string) Type {
|
||||||
|
p := new(Parser);
|
||||||
|
p.str = str;
|
||||||
|
p.Next();
|
||||||
|
return p.Type().Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up type string associated with name.
|
||||||
|
func TypeNameToTypeString(name string) string {
|
||||||
|
s, ok := typestrings[name];
|
||||||
|
if !ok {
|
||||||
|
s = MissingString;
|
||||||
|
typestrings[name] = s;
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type is known by name. Find (and create if necessary) its real type.
|
||||||
|
func ExpandType(name string) Type {
|
||||||
|
t, ok := types[name];
|
||||||
|
if ok {
|
||||||
|
return *t
|
||||||
|
}
|
||||||
|
types[name] = &Missing; // prevent recursion; will overwrite
|
||||||
|
t1 := ParseTypeString(TypeNameToTypeString(name));
|
||||||
|
p := new(Type);
|
||||||
|
*p = t1;
|
||||||
|
types[name] = p;
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue