tc_info.mx raw

   1  package main
   2  
   3  // TCTypeAndValue records the type and optional constant value for an expression.
   4  type TCTypeAndValue struct {
   5  	Type  Type
   6  	Value ConstVal // nil for non-constant expressions
   7  	mode  exprMode
   8  }
   9  
  10  type exprMode uint8
  11  
  12  const (
  13  	modeInvalid exprMode = iota
  14  	modeVoid             // no value (statement context)
  15  	modeValue            // an addressable or non-addressable value
  16  	modeVar              // addressable variable
  17  	modeConst            // constant expression
  18  	modeType             // a type expression
  19  	modeBuiltin          // a builtin identifier
  20  	modePkg              // a package name
  21  	modeNil              // the predeclared nil
  22  )
  23  
  24  func (tv TCTypeAndValue) IsValue() bool   { return tv.mode == modeValue || tv.mode == modeVar || tv.mode == modeConst || tv.mode == modeNil }
  25  func (tv TCTypeAndValue) IsType() bool    { return tv.mode == modeType }
  26  func (tv TCTypeAndValue) IsBuiltin() bool { return tv.mode == modeBuiltin }
  27  func (tv TCTypeAndValue) IsConst() bool   { return tv.mode == modeConst }
  28  func (tv TCTypeAndValue) Addressable() bool { return tv.mode == modeVar }
  29  
  30  // Info holds the result of type-checking a set of Files.
  31  // Consumers access type info for each expression and identifier.
  32  type Info struct {
  33  	// Types maps each expression to its type and value.
  34  	// For type expressions, TCTypeAndValue.IsType() is true.
  35  	// For constants, TCTypeAndValue.Value is non-nil.
  36  	Types map[Expr]TCTypeAndValue
  37  
  38  	// Defs maps each identifier that declares something to the object it declares.
  39  	// nil objects represent anonymous declarations (blank _ idents).
  40  	Defs map[*Name]Object
  41  
  42  	// Uses maps each identifier that is used (not declared) to the object it denotes.
  43  	Uses map[*Name]Object
  44  
  45  	// Implicits maps nodes to the object they implicitly declare.
  46  	// For imports: ImportDecl -> *PkgName
  47  	// For type switches: the guarded var in each case clause
  48  	Implicits map[Node]Object
  49  
  50  	// Scopes maps AST nodes to the scope they open.
  51  	// File -> file scope, FuncDecl/FuncLit -> function scope, etc.
  52  	Scopes map[Node]*Scope
  53  
  54  	// Selections maps selector expressions X.f to the selection.
  55  	Selections map[*SelectorExpr]*Selection
  56  }
  57  
  58  // Selection describes a field or method selection X.f.
  59  type Selection struct {
  60  	kind  SelectionKind
  61  	recv  Type   // type of X
  62  	obj   Object // selected field or method
  63  	index []int  // path of field indices (for embedded fields)
  64  	indir bool   // true if recv contains a pointer indirection
  65  }
  66  
  67  type SelectionKind int
  68  
  69  const (
  70  	FieldVal SelectionKind = iota
  71  	MethodVal
  72  	MethodExpr
  73  )
  74  
  75  func (s *Selection) Kind() SelectionKind { return s.kind }
  76  func (s *Selection) Recv() Type          { return s.recv }
  77  func (s *Selection) Obj() Object         { return s.obj }
  78  func (s *Selection) Index() []int        { return s.index }
  79  func (s *Selection) Indirect() bool      { return s.indir }
  80  func (s *Selection) Type() Type {
  81  	switch s.kind {
  82  	case FieldVal:
  83  		return s.obj.Type()
  84  	case MethodVal:
  85  		sig := s.obj.(*TCFunc).Signature()
  86  		// bound method: drop the receiver parameter
  87  		return NewSignature(nil, sig.params, sig.results, sig.variadic)
  88  	case MethodExpr:
  89  		// unbound: receiver becomes first parameter
  90  		return s.obj.(*TCFunc).Signature()
  91  	}
  92  	return nil
  93  }
  94  
  95  func newInfo() *Info {
  96  	return &Info{
  97  		Types:      map[Expr]TCTypeAndValue{},
  98  		Defs:       map[*Name]Object{},
  99  		Uses:       map[*Name]Object{},
 100  		Implicits:  map[Node]Object{},
 101  		Scopes:     map[Node]*Scope{},
 102  		Selections: map[*SelectorExpr]*Selection{},
 103  	}
 104  }
 105  
 106  // TypeOf returns the type of expression e, or nil if unknown.
 107  func (info *Info) TypeOf(e Expr) Type {
 108  	if tv, ok := info.Types[e]; ok {
 109  		return tv.Type
 110  	}
 111  	return nil
 112  }
 113  
 114  // ObjectOf returns the object denoted by identifier id, or nil.
 115  func (info *Info) ObjectOf(id *Name) Object {
 116  	if obj, ok := info.Defs[id]; ok {
 117  		return obj
 118  	}
 119  	return info.Uses[id]
 120  }
 121