Commit a45f947c authored by Rob Pike's avatar Rob Pike

type strings through the reflection library.

R=rsc
DELTA=187  (107 added, 28 deleted, 52 changed)
OCL=18510
CL=18510
parent 69e26bf2
...@@ -88,9 +88,11 @@ export type empty interface {} ...@@ -88,9 +88,11 @@ 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;
// Types
typedump("missing", "$missing$"); typedump("missing", "$missing$");
typedump("int", "int"); typedump("int", "int");
typedump("int8", "int8"); typedump("int8", "int8");
...@@ -126,6 +128,7 @@ func main() { ...@@ -126,6 +128,7 @@ func main() {
typedump("struct {a int8 \"hi \\x00there\\t\\n\\\"\\\\\"; }", "struct{a int8 \"hi \\x00there\\t\\n\\\"\\\\\"}"); typedump("struct {a int8 \"hi \\x00there\\t\\n\\\"\\\\\"; }", "struct{a int8 \"hi \\x00there\\t\\n\\\"\\\\\"}");
typedump("struct {f *(args ...)}", "struct{f *(args ...)}"); typedump("struct {f *(args ...)}", "struct{f *(args ...)}");
// Values
valuedump("int8", "8"); valuedump("int8", "8");
valuedump("int16", "16"); valuedump("int16", "16");
valuedump("int32", "32"); valuedump("int32", "32");
...@@ -191,4 +194,56 @@ func main() { ...@@ -191,4 +194,56 @@ func main() {
value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.IntValue).Put(123); value.(reflect.PtrValue).Sub().(reflect.ArrayValue).Elem(4).(reflect.IntValue).Put(123);
assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "main.AA·test{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"); assert(reflect.ValueToString(value.(reflect.PtrValue).Sub()), "main.AA·test{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}");
} }
var pt reflect.PtrType;
var st reflect.StructType;
var mt reflect.MapType;
var at reflect.ArrayType;
var ct reflect.ChanType;
var name string;
var typ reflect.Type;
var tag string;
var offset uint64;
// Type strings
t = reflect.ParseTypeString("", "int8");
assert(t.String(), "int8");
t = reflect.ParseTypeString("", "*int8");
assert(t.String(), "*int8");
pt = t.(reflect.PtrType);
assert(pt.Sub().String(), "int8");
t = reflect.ParseTypeString("", "*struct {c *chan *int32; d float32}");
assert(t.String(), "*struct {c *chan *int32; d float32}");
pt = t.(reflect.PtrType);
assert(pt.Sub().String(), "struct {c *chan *int32; d float32}");
st = pt.Sub().(reflect.StructType);
name, typ, tag, offset = st.Field(0);
assert(typ.String(), "*chan *int32");
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("", "*(a int8, b int32)");
assert(t.String(), "*(a int8, b int32)");
t = reflect.ParseTypeString("", "[32]int32");
assert(t.String(), "[32]int32");
at = t.(reflect.ArrayType);
assert(at.Elem().String(), "int32");
t = reflect.ParseTypeString("", "map[string]*int32");
assert(t.String(), "map[string]*int32");
mt = t.(reflect.MapType);
assert(mt.Key().String(), "string");
assert(mt.Elem().String(), "*int32");
t = reflect.ParseTypeString("", "chan<-string");
assert(t.String(), "chan<-string");
ct = t.(reflect.ChanType);
assert(ct.Elem().String(), "string");
} }
...@@ -50,22 +50,33 @@ var DotDotDotString = "..." ...@@ -50,22 +50,33 @@ var DotDotDotString = "..."
export type Type interface { export type Type interface {
Kind() int; Kind() int;
Name() string; Name() string;
String() string;
SetString(string); // TODO: remove when no longer needed
Size() uint64; Size() uint64;
} }
// Fields and methods common to all types // Fields and methods common to all types
type Common struct { type Common struct {
kind int; kind int;
str string;
name string; name string;
size uint64; size uint64;
} }
func (c *Common) Kind() int {
return c.kind
}
func (c *Common) Name() string { func (c *Common) Name() string {
return c.name return c.name
} }
func (c *Common) Kind() int { func (c *Common) String() string {
return c.kind return c.str
}
func (c *Common) SetString(s string) {
c.str = s
} }
func (c *Common) Size() uint64 { func (c *Common) Size() uint64 {
...@@ -79,7 +90,7 @@ type BasicType struct { ...@@ -79,7 +90,7 @@ type BasicType struct {
} }
func NewBasicType(name string, kind int, size uint64) Type { func NewBasicType(name string, kind int, size uint64) Type {
return &BasicType{ Common{kind, name, size} } return &BasicType{ Common{kind, name, name, size} }
} }
// Prebuilt basic types // Prebuilt basic types
...@@ -134,8 +145,8 @@ type PtrTypeStruct struct { ...@@ -134,8 +145,8 @@ type PtrTypeStruct struct {
sub *StubType; sub *StubType;
} }
func NewPtrTypeStruct(name string, sub *StubType) *PtrTypeStruct { func NewPtrTypeStruct(name, typestring string, sub *StubType) *PtrTypeStruct {
return &PtrTypeStruct{ Common{PtrKind, name, ptrsize}, sub} return &PtrTypeStruct{ Common{PtrKind, typestring, name, ptrsize}, sub}
} }
func (t *PtrTypeStruct) Sub() Type { func (t *PtrTypeStruct) Sub() Type {
...@@ -157,8 +168,8 @@ type ArrayTypeStruct struct { ...@@ -157,8 +168,8 @@ type ArrayTypeStruct struct {
len uint64; len uint64;
} }
func NewArrayTypeStruct(name string, open bool, len uint64, elem *StubType) *ArrayTypeStruct { func NewArrayTypeStruct(name, typestring string, open bool, len uint64, elem *StubType) *ArrayTypeStruct {
return &ArrayTypeStruct{ Common{ArrayKind, name, 0}, elem, open, len} return &ArrayTypeStruct{ Common{ArrayKind, typestring, name, 0}, elem, open, len}
} }
func (t *ArrayTypeStruct) Size() uint64 { func (t *ArrayTypeStruct) Size() uint64 {
...@@ -194,8 +205,8 @@ type MapTypeStruct struct { ...@@ -194,8 +205,8 @@ type MapTypeStruct struct {
elem *StubType; elem *StubType;
} }
func NewMapTypeStruct(name string, key, elem *StubType) *MapTypeStruct { func NewMapTypeStruct(name, typestring string, key, elem *StubType) *MapTypeStruct {
return &MapTypeStruct{ Common{MapKind, name, 0}, key, elem} return &MapTypeStruct{ Common{MapKind, typestring, name, 0}, key, elem}
} }
func (t *MapTypeStruct) Size() uint64 { func (t *MapTypeStruct) Size() uint64 {
...@@ -230,8 +241,8 @@ type ChanTypeStruct struct { ...@@ -230,8 +241,8 @@ type ChanTypeStruct struct {
dir int; dir int;
} }
func NewChanTypeStruct(name string, dir int, elem *StubType) *ChanTypeStruct { func NewChanTypeStruct(name, typestring string, dir int, elem *StubType) *ChanTypeStruct {
return &ChanTypeStruct{ Common{ChanKind, name, 0}, elem, dir} return &ChanTypeStruct{ Common{ChanKind, typestring, name, 0}, elem, dir}
} }
func (t *ChanTypeStruct) Size() uint64 { func (t *ChanTypeStruct) Size() uint64 {
...@@ -267,8 +278,8 @@ type StructTypeStruct struct { ...@@ -267,8 +278,8 @@ type StructTypeStruct struct {
field *[]Field; field *[]Field;
} }
func NewStructTypeStruct(name string, field *[]Field) *StructTypeStruct { func NewStructTypeStruct(name, typestring string, field *[]Field) *StructTypeStruct {
return &StructTypeStruct{ Common{StructKind, name, 0}, field} return &StructTypeStruct{ Common{StructKind, typestring, name, 0}, field}
} }
// TODO: not portable; depends on 6g // TODO: not portable; depends on 6g
...@@ -318,8 +329,8 @@ type InterfaceTypeStruct struct { ...@@ -318,8 +329,8 @@ type InterfaceTypeStruct struct {
field *[]Field; field *[]Field;
} }
func NewInterfaceTypeStruct(name string, field *[]Field) *InterfaceTypeStruct { func NewInterfaceTypeStruct(name, typestring string, field *[]Field) *InterfaceTypeStruct {
return &InterfaceTypeStruct{ Common{InterfaceKind, name, interfacesize}, field } return &InterfaceTypeStruct{ Common{InterfaceKind, typestring, name, interfacesize}, field }
} }
func (t *InterfaceTypeStruct) Field(i int) (name string, typ Type, tag string, offset uint64) { func (t *InterfaceTypeStruct) Field(i int) (name string, typ Type, tag string, offset uint64) {
...@@ -343,8 +354,8 @@ type FuncTypeStruct struct { ...@@ -343,8 +354,8 @@ type FuncTypeStruct struct {
out *StructTypeStruct; out *StructTypeStruct;
} }
func NewFuncTypeStruct(name string, in, out *StructTypeStruct) *FuncTypeStruct { func NewFuncTypeStruct(name, typestring string, in, out *StructTypeStruct) *FuncTypeStruct {
return &FuncTypeStruct{ Common{FuncKind, name, 0}, in, out } return &FuncTypeStruct{ Common{FuncKind, typestring, name, 0}, in, out }
} }
func (t *FuncTypeStruct) Size() uint64 { func (t *FuncTypeStruct) Size() uint64 {
...@@ -543,6 +554,7 @@ func unescape(s string, backslash bool) string { ...@@ -543,6 +554,7 @@ func unescape(s string, backslash bool) string {
type Parser struct { type Parser struct {
str string; // string being parsed str string; // string being parsed
token string; // the token being parsed now token string; // the token being parsed now
tokstart int; // starting position of token
index int; // next character position in str index int; // next character position in str
} }
...@@ -551,6 +563,7 @@ func (p *Parser) Next() { ...@@ -551,6 +563,7 @@ 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++ {
} }
p.tokstart = p.index;
if p.index >= len(p.str) { if p.index >= len(p.str) {
p.token = ""; p.token = "";
return; return;
...@@ -608,7 +621,7 @@ func (p *Parser) Next() { ...@@ -608,7 +621,7 @@ func (p *Parser) Next() {
func (p *Parser) Type(name string) *StubType func (p *Parser) Type(name string) *StubType
func (p *Parser) Array(name string) *StubType { func (p *Parser) Array(name string, tokstart int) *StubType {
size := uint64(0); size := uint64(0);
open := true; open := true;
if p.token != "]" { if p.token != "]" {
...@@ -628,10 +641,10 @@ func (p *Parser) Array(name string) *StubType { ...@@ -628,10 +641,10 @@ func (p *Parser) Array(name string) *StubType {
} }
p.Next(); p.Next();
elemtype := p.Type(""); elemtype := p.Type("");
return NewStubType(name, NewArrayTypeStruct(name, open, size, elemtype)); return NewStubType(name, NewArrayTypeStruct(name, p.str[tokstart:p.index], open, size, elemtype));
} }
func (p *Parser) Map(name string) *StubType { func (p *Parser) Map(name string, tokstart int) *StubType {
if p.token != "[" { if p.token != "[" {
return MissingStub return MissingStub
} }
...@@ -642,10 +655,10 @@ func (p *Parser) Map(name string) *StubType { ...@@ -642,10 +655,10 @@ func (p *Parser) Map(name string) *StubType {
} }
p.Next(); p.Next();
elemtype := p.Type(""); elemtype := p.Type("");
return NewStubType(name, NewMapTypeStruct(name, keytype, elemtype)); return NewStubType(name, NewMapTypeStruct(name, p.str[tokstart:p.index], keytype, elemtype));
} }
func (p *Parser) Chan(name string, dir int) *StubType { func (p *Parser) Chan(name string, tokstart, dir int) *StubType {
if p.token == "<-" { if p.token == "<-" {
if dir != BothDir { if dir != BothDir {
return MissingStub return MissingStub
...@@ -654,7 +667,7 @@ func (p *Parser) Chan(name string, dir int) *StubType { ...@@ -654,7 +667,7 @@ func (p *Parser) Chan(name string, dir int) *StubType {
dir = SendDir; dir = SendDir;
} }
elemtype := p.Type(""); elemtype := p.Type("");
return NewStubType(name, NewChanTypeStruct(name, dir, elemtype)); return NewStubType(name, NewChanTypeStruct(name, p.str[tokstart:p.index], dir, elemtype));
} }
// Parse array of fields for struct, interface, and func arguments // Parse array of fields for struct, interface, and func arguments
...@@ -685,59 +698,65 @@ func (p *Parser) Fields(sep string) *[]Field { ...@@ -685,59 +698,65 @@ func (p *Parser) Fields(sep string) *[]Field {
return a[0:nf]; return a[0:nf];
} }
func (p *Parser) Struct(name string) *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;
} }
ts := p.str[tokstart:p.index];
p.Next(); p.Next();
return NewStubType(name, NewStructTypeStruct(name, f)); return NewStubType(name, NewStructTypeStruct(name, ts, f));
} }
func (p *Parser) Interface(name string) *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;
} }
ts := p.str[tokstart:p.index];
p.Next(); p.Next();
return NewStubType(name, NewInterfaceTypeStruct(name, f)); return NewStubType(name, NewInterfaceTypeStruct(name, ts, f));
} }
func (p *Parser) Func(name string) *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;
p.Next(); p.Next();
if p.token != "(" { if p.token != "(" {
// 1 list: the in parameters only // 1 list: the in parameters only
return NewStubType(name, NewFuncTypeStruct(name, f1, nil)); return NewStubType(name, NewFuncTypeStruct(name, p.str[tokstart:end], f1, nil));
} }
p.Next(); p.Next();
f2 := NewStructTypeStruct("", p.Fields(",")); f2 := NewStructTypeStruct("", "", p.Fields(","));
if p.token != ")" { if p.token != ")" {
return MissingStub; return MissingStub;
} }
end = p.index;
p.Next(); p.Next();
// 2 lists: the in and out parameters are present // 2 lists: the in and out parameters are present
return NewStubType(name, NewFuncTypeStruct(name, f1, f2)); return NewStubType(name, NewFuncTypeStruct(name, p.str[tokstart:end], f1, f2));
} }
func (p *Parser) Type(name string) *StubType { func (p *Parser) Type(name string) *StubType {
dir := BothDir; dir := BothDir;
tokstart := p.tokstart;
switch { switch {
case p.token == "": case p.token == "":
return nil; return nil;
case p.token == "*": case p.token == "*":
p.Next(); p.Next();
return NewStubType(name, NewPtrTypeStruct(name, p.Type(""))); sub := p.Type("");
return NewStubType(name, NewPtrTypeStruct(name, p.str[tokstart:p.index], sub));
case p.token == "[": case p.token == "[":
p.Next(); p.Next();
return p.Array(name); return p.Array(name, tokstart);
case p.token == "map": case p.token == "map":
p.Next(); p.Next();
return p.Map(name); return p.Map(name, tokstart);
case p.token == "<-": case p.token == "<-":
p.Next(); p.Next();
dir = RecvDir; dir = RecvDir;
...@@ -747,24 +766,24 @@ func (p *Parser) Type(name string) *StubType { ...@@ -747,24 +766,24 @@ func (p *Parser) Type(name string) *StubType {
fallthrough; fallthrough;
case p.token == "chan": case p.token == "chan":
p.Next(); p.Next();
return p.Chan(name, dir); return p.Chan(name, tokstart, dir);
case p.token == "struct": case p.token == "struct":
p.Next(); p.Next();
if p.token != "{" { if p.token != "{" {
return MissingStub return MissingStub
} }
p.Next(); p.Next();
return p.Struct(name); return p.Struct(name, tokstart);
case p.token == "interface": case p.token == "interface":
p.Next(); p.Next();
if p.token != "{" { if p.token != "{" {
return MissingStub return MissingStub
} }
p.Next(); p.Next();
return p.Interface(name); return p.Interface(name, tokstart);
case p.token == "(": case p.token == "(":
p.Next(); p.Next();
return p.Func(name); return p.Func(name, tokstart);
case isdigit(p.token[0]): case isdigit(p.token[0]):
p.Next(); p.Next();
return MissingStub; return MissingStub;
......
...@@ -11,12 +11,35 @@ import ( ...@@ -11,12 +11,35 @@ import (
"reflect"; "reflect";
) )
type Addr uint64 // TODO: where are ptrint/intptr etc? type Addr uint64 // TODO: where are ptrint/intptr etc?
// Conversion functions, implemented in assembler
func AddrToPtrAddr(Addr) *Addr
func AddrToPtrInt(Addr) *int
func AddrToPtrInt8(Addr) *int8
func AddrToPtrInt16(Addr) *int16
func AddrToPtrInt32(Addr) *int32
func AddrToPtrInt64(Addr) *int64
func AddrToPtrUint(Addr) *uint
func AddrToPtrUint8(Addr) *uint8
func PtrUint8ToAddr(*uint8) Addr
func AddrToPtrUint16(Addr) *uint16
func AddrToPtrUint32(Addr) *uint32
func AddrToPtrUint64(Addr) *uint64
func PtrUint64ToAddr(*uint64) Addr
func AddrToPtrFloat(Addr) *float
func AddrToPtrFloat32(Addr) *float32
func AddrToPtrFloat64(Addr) *float64
func AddrToPtrFloat80(Addr) *float80
func AddrToPtrString(Addr) *string
func AddrToPtrBool(Addr) *bool
export type Empty interface {} // TODO(r): Delete when no longer needed?
export type Value interface { export type Value interface {
Kind() int; Kind() int;
Type() Type; Type() Type;
Unreflect() Empty;
} }
// Common fields and functionality for all values // Common fields and functionality for all values
...@@ -35,30 +58,14 @@ func (c *Common) Type() Type { ...@@ -35,30 +58,14 @@ func (c *Common) Type() Type {
return c.typ return c.typ
} }
func (c *Common) Unreflect() Empty {
return sys.unreflect(*AddrToPtrAddr(c.addr), c.typ.String());
}
func NewValueAddr(typ Type, addr Addr) Value func NewValueAddr(typ Type, addr Addr) Value
type Creator *(typ Type, addr Addr) Value type Creator *(typ Type, addr Addr) Value
// Conversion functions, implemented in assembler
func AddrToPtrAddr(Addr) *Addr
func AddrToPtrInt(Addr) *int
func AddrToPtrInt8(Addr) *int8
func AddrToPtrInt16(Addr) *int16
func AddrToPtrInt32(Addr) *int32
func AddrToPtrInt64(Addr) *int64
func AddrToPtrUint(Addr) *uint
func AddrToPtrUint8(Addr) *uint8
func PtrUint8ToAddr(*uint8) Addr
func AddrToPtrUint16(Addr) *uint16
func AddrToPtrUint32(Addr) *uint32
func AddrToPtrUint64(Addr) *uint64
func PtrUint64ToAddr(*uint64) Addr
func AddrToPtrFloat(Addr) *float
func AddrToPtrFloat32(Addr) *float32
func AddrToPtrFloat64(Addr) *float64
func AddrToPtrFloat80(Addr) *float80
func AddrToPtrString(Addr) *string
func AddrToPtrBool(Addr) *bool
// -- Missing // -- Missing
...@@ -743,8 +750,6 @@ export func NewInitValue(typ Type) Value { ...@@ -743,8 +750,6 @@ export func NewInitValue(typ Type) Value {
return NewValueAddr(typ, PtrUint8ToAddr(&data[0])); return NewValueAddr(typ, PtrUint8ToAddr(&data[0]));
} }
export type Empty interface {}
export func NewValue(e Empty) Value { export func NewValue(e Empty) Value {
value, typestring := sys.reflect(e); value, typestring := sys.reflect(e);
typ := ParseTypeString("", typestring); typ := ParseTypeString("", typestring);
......
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