// Copyright 2009 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 typecheck

import (
	"go/constant"

	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/types"
)

// tcArrayType typechecks an OTARRAY node.
func tcArrayType(n *ir.ArrayType) ir.Node {
	n.Elem = typecheckNtype(n.Elem)
	if n.Elem.Type() == nil {
		return n
	}
	if n.Len == nil { // [...]T
		if !n.Diag() {
			n.SetDiag(true)
			base.Errorf("use of [...] array outside of array literal")
		}
		return n
	}
	n.Len = indexlit(Expr(n.Len))
	size := n.Len
	if ir.ConstType(size) != constant.Int {
		switch {
		case size.Type() == nil:
			// Error already reported elsewhere.
		case size.Type().IsInteger() && size.Op() != ir.OLITERAL:
			base.Errorf("non-constant array bound %v", size)
		default:
			base.Errorf("invalid array bound %v", size)
		}
		return n
	}

	v := size.Val()
	if ir.ConstOverflow(v, types.Types[types.TINT]) {
		base.Errorf("array bound is too large")
		return n
	}

	if constant.Sign(v) < 0 {
		base.Errorf("array bound must be non-negative")
		return n
	}

	bound, _ := constant.Int64Val(v)
	t := types.NewArray(n.Elem.Type(), bound)
	n.SetOTYPE(t)
	types.CheckSize(t)
	return n
}

// tcChanType typechecks an OTCHAN node.
func tcChanType(n *ir.ChanType) ir.Node {
	n.Elem = typecheckNtype(n.Elem)
	l := n.Elem
	if l.Type() == nil {
		return n
	}
	if l.Type().NotInHeap() {
		base.Errorf("chan of incomplete (or unallocatable) type not allowed")
	}
	n.SetOTYPE(types.NewChan(l.Type(), n.Dir))
	return n
}

// tcFuncType typechecks an OTFUNC node.
func tcFuncType(n *ir.FuncType) ir.Node {
	misc := func(f *types.Field, nf *ir.Field) {
		f.SetIsDDD(nf.IsDDD)
		if nf.Decl != nil {
			nf.Decl.SetType(f.Type)
			f.Nname = nf.Decl
		}
	}

	lno := base.Pos

	var recv *types.Field
	if n.Recv != nil {
		recv = tcField(n.Recv, misc)
	}

	t := types.NewSignature(types.LocalPkg, recv, nil, tcFields(n.Params, misc), tcFields(n.Results, misc))
	checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())

	base.Pos = lno

	n.SetOTYPE(t)
	return n
}

// tcInterfaceType typechecks an OTINTER node.
func tcInterfaceType(n *ir.InterfaceType) ir.Node {
	if len(n.Methods) == 0 {
		n.SetOTYPE(types.Types[types.TINTER])
		return n
	}

	lno := base.Pos
	methods := tcFields(n.Methods, nil)
	base.Pos = lno

	n.SetOTYPE(types.NewInterface(types.LocalPkg, methods))
	return n
}

// tcMapType typechecks an OTMAP node.
func tcMapType(n *ir.MapType) ir.Node {
	n.Key = typecheckNtype(n.Key)
	n.Elem = typecheckNtype(n.Elem)
	l := n.Key
	r := n.Elem
	if l.Type() == nil || r.Type() == nil {
		return n
	}
	if l.Type().NotInHeap() {
		base.Errorf("incomplete (or unallocatable) map key not allowed")
	}
	if r.Type().NotInHeap() {
		base.Errorf("incomplete (or unallocatable) map value not allowed")
	}
	n.SetOTYPE(types.NewMap(l.Type(), r.Type()))
	mapqueue = append(mapqueue, n) // check map keys when all types are settled
	return n
}

// tcSliceType typechecks an OTSLICE node.
func tcSliceType(n *ir.SliceType) ir.Node {
	n.Elem = typecheckNtype(n.Elem)
	if n.Elem.Type() == nil {
		return n
	}
	t := types.NewSlice(n.Elem.Type())
	n.SetOTYPE(t)
	types.CheckSize(t)
	return n
}

// tcStructType typechecks an OTSTRUCT node.
func tcStructType(n *ir.StructType) ir.Node {
	lno := base.Pos

	fields := tcFields(n.Fields, func(f *types.Field, nf *ir.Field) {
		if nf.Embedded {
			checkembeddedtype(f.Type)
			f.Embedded = 1
		}
		f.Note = nf.Note
	})
	checkdupfields("field", fields)

	base.Pos = lno
	n.SetOTYPE(types.NewStruct(types.LocalPkg, fields))
	return n
}

// tcField typechecks a generic Field.
// misc can be provided to handle specialized typechecking.
func tcField(n *ir.Field, misc func(*types.Field, *ir.Field)) *types.Field {
	base.Pos = n.Pos
	if n.Ntype != nil {
		n.Type = typecheckNtype(n.Ntype).Type()
		n.Ntype = nil
	}
	f := types.NewField(n.Pos, n.Sym, n.Type)
	if misc != nil {
		misc(f, n)
	}
	return f
}

// tcFields typechecks a slice of generic Fields.
// misc can be provided to handle specialized typechecking.
func tcFields(l []*ir.Field, misc func(*types.Field, *ir.Field)) []*types.Field {
	fields := make([]*types.Field, len(l))
	for i, n := range l {
		fields[i] = tcField(n, misc)
	}
	return fields
}
