info.go raw

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