// run

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

// Test behavior of the blank identifier (_).

package main

import (
	"os"
	"unsafe"
)

import _ "fmt"

var call string

type T struct {
	_, _, _ int
}

func (T) _() {
}

func (T) _() {
}

type U struct {
	_ struct{ a, b, c int }
}

const (
	c0 = iota
	_
	_
	_
	c4
)

var ints = []string{
	"1",
	"2",
	"3",
}

func f() (int, int) {
	call += "f"
	return 1, 2
}

func g() (float64, float64) {
	call += "g"
	return 3, 4
}

func h(_ int, _ float64) {
}

func i() int {
	call += "i"
	return 23
}

var _ = i()

func main() {
	if call != "i" {
		panic("init did not run")
	}
	call = ""
	_, _ = f()
	a, _ := f()
	if a != 1 {
		panic(a)
	}
	b, _ := g()
	if b != 3 {
		panic(b)
	}
	_, a = f()
	if a != 2 {
		panic(a)
	}
	_, b = g()
	if b != 4 {
		panic(b)
	}
	_ = i()
	if call != "ffgfgi" {
		panic(call)
	}
	if c4 != 4 {
		panic(c4)
	}

	out := ""
	for _, s := range ints {
		out += s
	}
	if out != "123" {
		panic(out)
	}

	sum := 0
	for s := range ints {
		sum += s
	}
	if sum != 3 {
		panic(sum)
	}

	// go.tools/ssa/interp cannot support unsafe.Pointer.
	if os.Getenv("GOSSAINTERP") == "" {
		type T1 struct{ x, y, z int }
		t1 := *(*T)(unsafe.Pointer(&T1{1, 2, 3}))
		t2 := *(*T)(unsafe.Pointer(&T1{4, 5, 6}))
		if t1 != t2 {
			panic("T{} != T{}")
		}

		var u1, u2 interface{}
		u1 = *(*U)(unsafe.Pointer(&T1{1, 2, 3}))
		u2 = *(*U)(unsafe.Pointer(&T1{4, 5, 6}))
		if u1 != u2 {
			panic("U{} != U{}")
		}
	}

	h(a, b)

	m()
}

type I interface {
	M(_ int, y int)
}

type TI struct{}

func (_ TI) M(x int, y int) {
	if x != y {
		println("invalid M call:", x, y)
		panic("bad M")
	}
}

var fp = func(_ int, y int) {}

func init() {
	fp = fp1
}

func fp1(x, y int) {
	if x != y {
		println("invalid fp1 call:", x, y)
		panic("bad fp1")
	}
}

func m() {
	var i I

	i = TI{}
	i.M(1, 1)
	i.M(2, 2)

	fp(1, 1)
	fp(2, 2)
}

// useless but legal
var _ int = 1
var _ = 2
var _, _ = 3, 4

const _ = 3
const _, _ = 4, 5

type _ int

func _() {
	panic("oops")
}

func ff() {
	var _ int = 1
}
