// Copyright 2023 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 inline

// This file defines the callee side of the "fallible constant" analysis.

import (
	"fmt"
	"go/ast"
	"go/constant"
	"go/format"
	"go/token"
	"go/types"
	"strconv"
	"strings"

	"golang.org/x/tools/go/types/typeutil"
	"golang.org/x/tools/internal/typeparams"
)

// falconResult is the result of the analysis of the callee.
type falconResult struct {
	Types       []falconType // types for falcon constraint environment
	Constraints []string     // constraints (Go expressions) on values of fallible constants
}

// A falconType specifies the name and underlying type of a synthetic
// defined type for use in falcon constraints.
//
// Unique types from callee code are bijectively mapped onto falcon
// types so that constraints are independent of callee type
// information but preserve type equivalence classes.
//
// Fresh names are deliberately obscure to avoid shadowing even if a
// callee parameter has a nanme like "int" or "any".
type falconType struct {
	Name string
	Kind types.BasicKind // string/number/bool
}

// falcon identifies "fallible constant" expressions, which are
// expressions that may fail to compile if one or more of their
// operands is changed from non-constant to constant.
//
// Consider:
//
//	func sub(s string, i, j int) string { return s[i:j] }
//
// If parameters are replaced by constants, the compiler is
// required to perform these additional checks:
//
//   - if i is constant, 0 <= i.
//   - if s and i are constant, i <= len(s).
//   - ditto for j.
//   - if i and j are constant, i <= j.
//
// s[i:j] is thus a "fallible constant" expression dependent on {s, i,
// j}. Each falcon creates a set of conditional constraints across one
// or more parameter variables.
//
//   - When inlining a call such as sub("abc", -1, 2), the parameter i
//     cannot be eliminated by substitution as its argument value is
//     negative.
//
//   - When inlining sub("", 2, 1), all three parameters cannot be
//     simultaneously eliminated by substitution without violating i
//     <= len(s) and j <= len(s), but the parameters i and j could be
//     safely eliminated without s.
//
// Parameters that cannot be eliminated must remain non-constant,
// either in the form of a binding declaration:
//
//	{ var i int = -1; return "abc"[i:2] }
//
// or a parameter of a literalization:
//
//	func (i int) string { return "abc"[i:2] }(-1)
//
// These example expressions are obviously doomed to fail at run
// time, but in realistic cases such expressions are dominated by
// appropriate conditions that make them reachable only when safe:
//
//	if 0 <= i && i <= j && j <= len(s) { _ = s[i:j] }
//
// (In principle a more sophisticated inliner could entirely eliminate
// such unreachable blocks based on the condition being always-false
// for the given parameter substitution, but this is tricky to do safely
// because the type-checker considers only a single configuration.
// Consider: if runtime.GOOS == "linux" { ... }.)
//
// We believe this is an exhaustive list of "fallible constant" operations:
//
//   - switch z { case x: case y } 	// duplicate case values
//   - s[i], s[i:j], s[i:j:k]		// index out of bounds (0 <= i <= j <= k <= len(s))
//   - T{x: 0}				// index out of bounds, duplicate index
//   - x/y, x%y, x/=y, x%=y		// integer division by zero; minint/-1 overflow
//   - x+y, x-y, x*y			// arithmetic overflow
//   - x<<y				// shift out of range
//   - -x				// negation of minint
//   - T(x)				// value out of range
//
// The fundamental reason for this elaborate algorithm is that the
// "separate analysis" of callee and caller, as required when running
// in an environment such as unitchecker, means that there is no way
// for us to simply invoke the type checker on the combination of
// caller and callee code, as by the time we analyze the caller, we no
// longer have access to type information for the callee (and, in
// particular, any of its direct dependencies that are not direct
// dependencies of the caller). So, in effect, we are forced to map
// the problem in a neutral (callee-type-independent) constraint
// system that can be verified later.
func falcon(logf func(string, ...any), fset *token.FileSet, params map[*types.Var]*paramInfo, info *types.Info, decl *ast.FuncDecl) falconResult {

	st := &falconState{
		logf:   logf,
		fset:   fset,
		params: params,
		info:   info,
		decl:   decl,
	}

	// type mapping
	st.int = st.typename(types.Typ[types.Int])
	st.any = "interface{}" // don't use "any" as it may be shadowed
	for obj, info := range st.params {
		if isBasic(obj.Type(), types.IsConstType) {
			info.FalconType = st.typename(obj.Type())
		}
	}

	st.stmt(st.decl.Body)

	return st.result
}

type falconState struct {
	// inputs
	logf   func(string, ...any)
	fset   *token.FileSet
	params map[*types.Var]*paramInfo
	info   *types.Info
	decl   *ast.FuncDecl

	// working state
	int       string
	any       string
	typenames typeutil.Map

	result falconResult
}

// typename returns the name in the falcon constraint system
// of a given string/number/bool type t. Falcon types are
// specified directly in go/types data structures rather than
// by name, avoiding potential shadowing conflicts with
// confusing parameter names such as "int".
//
// Also, each distinct type (as determined by types.Identical)
// is mapped to a fresh type in the falcon system so that we
// can map the types in the callee code into a neutral form
// that does not depend on imports, allowing us to detect
// potential conflicts such as
//
//	map[any]{T1(1): 0, T2(1): 0}
//
// where T1=T2.
func (st *falconState) typename(t types.Type) string {
	name, ok := st.typenames.At(t).(string)
	if !ok {
		basic := t.Underlying().(*types.Basic)

		// That dot ۰ is an Arabic zero numeral U+06F0.
		// It is very unlikely to appear in a real program.
		// TODO(adonovan): use a non-heuristic solution.
		name = fmt.Sprintf("%s۰%d", basic, st.typenames.Len())
		st.typenames.Set(t, name)
		st.logf("falcon: emit type %s %s // %q", name, basic, t)
		st.result.Types = append(st.result.Types, falconType{
			Name: name,
			Kind: basic.Kind(),
		})
	}
	return name
}

// -- constraint emission --

// emit emits a Go expression that must have a legal type.
// In effect, we let the go/types constant folding algorithm
// do most of the heavy lifting (though it may be hard to
// believe from the complexity of this algorithm!).
func (st *falconState) emit(constraint ast.Expr) {
	var out strings.Builder
	if err := format.Node(&out, st.fset, constraint); err != nil {
		panic(err) // can't happen
	}
	syntax := out.String()
	st.logf("falcon: emit constraint %s", syntax)
	st.result.Constraints = append(st.result.Constraints, syntax)
}

// emitNonNegative emits an []T{}[index] constraint,
// which ensures index is non-negative if constant.
func (st *falconState) emitNonNegative(index ast.Expr) {
	st.emit(&ast.IndexExpr{
		X: &ast.CompositeLit{
			Type: &ast.ArrayType{
				Elt: makeIdent(st.int),
			},
		},
		Index: index,
	})
}

// emitMonotonic emits an []T{}[i:j] constraint,
// which ensures i <= j if both are constant.
func (st *falconState) emitMonotonic(i, j ast.Expr) {
	st.emit(&ast.SliceExpr{
		X: &ast.CompositeLit{
			Type: &ast.ArrayType{
				Elt: makeIdent(st.int),
			},
		},
		Low:  i,
		High: j,
	})
}

// emitUnique emits a T{elem1: 0, ... elemN: 0} constraint,
// which ensures that all constant elems are unique.
// T may be a map, slice, or array depending
// on the desired check semantics.
func (st *falconState) emitUnique(typ ast.Expr, elems []ast.Expr) {
	if len(elems) > 1 {
		var elts []ast.Expr
		for _, elem := range elems {
			elts = append(elts, &ast.KeyValueExpr{
				Key:   elem,
				Value: makeIntLit(0),
			})
		}
		st.emit(&ast.CompositeLit{
			Type: typ,
			Elts: elts,
		})
	}
}

// -- traversal --

// The traversal functions scan the callee body for expressions that
// are not constant but would become constant if the parameter vars
// were redeclared as constants, and emits for each one a constraint
// (a Go expression) with the property that it will not type-check
// (using types.CheckExpr) if the particular argument values are
// unsuitable.
//
// These constraints are checked by Inline with the actual
// constant argument values. Violations cause it to reject
// parameters as candidates for substitution.

func (st *falconState) stmt(s ast.Stmt) {
	ast.Inspect(s, func(n ast.Node) bool {
		switch n := n.(type) {
		case ast.Expr:
			_ = st.expr(n)
			return false // skip usual traversal

		case *ast.AssignStmt:
			switch n.Tok {
			case token.QUO_ASSIGN, token.REM_ASSIGN:
				// x /= y
				// Possible "integer division by zero"
				// Emit constraint: 1/y.
				_ = st.expr(n.Lhs[0])
				kY := st.expr(n.Rhs[0])
				if kY, ok := kY.(ast.Expr); ok {
					op := token.QUO
					if n.Tok == token.REM_ASSIGN {
						op = token.REM
					}
					st.emit(&ast.BinaryExpr{
						Op: op,
						X:  makeIntLit(1),
						Y:  kY,
					})
				}
				return false // skip usual traversal
			}

		case *ast.SwitchStmt:
			if n.Init != nil {
				st.stmt(n.Init)
			}
			tBool := types.Type(types.Typ[types.Bool])
			tagType := tBool // default: true
			if n.Tag != nil {
				st.expr(n.Tag)
				tagType = st.info.TypeOf(n.Tag)
			}

			// Possible "duplicate case value".
			// Emit constraint map[T]int{v1: 0, ..., vN:0}
			// to ensure all maybe-constant case values are unique
			// (unless switch tag is boolean, which is relaxed).
			var unique []ast.Expr
			for _, clause := range n.Body.List {
				clause := clause.(*ast.CaseClause)
				for _, caseval := range clause.List {
					if k := st.expr(caseval); k != nil {
						unique = append(unique, st.toExpr(k))
					}
				}
				for _, stmt := range clause.Body {
					st.stmt(stmt)
				}
			}
			if unique != nil && !types.Identical(tagType.Underlying(), tBool) {
				tname := st.any
				if !types.IsInterface(tagType) {
					tname = st.typename(tagType)
				}
				t := &ast.MapType{
					Key:   makeIdent(tname),
					Value: makeIdent(st.int),
				}
				st.emitUnique(t, unique)
			}
		}
		return true
	})
}

// fieldTypes visits the .Type of each field in the list.
func (st *falconState) fieldTypes(fields *ast.FieldList) {
	if fields != nil {
		for _, field := range fields.List {
			_ = st.expr(field.Type)
		}
	}
}

// expr visits the expression (or type) and returns a
// non-nil result if the expression is constant or would
// become constant if all suitable function parameters were
// redeclared as constants.
//
// If the expression is constant, st.expr returns its type
// and value (types.TypeAndValue). If the expression would
// become constant, st.expr returns an ast.Expr tree whose
// leaves are literals and parameter references, and whose
// interior nodes are operations that may become constant,
// such as -x, x+y, f(x), and T(x). We call these would-be
// constant expressions "fallible constants", since they may
// fail to type-check for some values of x, i, and j. (We
// refer to the non-nil cases collectively as "maybe
// constant", and the nil case as "definitely non-constant".)
//
// As a side effect, st.expr emits constraints for each
// fallible constant expression; this is its main purpose.
//
// Consequently, st.expr must visit the entire subtree so
// that all necessary constraints are emitted. It may not
// short-circuit the traversal when it encounters a constant
// subexpression as constants may contain arbitrary other
// syntax that may impose constraints. Consider (as always)
// this contrived but legal example of a type parameter (!)
// that contains statement syntax:
//
//	func f[T [unsafe.Sizeof(func() { stmts })]int]()
//
// There is no need to emit constraints for (e.g.) s[i] when s
// and i are already constants, because we know the expression
// is sound, but it is sometimes easier to emit these
// redundant constraints than to avoid them.
func (st *falconState) expr(e ast.Expr) (res any) { // = types.TypeAndValue | ast.Expr
	tv := st.info.Types[e]
	if tv.Value != nil {
		// A constant value overrides any other result.
		defer func() { res = tv }()
	}

	switch e := e.(type) {
	case *ast.Ident:
		if v, ok := st.info.Uses[e].(*types.Var); ok {
			if _, ok := st.params[v]; ok && isBasic(v.Type(), types.IsConstType) {
				return e // reference to constable parameter
			}
		}
		// (References to *types.Const are handled by the defer.)

	case *ast.BasicLit:
		// constant

	case *ast.ParenExpr:
		return st.expr(e.X)

	case *ast.FuncLit:
		_ = st.expr(e.Type)
		st.stmt(e.Body)
		// definitely non-constant

	case *ast.CompositeLit:
		// T{k: v, ...}, where T ∈ {array,*array,slice,map},
		// imposes a constraint that all constant k are
		// distinct and, for arrays [n]T, within range 0-n.
		//
		// Types matter, not just values. For example,
		// an interface-keyed map may contain keys
		// that are numerically equal so long as they
		// are of distinct types. For example:
		//
		//   type myint int
		//   map[any]bool{1: true, 1:        true} // error: duplicate key
		//   map[any]bool{1: true, int16(1): true} // ok
		//   map[any]bool{1: true, myint(1): true} // ok
		//
		// This can be asserted by emitting a
		// constraint of the form T{k1: 0, ..., kN: 0}.
		if e.Type != nil {
			_ = st.expr(e.Type)
		}
		t := types.Unalias(typeparams.Deref(tv.Type))
		ct := typeparams.CoreType(t)
		var mapKeys []ast.Expr // map key expressions; must be distinct if constant
		for _, elt := range e.Elts {
			if kv, ok := elt.(*ast.KeyValueExpr); ok {
				if is[*types.Map](ct) {
					if k := st.expr(kv.Key); k != nil {
						mapKeys = append(mapKeys, st.toExpr(k))
					}
				}
				_ = st.expr(kv.Value)
			} else {
				_ = st.expr(elt)
			}
		}
		if len(mapKeys) > 0 {
			// Inlining a map literal may replace variable key expressions by constants.
			// All such constants must have distinct values.
			// (Array and slice literals do not permit non-constant keys.)
			t := ct.(*types.Map)
			var typ ast.Expr
			if types.IsInterface(t.Key()) {
				typ = &ast.MapType{
					Key:   makeIdent(st.any),
					Value: makeIdent(st.int),
				}
			} else {
				typ = &ast.MapType{
					Key:   makeIdent(st.typename(t.Key())),
					Value: makeIdent(st.int),
				}
			}
			st.emitUnique(typ, mapKeys)
		}
		// definitely non-constant

	case *ast.SelectorExpr:
		_ = st.expr(e.X)
		_ = st.expr(e.Sel)
		// The defer is sufficient to handle
		// qualified identifiers (pkg.Const).
		// All other cases are definitely non-constant.

	case *ast.IndexExpr:
		if tv.IsType() {
			// type C[T]
			_ = st.expr(e.X)
			_ = st.expr(e.Index)
		} else {
			// term x[i]
			//
			// Constraints (if x is slice/string/array/*array, not map):
			// - i >= 0
			//     if i is a fallible constant
			// - i < len(x)
			//     if x is array/*array and
			//     i is a fallible constant;
			//  or if s is a string and both i,
			//     s are maybe-constants,
			//     but not both are constants.
			kX := st.expr(e.X)
			kI := st.expr(e.Index)
			if kI != nil && !is[*types.Map](st.info.TypeOf(e.X).Underlying()) {
				if kI, ok := kI.(ast.Expr); ok {
					st.emitNonNegative(kI)
				}
				// Emit constraint to check indices against known length.
				// TODO(adonovan): factor with SliceExpr logic.
				var x ast.Expr
				if kX != nil {
					// string
					x = st.toExpr(kX)
				} else if arr, ok := typeparams.CoreType(typeparams.Deref(st.info.TypeOf(e.X))).(*types.Array); ok {
					// array, *array
					x = &ast.CompositeLit{
						Type: &ast.ArrayType{
							Len: makeIntLit(arr.Len()),
							Elt: makeIdent(st.int),
						},
					}
				}
				if x != nil {
					st.emit(&ast.IndexExpr{
						X:     x,
						Index: st.toExpr(kI),
					})
				}
			}
		}
		// definitely non-constant

	case *ast.SliceExpr:
		// x[low:high:max]
		//
		// Emit non-negative constraints for each index,
		// plus low <= high <= max <= len(x)
		// for each pair that are maybe-constant
		// but not definitely constant.

		kX := st.expr(e.X)
		var kLow, kHigh, kMax any
		if e.Low != nil {
			kLow = st.expr(e.Low)
			if kLow != nil {
				if kLow, ok := kLow.(ast.Expr); ok {
					st.emitNonNegative(kLow)
				}
			}
		}
		if e.High != nil {
			kHigh = st.expr(e.High)
			if kHigh != nil {
				if kHigh, ok := kHigh.(ast.Expr); ok {
					st.emitNonNegative(kHigh)
				}
				if kLow != nil {
					st.emitMonotonic(st.toExpr(kLow), st.toExpr(kHigh))
				}
			}
		}
		if e.Max != nil {
			kMax = st.expr(e.Max)
			if kMax != nil {
				if kMax, ok := kMax.(ast.Expr); ok {
					st.emitNonNegative(kMax)
				}
				if kHigh != nil {
					st.emitMonotonic(st.toExpr(kHigh), st.toExpr(kMax))
				}
			}
		}

		// Emit constraint to check indices against known length.
		var x ast.Expr
		if kX != nil {
			// string
			x = st.toExpr(kX)
		} else if arr, ok := typeparams.CoreType(typeparams.Deref(st.info.TypeOf(e.X))).(*types.Array); ok {
			// array, *array
			x = &ast.CompositeLit{
				Type: &ast.ArrayType{
					Len: makeIntLit(arr.Len()),
					Elt: makeIdent(st.int),
				},
			}
		}
		if x != nil {
			// Avoid slice[::max] if kHigh is nonconstant (nil).
			high, max := st.toExpr(kHigh), st.toExpr(kMax)
			if high == nil {
				high = max // => slice[:max:max]
			}
			st.emit(&ast.SliceExpr{
				X:    x,
				Low:  st.toExpr(kLow),
				High: high,
				Max:  max,
			})
		}
		// definitely non-constant

	case *ast.TypeAssertExpr:
		_ = st.expr(e.X)
		if e.Type != nil {
			_ = st.expr(e.Type)
		}

	case *ast.CallExpr:
		_ = st.expr(e.Fun)
		if tv, ok := st.info.Types[e.Fun]; ok && tv.IsType() {
			// conversion T(x)
			//
			// Possible "value out of range".
			kX := st.expr(e.Args[0])
			if kX != nil && isBasic(tv.Type, types.IsConstType) {
				conv := convert(makeIdent(st.typename(tv.Type)), st.toExpr(kX))
				if is[ast.Expr](kX) {
					st.emit(conv)
				}
				return conv
			}
			return nil // definitely non-constant
		}

		// call f(x)

		all := true // all args are possibly-constant
		kArgs := make([]ast.Expr, len(e.Args))
		for i, arg := range e.Args {
			if kArg := st.expr(arg); kArg != nil {
				kArgs[i] = st.toExpr(kArg)
			} else {
				all = false
			}
		}

		// Calls to built-ins with fallibly constant arguments
		// may become constant. All other calls are either
		// constant or non-constant
		if id, ok := e.Fun.(*ast.Ident); ok && all && tv.Value == nil {
			if builtin, ok := st.info.Uses[id].(*types.Builtin); ok {
				switch builtin.Name() {
				case "len", "imag", "real", "complex", "min", "max":
					return &ast.CallExpr{
						Fun:      id,
						Args:     kArgs,
						Ellipsis: e.Ellipsis,
					}
				}
			}
		}

	case *ast.StarExpr: // *T, *ptr
		_ = st.expr(e.X)

	case *ast.UnaryExpr:
		// + - ! ^ & <- ~
		//
		// Possible "negation of minint".
		// Emit constraint: -x
		kX := st.expr(e.X)
		if kX != nil && !is[types.TypeAndValue](kX) {
			if e.Op == token.SUB {
				st.emit(&ast.UnaryExpr{
					Op: e.Op,
					X:  st.toExpr(kX),
				})
			}

			return &ast.UnaryExpr{
				Op: e.Op,
				X:  st.toExpr(kX),
			}
		}

	case *ast.BinaryExpr:
		kX := st.expr(e.X)
		kY := st.expr(e.Y)
		switch e.Op {
		case token.QUO, token.REM:
			// x/y, x%y
			//
			// Possible "integer division by zero" or
			// "minint / -1" overflow.
			// Emit constraint: x/y or 1/y
			if kY != nil {
				if kX == nil {
					kX = makeIntLit(1)
				}
				st.emit(&ast.BinaryExpr{
					Op: e.Op,
					X:  st.toExpr(kX),
					Y:  st.toExpr(kY),
				})
			}

		case token.ADD, token.SUB, token.MUL:
			// x+y, x-y, x*y
			//
			// Possible "arithmetic overflow".
			// Emit constraint: x+y
			if kX != nil && kY != nil {
				st.emit(&ast.BinaryExpr{
					Op: e.Op,
					X:  st.toExpr(kX),
					Y:  st.toExpr(kY),
				})
			}

		case token.SHL, token.SHR:
			// x << y, x >> y
			//
			// Possible "constant shift too large".
			// Either operand may be too large individually,
			// and they may be too large together.
			// Emit constraint:
			//    x << y (if both maybe-constant)
			//    x << 0 (if y is non-constant)
			//    1 << y (if x is non-constant)
			if kX != nil || kY != nil {
				x := st.toExpr(kX)
				if x == nil {
					x = makeIntLit(1)
				}
				y := st.toExpr(kY)
				if y == nil {
					y = makeIntLit(0)
				}
				st.emit(&ast.BinaryExpr{
					Op: e.Op,
					X:  x,
					Y:  y,
				})
			}

		case token.LSS, token.GTR, token.EQL, token.NEQ, token.LEQ, token.GEQ:
			// < > == != <= <=
			//
			// A "x cmp y" expression with constant operands x, y is
			// itself constant, but I can't see how a constant bool
			// could be fallible: the compiler doesn't reject duplicate
			// boolean cases in a switch, presumably because boolean
			// switches are less like n-way branches and more like
			// sequential if-else chains with possibly overlapping
			// conditions; and there is (sadly) no way to convert a
			// boolean constant to an int constant.
		}
		if kX != nil && kY != nil {
			return &ast.BinaryExpr{
				Op: e.Op,
				X:  st.toExpr(kX),
				Y:  st.toExpr(kY),
			}
		}

	// types
	//
	// We need to visit types (and even type parameters)
	// in order to reach all the places where things could go wrong:
	//
	// 	const (
	// 		s = ""
	// 		i = 0
	// 	)
	// 	type C[T [unsafe.Sizeof(func() { _ = s[i] })]int] bool

	case *ast.IndexListExpr:
		_ = st.expr(e.X)
		for _, expr := range e.Indices {
			_ = st.expr(expr)
		}

	case *ast.Ellipsis:
		if e.Elt != nil {
			_ = st.expr(e.Elt)
		}

	case *ast.ArrayType:
		if e.Len != nil {
			_ = st.expr(e.Len)
		}
		_ = st.expr(e.Elt)

	case *ast.StructType:
		st.fieldTypes(e.Fields)

	case *ast.FuncType:
		st.fieldTypes(e.TypeParams)
		st.fieldTypes(e.Params)
		st.fieldTypes(e.Results)

	case *ast.InterfaceType:
		st.fieldTypes(e.Methods)

	case *ast.MapType:
		_ = st.expr(e.Key)
		_ = st.expr(e.Value)

	case *ast.ChanType:
		_ = st.expr(e.Value)
	}
	return
}

// toExpr converts the result of visitExpr to a falcon expression.
// (We don't do this in visitExpr as we first need to discriminate
// constants from maybe-constants.)
func (st *falconState) toExpr(x any) ast.Expr {
	switch x := x.(type) {
	case nil:
		return nil

	case types.TypeAndValue:
		lit := makeLiteral(x.Value)
		if !isBasic(x.Type, types.IsUntyped) {
			// convert to "typed" type
			lit = &ast.CallExpr{
				Fun:  makeIdent(st.typename(x.Type)),
				Args: []ast.Expr{lit},
			}
		}
		return lit

	case ast.Expr:
		return x

	default:
		panic(x)
	}
}

func makeLiteral(v constant.Value) ast.Expr {
	switch v.Kind() {
	case constant.Bool:
		// Rather than refer to the true or false built-ins,
		// which could be shadowed by poorly chosen parameter
		// names, we use 0 == 0 for true and 0 != 0 for false.
		op := token.EQL
		if !constant.BoolVal(v) {
			op = token.NEQ
		}
		return &ast.BinaryExpr{
			Op: op,
			X:  makeIntLit(0),
			Y:  makeIntLit(0),
		}

	case constant.String:
		return &ast.BasicLit{
			Kind:  token.STRING,
			Value: v.ExactString(),
		}

	case constant.Int:
		return &ast.BasicLit{
			Kind:  token.INT,
			Value: v.ExactString(),
		}

	case constant.Float:
		return &ast.BasicLit{
			Kind:  token.FLOAT,
			Value: v.ExactString(),
		}

	case constant.Complex:
		// The components could be float or int.
		y := makeLiteral(constant.Imag(v))
		y.(*ast.BasicLit).Value += "i" // ugh
		if re := constant.Real(v); !consteq(re, kZeroInt) {
			// complex: x + yi
			y = &ast.BinaryExpr{
				Op: token.ADD,
				X:  makeLiteral(re),
				Y:  y,
			}
		}
		return y

	default:
		panic(v.Kind())
	}
}

func makeIntLit(x int64) *ast.BasicLit {
	return &ast.BasicLit{
		Kind:  token.INT,
		Value: strconv.FormatInt(x, 10),
	}
}

func isBasic(t types.Type, info types.BasicInfo) bool {
	basic, ok := t.Underlying().(*types.Basic)
	return ok && basic.Info()&info != 0
}
