// Copyright 2012 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 statements.

package types

import (
	"go/ast"
	"go/token"
)

func (check *checker) optionalStmt(s ast.Stmt) {
	if s != nil {
		scope := check.topScope
		check.stmt(s, false)
		assert(check.topScope == scope)
	}
}

func (check *checker) stmtList(list []ast.Stmt, fallthroughOk bool) {
	scope := check.topScope
	for i, s := range list {
		check.stmt(s, fallthroughOk && i+1 == len(list))
	}
	assert(check.topScope == scope)
}

func (check *checker) multipleDefaults(list []ast.Stmt) {
	var first ast.Stmt
	for _, s := range list {
		var d ast.Stmt
		switch c := s.(type) {
		case *ast.CaseClause:
			if len(c.List) == 0 {
				d = s
			}
		case *ast.CommClause:
			if c.Comm == nil {
				d = s
			}
		default:
			check.invalidAST(s.Pos(), "case/communication clause expected")
		}
		if d != nil {
			if first != nil {
				check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
			} else {
				first = d
			}
		}
	}
}

func (check *checker) openScope(node ast.Node) {
	s := NewScope(check.topScope)
	check.recordScope(node, s)
	check.topScope = s
}

func (check *checker) closeScope() {
	check.topScope = check.topScope.Parent()
}

// stmt typechecks statement s.
func (check *checker) stmt(s ast.Stmt, fallthroughOk bool) {
	// statements cannot use iota in general
	// (constant declarations set it explicitly)
	assert(check.iota == nil)

	switch s := s.(type) {
	case *ast.BadStmt, *ast.EmptyStmt:
		// ignore

	case *ast.DeclStmt:
		check.declStmt(s.Decl)

	case *ast.LabeledStmt:
		scope := check.funcSig.labels
		if scope == nil {
			scope = NewScope(nil) // no label scope chain
			check.funcSig.labels = scope
		}
		label := s.Label
		check.declareObj(scope, label, NewLabel(label.Pos(), label.Name))
		check.stmt(s.Stmt, fallthroughOk)

	case *ast.ExprStmt:
		var x operand
		used := false
		switch e := unparen(s.X).(type) {
		case *ast.CallExpr:
			// function calls are permitted
			used = true
			// but some builtins are excluded
			// (Caution: This evaluates e.Fun twice, once here and once
			//           below as part of s.X. Perhaps this can be avoided.)
			check.expr(&x, e.Fun)
			if x.mode != invalid {
				if b, ok := x.typ.(*Builtin); ok && !b.isStatement {
					used = false
				}
			}
		case *ast.UnaryExpr:
			// receive operations are permitted
			if e.Op == token.ARROW {
				used = true
			}
		}
		if !used {
			check.errorf(s.Pos(), "%s not used", s.X)
			// ok to continue
		}
		check.rawExpr(&x, s.X, nil)
		if x.mode == typexpr {
			check.errorf(x.pos(), "%s is not an expression", &x)
		}

	case *ast.SendStmt:
		var ch, x operand
		check.expr(&ch, s.Chan)
		check.expr(&x, s.Value)
		if ch.mode == invalid || x.mode == invalid {
			return
		}
		if tch, ok := ch.typ.Underlying().(*Chan); !ok || tch.dir&ast.SEND == 0 || !check.assignment(&x, tch.elt) {
			if x.mode != invalid {
				check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
			}
		}

	case *ast.IncDecStmt:
		var op token.Token
		switch s.Tok {
		case token.INC:
			op = token.ADD
		case token.DEC:
			op = token.SUB
		default:
			check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
			return
		}
		var x operand
		Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
		check.binary(&x, s.X, Y, op)
		if x.mode == invalid {
			return
		}
		check.assignVar(s.X, &x)

	case *ast.AssignStmt:
		switch s.Tok {
		case token.ASSIGN, token.DEFINE:
			if len(s.Lhs) == 0 {
				check.invalidAST(s.Pos(), "missing lhs in assignment")
				return
			}
			if s.Tok == token.DEFINE {
				check.shortVarDecl(s.Lhs, s.Rhs)
			} else {
				// regular assignment
				check.assignVars(s.Lhs, s.Rhs)
			}

		default:
			// assignment operations
			if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
				check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
				return
			}
			// TODO(gri) make this conversion more efficient
			var op token.Token
			switch s.Tok {
			case token.ADD_ASSIGN:
				op = token.ADD
			case token.SUB_ASSIGN:
				op = token.SUB
			case token.MUL_ASSIGN:
				op = token.MUL
			case token.QUO_ASSIGN:
				op = token.QUO
			case token.REM_ASSIGN:
				op = token.REM
			case token.AND_ASSIGN:
				op = token.AND
			case token.OR_ASSIGN:
				op = token.OR
			case token.XOR_ASSIGN:
				op = token.XOR
			case token.SHL_ASSIGN:
				op = token.SHL
			case token.SHR_ASSIGN:
				op = token.SHR
			case token.AND_NOT_ASSIGN:
				op = token.AND_NOT
			default:
				check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
				return
			}
			var x operand
			check.binary(&x, s.Lhs[0], s.Rhs[0], op)
			if x.mode == invalid {
				return
			}
			check.assignVar(s.Lhs[0], &x)
		}

	case *ast.GoStmt:
		var x operand
		check.call(&x, s.Call)
		// TODO(gri) If a builtin is called, the builtin must be valid this context.

	case *ast.DeferStmt:
		var x operand
		check.call(&x, s.Call)
		// TODO(gri) If a builtin is called, the builtin must be valid this context.

	case *ast.ReturnStmt:
		sig := check.funcSig
		if n := sig.results.Len(); n > 0 {
			// determine if the function has named results
			named := false
			lhs := make([]*Var, n)
			for i, res := range sig.results.vars {
				if res.name != "" {
					// a blank (_) result parameter is a named result
					named = true
				}
				lhs[i] = res
			}
			if len(s.Results) > 0 || !named {
				check.initVars(lhs, s.Results, false)
				return
			}
		} else if len(s.Results) > 0 {
			check.errorf(s.Pos(), "no result values expected")
		}

	case *ast.BranchStmt:
		switch s.Tok {
		case token.BREAK:
			// TODO(gri) implement checks
		case token.CONTINUE:
			// TODO(gri) implement checks
		case token.GOTO:
			// TODO(gri) implement checks
		case token.FALLTHROUGH:
			if s.Label != nil {
				check.invalidAST(s.Label.Pos(), "fallthrough statement cannot have label")
				// ok to continue
			}
			if !fallthroughOk {
				check.errorf(s.Pos(), "fallthrough statement out of place")
			}
		default:
			check.invalidAST(s.Pos(), "unknown branch statement (%s)", s.Tok)
		}

	case *ast.BlockStmt:
		check.openScope(s)
		check.stmtList(s.List, false)
		check.closeScope()

	case *ast.IfStmt:
		check.openScope(s)
		check.optionalStmt(s.Init)
		var x operand
		check.expr(&x, s.Cond)
		if x.mode != invalid && !isBoolean(x.typ) {
			check.errorf(s.Cond.Pos(), "non-boolean condition in if statement")
		}
		check.stmt(s.Body, false)
		check.optionalStmt(s.Else)
		check.closeScope()

	case *ast.SwitchStmt:
		check.openScope(s)
		check.optionalStmt(s.Init)
		var x operand
		tag := s.Tag
		if tag == nil {
			// use fake true tag value and position it at the opening { of the switch
			ident := &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
			check.recordObject(ident, Universe.Lookup("true"))
			tag = ident
		}
		check.expr(&x, tag)

		check.multipleDefaults(s.Body.List)
		// TODO(gri) check also correct use of fallthrough
		seen := make(map[interface{}]token.Pos)
		for i, c := range s.Body.List {
			clause, _ := c.(*ast.CaseClause)
			if clause == nil {
				continue // error reported before
			}
			if x.mode != invalid {
				for _, expr := range clause.List {
					x := x // copy of x (don't modify original)
					var y operand
					check.expr(&y, expr)
					if y.mode == invalid {
						continue // error reported before
					}
					// If we have a constant case value, it must appear only
					// once in the switch statement. Determine if there is a
					// duplicate entry, but only report an error if there are
					// no other errors.
					var dupl token.Pos
					var yy operand
					if y.mode == constant {
						// TODO(gri) This code doesn't work correctly for
						//           large integer, floating point, or
						//           complex values - the respective struct
						//           comparisons are shallow. Need to use a
						//           hash function to index the map.
						dupl = seen[y.val]
						seen[y.val] = y.pos()
						yy = y // remember y
					}
					// TODO(gri) The convertUntyped call pair below appears in other places. Factor!
					// Order matters: By comparing y against x, error positions are at the case values.
					check.convertUntyped(&y, x.typ)
					if y.mode == invalid {
						continue // error reported before
					}
					check.convertUntyped(&x, y.typ)
					if x.mode == invalid {
						continue // error reported before
					}
					check.comparison(&y, &x, token.EQL)
					if y.mode != invalid && dupl.IsValid() {
						check.errorf(yy.pos(), "%s is duplicate case (previous at %s)",
							&yy, check.fset.Position(dupl))
					}
				}
			}
			check.openScope(clause)
			check.stmtList(clause.Body, i+1 < len(s.Body.List))
			check.closeScope()
		}
		check.closeScope()

	case *ast.TypeSwitchStmt:
		check.openScope(s)
		defer check.closeScope()
		check.optionalStmt(s.Init)

		// A type switch guard must be of the form:
		//
		//     TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
		//
		// The parser is checking syntactic correctness;
		// remaining syntactic errors are considered AST errors here.
		// TODO(gri) better factoring of error handling (invalid ASTs)
		//
		var lhs *ast.Ident // lhs identifier or nil
		var rhs ast.Expr
		switch guard := s.Assign.(type) {
		case *ast.ExprStmt:
			rhs = guard.X
		case *ast.AssignStmt:
			if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
				return
			}

			lhs, _ = guard.Lhs[0].(*ast.Ident)
			if lhs == nil {
				check.invalidAST(s.Pos(), "incorrect form of type switch guard")
				return
			}
			check.recordObject(lhs, nil) // lhs is implicitly declared in each cause clause

			rhs = guard.Rhs[0]

		default:
			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
			return
		}

		// rhs must be of the form: expr.(type) and expr must be an interface
		expr, _ := rhs.(*ast.TypeAssertExpr)
		if expr == nil || expr.Type != nil {
			check.invalidAST(s.Pos(), "incorrect form of type switch guard")
			return
		}
		var x operand
		check.expr(&x, expr.X)
		if x.mode == invalid {
			return
		}
		xtyp, _ := x.typ.Underlying().(*Interface)
		if xtyp == nil {
			check.errorf(x.pos(), "%s is not an interface", &x)
			return
		}

		check.multipleDefaults(s.Body.List)
		for _, s := range s.Body.List {
			clause, _ := s.(*ast.CaseClause)
			if clause == nil {
				continue // error reported before
			}
			// Check each type in this type switch case.
			var T Type
			for _, expr := range clause.List {
				T = check.typOrNil(expr)
				if T != nil && T != Typ[Invalid] {
					check.typeAssertion(expr.Pos(), &x, xtyp, T)
				}
			}
			check.openScope(clause)
			// If lhs exists, declare a corresponding variable in the case-local scope if necessary.
			if lhs != nil {
				// spec: "The TypeSwitchGuard may include a short variable declaration.
				// When that form is used, the variable is declared at the beginning of
				// the implicit block in each clause. In clauses with a case listing
				// exactly one type, the variable has that type; otherwise, the variable
				// has the type of the expression in the TypeSwitchGuard."
				if len(clause.List) != 1 || T == nil {
					T = x.typ
				}
				obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
				check.declareObj(check.topScope, nil, obj)
				check.recordImplicit(clause, obj)
			}
			check.stmtList(clause.Body, false)
			check.closeScope()
		}

	case *ast.SelectStmt:
		check.multipleDefaults(s.Body.List)
		for _, s := range s.Body.List {
			clause, _ := s.(*ast.CommClause)
			if clause == nil {
				continue // error reported before
			}
			check.openScope(clause)
			check.optionalStmt(clause.Comm) // TODO(gri) check correctness of c.Comm (must be Send/RecvStmt)
			check.stmtList(clause.Body, false)
			check.closeScope()
		}

	case *ast.ForStmt:
		check.openScope(s)
		check.optionalStmt(s.Init)
		if s.Cond != nil {
			var x operand
			check.expr(&x, s.Cond)
			if x.mode != invalid && !isBoolean(x.typ) {
				check.errorf(s.Cond.Pos(), "non-boolean condition in for statement")
			}
		}
		check.optionalStmt(s.Post)
		check.stmt(s.Body, false)
		check.closeScope()

	case *ast.RangeStmt:
		check.openScope(s)
		defer check.closeScope()

		// check expression to iterate over
		decl := s.Tok == token.DEFINE
		var x operand
		check.expr(&x, s.X)
		if x.mode == invalid {
			// if we don't have a declaration, we can still check the loop's body
			// (otherwise we can't because we are missing the declared variables)
			if !decl {
				check.stmt(s.Body, false)
			}
			return
		}

		// determine key/value types
		var key, val Type
		switch typ := x.typ.Underlying().(type) {
		case *Basic:
			if isString(typ) {
				key = Typ[UntypedInt]
				val = Typ[UntypedRune]
			}
		case *Array:
			key = Typ[UntypedInt]
			val = typ.elt
		case *Slice:
			key = Typ[UntypedInt]
			val = typ.elt
		case *Pointer:
			if typ, _ := typ.base.Underlying().(*Array); typ != nil {
				key = Typ[UntypedInt]
				val = typ.elt
			}
		case *Map:
			key = typ.key
			val = typ.elt
		case *Chan:
			key = typ.elt
			val = Typ[Invalid]
			if typ.dir&ast.RECV == 0 {
				check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
				// ok to continue
			}
			if s.Value != nil {
				check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
				// ok to continue
			}
		}

		if key == nil {
			check.errorf(x.pos(), "cannot range over %s", &x)
			// if we don't have a declaration, we can still check the loop's body
			if !decl {
				check.stmt(s.Body, false)
			}
			return
		}

		// check assignment to/declaration of iteration variables
		// (irregular assignment, cannot easily map to existing assignment checks)
		if s.Key == nil {
			check.invalidAST(s.Pos(), "range clause requires index iteration variable")
			// ok to continue
		}

		// lhs expressions and initialization value (rhs) types
		lhs := [2]ast.Expr{s.Key, s.Value}
		rhs := [2]Type{key, val}

		if decl {
			// declaration; variable scope starts after the range clause
			var idents []*ast.Ident
			var vars []*Var
			for i, lhs := range lhs {
				if lhs == nil {
					continue
				}

				// determine lhs variable
				name := "_" // dummy, in case lhs is not an identifier
				ident, _ := lhs.(*ast.Ident)
				if ident != nil {
					name = ident.Name
				} else {
					check.errorf(lhs.Pos(), "cannot declare %s", lhs)
				}
				idents = append(idents, ident)

				obj := NewVar(lhs.Pos(), check.pkg, name, nil)
				vars = append(vars, obj)

				// initialize lhs variable
				x.mode = value
				x.expr = lhs // we don't have a better rhs expression to use here
				x.typ = rhs[i]
				check.initVar(obj, &x)
			}

			// declare variables
			for i, ident := range idents {
				check.declareObj(check.topScope, ident, vars[i])
			}
		} else {
			// ordinary assignment
			for i, lhs := range lhs {
				if lhs == nil {
					continue
				}
				x.mode = value
				x.expr = lhs // we don't have a better rhs expression to use here
				x.typ = rhs[i]
				check.assignVar(lhs, &x)
			}
		}

		check.stmt(s.Body, false)

	default:
		check.errorf(s.Pos(), "invalid statement")
	}
}
