package ssa

// This file defines utilities for querying the results of typechecker:
// types of expressions, values of constant expressions, referents of identifiers.

import (
	"code.google.com/p/go.exp/go/types"
	"fmt"
	"go/ast"
)

// TypeInfo contains information provided by the type checker about
// the abstract syntax for a single package.
type TypeInfo struct {
	types     map[ast.Expr]types.Type     // inferred types of expressions
	constants map[ast.Expr]*Literal       // values of constant expressions
	idents    map[*ast.Ident]types.Object // canonical type objects for named entities
}

// TypeOf returns the type of expression e.
// Precondition: e belongs to the package's ASTs.
func (info *TypeInfo) TypeOf(e ast.Expr) types.Type {
	// For Ident, b.types may be more specific than
	// b.obj(id.(*ast.Ident)).GetType(),
	// e.g. in the case of typeswitch.
	if t, ok := info.types[e]; ok {
		return t
	}
	// The typechecker doesn't notify us of all Idents,
	// e.g. s.Key and s.Value in a RangeStmt.
	// So we have this fallback.
	// TODO(gri): This is a typechecker bug.  When fixed,
	// eliminate this case and panic.
	if id, ok := e.(*ast.Ident); ok {
		return info.ObjectOf(id).Type()
	}
	panic("no type for expression")
}

// ValueOf returns the value of expression e if it is a constant,
// nil otherwise.
//
func (info *TypeInfo) ValueOf(e ast.Expr) *Literal {
	return info.constants[e]
}

// ObjectOf returns the typechecker object denoted by the specified id.
// Precondition: id belongs to the package's ASTs.
//
func (info *TypeInfo) ObjectOf(id *ast.Ident) types.Object {
	if obj, ok := info.idents[id]; ok {
		return obj
	}
	panic(fmt.Sprintf("no types.Object for ast.Ident %s @ %p", id.Name, id))
}

// IsType returns true iff expression e denotes a type.
// Precondition: e belongs to the package's ASTs.
//
func (info *TypeInfo) IsType(e ast.Expr) bool {
	switch e := e.(type) {
	case *ast.SelectorExpr: // pkg.Type
		if obj := info.isPackageRef(e); obj != nil {
			return objKind(obj) == ast.Typ
		}
	case *ast.StarExpr: // *T
		return info.IsType(e.X)
	case *ast.Ident:
		return objKind(info.ObjectOf(e)) == ast.Typ
	case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
		return true
	case *ast.ParenExpr:
		return info.IsType(e.X)
	}
	return false
}

// isPackageRef returns the identity of the object if sel is a
// package-qualified reference to a named const, var, func or type.
// Otherwise it returns nil.
// Precondition: sel belongs to the package's ASTs.
//
func (info *TypeInfo) isPackageRef(sel *ast.SelectorExpr) types.Object {
	if id, ok := sel.X.(*ast.Ident); ok {
		if obj := info.ObjectOf(id); objKind(obj) == ast.Pkg {
			return obj.(*types.Package).Scope().Lookup(sel.Sel.Name)
		}
	}
	return nil
}

// builtinCallSignature returns a new Signature describing the
// effective type of a builtin operator for the particular call e.
//
// This requires ad-hoc typing rules for all variadic (append, print,
// println) and polymorphic (append, copy, delete, close) built-ins.
// This logic could be part of the typechecker, and should arguably
// be moved there and made accessible via an additional types.Context
// callback.
//
// The returned Signature is degenerate and only intended for use by
// emitCallArgs.
//
func builtinCallSignature(info *TypeInfo, e *ast.CallExpr) *types.Signature {
	var params []*types.Var
	var isVariadic bool

	switch builtin := noparens(e.Fun).(*ast.Ident).Name; builtin {
	case "append":
		var t0, t1 types.Type
		t0 = info.TypeOf(e) // infer arg[0] type from result type
		if e.Ellipsis != 0 {
			// append([]T, []T) []T
			// append([]byte, string) []byte
			t1 = info.TypeOf(e.Args[1]) // no conversion
		} else {
			// append([]T, ...T) []T
			t1 = underlyingType(t0).(*types.Slice).Elt()
			isVariadic = true
		}
		params = append(params,
			types.NewVar(nil, "", t0),
			types.NewVar(nil, "", t1))

	case "print", "println": // print{,ln}(any, ...interface{})
		isVariadic = true
		// Note, arg0 may have any type, not necessarily tEface.
		params = append(params,
			types.NewVar(nil, "", info.TypeOf(e.Args[0])),
			types.NewVar(nil, "", tEface))

	case "close":
		params = append(params, types.NewVar(nil, "", info.TypeOf(e.Args[0])))

	case "copy":
		// copy([]T, []T) int
		// Infer arg types from each other.  Sleazy.
		var st *types.Slice
		if t, ok := underlyingType(info.TypeOf(e.Args[0])).(*types.Slice); ok {
			st = t
		} else if t, ok := underlyingType(info.TypeOf(e.Args[1])).(*types.Slice); ok {
			st = t
		} else {
			panic("cannot infer types in call to copy()")
		}
		stvar := types.NewVar(nil, "", st)
		params = append(params, stvar, stvar)

	case "delete":
		// delete(map[K]V, K)
		tmap := info.TypeOf(e.Args[0])
		tkey := underlyingType(tmap).(*types.Map).Key()
		params = append(params,
			types.NewVar(nil, "", tmap),
			types.NewVar(nil, "", tkey))

	case "len", "cap":
		params = append(params, types.NewVar(nil, "", info.TypeOf(e.Args[0])))

	case "real", "imag":
		// Reverse conversion to "complex" case below.
		var argType types.Type
		switch info.TypeOf(e).(*types.Basic).Kind() {
		case types.UntypedFloat:
			argType = types.Typ[types.UntypedComplex]
		case types.Float64:
			argType = tComplex128
		case types.Float32:
			argType = tComplex64
		default:
			unreachable()
		}
		params = append(params, types.NewVar(nil, "", argType))

	case "complex":
		var argType types.Type
		switch info.TypeOf(e).(*types.Basic).Kind() {
		case types.UntypedComplex:
			argType = types.Typ[types.UntypedFloat]
		case types.Complex128:
			argType = tFloat64
		case types.Complex64:
			argType = tFloat32
		default:
			unreachable()
		}
		v := types.NewVar(nil, "", argType)
		params = append(params, v, v)

	case "panic":
		params = append(params, types.NewVar(nil, "", tEface))

	case "recover":
		// no params

	default:
		panic("unknown builtin: " + builtin)
	}

	return types.NewSignature(nil, types.NewTuple(params...), nil, isVariadic)
}
