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