tc_info.mx raw

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