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  func (info *Info) Release() {
 107  	for k := range info.Types {
 108  		delete(info.Types, k)
 109  	}
 110  	info.Types = nil
 111  	for k := range info.Defs {
 112  		delete(info.Defs, k)
 113  	}
 114  	info.Defs = nil
 115  	for k := range info.Uses {
 116  		delete(info.Uses, k)
 117  	}
 118  	info.Uses = nil
 119  	for k := range info.Implicits {
 120  		delete(info.Implicits, k)
 121  	}
 122  	info.Implicits = nil
 123  	for k := range info.Scopes {
 124  		delete(info.Scopes, k)
 125  	}
 126  	info.Scopes = nil
 127  	for k := range info.Selections {
 128  		delete(info.Selections, k)
 129  	}
 130  	info.Selections = nil
 131  }
 132  
 133  func (info *Info) TypeOf(e Expr) Type {
 134  	if tv, ok := info.Types[e]; ok {
 135  		return tv.Type
 136  	}
 137  	return nil
 138  }
 139  
 140  // ObjectOf returns the object denoted by identifier id, or nil.
 141  func (info *Info) ObjectOf(id *Name) Object {
 142  	if obj, ok := info.Defs[id]; ok {
 143  		return obj
 144  	}
 145  	return info.Uses[id]
 146  }
 147