Commit 0061e561 authored by Rob Pike's avatar Rob Pike

Add names to types to avoid recursive explosion and to get

the right answer when a type name redefines an existing type.

R=rsc
DELTA=133  (53 added, 8 deleted, 72 changed)
OCL=17637
CL=17639
parent 79985fa5
...@@ -9,12 +9,12 @@ import ( ...@@ -9,12 +9,12 @@ import (
) )
func typedump(s string) { func typedump(s string) {
t := reflect.ParseTypeString(s); t := reflect.ParseTypeString("", s);
print(reflect.TypeToString(t),"; size = ", t.Size(), "\n"); print(reflect.TypeToString(t),"; size = ", t.Size(), "\n");
} }
func valuedump(s string) { func valuedump(s string) {
t := reflect.ParseTypeString(s); t := reflect.ParseTypeString("", s);
v := reflect.NewInitValue(t); v := reflect.NewInitValue(t);
switch v.Kind() { switch v.Kind() {
case reflect.Int8Kind: case reflect.Int8Kind:
......
...@@ -35,6 +35,9 @@ func TypeFieldsToString(t HasFields, sep string) string { ...@@ -35,6 +35,9 @@ func TypeFieldsToString(t HasFields, sep string) string {
func TypeToString(typ Type) string { func TypeToString(typ Type) string {
var str string; var str string;
if name := typ.Name(); name != "" {
return name
}
switch(typ.Kind()) { switch(typ.Kind()) {
case MissingKind: case MissingKind:
return "$missing$"; return "$missing$";
......
...@@ -43,14 +43,15 @@ var MissingString = "$missing$" // syntactic name for undefined type names ...@@ -43,14 +43,15 @@ var MissingString = "$missing$" // syntactic name for undefined type names
export type Type interface { export type Type interface {
Kind() int; Kind() int;
Name() string;
Size() uint64; Size() uint64;
} }
// -- Basic // -- Basic
type BasicType struct{ type BasicType struct{
name string;
kind int; kind int;
name string;
size uint64; size uint64;
} }
...@@ -106,18 +107,13 @@ func (t *StubType) Get() Type { ...@@ -106,18 +107,13 @@ func (t *StubType) Get() Type {
return t.typ return t.typ
} }
func NewStubType(t Type) *StubType { func NewStubType(name string, t Type) *StubType {
s := new(StubType); s := new(StubType);
s.name = name;
s.typ = t; s.typ = t;
return s; return s;
} }
func NewNamedStubType(n string) *StubType {
s := new(StubType);
s.name = n;
return s;
}
// -- Pointer // -- Pointer
export type PtrType interface { export type PtrType interface {
...@@ -125,13 +121,18 @@ export type PtrType interface { ...@@ -125,13 +121,18 @@ export type PtrType interface {
} }
type PtrTypeStruct struct { type PtrTypeStruct struct {
sub *StubType name string;
sub *StubType;
} }
func (t *PtrTypeStruct) Kind() int { func (t *PtrTypeStruct) Kind() int {
return PtrKind return PtrKind
} }
func (t *PtrTypeStruct) Name() string {
return t.name
}
func (t *PtrTypeStruct) Size() uint64 { func (t *PtrTypeStruct) Size() uint64 {
return ptrsize return ptrsize
} }
...@@ -140,8 +141,9 @@ func (t *PtrTypeStruct) Sub() Type { ...@@ -140,8 +141,9 @@ func (t *PtrTypeStruct) Sub() Type {
return t.sub.Get() return t.sub.Get()
} }
func NewPtrTypeStruct(sub *StubType) *PtrTypeStruct { func NewPtrTypeStruct(name string, sub *StubType) *PtrTypeStruct {
t := new(PtrTypeStruct); t := new(PtrTypeStruct);
t.name = name;
t.sub = sub; t.sub = sub;
return t; return t;
} }
...@@ -155,6 +157,7 @@ export type ArrayType interface { ...@@ -155,6 +157,7 @@ export type ArrayType interface {
} }
type ArrayTypeStruct struct { type ArrayTypeStruct struct {
name string;
elem *StubType; elem *StubType;
open bool; // otherwise fixed size open bool; // otherwise fixed size
len uint64; len uint64;
...@@ -164,6 +167,10 @@ func (t *ArrayTypeStruct) Kind() int { ...@@ -164,6 +167,10 @@ func (t *ArrayTypeStruct) Kind() int {
return ArrayKind return ArrayKind
} }
func (t *ArrayTypeStruct) Name() string {
return t.name
}
func (t *ArrayTypeStruct) Size() uint64 { func (t *ArrayTypeStruct) Size() uint64 {
if t.open { if t.open {
return ptrsize // open arrays are pointers to structures return ptrsize // open arrays are pointers to structures
...@@ -184,8 +191,9 @@ func (t *ArrayTypeStruct) Elem() Type { ...@@ -184,8 +191,9 @@ func (t *ArrayTypeStruct) Elem() Type {
return t.elem.Get() return t.elem.Get()
} }
func NewArrayTypeStruct(open bool, len uint64, elem *StubType) *ArrayTypeStruct { func NewArrayTypeStruct(name string, open bool, len uint64, elem *StubType) *ArrayTypeStruct {
t := new(ArrayTypeStruct); t := new(ArrayTypeStruct);
t.name = name;
t.open = open; t.open = open;
t.len = len; t.len = len;
t.elem = elem; t.elem = elem;
...@@ -200,6 +208,7 @@ export type MapType interface { ...@@ -200,6 +208,7 @@ export type MapType interface {
} }
type MapTypeStruct struct { type MapTypeStruct struct {
name string;
key *StubType; key *StubType;
elem *StubType; elem *StubType;
} }
...@@ -208,6 +217,10 @@ func (t *MapTypeStruct) Kind() int { ...@@ -208,6 +217,10 @@ func (t *MapTypeStruct) Kind() int {
return MapKind return MapKind
} }
func (t *MapTypeStruct) Name() string {
return t.name
}
func (t *MapTypeStruct) Size() uint64 { func (t *MapTypeStruct) Size() uint64 {
panic("reflect.type: map.Size(): cannot happen"); panic("reflect.type: map.Size(): cannot happen");
return 0 return 0
...@@ -221,8 +234,9 @@ func (t *MapTypeStruct) Elem() Type { ...@@ -221,8 +234,9 @@ func (t *MapTypeStruct) Elem() Type {
return t.elem.Get() return t.elem.Get()
} }
func NewMapTypeStruct(key, elem *StubType) *MapTypeStruct { func NewMapTypeStruct(name string, key, elem *StubType) *MapTypeStruct {
t := new(MapTypeStruct); t := new(MapTypeStruct);
t.name = name;
t.key = key; t.key = key;
t.elem = elem; t.elem = elem;
return t; return t;
...@@ -242,6 +256,7 @@ export const ( // channel direction ...@@ -242,6 +256,7 @@ export const ( // channel direction
) )
type ChanTypeStruct struct { type ChanTypeStruct struct {
name string;
elem *StubType; elem *StubType;
dir int; dir int;
} }
...@@ -250,6 +265,10 @@ func (t *ChanTypeStruct) Kind() int { ...@@ -250,6 +265,10 @@ func (t *ChanTypeStruct) Kind() int {
return ChanKind return ChanKind
} }
func (t *ChanTypeStruct) Name() string {
return t.name
}
func (t *ChanTypeStruct) Size() uint64 { func (t *ChanTypeStruct) Size() uint64 {
panic("reflect.type: chan.Size(): cannot happen"); panic("reflect.type: chan.Size(): cannot happen");
return 0 return 0
...@@ -264,8 +283,9 @@ func (t *ChanTypeStruct) Elem() Type { ...@@ -264,8 +283,9 @@ func (t *ChanTypeStruct) Elem() Type {
return t.elem.Get() return t.elem.Get()
} }
func NewChanTypeStruct(dir int, elem *StubType) *ChanTypeStruct { func NewChanTypeStruct(name string, dir int, elem *StubType) *ChanTypeStruct {
t := new(ChanTypeStruct); t := new(ChanTypeStruct);
t.name = name;
t.dir = dir; t.dir = dir;
t.elem = elem; t.elem = elem;
return t; return t;
...@@ -286,6 +306,7 @@ type Field struct { ...@@ -286,6 +306,7 @@ type Field struct {
} }
type StructTypeStruct struct { type StructTypeStruct struct {
name string;
field *[]Field; field *[]Field;
} }
...@@ -293,6 +314,10 @@ func (t *StructTypeStruct) Kind() int { ...@@ -293,6 +314,10 @@ func (t *StructTypeStruct) Kind() int {
return StructKind return StructKind
} }
func (t *StructTypeStruct) Name() string {
return t.name
}
// TODO: not portable; depends on 6g // TODO: not portable; depends on 6g
func (t *StructTypeStruct) Size() uint64 { func (t *StructTypeStruct) Size() uint64 {
size := uint64(0); size := uint64(0);
...@@ -324,8 +349,9 @@ func (t *StructTypeStruct) Len() int { ...@@ -324,8 +349,9 @@ func (t *StructTypeStruct) Len() int {
return len(t.field) return len(t.field)
} }
func NewStructTypeStruct(field *[]Field) *StructTypeStruct { func NewStructTypeStruct(name string, field *[]Field) *StructTypeStruct {
t := new(StructTypeStruct); t := new(StructTypeStruct);
t.name = name;
t.field = field; t.field = field;
return t; return t;
} }
...@@ -338,6 +364,7 @@ export type InterfaceType interface { ...@@ -338,6 +364,7 @@ export type InterfaceType interface {
} }
type InterfaceTypeStruct struct { type InterfaceTypeStruct struct {
name string;
field *[]Field; field *[]Field;
} }
...@@ -349,8 +376,9 @@ func (t *InterfaceTypeStruct) Len() int { ...@@ -349,8 +376,9 @@ func (t *InterfaceTypeStruct) Len() int {
return len(t.field) return len(t.field)
} }
func NewInterfaceTypeStruct(field *[]Field) *InterfaceTypeStruct { func NewInterfaceTypeStruct(name string, field *[]Field) *InterfaceTypeStruct {
t := new(InterfaceTypeStruct); t := new(InterfaceTypeStruct);
t.name = name;
t.field = field; t.field = field;
return t; return t;
} }
...@@ -359,6 +387,10 @@ func (t *InterfaceTypeStruct) Kind() int { ...@@ -359,6 +387,10 @@ func (t *InterfaceTypeStruct) Kind() int {
return InterfaceKind return InterfaceKind
} }
func (t *InterfaceTypeStruct) Name() string {
return t.name
}
func (t *InterfaceTypeStruct) Size() uint64 { func (t *InterfaceTypeStruct) Size() uint64 {
return interfacesize return interfacesize
} }
...@@ -371,6 +403,7 @@ export type FuncType interface { ...@@ -371,6 +403,7 @@ export type FuncType interface {
} }
type FuncTypeStruct struct { type FuncTypeStruct struct {
name string;
in *StructTypeStruct; in *StructTypeStruct;
out *StructTypeStruct; out *StructTypeStruct;
} }
...@@ -379,6 +412,10 @@ func (t *FuncTypeStruct) Kind() int { ...@@ -379,6 +412,10 @@ func (t *FuncTypeStruct) Kind() int {
return FuncKind return FuncKind
} }
func (t *FuncTypeStruct) Name() string {
return t.name
}
func (t *FuncTypeStruct) Size() uint64 { func (t *FuncTypeStruct) Size() uint64 {
panic("reflect.type: func.Size(): cannot happen"); panic("reflect.type: func.Size(): cannot happen");
return 0 return 0
...@@ -395,8 +432,9 @@ func (t *FuncTypeStruct) Out() StructType { ...@@ -395,8 +432,9 @@ func (t *FuncTypeStruct) Out() StructType {
return t.out return t.out
} }
func NewFuncTypeStruct(in, out *StructTypeStruct) *FuncTypeStruct { func NewFuncTypeStruct(name string, in, out *StructTypeStruct) *FuncTypeStruct {
t := new(FuncTypeStruct); t := new(FuncTypeStruct);
t.name = name;
t.in = in; t.in = in;
t.out = out; t.out = out;
return t; return t;
...@@ -452,20 +490,20 @@ func init() { ...@@ -452,20 +490,20 @@ func init() {
types["string"] = &String; types["string"] = &String;
// Basics get prebuilt stubs // Basics get prebuilt stubs
MissingStub = NewStubType(Missing); MissingStub = NewStubType(MissingString, Missing);
basicstub[MissingString] = MissingStub; basicstub[MissingString] = MissingStub;
basicstub["int8"] = NewStubType(Int8); basicstub["int8"] = NewStubType("int8", Int8);
basicstub["int16"] = NewStubType(Int16); basicstub["int16"] = NewStubType("int16", Int16);
basicstub["int32"] = NewStubType(Int32); basicstub["int32"] = NewStubType("int32", Int32);
basicstub["int64"] = NewStubType(Int64); basicstub["int64"] = NewStubType("int64", Int64);
basicstub["uint8"] = NewStubType(Uint8); basicstub["uint8"] = NewStubType("uint8", Uint8);
basicstub["uint16"] = NewStubType(Uint16); basicstub["uint16"] = NewStubType("uint16", Uint16);
basicstub["uint32"] = NewStubType(Uint32); basicstub["uint32"] = NewStubType("uint32", Uint32);
basicstub["uint64"] = NewStubType(Uint64); basicstub["uint64"] = NewStubType("uint64", Uint64);
basicstub["float32"] = NewStubType(Float32); basicstub["float32"] = NewStubType("float32", Float32);
basicstub["float64"] = NewStubType(Float64); basicstub["float64"] = NewStubType("float64", Float64);
basicstub["float80"] = NewStubType(Float80); basicstub["float80"] = NewStubType("float80", Float80);
basicstub["string"] = NewStubType(String); basicstub["string"] = NewStubType("string", String);
Unlock(); Unlock();
} }
...@@ -571,9 +609,9 @@ func (p *Parser) Next() { ...@@ -571,9 +609,9 @@ func (p *Parser) Next() {
p.token = p.str[start : p.index]; p.token = p.str[start : p.index];
} }
func (p *Parser) Type() *StubType func (p *Parser) Type(name string) *StubType
func (p *Parser) Array() *StubType { func (p *Parser) Array(name string) *StubType {
size := uint64(0); size := uint64(0);
open := true; open := true;
if p.token != "]" { if p.token != "]" {
...@@ -592,25 +630,25 @@ func (p *Parser) Array() *StubType { ...@@ -592,25 +630,25 @@ func (p *Parser) Array() *StubType {
return MissingStub return MissingStub
} }
p.Next(); p.Next();
elemtype := p.Type(); elemtype := p.Type("");
return NewStubType(NewArrayTypeStruct(open, size, elemtype)); return NewStubType(name, NewArrayTypeStruct(name, open, size, elemtype));
} }
func (p *Parser) Map() *StubType { func (p *Parser) Map(name string) *StubType {
if p.token != "[" { if p.token != "[" {
return MissingStub return MissingStub
} }
p.Next(); p.Next();
keytype := p.Type(); keytype := p.Type("");
if p.token != "]" { if p.token != "]" {
return MissingStub return MissingStub
} }
p.Next(); p.Next();
elemtype := p.Type(); elemtype := p.Type("");
return NewStubType(NewMapTypeStruct(keytype, elemtype)); return NewStubType(name, NewMapTypeStruct(name, keytype, elemtype));
} }
func (p *Parser) Chan(dir int) *StubType { func (p *Parser) Chan(name string, dir int) *StubType {
if p.token == "<-" { if p.token == "<-" {
if dir != BothDir { if dir != BothDir {
return MissingStub return MissingStub
...@@ -618,8 +656,8 @@ func (p *Parser) Chan(dir int) *StubType { ...@@ -618,8 +656,8 @@ func (p *Parser) Chan(dir int) *StubType {
p.Next(); p.Next();
dir = SendDir; dir = SendDir;
} }
elemtype := p.Type(); elemtype := p.Type("");
return NewStubType(NewChanTypeStruct(dir, elemtype)); return NewStubType(name, NewChanTypeStruct(name, dir, elemtype));
} }
// Parse array of fields for struct, interface, and func arguments // Parse array of fields for struct, interface, and func arguments
...@@ -636,7 +674,7 @@ func (p *Parser) Fields(sep string) *[]Field { ...@@ -636,7 +674,7 @@ func (p *Parser) Fields(sep string) *[]Field {
} }
a[nf].name = p.token; a[nf].name = p.token;
p.Next(); p.Next();
a[nf].typ = p.Type(); a[nf].typ = p.Type("");
nf++; nf++;
if p.token != sep { if p.token != sep {
break; break;
...@@ -646,59 +684,59 @@ func (p *Parser) Fields(sep string) *[]Field { ...@@ -646,59 +684,59 @@ func (p *Parser) Fields(sep string) *[]Field {
return a[0:nf]; return a[0:nf];
} }
func (p *Parser) Struct() *StubType { func (p *Parser) Struct(name string) *StubType {
f := p.Fields(";"); f := p.Fields(";");
if p.token != "}" { if p.token != "}" {
return MissingStub; return MissingStub;
} }
p.Next(); p.Next();
return NewStubType(NewStructTypeStruct(f)); return NewStubType(name, NewStructTypeStruct(name, f));
} }
func (p *Parser) Interface() *StubType { func (p *Parser) Interface(name string) *StubType {
f := p.Fields(";"); f := p.Fields(";");
if p.token != "}" { if p.token != "}" {
return MissingStub; return MissingStub;
} }
p.Next(); p.Next();
return NewStubType(NewInterfaceTypeStruct(f)); return NewStubType(name, NewInterfaceTypeStruct(name, f));
} }
func (p *Parser) Func() *StubType { func (p *Parser) Func(name string) *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;
} }
p.Next(); p.Next();
if p.token != "(" { if p.token != "(" {
// 1 list: the in parameters only // 1 list: the in parameters only
return NewStubType(NewFuncTypeStruct(f1, nil)); return NewStubType(name, NewFuncTypeStruct(name, f1, nil));
} }
p.Next(); p.Next();
f2 := NewStructTypeStruct(p.Fields(",")); f2 := NewStructTypeStruct("", p.Fields(","));
if p.token != ")" { if p.token != ")" {
return MissingStub; return MissingStub;
} }
p.Next(); p.Next();
// 2 lists: the in and out parameters are present // 2 lists: the in and out parameters are present
return NewStubType(NewFuncTypeStruct(f1, f2)); return NewStubType(name, NewFuncTypeStruct(name, f1, f2));
} }
func (p *Parser) Type() *StubType { func (p *Parser) Type(name string) *StubType {
dir := BothDir; 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.Type())); return NewStubType(name, NewPtrTypeStruct(name, p.Type("")));
case p.token == "[": case p.token == "[":
p.Next(); p.Next();
return p.Array(); return p.Array(name);
case p.token == "map": case p.token == "map":
p.Next(); p.Next();
return p.Map(); return p.Map(name);
case p.token == "<-": case p.token == "<-":
p.Next(); p.Next();
dir = RecvDir; dir = RecvDir;
...@@ -708,24 +746,24 @@ func (p *Parser) Type() *StubType { ...@@ -708,24 +746,24 @@ func (p *Parser) Type() *StubType {
fallthrough; fallthrough;
case p.token == "chan": case p.token == "chan":
p.Next(); p.Next();
return p.Chan(dir); return p.Chan(name, 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(); return p.Struct(name);
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(); return p.Interface(name);
case p.token == "(": case p.token == "(":
p.Next(); p.Next();
return p.Func(); return p.Func(name);
case isdigit(p.token[0]): case isdigit(p.token[0]):
p.Next(); p.Next();
return MissingStub; return MissingStub;
...@@ -736,6 +774,11 @@ func (p *Parser) Type() *StubType { ...@@ -736,6 +774,11 @@ func (p *Parser) Type() *StubType {
// 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
if s, ok := basicstub[p.token]; ok { if s, ok := basicstub[p.token]; ok {
p.Next(); p.Next();
if name != "" {
// Need to make a copy because we are renaming a basic type
b := s.Get();
s = NewStubType(name, NewBasicType(name, b.Kind(), b.Size()));
}
return s return s
} }
// not a basic - must be of the form "P.T" // not a basic - must be of the form "P.T"
...@@ -749,17 +792,16 @@ func (p *Parser) Type() *StubType { ...@@ -749,17 +792,16 @@ func (p *Parser) Type() *StubType {
p.Next(); p.Next();
return MissingStub; return MissingStub;
} }
s := new(StubType); s := NewStubType(p.token, nil);
s.name = p.token;
p.Next(); p.Next();
return s; return s;
} }
export func ParseTypeString(str string) Type { export func ParseTypeString(name, typestring string) Type {
p := new(Parser); p := new(Parser);
p.str = str; p.str = typestring;
p.Next(); p.Next();
return p.Type().Get(); return p.Type(name).Get();
} }
// Create typestring map from reflect.typestrings() data. Lock is held. // Create typestring map from reflect.typestrings() data. Lock is held.
...@@ -819,7 +861,7 @@ func ExpandType(name string) Type { ...@@ -819,7 +861,7 @@ func ExpandType(name string) Type {
return *t return *t
} }
types[name] = &Missing; // prevent recursion; will overwrite types[name] = &Missing; // prevent recursion; will overwrite
t1 := ParseTypeString(TypeNameToTypeString(name)); t1 := ParseTypeString(name, TypeNameToTypeString(name));
p := new(Type); p := new(Type);
*p = t1; *p = t1;
types[name] = p; types[name] = p;
......
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