3 // This file defines a number of miscellaneous utility functions.
17 // noparens returns e with any enclosing parentheses stripped.
18 func noparens(e ast.Expr) ast.Expr {
20 p, ok := e.(*ast.ParenExpr)
29 // isBlankIdent returns true iff e is an Ident with name "_".
30 // They have no associated types.Object, and thus no type.
32 // TODO(gri): consider making typechecker not treat them differently.
33 // It's one less thing for clients like us to worry about.
35 func isBlankIdent(e ast.Expr) bool {
36 id, ok := e.(*ast.Ident)
37 return ok && id.Name == "_"
40 //// Type utilities. Some of these belong in go/types.
42 // underlyingType returns the underlying type of typ.
43 // TODO(gri): this is a copy of go/types.underlying; export that function.
45 func underlyingType(typ types.Type) types.Type {
46 if typ, ok := typ.(*types.NamedType); ok {
47 return typ.Underlying // underlying types are never NamedTypes
50 panic("underlyingType(nil)")
55 // isPointer returns true for types whose underlying type is a pointer.
56 func isPointer(typ types.Type) bool {
57 if nt, ok := typ.(*types.NamedType); ok {
60 _, ok := typ.(*types.Pointer)
64 // pointer(typ) returns the type that is a pointer to typ.
65 func pointer(typ types.Type) *types.Pointer {
66 return &types.Pointer{Base: typ}
69 // indirect(typ) assumes that typ is a pointer type,
70 // or named alias thereof, and returns its base type.
71 // Panic ensures if it is not a pointer.
73 func indirectType(ptr types.Type) types.Type {
74 if v, ok := underlyingType(ptr).(*types.Pointer); ok {
77 // When debugging it is convenient to comment out this line
78 // and let it continue to print the (illegal) SSA form.
79 panic("indirect() of non-pointer type: " + ptr.String())
83 // deref returns a pointer's base type; otherwise it returns typ.
84 func deref(typ types.Type) types.Type {
85 if typ, ok := underlyingType(typ).(*types.Pointer); ok {
91 // methodIndex returns the method (and its index) named id within the
92 // method table methods of named or interface type typ. If not found,
95 func methodIndex(typ types.Type, methods []*types.Method, id Id) (i int, m *types.Method) {
96 for i, m = range methods {
97 if IdFromQualifiedName(m.QualifiedName) == id {
101 panic(fmt.Sprint("method not found: ", id, " in interface ", typ))
104 // objKind returns the syntactic category of the named entity denoted by obj.
105 func objKind(obj types.Object) ast.ObjKind {
109 case *types.TypeName:
118 panic(fmt.Sprintf("unexpected Object type: %T", obj))
121 // DefaultType returns the default "typed" type for an "untyped" type;
122 // it returns the incoming type for all other types. If there is no
123 // corresponding untyped type, the result is types.Typ[types.Invalid].
125 // Exported to exp/ssa/interp.
127 // TODO(gri): this is a copy of go/types.defaultType; export that function.
129 func DefaultType(typ types.Type) types.Type {
130 if t, ok := typ.(*types.Basic); ok {
134 // There is no default type for nil. For a good error message,
135 // catch this case before calling this function.
136 case types.UntypedBool:
138 case types.UntypedInt:
140 case types.UntypedRune:
142 case types.UntypedFloat:
144 case types.UntypedComplex:
146 case types.UntypedString:
154 // makeId returns the Id (name, pkg) if the name is exported or
155 // (name, nil) otherwise.
157 func makeId(name string, pkg *types.Package) (id Id) {
159 if !ast.IsExported(name) {
165 // IdFromQualifiedName returns the Id (qn.Name, qn.Pkg) if qn is an
166 // exported name or (qn.Name, nil) otherwise.
168 // Exported to exp/ssa/interp.
170 func IdFromQualifiedName(qn types.QualifiedName) Id {
171 return makeId(qn.Name, qn.Pkg)