Source file src/cmd/compile/internal/ir/type.go

     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  
     5  package ir
     6  
     7  import (
     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.
    24  type 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.
    31  type miniType struct {
    32  	miniNode
    33  	typ *types.Type
    34  }
    35  
    36  func (*miniType) CanBeNtype() {}
    37  
    38  func (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.)
    49  func (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  
    58  func (n *miniType) Sym() *types.Sym { return nil }   // for Format OTYPE
    59  func (n *miniType) Implicit() bool  { return false } // for Format OTYPE
    60  
    61  // A ChanType represents a chan Elem syntax with the direction Dir.
    62  type ChanType struct {
    63  	miniType
    64  	Elem Ntype
    65  	Dir  types.ChanDir
    66  }
    67  
    68  func 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  
    75  func (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.
    81  type MapType struct {
    82  	miniType
    83  	Key  Ntype
    84  	Elem Ntype
    85  }
    86  
    87  func 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  
    94  func (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.
   101  type StructType struct {
   102  	miniType
   103  	Fields []*Field
   104  }
   105  
   106  func 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  
   113  func (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.
   119  type InterfaceType struct {
   120  	miniType
   121  	Methods []*Field
   122  }
   123  
   124  func 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  
   131  func (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.
   137  type FuncType struct {
   138  	miniType
   139  	Recv    *Field
   140  	Params  []*Field
   141  	Results []*Field
   142  }
   143  
   144  func 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  
   151  func (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.
   160  type 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  
   171  func 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  
   175  func (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  
   191  func copyField(f *Field) *Field {
   192  	if f == nil {
   193  		return nil
   194  	}
   195  	c := *f
   196  	return &c
   197  }
   198  func 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  }
   210  func 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  
   222  func 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  }
   229  func 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  }
   237  func 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.
   245  type SliceType struct {
   246  	miniType
   247  	Elem Ntype
   248  	DDD  bool
   249  }
   250  
   251  func 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  
   258  func (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.
   265  type ArrayType struct {
   266  	miniType
   267  	Len  Node
   268  	Elem Ntype
   269  }
   270  
   271  func 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  
   278  func (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.
   285  type typeNode struct {
   286  	miniNode
   287  	typ *types.Type
   288  }
   289  
   290  func 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  
   297  func (n *typeNode) Type() *types.Type { return n.typ }
   298  func (n *typeNode) Sym() *types.Sym   { return n.typ.Sym() }
   299  func (n *typeNode) CanBeNtype()       {}
   300  
   301  // TypeNode returns the Node representing the type t.
   302  func 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.
   313  func 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.
   324  type 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  
   330  func 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  

View as plain text