// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package analysis

// This file computes the "implements" relation over all pairs of
// named types in the program.  (The mark-up is done by typeinfo.go.)

// TODO(adonovan): do we want to report implements(C, I) where C and I
// belong to different packages and at least one is not exported?

import (
	"sort"

	"code.google.com/p/go.tools/go/types"
)

// computeImplements computes the "implements" relation over all pairs
// of named types in allNamed.
func computeImplements(cache *types.MethodSetCache, allNamed []*types.Named) map[*types.Named]implementsFacts {
	// Information about a single type's method set.
	type msetInfo struct {
		typ          types.Type
		mset         *types.MethodSet
		mask1, mask2 uint64
	}

	initMsetInfo := func(info *msetInfo, typ types.Type) {
		info.typ = typ
		info.mset = cache.MethodSet(typ)
		for i := 0; i < info.mset.Len(); i++ {
			name := info.mset.At(i).Obj().Name()
			info.mask1 |= 1 << methodBit(name[0])
			info.mask2 |= 1 << methodBit(name[len(name)-1])
		}
	}

	// satisfies(T, U) reports whether type T satisfies type U.
	// U must be an interface.
	//
	// Since there are thousands of types (and thus millions of
	// pairs of types) and types.Assignable(T, U) is relatively
	// expensive, we compute assignability directly from the
	// method sets.  (At least one of T and U must be an
	// interface.)
	//
	// We use a trick (thanks gri!) related to a Bloom filter to
	// quickly reject most tests, which are false.  For each
	// method set, we precompute a mask, a set of bits, one per
	// distinct initial byte of each method name.  Thus the mask
	// for io.ReadWriter would be {'R','W'}.  AssignableTo(T, U)
	// cannot be true unless mask(T)&mask(U)==mask(U).
	//
	// As with a Bloom filter, we can improve precision by testing
	// additional hashes, e.g. using the last letter of each
	// method name, so long as the subset mask property holds.
	//
	// When analyzing the standard library, there are about 1e6
	// calls to satisfies(), of which 0.6% return true.  With a
	// 1-hash filter, 95% of calls avoid the expensive check; with
	// a 2-hash filter, this grows to 98.2%.
	satisfies := func(T, U *msetInfo) bool {
		return T.mask1&U.mask1 == U.mask1 &&
			T.mask2&U.mask2 == U.mask2 &&
			containsAllIdsOf(T.mset, U.mset)
	}

	// Information about a named type N, and perhaps also *N.
	type namedInfo struct {
		isInterface bool
		base        msetInfo // N
		ptr         msetInfo // *N, iff N !isInterface
	}

	var infos []namedInfo

	// Precompute the method sets and their masks.
	for _, N := range allNamed {
		var info namedInfo
		initMsetInfo(&info.base, N)
		_, info.isInterface = N.Underlying().(*types.Interface)
		if !info.isInterface {
			initMsetInfo(&info.ptr, types.NewPointer(N))
		}

		if info.base.mask1|info.ptr.mask1 == 0 {
			continue // neither N nor *N has methods
		}

		infos = append(infos, info)
	}

	facts := make(map[*types.Named]implementsFacts)

	// Test all pairs of distinct named types (T, U).
	// TODO(adonovan): opt: compute (U, T) at the same time.
	for t := range infos {
		T := &infos[t]
		var to, from, fromPtr []types.Type
		for u := range infos {
			if t == u {
				continue
			}
			U := &infos[u]
			switch {
			case T.isInterface && U.isInterface:
				if satisfies(&U.base, &T.base) {
					to = append(to, U.base.typ)
				}
				if satisfies(&T.base, &U.base) {
					from = append(from, U.base.typ)
				}
			case T.isInterface: // U concrete
				if satisfies(&U.base, &T.base) {
					to = append(to, U.base.typ)
				} else if satisfies(&U.ptr, &T.base) {
					to = append(to, U.ptr.typ)
				}
			case U.isInterface: // T concrete
				if satisfies(&T.base, &U.base) {
					from = append(from, U.base.typ)
				} else if satisfies(&T.ptr, &U.base) {
					fromPtr = append(fromPtr, U.base.typ)
				}
			}
		}

		// Sort types (arbitrarily) to avoid nondeterminism.
		sort.Sort(typesByString(to))
		sort.Sort(typesByString(from))
		sort.Sort(typesByString(fromPtr))

		facts[T.base.typ.(*types.Named)] = implementsFacts{to, from, fromPtr}
	}

	return facts
}

type implementsFacts struct {
	to      []types.Type // named or ptr-to-named types assignable to interface T
	from    []types.Type // named interfaces assignable from T
	fromPtr []types.Type // named interfaces assignable only from *T
}

type typesByString []types.Type

func (p typesByString) Len() int           { return len(p) }
func (p typesByString) Less(i, j int) bool { return p[i].String() < p[j].String() }
func (p typesByString) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

// methodBit returns the index of x in [a-zA-Z], or 52 if not found.
func methodBit(x byte) uint64 {
	switch {
	case 'a' <= x && x <= 'z':
		return uint64(x - 'a')
	case 'A' <= x && x <= 'Z':
		return uint64(26 + x - 'A')
	}
	return 52 // all other bytes
}

// containsAllIdsOf reports whether the method identifiers of T are a
// superset of those in U.  If U belongs to an interface type, the
// result is equal to types.Assignable(T, U), but is cheaper to compute.
//
// TODO(gri): make this a method of *types.MethodSet.
//
func containsAllIdsOf(T, U *types.MethodSet) bool {
	t, tlen := 0, T.Len()
	u, ulen := 0, U.Len()
	for t < tlen && u < ulen {
		tMeth := T.At(t).Obj()
		uMeth := U.At(u).Obj()
		tId := tMeth.Id()
		uId := uMeth.Id()
		if tId > uId {
			// U has a method T lacks: fail.
			return false
		}
		if tId < uId {
			// T has a method U lacks: ignore it.
			t++
			continue
		}
		// U and T both have a method of this Id.  Check types.
		if !types.Identical(tMeth.Type(), uMeth.Type()) {
			return false // type mismatch
		}
		u++
		t++
	}
	return u == ulen
}
