// Copyright 2013 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.

// This file implements typechecking of call and selector expressions.

package types

import (
	
	
	
	
)

func ( *Checker) ( *operand,  *ast.CallExpr) exprKind {
	.exprOrType(, .Fun)

	switch .mode {
	case invalid:
		.use(.Args...)
		.mode = invalid
		.expr = 
		return statement

	case typexpr:
		// conversion
		 := .typ
		.mode = invalid
		switch  := len(.Args);  {
		case 0:
			.errorf(inNode(, .Rparen), _WrongArgCount, "missing argument in conversion to %s", )
		case 1:
			.expr(, .Args[0])
			if .mode != invalid {
				if .Ellipsis.IsValid() {
					.errorf(.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", )
					break
				}
				.conversion(, )
			}
		default:
			.use(.Args...)
			.errorf(.Args[-1], _WrongArgCount, "too many arguments in conversion to %s", )
		}
		.expr = 
		return conversion

	case builtin:
		 := .id
		if !.builtin(, , ) {
			.mode = invalid
		}
		.expr = 
		// a non-constant result implies a function call
		if .mode != invalid && .mode != constant_ {
			.hasCallOrRecv = true
		}
		return predeclaredFuncs[].kind

	default:
		// function/method call
		 := .mode == cgofunc

		,  := .typ.Underlying().(*Signature)
		if  == nil {
			.invalidOp(, _InvalidCall, "cannot call non-function %s", )
			.mode = invalid
			.expr = 
			return statement
		}

		, ,  := unpack(func( *operand,  int) { .multiExpr(, .Args[]) }, len(.Args), false)
		if  != nil {
			.arguments(, , , , )
		} else {
			.mode = invalid
		}

		// determine result
		switch .results.Len() {
		case 0:
			.mode = novalue
		case 1:
			if  {
				.mode = commaerr
			} else {
				.mode = value
			}
			.typ = .results.vars[0].typ // unpack tuple
		default:
			.mode = value
			.typ = .results
		}

		.expr = 
		.hasCallOrRecv = true

		return statement
	}
}

// use type-checks each argument.
// Useful to make sure expressions are evaluated
// (and variables are "used") in the presence of other errors.
// The arguments may be nil.
func ( *Checker) ( ...ast.Expr) {
	var  operand
	for ,  := range  {
		// The nil check below is necessary since certain AST fields
		// may legally be nil (e.g., the ast.SliceExpr.High field).
		if  != nil {
			.rawExpr(&, , nil)
		}
	}
}

// useLHS is like use, but doesn't "use" top-level identifiers.
// It should be called instead of use if the arguments are
// expressions on the lhs of an assignment.
// The arguments must not be nil.
func ( *Checker) ( ...ast.Expr) {
	var  operand
	for ,  := range  {
		// If the lhs is an identifier denoting a variable v, this assignment
		// is not a 'use' of v. Remember current value of v.used and restore
		// after evaluating the lhs via check.rawExpr.
		var  *Var
		var  bool
		if ,  := unparen().(*ast.Ident);  != nil {
			// never type-check the blank name on the lhs
			if .Name == "_" {
				continue
			}
			if ,  := .scope.LookupParent(.Name, token.NoPos);  != nil {
				// It's ok to mark non-local variables, but ignore variables
				// from other packages to avoid potential race conditions with
				// dot-imported variables.
				if ,  := .(*Var);  != nil && .pkg == .pkg {
					 = 
					 = .used
				}
			}
		}
		.rawExpr(&, , nil)
		if  != nil {
			.used =  // restore v.used
		}
	}
}

// useGetter is like use, but takes a getter instead of a list of expressions.
// It should be called instead of use if a getter is present to avoid repeated
// evaluation of the first argument (since the getter was likely obtained via
// unpack, which may have evaluated the first argument already).
func ( *Checker) ( getter,  int) {
	var  operand
	for  := 0;  < ; ++ {
		(&, )
	}
}

// A getter sets x as the i'th operand, where 0 <= i < n and n is the total
// number of operands (context-specific, and maintained elsewhere). A getter
// type-checks the i'th operand; the details of the actual check are getter-
// specific.
type getter func(x *operand, i int)

// unpack takes a getter get and a number of operands n. If n == 1, unpack
// calls the incoming getter for the first operand. If that operand is
// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
// function call, or a comma-ok expression and allowCommaOk is set, the result
// is a new getter and operand count providing access to the function results,
// or comma-ok values, respectively. The third result value reports if it
// is indeed the comma-ok case. In all other cases, the incoming getter and
// operand count are returned unchanged, and the third result value is false.
//
// In other words, if there's exactly one operand that - after type-checking
// by calling get - stands for multiple operands, the resulting getter provides
// access to those operands instead.
//
// If the returned getter is called at most once for a given operand index i
// (including i == 0), that operand is guaranteed to cause only one call of
// the incoming getter with that i.
//
func unpack( getter,  int,  bool) (getter, int, bool) {
	if  != 1 {
		// zero or multiple values
		return , , false
	}
	// possibly result of an n-valued function call or comma,ok value
	var  operand
	(&, 0)
	if .mode == invalid {
		return nil, 0, false
	}

	if ,  := .typ.(*Tuple);  {
		// result of an n-valued function call
		return func( *operand,  int) {
			.mode = value
			.expr = .expr
			.typ = .At().typ
		}, .Len(), false
	}

	if .mode == mapindex || .mode == commaok || .mode == commaerr {
		// comma-ok value
		if  {
			 := [2]Type{.typ, Typ[UntypedBool]}
			if .mode == commaerr {
				[1] = universeError
			}
			return func( *operand,  int) {
				.mode = value
				.expr = .expr
				.typ = []
			}, 2, true
		}
		.mode = value
	}

	// single value
	return func( *operand,  int) {
		if  != 0 {
			unreachable()
		}
		* = 
	}, 1, false
}

// arguments checks argument passing for the call with the given signature.
// The arg function provides the operand for the i'th argument.
func ( *Checker) ( *operand,  *ast.CallExpr,  *Signature,  getter,  int) {
	if .Ellipsis.IsValid() {
		// last argument is of the form x...
		if !.variadic {
			.errorf(atPos(.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", .Fun)
			.useGetter(, )
			return
		}
		if len(.Args) == 1 &&  > 1 {
			// f()... is not permitted if f() is multi-valued
			.errorf(atPos(.Ellipsis), _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", , .Args[0])
			.useGetter(, )
			return
		}
	}

	// evaluate arguments
	 := .sprintf("argument to %s", .Fun)
	for  := 0;  < ; ++ {
		(, )
		if .mode != invalid {
			var  token.Pos
			if  == -1 && .Ellipsis.IsValid() {
				 = .Ellipsis
			}
			.argument(, , , , )
		}
	}

	// check argument count
	if .variadic {
		// a variadic function accepts an "empty"
		// last argument: count one extra
		++
	}
	if  < .params.Len() {
		.errorf(inNode(, .Rparen), _WrongArgCount, "too few arguments in call to %s", .Fun)
		// ok to continue
	}
}

// argument checks passing of argument x to the i'th parameter of the given signature.
// If ellipsis is valid, the argument is followed by ... at that position in the call.
func ( *Checker) ( *Signature,  int,  *operand,  token.Pos,  string) {
	.singleValue()
	if .mode == invalid {
		return
	}

	 := .params.Len()

	// determine parameter type
	var  Type
	switch {
	case  < :
		 = .params.vars[].typ
	case .variadic:
		 = .params.vars[-1].typ
		if debug {
			if ,  := .(*Slice); ! {
				.dump("%v: expected unnamed slice type, got %s", .params.vars[-1].Pos(), )
			}
		}
	default:
		.errorf(, _WrongArgCount, "too many arguments")
		return
	}

	if .IsValid() {
		if  != -1 {
			.errorf(atPos(), _MisplacedDotDotDot, "can only use ... with matching parameter")
			return
		}
		// argument is of the form x... and x is single-valued
		if ,  := .typ.Underlying().(*Slice); ! && .typ != Typ[UntypedNil] { // see issue #18268
			.errorf(, _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", , )
			return
		}
	} else if .variadic &&  >= -1 {
		// use the variadic parameter slice's element type
		 = .(*Slice).elem
	}

	.assignment(, , )
}

var cgoPrefixes = [...]string{
	"_Ciconst_",
	"_Cfconst_",
	"_Csconst_",
	"_Ctype_",
	"_Cvar_", // actually a pointer to the var
	"_Cfpvar_fp_",
	"_Cfunc_",
	"_Cmacro_", // function to evaluate the expanded expression
}

func ( *Checker) ( *operand,  *ast.SelectorExpr) {
	// these must be declared before the "goto Error" statements
	var (
		      Object
		    []int
		 bool
	)

	 := .Sel.Name
	// If the identifier refers to a package, handle everything here
	// so we don't need a "package" mode for operands: package names
	// can only appear in qualified identifiers which are mapped to
	// selector expressions.
	if ,  := .X.(*ast.Ident);  {
		 := .lookup(.Name)
		if ,  := .(*PkgName);  != nil {
			assert(.pkg == .pkg)
			.recordUse(, )
			.used = true
			 := .imported

			var  Object
			 := value
			if .cgo {
				// cgo special cases C.malloc: it's
				// rewritten to _CMalloc and does not
				// support two-result calls.
				if  == "malloc" {
					 = "_CMalloc"
				} else {
					 = cgofunc
				}
				for ,  := range cgoPrefixes {
					// cgo objects are part of the current package (in file
					// _cgo_gotypes.go). Use regular lookup.
					_,  = .scope.LookupParent(+, .pos)
					if  != nil {
						break
					}
				}
				if  == nil {
					.errorf(.Sel, _UndeclaredImportedName, "%s not declared by package C", )
					goto 
				}
				.objDecl(, nil)
			} else {
				 = .scope.Lookup()
				if  == nil {
					if !.fake {
						.errorf(.Sel, _UndeclaredImportedName, "%s not declared by package %s", , .name)
					}
					goto 
				}
				if !.Exported() {
					.errorf(.Sel, _UnexportedName, "%s not exported by package %s", , .name)
					// ok to continue
				}
			}
			.recordUse(.Sel, )

			// Simplified version of the code for *ast.Idents:
			// - imported objects are always fully initialized
			switch exp := .(type) {
			case *Const:
				assert(.Val() != nil)
				.mode = constant_
				.typ = .typ
				.val = .val
			case *TypeName:
				.mode = typexpr
				.typ = .typ
			case *Var:
				.mode = variable
				.typ = .typ
				if .cgo && strings.HasPrefix(.name, "_Cvar_") {
					.typ = .typ.(*Pointer).base
				}
			case *Func:
				.mode = 
				.typ = .typ
				if .cgo && strings.HasPrefix(.name, "_Cmacro_") {
					.mode = value
					.typ = .typ.(*Signature).results.vars[0].typ
				}
			case *Builtin:
				.mode = builtin
				.typ = .typ
				.id = .id
			default:
				.dump("unexpected object %v", )
				unreachable()
			}
			.expr = 
			return
		}
	}

	.exprOrType(, .X)
	if .mode == invalid {
		goto 
	}

	, ,  = .lookupFieldOrMethod(.typ, .mode == variable, .pkg, )
	if  == nil {
		switch {
		case  != nil:
			// TODO(gri) should provide actual type where the conflict happens
			.errorf(.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", .expr, )
		case :
			.errorf(.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", , .typ)
		default:
			// Check if capitalization of sel matters and provide better error
			// message in that case.
			if len() > 0 {
				var  string
				if  := rune([0]); unicode.IsUpper() {
					 = string(unicode.ToLower()) + [1:]
				} else {
					 = string(unicode.ToUpper()) + [1:]
				}
				if , _, _ = .lookupFieldOrMethod(.typ, .mode == variable, .pkg, );  != nil {
					.errorf(.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", .expr, , .typ, , )
					break
				}
			}
			.errorf(.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", .expr, , .typ, )
		}
		goto 
	}

	// methods may not have a fully set up signature yet
	if ,  := .(*Func);  != nil {
		.objDecl(, nil)
	}

	if .mode == typexpr {
		// method expression
		,  := .(*Func)
		if  == nil {
			// TODO(gri) should check if capitalization of sel matters and provide better error message in that case
			.errorf(.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", .expr, , .typ, )
			goto 
		}

		.recordSelection(, MethodExpr, .typ, , , )

		// the receiver type becomes the type of the first function
		// argument of the method expression's function type
		var  []*Var
		 := .typ.(*Signature)
		if .params != nil {
			 = .params.vars
		}
		.mode = value
		.typ = &Signature{
			params:   NewTuple(append([]*Var{NewVar(token.NoPos, .pkg, "", .typ)}, ...)...),
			results:  .results,
			variadic: .variadic,
		}

		.addDeclDep()

	} else {
		// regular selector
		switch obj := .(type) {
		case *Var:
			.recordSelection(, FieldVal, .typ, , , )
			if .mode == variable ||  {
				.mode = variable
			} else {
				.mode = value
			}
			.typ = .typ

		case *Func:
			// TODO(gri) If we needed to take into account the receiver's
			// addressability, should we report the type &(x.typ) instead?
			.recordSelection(, MethodVal, .typ, , , )

			if debug {
				// Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
				// TODO(gri) This only works because we call LookupFieldOrMethod
				// _before_ calling NewMethodSet: LookupFieldOrMethod completes
				// any incomplete interfaces so they are available to NewMethodSet
				// (which assumes that interfaces have been completed already).
				 := .typ
				if .mode == variable {
					// If typ is not an (unnamed) pointer or an interface,
					// use *typ instead, because the method set of *typ
					// includes the methods of typ.
					// Variables are addressable, so we can always take their
					// address.
					if ,  := .(*Pointer); ! && !IsInterface() {
						 = &Pointer{base: }
					}
				}
				// If we created a synthetic pointer type above, we will throw
				// away the method set computed here after use.
				// TODO(gri) Method set computation should probably always compute
				// both, the value and the pointer receiver method set and represent
				// them in a single structure.
				// TODO(gri) Consider also using a method set cache for the lifetime
				// of checker once we rely on MethodSet lookup instead of individual
				// lookup.
				 := NewMethodSet()
				if  := .Lookup(.pkg, );  == nil || .obj !=  {
					.dump("%v: (%s).%v -> %s", .Pos(), , .name, )
					.dump("%s\n", )
					// Caution: MethodSets are supposed to be used externally
					// only (after all interface types were completed). It's
					// now possible that we get here incorrectly. Not urgent
					// to fix since we only run this code in debug mode.
					// TODO(gri) fix this eventually.
					panic("method sets and lookup don't agree")
				}
			}

			.mode = value

			// remove receiver
			 := *.typ.(*Signature)
			.recv = nil
			.typ = &

			.addDeclDep()

		default:
			unreachable()
		}
	}

	// everything went well
	.expr = 
	return

:
	.mode = invalid
	.expr = 
}