...

Source file src/pkg/go/types/selection.go

     1	// Copyright 2013 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	// This file implements Selections.
     6	
     7	package types
     8	
     9	import (
    10		"bytes"
    11		"fmt"
    12	)
    13	
    14	// SelectionKind describes the kind of a selector expression x.f
    15	// (excluding qualified identifiers).
    16	type SelectionKind int
    17	
    18	const (
    19		FieldVal   SelectionKind = iota // x.f is a struct field selector
    20		MethodVal                       // x.f is a method selector
    21		MethodExpr                      // x.f is a method expression
    22	)
    23	
    24	// A Selection describes a selector expression x.f.
    25	// For the declarations:
    26	//
    27	//	type T struct{ x int; E }
    28	//	type E struct{}
    29	//	func (e E) m() {}
    30	//	var p *T
    31	//
    32	// the following relations exist:
    33	//
    34	//	Selector    Kind          Recv    Obj    Type               Index     Indirect
    35	//
    36	//	p.x         FieldVal      T       x      int                {0}       true
    37	//	p.m         MethodVal     *T      m      func (e *T) m()    {1, 0}    true
    38	//	T.m         MethodExpr    T       m      func m(_ T)        {1, 0}    false
    39	//
    40	type Selection struct {
    41		kind     SelectionKind
    42		recv     Type   // type of x
    43		obj      Object // object denoted by x.f
    44		index    []int  // path from x to x.f
    45		indirect bool   // set if there was any pointer indirection on the path
    46	}
    47	
    48	// Kind returns the selection kind.
    49	func (s *Selection) Kind() SelectionKind { return s.kind }
    50	
    51	// Recv returns the type of x in x.f.
    52	func (s *Selection) Recv() Type { return s.recv }
    53	
    54	// Obj returns the object denoted by x.f; a *Var for
    55	// a field selection, and a *Func in all other cases.
    56	func (s *Selection) Obj() Object { return s.obj }
    57	
    58	// Type returns the type of x.f, which may be different from the type of f.
    59	// See Selection for more information.
    60	func (s *Selection) Type() Type {
    61		switch s.kind {
    62		case MethodVal:
    63			// The type of x.f is a method with its receiver type set
    64			// to the type of x.
    65			sig := *s.obj.(*Func).typ.(*Signature)
    66			recv := *sig.recv
    67			recv.typ = s.recv
    68			sig.recv = &recv
    69			return &sig
    70	
    71		case MethodExpr:
    72			// The type of x.f is a function (without receiver)
    73			// and an additional first argument with the same type as x.
    74			// TODO(gri) Similar code is already in call.go - factor!
    75			// TODO(gri) Compute this eagerly to avoid allocations.
    76			sig := *s.obj.(*Func).typ.(*Signature)
    77			arg0 := *sig.recv
    78			sig.recv = nil
    79			arg0.typ = s.recv
    80			var params []*Var
    81			if sig.params != nil {
    82				params = sig.params.vars
    83			}
    84			sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
    85			return &sig
    86		}
    87	
    88		// In all other cases, the type of x.f is the type of x.
    89		return s.obj.Type()
    90	}
    91	
    92	// Index describes the path from x to f in x.f.
    93	// The last index entry is the field or method index of the type declaring f;
    94	// either:
    95	//
    96	//	1) the list of declared methods of a named type; or
    97	//	2) the list of methods of an interface type; or
    98	//	3) the list of fields of a struct type.
    99	//
   100	// The earlier index entries are the indices of the embedded fields implicitly
   101	// traversed to get from (the type of) x to f, starting at embedding depth 0.
   102	func (s *Selection) Index() []int { return s.index }
   103	
   104	// Indirect reports whether any pointer indirection was required to get from
   105	// x to f in x.f.
   106	func (s *Selection) Indirect() bool { return s.indirect }
   107	
   108	func (s *Selection) String() string { return SelectionString(s, nil) }
   109	
   110	// SelectionString returns the string form of s.
   111	// The Qualifier controls the printing of
   112	// package-level objects, and may be nil.
   113	//
   114	// Examples:
   115	//	"field (T) f int"
   116	//	"method (T) f(X) Y"
   117	//	"method expr (T) f(X) Y"
   118	//
   119	func SelectionString(s *Selection, qf Qualifier) string {
   120		var k string
   121		switch s.kind {
   122		case FieldVal:
   123			k = "field "
   124		case MethodVal:
   125			k = "method "
   126		case MethodExpr:
   127			k = "method expr "
   128		default:
   129			unreachable()
   130		}
   131		var buf bytes.Buffer
   132		buf.WriteString(k)
   133		buf.WriteByte('(')
   134		WriteType(&buf, s.Recv(), qf)
   135		fmt.Fprintf(&buf, ") %s", s.obj.Name())
   136		if T := s.Type(); s.kind == FieldVal {
   137			buf.WriteByte(' ')
   138			WriteType(&buf, T, qf)
   139		} else {
   140			WriteSignature(&buf, T.(*Signature), qf)
   141		}
   142		return buf.String()
   143	}
   144	

View as plain text