1
0
mirror of https://github.com/golang/go synced 2024-10-01 13:18:33 -06:00
go/ssa/util.go
Alan Donovan 4da31df1c8 go.tools/ssa: (another) major refactoring of method-set logic.
We now use LookupFieldOrMethod for all SelectorExprs, and
simplify the logic to discriminate the various cases.

We inline static calls to promoted/indirected functions,
dramatically reducing the number of functions created.

More tests are needed, but I'd like to submit this as-is.

In this CL, we:
- rely less on Id strings.  Internally we now use
  *types.Method (and its components) almost everywhere.
- stop thinking of types.Methods as objects. They don't
  have stable identities. (Hopefully they will become
  plain-old structs soon.)
- eliminate receiver indirection wrappers:
  indirection and promotion are handled together by makeWrapper.
- Handle the interactions of promotion, indirection and
  abstract methods much more cleanly.
- support receiver-bound interface method closures.
- break up builder.selectField so we can re-use parts
  (emitFieldSelection).
- add importer.PackageInfo.classifySelector utility.
- delete interfaceMethodIndex()
- delete namedTypeMethodIndex()
- delete isSuperInterface() (replaced by types.IsAssignable)
- call memberFromObject on each declared concrete method's
  *types.Func, not on every Method frem each method set, in the
  CREATE phase for packages loaded by gcimporter.

go/types:
- document Func, Signature.Recv() better.
- use fmt in {Package,Label}.String
- reimplement Func.String to be prettier and to include method
  receivers.

API changes:
- Function.method now holds the types.Method (soon to be
  not-an-object) for synthetic wrappers.
- CallCommon.Method now contains an abstract (interface)
  method object; was an abstract method index.
- CallCommon.MethodId() gone.
- Program.LookupMethod now takes a *Method not an Id string.

R=gri
CC=golang-dev
https://golang.org/cl/11674043
2013-07-26 11:22:34 -04:00

100 lines
2.2 KiB
Go

package ssa
// This file defines a number of miscellaneous utility functions.
import (
"fmt"
"go/ast"
"io"
"os"
"code.google.com/p/go.tools/go/types"
)
func unreachable() {
panic("unreachable")
}
//// AST utilities
// unparen returns e with any enclosing parentheses stripped.
func unparen(e ast.Expr) ast.Expr {
for {
p, ok := e.(*ast.ParenExpr)
if !ok {
break
}
e = p.X
}
return e
}
// isBlankIdent returns true iff e is an Ident with name "_".
// They have no associated types.Object, and thus no type.
//
func isBlankIdent(e ast.Expr) bool {
id, ok := e.(*ast.Ident)
return ok && id.Name == "_"
}
//// Type utilities. Some of these belong in go/types.
// isPointer returns true for types whose underlying type is a pointer.
func isPointer(typ types.Type) bool {
_, ok := typ.Underlying().(*types.Pointer)
return ok
}
// deref returns a pointer's element type; otherwise it returns typ.
func deref(typ types.Type) types.Type {
if p, ok := typ.Underlying().(*types.Pointer); ok {
return p.Elem()
}
return typ
}
// DefaultType returns the default "typed" type for an "untyped" type;
// it returns the incoming type for all other types. The default type
// for untyped nil is untyped nil.
//
// Exported to exp/ssa/interp.
//
// TODO(gri): this is a copy of go/types.defaultType; export that function.
//
func DefaultType(typ types.Type) types.Type {
if t, ok := typ.(*types.Basic); ok {
k := t.Kind()
switch k {
case types.UntypedBool:
k = types.Bool
case types.UntypedInt:
k = types.Int
case types.UntypedRune:
k = types.Rune
case types.UntypedFloat:
k = types.Float64
case types.UntypedComplex:
k = types.Complex128
case types.UntypedString:
k = types.String
}
typ = types.Typ[k]
}
return typ
}
// logStack prints the formatted "start" message to stderr and
// returns a closure that prints the corresponding "end" message.
// Call using 'defer logStack(...)()' to show builder stack on panic.
// Don't forget trailing parens!
//
func logStack(format string, args ...interface{}) func() {
msg := fmt.Sprintf(format, args...)
io.WriteString(os.Stderr, msg)
io.WriteString(os.Stderr, "\n")
return func() {
io.WriteString(os.Stderr, msg)
io.WriteString(os.Stderr, " end\n")
}
}