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