Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 package ssa | |
2 | |
3 // This file defines utilities for querying the results of typechecker: | |
4 // types of expressions, values of constant expressions, referents of identifier s. | |
5 | |
6 import ( | |
7 "code.google.com/p/go.exp/go/types" | |
8 "fmt" | |
9 "go/ast" | |
10 ) | |
11 | |
12 // TypeInfo containsinformation provided by the typechecker about the | |
gri
2013/04/23 23:35:15
contains information
adonovan
2013/04/24 14:06:29
Done.
| |
13 // abstract syntax for a single package. | |
14 type TypeInfo struct { | |
15 types map[ast.Expr]types.Type // inferred types of expressions | |
16 constants map[ast.Expr]*Literal // values of constant expressions | |
17 idents map[*ast.Ident]types.Object // canonical type objects for name d entities | |
18 } | |
19 | |
20 // TypeOf returns the type of expression e. | |
21 // Precondition: e belongs to the package's ASTs. | |
22 func (info *TypeInfo) TypeOf(e ast.Expr) types.Type { | |
23 // For Ident, b.types may be more specific than | |
24 // b.obj(id.(*ast.Ident)).GetType(), | |
25 // e.g. in the case of typeswitch. | |
26 if t, ok := info.types[e]; ok { | |
27 return t | |
28 } | |
29 // The typechecker doesn't notify us of all Idents, | |
30 // e.g. s.Key and s.Value in a RangeStmt. | |
31 // So we have this fallback. | |
32 // TODO(gri): Is this a typechecker bug? If so, eliminate | |
gri
2013/04/23 23:35:15
probably - the typechecker should do a better job
adonovan
2013/04/24 14:06:29
This isn't new, the code just moved from builder.g
| |
33 // this case and panic. | |
34 if id, ok := e.(*ast.Ident); ok { | |
35 return info.ObjectOf(id).GetType() | |
36 } | |
37 panic("no type for expression") | |
38 } | |
39 | |
40 // ValueOf returns the value of expression e if it is a constant, | |
41 // nil otherwise. | |
42 // | |
43 func (info *TypeInfo) ValueOf(e ast.Expr) *Literal { | |
44 return info.constants[e] | |
45 } | |
46 | |
47 // ObjectOf returns the typechecker object denoted by the specified id. | |
48 // Precondition: id belongs to the package's ASTs. | |
49 // | |
50 func (info *TypeInfo) ObjectOf(id *ast.Ident) types.Object { | |
gri
2013/04/23 23:35:15
also accept selector expressions?
adonovan
2013/04/24 14:06:29
It wouldn't actually simplify any other code in th
| |
51 if obj, ok := info.idents[id]; ok { | |
52 return obj | |
53 } | |
54 panic(fmt.Sprintf("no types.Object for ast.Ident %s @ %p", id.Name, id)) | |
55 } | |
56 | |
57 // IsType returns true iff expression e denotes a type. | |
58 // Precondition: e belongs to the package's ASTs. | |
59 // | |
60 func (info *TypeInfo) IsType(e ast.Expr) bool { | |
61 switch e := e.(type) { | |
62 case *ast.SelectorExpr: // pkg.Type | |
63 if obj := info.isPackageRef(e); obj != nil { | |
64 return objKind(obj) == ast.Typ | |
65 } | |
66 case *ast.StarExpr: // *T | |
67 return info.IsType(e.X) | |
68 case *ast.Ident: | |
69 return objKind(info.ObjectOf(e)) == ast.Typ | |
70 case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType: | |
71 return true | |
72 case *ast.ParenExpr: | |
73 return info.IsType(e.X) | |
74 } | |
75 return false | |
76 } | |
77 | |
78 // isPackageRef returns the identity of the object if sel is a | |
79 // package-qualified reference to a named const, var, func or type. | |
80 // Otherwise it returns nil. | |
81 // Precondition: sel belongs to the package's ASTs. | |
82 // | |
83 func (info *TypeInfo) isPackageRef(sel *ast.SelectorExpr) types.Object { | |
84 if id, ok := sel.X.(*ast.Ident); ok { | |
85 if obj := info.ObjectOf(id); objKind(obj) == ast.Pkg { | |
86 return obj.(*types.Package).Scope.Lookup(sel.Sel.Name) | |
87 } | |
88 } | |
89 return nil | |
90 } | |
OLD | NEW |