// Copyright 2011 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 types

import 

// A Type represents a type of Go.
// All types implement the Type interface.
type Type interface {
	// Underlying returns the underlying type of a type.
	Underlying() Type

	// String returns a string representation of a type.
	String() string
}

// BasicKind describes the kind of basic type.
type BasicKind int

const (
	Invalid BasicKind = iota // type is invalid

	// predeclared types
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	String
	UnsafePointer

	// types for untyped values
	UntypedBool
	UntypedInt
	UntypedRune
	UntypedFloat
	UntypedComplex
	UntypedString
	UntypedNil

	// aliases
	Byte = Uint8
	Rune = Int32
)

// BasicInfo is a set of flags describing properties of a basic type.
type BasicInfo int

// Properties of basic types.
const (
	IsBoolean BasicInfo = 1 << iota
	IsInteger
	IsUnsigned
	IsFloat
	IsComplex
	IsString
	IsUntyped

	IsOrdered   = IsInteger | IsFloat | IsString
	IsNumeric   = IsInteger | IsFloat | IsComplex
	IsConstType = IsBoolean | IsNumeric | IsString
)

// A Basic represents a basic type.
type Basic struct {
	kind BasicKind
	info BasicInfo
	name string
}

// Kind returns the kind of basic type b.
func ( *Basic) () BasicKind { return .kind }

// Info returns information about properties of basic type b.
func ( *Basic) () BasicInfo { return .info }

// Name returns the name of basic type b.
func ( *Basic) () string { return .name }

// An Array represents an array type.
type Array struct {
	len  int64
	elem Type
}

// NewArray returns a new array type for the given element type and length.
// A negative length indicates an unknown length.
func ( Type,  int64) *Array { return &Array{, } }

// Len returns the length of array a.
// A negative result indicates an unknown length.
func ( *Array) () int64 { return .len }

// Elem returns element type of array a.
func ( *Array) () Type { return .elem }

// A Slice represents a slice type.
type Slice struct {
	elem Type
}

// NewSlice returns a new slice type for the given element type.
func ( Type) *Slice { return &Slice{} }

// Elem returns the element type of slice s.
func ( *Slice) () Type { return .elem }

// A Struct represents a struct type.
type Struct struct {
	fields []*Var
	tags   []string // field tags; nil if there are no tags
}

// NewStruct returns a new struct with the given fields and corresponding field tags.
// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be
// only as long as required to hold the tag with the largest index i. Consequently,
// if no field has a tag, tags may be nil.
func ( []*Var,  []string) *Struct {
	var  objset
	for ,  := range  {
		if .name != "_" && .insert() != nil {
			panic("multiple fields with the same name")
		}
	}
	if len() > len() {
		panic("more tags than fields")
	}
	return &Struct{fields: , tags: }
}

// NumFields returns the number of fields in the struct (including blank and embedded fields).
func ( *Struct) () int { return len(.fields) }

// Field returns the i'th field for 0 <= i < NumFields().
func ( *Struct) ( int) *Var { return .fields[] }

// Tag returns the i'th field tag for 0 <= i < NumFields().
func ( *Struct) ( int) string {
	if  < len(.tags) {
		return .tags[]
	}
	return ""
}

// A Pointer represents a pointer type.
type Pointer struct {
	base Type // element type
}

// NewPointer returns a new pointer type for the given element (base) type.
func ( Type) *Pointer { return &Pointer{base: } }

// Elem returns the element type for the given pointer p.
func ( *Pointer) () Type { return .base }

// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple.
// Tuples are used as components of signatures and to represent the type of multiple
// assignments; they are not first class types of Go.
type Tuple struct {
	vars []*Var
}

// NewTuple returns a new tuple for the given variables.
func ( ...*Var) *Tuple {
	if len() > 0 {
		return &Tuple{}
	}
	return nil
}

// Len returns the number variables of tuple t.
func ( *Tuple) () int {
	if  != nil {
		return len(.vars)
	}
	return 0
}

// At returns the i'th variable of tuple t.
func ( *Tuple) ( int) *Var { return .vars[] }

// A Signature represents a (non-builtin) function or method type.
// The receiver is ignored when comparing signatures for identity.
type Signature struct {
	// We need to keep the scope in Signature (rather than passing it around
	// and store it in the Func Object) because when type-checking a function
	// literal we call the general type checker which returns a general Type.
	// We then unpack the *Signature and use the scope for the literal body.
	scope    *Scope // function scope, present for package-local signatures
	recv     *Var   // nil if not a method
	params   *Tuple // (incoming) parameters from left to right; or nil
	results  *Tuple // (outgoing) results from left to right; or nil
	variadic bool   // true if the last parameter's type is of the form ...T (or string, for append built-in only)
}

// NewSignature returns a new function type for the given receiver, parameters,
// and results, either of which may be nil. If variadic is set, the function
// is variadic, it must have at least one parameter, and the last parameter
// must be of unnamed slice type.
func ( *Var, ,  *Tuple,  bool) *Signature {
	if  {
		 := .Len()
		if  == 0 {
			panic("types.NewSignature: variadic function must have at least one parameter")
		}
		if ,  := .At( - 1).typ.(*Slice); ! {
			panic("types.NewSignature: variadic parameter must be of unnamed slice type")
		}
	}
	return &Signature{nil, , , , }
}

// Recv returns the receiver of signature s (if a method), or nil if a
// function. It is ignored when comparing signatures for identity.
//
// For an abstract method, Recv returns the enclosing interface either
// as a *Named or an *Interface. Due to embedding, an interface may
// contain methods whose receiver type is a different interface.
func ( *Signature) () *Var { return .recv }

// Params returns the parameters of signature s, or nil.
func ( *Signature) () *Tuple { return .params }

// Results returns the results of signature s, or nil.
func ( *Signature) () *Tuple { return .results }

// Variadic reports whether the signature s is variadic.
func ( *Signature) () bool { return .variadic }

// An Interface represents an interface type.
type Interface struct {
	methods   []*Func // ordered list of explicitly declared methods
	embeddeds []Type  // ordered list of explicitly embedded types

	allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
}

// emptyInterface represents the empty (completed) interface
var emptyInterface = Interface{allMethods: markComplete}

// markComplete is used to mark an empty interface as completely
// set up by setting the allMethods field to a non-nil empty slice.
var markComplete = make([]*Func, 0)

// NewInterface returns a new (incomplete) interface for the given methods and embedded types.
// Each embedded type must have an underlying type of interface type.
// NewInterface takes ownership of the provided methods and may modify their types by setting
// missing receivers. To compute the method set of the interface, Complete must be called.
//
// Deprecated: Use NewInterfaceType instead which allows any (even non-defined) interface types
// to be embedded. This is necessary for interfaces that embed alias type names referring to
// non-defined (literal) interface types.
func ( []*Func,  []*Named) *Interface {
	 := make([]Type, len())
	for ,  := range  {
		[] = 
	}
	return NewInterfaceType(, )
}

// NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types.
// Each embedded type must have an underlying type of interface type (this property is not
// verified for defined types, which may be in the process of being set up and which don't
// have a valid underlying type yet).
// NewInterfaceType takes ownership of the provided methods and may modify their types by setting
// missing receivers. To compute the method set of the interface, Complete must be called.
func ( []*Func,  []Type) *Interface {
	if len() == 0 && len() == 0 {
		return &emptyInterface
	}

	// set method receivers if necessary
	 := new(Interface)
	for ,  := range  {
		if  := .typ.(*Signature); .recv == nil {
			.recv = NewVar(.pos, .pkg, "", )
		}
	}

	// All embedded types should be interfaces; however, defined types
	// may not yet be fully resolved. Only verify that non-defined types
	// are interfaces. This matches the behavior of the code before the
	// fix for #25301 (issue #25596).
	for ,  := range  {
		if ,  := .(*Named); ! && !IsInterface() {
			panic("embedded type is not an interface")
		}
	}

	// sort for API stability
	sort.Sort(byUniqueMethodName())
	sort.Stable(byUniqueTypeName())

	.methods = 
	.embeddeds = 
	return 
}

// NumExplicitMethods returns the number of explicitly declared methods of interface t.
func ( *Interface) () int { return len(.methods) }

// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods().
// The methods are ordered by their unique Id.
func ( *Interface) ( int) *Func { return .methods[] }

// NumEmbeddeds returns the number of embedded types in interface t.
func ( *Interface) () int { return len(.embeddeds) }

// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds().
// The result is nil if the i'th embedded type is not a defined type.
//
// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types.
func ( *Interface) ( int) *Named { ,  := .embeddeds[].(*Named); return  }

// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
func ( *Interface) ( int) Type { return .embeddeds[] }

// NumMethods returns the total number of methods of interface t.
// The interface must have been completed.
func ( *Interface) () int { .assertCompleteness(); return len(.allMethods) }

func ( *Interface) () {
	if .allMethods == nil {
		panic("interface is incomplete")
	}
}

// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
// The methods are ordered by their unique Id.
// The interface must have been completed.
func ( *Interface) ( int) *Func { .assertCompleteness(); return .allMethods[] }

// Empty reports whether t is the empty interface.
// The interface must have been completed.
func ( *Interface) () bool { .assertCompleteness(); return len(.allMethods) == 0 }

// Complete computes the interface's method set. It must be called by users of
// NewInterfaceType and NewInterface after the interface's embedded types are
// fully defined and before using the interface type in any way other than to
// form other types. The interface must not contain duplicate methods or a
// panic occurs. Complete returns the receiver.
func ( *Interface) () *Interface {
	// TODO(gri) consolidate this method with Checker.completeInterface
	if .allMethods != nil {
		return 
	}

	.allMethods = markComplete // avoid infinite recursion

	var  []*Func
	var  []*Func
	var  objset
	 := func( *Func,  bool) {
		switch  := .insert(); {
		case  == nil:
			 = append(, )
		case :
			panic("duplicate method " + .name)
		default:
			// check method signatures after all locally embedded interfaces are computed
			 = append(, , .(*Func))
		}
	}

	for ,  := range .methods {
		(, true)
	}

	for ,  := range .embeddeds {
		 := .Underlying().(*Interface)
		.()
		for ,  := range .allMethods {
			(, false)
		}
	}

	for  := 0;  < len();  += 2 {
		 := []
		 := [+1]
		if !Identical(.typ, .typ) {
			panic("duplicate method " + .name)
		}
	}

	if  != nil {
		sort.Sort(byUniqueMethodName())
		.allMethods = 
	}

	return 
}

// A Map represents a map type.
type Map struct {
	key, elem Type
}

// NewMap returns a new map for the given key and element types.
func (,  Type) *Map {
	return &Map{, }
}

// Key returns the key type of map m.
func ( *Map) () Type { return .key }

// Elem returns the element type of map m.
func ( *Map) () Type { return .elem }

// A Chan represents a channel type.
type Chan struct {
	dir  ChanDir
	elem Type
}

// A ChanDir value indicates a channel direction.
type ChanDir int

// The direction of a channel is indicated by one of these constants.
const (
	SendRecv ChanDir = iota
	SendOnly
	RecvOnly
)

// NewChan returns a new channel type for the given direction and element type.
func ( ChanDir,  Type) *Chan {
	return &Chan{, }
}

// Dir returns the direction of channel c.
func ( *Chan) () ChanDir { return .dir }

// Elem returns the element type of channel c.
func ( *Chan) () Type { return .elem }

// A Named represents a named type.
type Named struct {
	info       typeInfo  // for cycle detection
	obj        *TypeName // corresponding declared object
	orig       Type      // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
	underlying Type      // possibly a *Named during setup; never a *Named once set up completely
	methods    []*Func   // methods declared for this type (not the method set of this type); signatures are type-checked lazily
}

// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
// If the given type name obj doesn't have a type yet, its type is set to the returned named type.
// The underlying type must not be a *Named.
func ( *TypeName,  Type,  []*Func) *Named {
	if ,  := .(*Named);  {
		panic("types.NewNamed: underlying type must not be *Named")
	}
	 := &Named{obj: , orig: , underlying: , methods: }
	if .typ == nil {
		.typ = 
	}
	return 
}

// Obj returns the type name for the named type t.
func ( *Named) () *TypeName { return .obj }

// NumMethods returns the number of explicit methods whose receiver is named type t.
func ( *Named) () int { return len(.methods) }

// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
func ( *Named) ( int) *Func { return .methods[] }

// SetUnderlying sets the underlying type and marks t as complete.
func ( *Named) ( Type) {
	if  == nil {
		panic("types.Named.SetUnderlying: underlying type must not be nil")
	}
	if ,  := .(*Named);  {
		panic("types.Named.SetUnderlying: underlying type must not be *Named")
	}
	.underlying = 
}

// AddMethod adds method m unless it is already in the method list.
func ( *Named) ( *Func) {
	if ,  := lookupMethod(.methods, .pkg, .name);  < 0 {
		.methods = append(.methods, )
	}
}

// Implementations for Type methods.

func ( *Basic) () Type     { return  }
func ( *Array) () Type     { return  }
func ( *Slice) () Type     { return  }
func ( *Struct) () Type    { return  }
func ( *Pointer) () Type   { return  }
func ( *Tuple) () Type     { return  }
func ( *Signature) () Type { return  }
func ( *Interface) () Type { return  }
func ( *Map) () Type       { return  }
func ( *Chan) () Type      { return  }
func ( *Named) () Type     { return .underlying }

func ( *Basic) () string     { return TypeString(, nil) }
func ( *Array) () string     { return TypeString(, nil) }
func ( *Slice) () string     { return TypeString(, nil) }
func ( *Struct) () string    { return TypeString(, nil) }
func ( *Pointer) () string   { return TypeString(, nil) }
func ( *Tuple) () string     { return TypeString(, nil) }
func ( *Signature) () string { return TypeString(, nil) }
func ( *Interface) () string { return TypeString(, nil) }
func ( *Map) () string       { return TypeString(, nil) }
func ( *Chan) () string      { return TypeString(, nil) }
func ( *Named) () string     { return TypeString(, nil) }