package ssa

// This file defines a number of miscellaneous utility functions.

import (
	"fmt"
	"go/ast"
	"io"
	"os"
	"reflect"

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

func unreachable() {
	panic("unreachable")
}

//// AST utilities

// noparens returns e with any enclosing parentheses stripped.
func noparens(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.
//
// TODO(gri): consider making typechecker not treat them differently.
// It's one less thing for clients like us to worry about.
//
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 {
	if nt, ok := typ.(*types.Named); ok {
		typ = nt.Underlying()
	}
	_, ok := typ.(*types.Pointer)
	return ok
}

// pointer(typ) returns the type that is a pointer to typ.
func pointer(typ types.Type) *types.Pointer {
	return types.NewPointer(typ)
}

// methodIndex returns the method (and its index) named id within the
// method table of named or interface type typ.  If not found,
// panic ensues.
//
func methodIndex(typ types.Type, id Id) (int, *types.Func) {
	t := typ.(interface {
		NumMethods() int
		Method(i int) *types.Func
	})
	for i, n := 0, t.NumMethods(); i < n; i++ {
		m := t.Method(i)
		if MakeId(m.Name(), m.Pkg()) == id {
			return i, m
		}
	}
	panic(fmt.Sprint("method not found: ", id, " in interface ", typ))
}

// isSuperinterface returns true if x is a superinterface of y,
// i.e.  x's methods are a subset of y's.
//
func isSuperinterface(x, y *types.Interface) bool {
	if y.NumMethods() < x.NumMethods() {
		return false
	}
	// TODO(adonovan): opt: this is quadratic.
outer:
	for i, n := 0, x.NumMethods(); i < n; i++ {
		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 !types.IsIdentical(xm.Type(), ym.Type()) {
					return false // common name but conflicting types
				}
				continue outer
			}
		}
		return false // y doesn't have this method
	}
	return true
}

// objKind returns the syntactic category of the named entity denoted by obj.
func objKind(obj types.Object) ast.ObjKind {
	switch obj.(type) {
	case *types.Package:
		return ast.Pkg
	case *types.TypeName:
		return ast.Typ
	case *types.Const:
		return ast.Con
	case *types.Var:
		return ast.Var
	case *types.Func:
		return ast.Fun
	}
	panic(fmt.Sprintf("unexpected Object type: %T", obj))
}

// canHaveConcreteMethods returns true iff typ may have concrete
// methods associated with it.  Callers must supply allowPtr=true.
//
// TODO(gri): consider putting this in go/types.  It's surprisingly subtle.
func canHaveConcreteMethods(typ types.Type, allowPtr bool) bool {
	switch typ := typ.(type) {
	case *types.Pointer:
		return allowPtr && canHaveConcreteMethods(typ.Elem(), false)
	case *types.Named:
		switch typ.Underlying().(type) {
		case *types.Pointer, *types.Interface:
			return false
		}
		return true
	case *types.Struct:
		return true
	}
	return false
}

// DefaultType returns the default "typed" type for an "untyped" type;
// it returns the incoming type for all other types. If there is no
// corresponding untyped type, the result is types.Typ[types.Invalid].
//
// 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 := types.Invalid
		switch t.Kind() {
		// case UntypedNil:
		//      There is no default type for nil. For a good error message,
		//      catch this case before calling this function.
		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
}

// makeId returns the Id (name, pkg) if the name is exported or
// (name, nil) otherwise.
//
// Exported to exp/ssa/interp.
//
func MakeId(name string, pkg *types.Package) (id Id) {
	id.Name = name
	if !ast.IsExported(name) {
		id.Pkg = pkg
		// TODO(gri): fix
		// if pkg.Path == "" {
		// 	panic("Package " + pkg.Name + "has empty 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]
	// *Package pointers are canonical so order by them.
	// Don't use x.Pkg.ImportPath because sometimes it's empty.
	// (TODO(gri): fix that.)
	return reflect.ValueOf(x.Pkg).Pointer() < reflect.ValueOf(y.Pkg).Pointer() ||
		x.Pkg == y.Pkg && 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.
// 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")
	}
}
