1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package ir 6 7import ( 8 "cmd/compile/internal/base" 9 "cmd/compile/internal/types" 10 "cmd/internal/src" 11 "fmt" 12) 13 14// Nodes that represent the syntax of a type before type-checking. 15// After type-checking, they serve only as shells around a *types.Type. 16// Calling TypeNode converts a *types.Type to a Node shell. 17 18// An Ntype is a Node that syntactically looks like a type. 19// It can be the raw syntax for a type before typechecking, 20// or it can be an OTYPE with Type() set to a *types.Type. 21// Note that syntax doesn't guarantee it's a type: an expression 22// like *fmt is an Ntype (we don't know whether names are types yet), 23// but at least 1+1 is not an Ntype. 24type Ntype interface { 25 Node 26 CanBeNtype() 27} 28 29// A miniType is a minimal type syntax Node implementation, 30// to be embedded as the first field in a larger node implementation. 31type miniType struct { 32 miniNode 33 typ *types.Type 34} 35 36func (*miniType) CanBeNtype() {} 37 38func (n *miniType) Type() *types.Type { return n.typ } 39 40// setOTYPE changes n to be an OTYPE node returning t. 41// Rewriting the node in place this way should not be strictly 42// necessary (we should be able to update the uses with 43// proper OTYPE nodes), but it's mostly harmless and easy 44// to keep doing for now. 45// 46// setOTYPE also records t.Nod = self if t.Nod is not already set. 47// (Some types are shared by multiple OTYPE nodes, so only 48// the first such node is used as t.Nod.) 49func (n *miniType) setOTYPE(t *types.Type, self Ntype) { 50 if n.typ != nil { 51 panic(n.op.String() + " SetType: type already set") 52 } 53 n.op = OTYPE 54 n.typ = t 55 t.SetNod(self) 56} 57 58func (n *miniType) Sym() *types.Sym { return nil } // for Format OTYPE 59func (n *miniType) Implicit() bool { return false } // for Format OTYPE 60 61// A ChanType represents a chan Elem syntax with the direction Dir. 62type ChanType struct { 63 miniType 64 Elem Ntype 65 Dir types.ChanDir 66} 67 68func NewChanType(pos src.XPos, elem Ntype, dir types.ChanDir) *ChanType { 69 n := &ChanType{Elem: elem, Dir: dir} 70 n.op = OTCHAN 71 n.pos = pos 72 return n 73} 74 75func (n *ChanType) SetOTYPE(t *types.Type) { 76 n.setOTYPE(t, n) 77 n.Elem = nil 78} 79 80// A MapType represents a map[Key]Value type syntax. 81type MapType struct { 82 miniType 83 Key Ntype 84 Elem Ntype 85} 86 87func NewMapType(pos src.XPos, key, elem Ntype) *MapType { 88 n := &MapType{Key: key, Elem: elem} 89 n.op = OTMAP 90 n.pos = pos 91 return n 92} 93 94func (n *MapType) SetOTYPE(t *types.Type) { 95 n.setOTYPE(t, n) 96 n.Key = nil 97 n.Elem = nil 98} 99 100// A StructType represents a struct { ... } type syntax. 101type StructType struct { 102 miniType 103 Fields []*Field 104} 105 106func NewStructType(pos src.XPos, fields []*Field) *StructType { 107 n := &StructType{Fields: fields} 108 n.op = OTSTRUCT 109 n.pos = pos 110 return n 111} 112 113func (n *StructType) SetOTYPE(t *types.Type) { 114 n.setOTYPE(t, n) 115 n.Fields = nil 116} 117 118// An InterfaceType represents a struct { ... } type syntax. 119type InterfaceType struct { 120 miniType 121 Methods []*Field 122} 123 124func NewInterfaceType(pos src.XPos, methods []*Field) *InterfaceType { 125 n := &InterfaceType{Methods: methods} 126 n.op = OTINTER 127 n.pos = pos 128 return n 129} 130 131func (n *InterfaceType) SetOTYPE(t *types.Type) { 132 n.setOTYPE(t, n) 133 n.Methods = nil 134} 135 136// A FuncType represents a func(Args) Results type syntax. 137type FuncType struct { 138 miniType 139 Recv *Field 140 Params []*Field 141 Results []*Field 142} 143 144func NewFuncType(pos src.XPos, rcvr *Field, args, results []*Field) *FuncType { 145 n := &FuncType{Recv: rcvr, Params: args, Results: results} 146 n.op = OTFUNC 147 n.pos = pos 148 return n 149} 150 151func (n *FuncType) SetOTYPE(t *types.Type) { 152 n.setOTYPE(t, n) 153 n.Recv = nil 154 n.Params = nil 155 n.Results = nil 156} 157 158// A Field is a declared struct field, interface method, or function argument. 159// It is not a Node. 160type Field struct { 161 Pos src.XPos 162 Sym *types.Sym 163 Ntype Ntype 164 Type *types.Type 165 Embedded bool 166 IsDDD bool 167 Note string 168 Decl *Name 169} 170 171func NewField(pos src.XPos, sym *types.Sym, ntyp Ntype, typ *types.Type) *Field { 172 return &Field{Pos: pos, Sym: sym, Ntype: ntyp, Type: typ} 173} 174 175func (f *Field) String() string { 176 var typ string 177 if f.Type != nil { 178 typ = fmt.Sprint(f.Type) 179 } else { 180 typ = fmt.Sprint(f.Ntype) 181 } 182 if f.Sym != nil { 183 return fmt.Sprintf("%v %v", f.Sym, typ) 184 } 185 return typ 186} 187 188// TODO(mdempsky): Make Field a Node again so these can be generated? 189// Fields are Nodes in go/ast and cmd/compile/internal/syntax. 190 191func copyField(f *Field) *Field { 192 if f == nil { 193 return nil 194 } 195 c := *f 196 return &c 197} 198func doField(f *Field, do func(Node) bool) bool { 199 if f == nil { 200 return false 201 } 202 if f.Decl != nil && do(f.Decl) { 203 return true 204 } 205 if f.Ntype != nil && do(f.Ntype) { 206 return true 207 } 208 return false 209} 210func editField(f *Field, edit func(Node) Node) { 211 if f == nil { 212 return 213 } 214 if f.Decl != nil { 215 f.Decl = edit(f.Decl).(*Name) 216 } 217 if f.Ntype != nil { 218 f.Ntype = edit(f.Ntype).(Ntype) 219 } 220} 221 222func copyFields(list []*Field) []*Field { 223 out := make([]*Field, len(list)) 224 for i, f := range list { 225 out[i] = copyField(f) 226 } 227 return out 228} 229func doFields(list []*Field, do func(Node) bool) bool { 230 for _, x := range list { 231 if doField(x, do) { 232 return true 233 } 234 } 235 return false 236} 237func editFields(list []*Field, edit func(Node) Node) { 238 for _, f := range list { 239 editField(f, edit) 240 } 241} 242 243// A SliceType represents a []Elem type syntax. 244// If DDD is true, it's the ...Elem at the end of a function list. 245type SliceType struct { 246 miniType 247 Elem Ntype 248 DDD bool 249} 250 251func NewSliceType(pos src.XPos, elem Ntype) *SliceType { 252 n := &SliceType{Elem: elem} 253 n.op = OTSLICE 254 n.pos = pos 255 return n 256} 257 258func (n *SliceType) SetOTYPE(t *types.Type) { 259 n.setOTYPE(t, n) 260 n.Elem = nil 261} 262 263// An ArrayType represents a [Len]Elem type syntax. 264// If Len is nil, the type is a [...]Elem in an array literal. 265type ArrayType struct { 266 miniType 267 Len Node 268 Elem Ntype 269} 270 271func NewArrayType(pos src.XPos, len Node, elem Ntype) *ArrayType { 272 n := &ArrayType{Len: len, Elem: elem} 273 n.op = OTARRAY 274 n.pos = pos 275 return n 276} 277 278func (n *ArrayType) SetOTYPE(t *types.Type) { 279 n.setOTYPE(t, n) 280 n.Len = nil 281 n.Elem = nil 282} 283 284// A typeNode is a Node wrapper for type t. 285type typeNode struct { 286 miniNode 287 typ *types.Type 288} 289 290func newTypeNode(pos src.XPos, typ *types.Type) *typeNode { 291 n := &typeNode{typ: typ} 292 n.pos = pos 293 n.op = OTYPE 294 return n 295} 296 297func (n *typeNode) Type() *types.Type { return n.typ } 298func (n *typeNode) Sym() *types.Sym { return n.typ.Sym() } 299func (n *typeNode) CanBeNtype() {} 300 301// TypeNode returns the Node representing the type t. 302func TypeNode(t *types.Type) Ntype { 303 return TypeNodeAt(src.NoXPos, t) 304} 305 306// TypeNodeAt is like TypeNode, but allows specifying the position 307// information if a new OTYPE needs to be constructed. 308// 309// Deprecated: Use TypeNode instead. For typical use, the position for 310// an anonymous OTYPE node should not matter. However, TypeNodeAt is 311// available for use with toolstash -cmp to refactor existing code 312// that is sensitive to OTYPE position. 313func TypeNodeAt(pos src.XPos, t *types.Type) Ntype { 314 if n := t.Obj(); n != nil { 315 if n.Type() != t { 316 base.Fatalf("type skew: %v has type %v, but expected %v", n, n.Type(), t) 317 } 318 return n.(Ntype) 319 } 320 return newTypeNode(pos, t) 321} 322 323// A DynamicType represents the target type in a type switch. 324type DynamicType struct { 325 miniExpr 326 X Node // a *runtime._type for the targeted type 327 ITab Node // for type switches from nonempty interfaces to non-interfaces, this is the itab for that pair. 328} 329 330func NewDynamicType(pos src.XPos, x Node) *DynamicType { 331 n := &DynamicType{X: x} 332 n.pos = pos 333 n.op = ODYNAMICTYPE 334 return n 335} 336