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