1
0
mirror of https://github.com/golang/go synced 2024-11-18 18:04:46 -07:00

go.tools/ssa: drop ssa.Id in favour of types.Id function.

Also exploit fact that Recv() is now always non-nil, even for interfaces.

R=gri
CC=golang-dev
https://golang.org/cl/11613043
This commit is contained in:
Alan Donovan 2013-07-19 19:38:16 -04:00
parent d722d82c52
commit d203f128e2
7 changed files with 32 additions and 91 deletions

View File

@ -681,7 +681,7 @@ func (b *builder) expr(fn *Function, e ast.Expr) Value {
return b.expr(fn, e.Sel)
}
id := makeId(e.Sel.Name, fn.Pkg.Object)
id := types.Id(fn.Pkg.Object, e.Sel.Name)
// (*T).f or T.f, the method f from the method-set of type T.
if fn.Pkg.info.IsType(e.X) {
@ -772,7 +772,7 @@ func (b *builder) stmtList(fn *Function, list []ast.Stmt) {
//
// findMethod returns (nil, nil) if no such method was found.
//
func (b *builder) findMethod(fn *Function, base ast.Expr, id Id) (*Function, Value) {
func (b *builder) findMethod(fn *Function, base ast.Expr, id string) (*Function, Value) {
typ := fn.Pkg.typeOf(base)
// Consult method-set of X.
@ -831,7 +831,7 @@ func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
return
}
id := makeId(sel.Sel.Name, fn.Pkg.Object)
id := types.Id(fn.Pkg.Object, sel.Sel.Name)
// Let X be the type of x.

View File

@ -118,6 +118,10 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
pkg.values[obj] = fn
pkg.Members[name] = fn
} else {
// TODO(adonovan): interface methods now have
// objects, but we probably don't want to call
// memberFromObject for them.
// Method declaration.
// TODO(adonovan) Move this test elsewhere.
if _, ok := recv.Type().Underlying().(*types.Interface); ok {
@ -125,7 +129,7 @@ func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
}
_, method := namedTypeMethodIndex(
deref(recv.Type()).(*types.Named),
makeId(name, pkg.Object))
types.Id(pkg.Object, name))
pkg.Prog.concreteMethods[method] = fn
}

View File

@ -409,14 +409,14 @@ func initReflect(i *interpreter) {
}
i.rtypeMethods = ssa.MethodSet{
ssa.Id{nil, "Bits"}: newMethod(i.reflectPackage, rtypeType, "Bits"),
ssa.Id{nil, "Elem"}: newMethod(i.reflectPackage, rtypeType, "Elem"),
ssa.Id{nil, "Kind"}: newMethod(i.reflectPackage, rtypeType, "Kind"),
ssa.Id{nil, "NumOut"}: newMethod(i.reflectPackage, rtypeType, "NumOut"),
ssa.Id{nil, "Out"}: newMethod(i.reflectPackage, rtypeType, "Out"),
ssa.Id{nil, "String"}: newMethod(i.reflectPackage, rtypeType, "String"),
"Bits": newMethod(i.reflectPackage, rtypeType, "Bits"),
"Elem": newMethod(i.reflectPackage, rtypeType, "Elem"),
"Kind": newMethod(i.reflectPackage, rtypeType, "Kind"),
"NumOut": newMethod(i.reflectPackage, rtypeType, "NumOut"),
"Out": newMethod(i.reflectPackage, rtypeType, "Out"),
"String": newMethod(i.reflectPackage, rtypeType, "String"),
}
i.errorMethods = ssa.MethodSet{
ssa.Id{nil, "Error"}: newMethod(i.reflectPackage, errorType, "Error"),
"Error": newMethod(i.reflectPackage, errorType, "Error"),
}
}

View File

@ -13,13 +13,6 @@ import (
"code.google.com/p/go.tools/go/types"
)
func (id Id) String() string {
if id.Pkg == nil {
return id.Name
}
return fmt.Sprintf("%s/%s", id.Pkg.Path(), id.Name)
}
// relName returns the name of v relative to i.
// In most cases, this is identical to v.Name(), but for references to
// Functions (including methods) and Globals, the FullName is used
@ -397,11 +390,11 @@ func (p *Package) DumpTo(w io.Writer) {
// entire ssa.MethodSet by using the
// types.MethodSet if possible.
mset := p.Prog.MethodSet(types.NewPointer(mem.Type()))
var keys ids
var keys []string
for id := range mset {
keys = append(keys, id)
}
sort.Sort(keys)
sort.Strings(keys)
for _, id := range keys {
method := mset[id]
// TODO(adonovan): show pointerness of receiver of declared method, not the index

View File

@ -57,7 +57,7 @@ func (prog *Program) MethodSet(typ types.Type) MethodSet {
tmset := typ.MethodSet()
for i, n := 0, tmset.Len(); i < n; i++ {
obj := tmset.At(i)
mset[makeId(obj.Func.Name(), obj.Func.Pkg())] = makeMethod(prog, typ, obj)
mset[obj.Func.Id()] = makeMethod(prog, typ, obj)
}
prog.methodSets.Set(typ, mset)
return mset
@ -112,21 +112,8 @@ func promotionWrapper(prog *Program, typ types.Type, obj *types.Method) *Functio
old := obj.Func.Type().(*types.Signature)
sig := types.NewSignature(types.NewVar(token.NoPos, nil, "recv", typ), old.Params(), old.Results(), old.IsVariadic())
promotedRecv := obj.Func.Type().(*types.Signature).Recv()
// TODO(adonovan): Interface method receivers used to be nil, but
// aren't anymore. Nil them again so this code works for now. Fix.
var promotedRecvString string
if _, ok := promotedRecv.Type().Underlying().(*types.Interface); ok {
promotedRecv = nil
promotedRecvString = "INTERFACE?"
} else {
promotedRecvString = promotedRecv.String()
}
// TODO(adonovan): include implicit field path in description.
description := fmt.Sprintf("promotion wrapper for (%s).%s",
promotedRecvString, obj.Func.Name())
description := fmt.Sprintf("promotion wrapper for (%s).%s", old.Recv(), obj.Func.Name())
if prog.mode&LogSource != 0 {
defer logStack("make %s to (%s)", description, typ)()
@ -164,7 +151,7 @@ func promotionWrapper(prog *Program, typ types.Type, obj *types.Method) *Functio
// address of implicit C field.
var c Call
if promotedRecv != nil { // concrete method TODO(gri): temporary hack
if _, ok := old.Recv().Type().Underlying().(*types.Interface); !ok { // concrete method
if !isPointer(old.Recv().Type()) {
v = emitLoad(fn, v)
}
@ -222,7 +209,7 @@ func createParams(fn *Function) {
//
// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
//
func interfaceMethodWrapper(prog *Program, typ types.Type, id Id) *Function {
func interfaceMethodWrapper(prog *Program, typ types.Type, id string) *Function {
index, meth := interfaceMethodIndex(typ.Underlying().(*types.Interface), id)
prog.methodsMu.Lock()
defer prog.methodsMu.Unlock()

View File

@ -63,26 +63,6 @@ type Member interface {
Token() token.Token // token.{VAR,FUNC,CONST,TYPE}
}
// An Id identifies the name of a field of a struct type, or the name
// of a method of an interface or a named type.
//
// For exported names, i.e. those beginning with a Unicode upper-case
// letter, a simple string is unambiguous.
//
// However, a method set or struct may contain multiple unexported
// names with identical spelling that are logically distinct because
// they originate in different packages. Unexported names must
// therefore be disambiguated by their package too.
//
// The Pkg field of an Id is therefore nil iff the name is exported.
//
// This type is suitable for use as a map key because the equivalence
// relation == is consistent with identifier equality.
type Id struct {
Pkg *types.Package
Name string
}
// A MethodSet contains all the methods for a particular type T.
// The method sets for T and *T are distinct entities.
//
@ -90,7 +70,10 @@ type Id struct {
// T. The method set of *T may contain synthetic indirection methods
// that wrap methods whose receiver type is T.
//
type MethodSet map[Id]*Function
// The keys of a method set are strings returned by the types.Id()
// function.
//
type MethodSet map[string]*Function
// A Type is a Member of a Package representing a package-level named type.
//
@ -1284,9 +1267,8 @@ func (c *CallCommon) StaticCallee() *Function {
// MethodId returns the Id for the method called by c, which must
// have "invoke" mode.
func (c *CallCommon) MethodId() Id {
m := c.Recv.Type().Underlying().(*types.Interface).Method(c.Method)
return makeId(m.Name(), m.Pkg())
func (c *CallCommon) MethodId() string {
return c.Recv.Type().Underlying().(*types.Interface).Method(c.Method).Id()
}
// Description returns a description of the mode of this call suitable

View File

@ -57,10 +57,10 @@ func deref(typ types.Type) types.Type {
// within the set of explicitly declared concrete methods of named
// type typ. If not found, panic ensues.
//
func namedTypeMethodIndex(typ *types.Named, id Id) (int, *types.Func) {
func namedTypeMethodIndex(typ *types.Named, id string) (int, *types.Func) {
for i, n := 0, typ.NumMethods(); i < n; i++ {
m := typ.Method(i)
if makeId(m.Name(), m.Pkg()) == id {
if m.Id() == id {
return i, m
}
}
@ -71,10 +71,10 @@ func namedTypeMethodIndex(typ *types.Named, id Id) (int, *types.Func) {
// within the method-set of interface type typ. If not found, panic
// ensues.
//
func interfaceMethodIndex(typ *types.Interface, id Id) (int, *types.Func) {
func interfaceMethodIndex(typ *types.Interface, id string) (int, *types.Func) {
for i, n := 0, typ.NumMethods(); i < n; i++ {
m := typ.Method(i)
if makeId(m.Name(), m.Pkg()) == id {
if m.Id() == id {
return i, m
}
}
@ -94,7 +94,7 @@ outer:
xm := x.Method(i)
for j, m := 0, y.NumMethods(); j < m; j++ {
ym := y.Method(j)
if makeId(xm.Name(), xm.Pkg()) == makeId(ym.Name(), ym.Pkg()) {
if xm.Id() == ym.Id() {
if !types.IsIdentical(xm.Type(), ym.Type()) {
return false // common name but conflicting types
}
@ -156,31 +156,6 @@ func DefaultType(typ types.Type) types.Type {
return typ
}
// makeId returns the Id (name, pkg) if the name is exported or
// (name, nil) otherwise.
//
func makeId(name string, pkg *types.Package) (id Id) {
id.Name = name
if !ast.IsExported(name) {
id.Pkg = pkg
if pkg.Path() == "" {
panic("empty types.Package.Path()")
}
}
return
}
type ids []Id // a sortable slice of Id
func (p ids) Len() int { return len(p) }
func (p ids) Less(i, j int) bool {
x, y := p[i], p[j]
// TODO(adonovan): opt: where's Go's 3-valued strings.Compare function?
return x.Pkg.Path() < y.Pkg.Path() ||
x.Pkg.Path() == y.Pkg.Path() && x.Name < y.Name
}
func (p ids) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// 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.