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

// various expressions

package expr3

func shifts1() {
	var (
		i0 int
		u0 uint
	)

	var (
		v0 = 1<<0
		v1 = 1<<i0 /* ERROR "must be unsigned" */
		v2 = 1<<u0
		v3 = 1<<"foo" /* ERROR "must be unsigned" */
		v4 = 1<<- /* ERROR "stupid shift" */ 1
		v5 = 1<<1025 /* ERROR "stupid shift" */
		v6 = 1 /* ERROR "overflows" */ <<100

		v10 uint = 1 << 0
		v11 uint = 1 << u0
		v12 float32 = 1 /* ERROR "must be integer" */ << u0
	)
}

func shifts2() {
	// TODO(gri) enable commented out tests below.
	var (
		s uint = 33
		i = 1<<s           // 1 has type int
		j int32 = 1<<s     // 1 has type int32; j == 0
		k = uint64(1<<s)   // 1 has type uint64; k == 1<<33
		m int = 1.0<<s     // 1.0 has type int
	//	n = 1.0<<s != 0    // 1.0 has type int; n == false if ints are 32bits in size
		o = 1<<s == 2<<s   // 1 and 2 have type int; o == true if ints are 32bits in size
	//	p = 1<<s == 1 /* ERROR "overflows" */ <<33  // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
		u = 1.0 /* ERROR "must be integer" */ <<s         // illegal: 1.0 has type float64, cannot shift
		v float32 = 1 /* ERROR "must be integer" */ <<s   // illegal: 1 has type float32, cannot shift
		w int64 = 1.0<<33  // 1.0<<33 is a constant shift expression
	)
}

// TODO(gri) The error messages below depond on adjusting the spec
//           to reflect what gc is doing at the moment (the spec
//           asks for run-time errors at the moment - see issue 4231).
//
func indexes() {
	_ = 1 /* ERROR "cannot index" */ [0]
	_ = indexes /* ERROR "cannot index" */ [0]
	_ = ( /* ERROR "cannot slice" */ 12 + 3)[1:2]

	var a [10]int
	_ = a[true /* ERROR "must be integer" */ ]
	_ = a["foo" /* ERROR "must be integer" */ ]
	_ = a[1.1 /* ERROR "must be integer" */ ]
	_ = a[1.0]
	_ = a[- /* ERROR "index .* negative" */ 1]
	_ = a[- /* ERROR "index .* negative" */ 1 :]
	_ = a[: - /* ERROR "index .* negative" */ 1]
	var a0 int
	a0 = a[0]
	var a1 int32
	a1 = a /* ERROR "cannot assign" */ [1] 
	_ = a[9]
	_ = a[10 /* ERROR "index .* out of bounds" */ ]
	_ = a[1 /* ERROR "stupid index" */ <<100]
	_ = a[10:]
	_ = a[:10]
	_ = a[10:10]
	_ = a[11 /* ERROR "index .* out of bounds" */ :]
	_ = a[: 11 /* ERROR "index .* out of bounds" */ ]
	_ = a[: 1 /* ERROR "stupid index" */ <<100]

	pa := &a
	_ = pa[9]
	_ = pa[10 /* ERROR "index .* out of bounds" */ ]
	_ = pa[1 /* ERROR "stupid index" */ <<100]
	_ = pa[10:]
	_ = pa[:10]
	_ = pa[10:10]
	_ = pa[11 /* ERROR "index .* out of bounds" */ :]
	_ = pa[: 11 /* ERROR "index .* out of bounds" */ ]
	_ = pa[: 1 /* ERROR "stupid index" */ <<100]

	var b [0]int
	_ = b[0 /* ERROR "index .* out of bounds" */ ]
	_ = b[:]
	_ = b[0:]
	_ = b[:0]
	_ = b[0:0]

	var s []int
	_ = s[- /* ERROR "index .* negative" */ 1]
	_ = s[- /* ERROR "index .* negative" */ 1 :]
	_ = s[: - /* ERROR "index .* negative" */ 1]
	_ = s[0]
	_ = s[1 : 2]
	_ = s[2 /* ERROR "inverted slice range" */ : 1]
	_ = s[2 :]
	_ = s[: 1 /* ERROR "stupid index" */ <<100]
	_ = s[1 /* ERROR "stupid index" */ <<100 :]
	_ = s[1 /* ERROR "stupid index" */ <<100 : 1 /* ERROR "stupid index" */ <<100]

	var t string
	_ = t[- /* ERROR "index .* negative" */ 1]
	_ = t[- /* ERROR "index .* negative" */ 1 :]
	_ = t[: - /* ERROR "index .* negative" */ 1]
	var t0 byte
	t0 = t[0]
	var t1 rune
	t1 = t /* ERROR "cannot assign" */ [2]
	_ = ("foo" + "bar")[5]
	_ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]

	const c = "foo"
	_ = c[- /* ERROR "index .* negative" */ 1]
	_ = c[- /* ERROR "index .* negative" */ 1 :]
	_ = c[: - /* ERROR "index .* negative" */ 1]
	var c0 byte
	c0 = c[0]
	var c2 float32
	c2 = c /* ERROR "cannot assign" */ [2]
	_ = c[3 /* ERROR "index .* out of bounds" */ ]
	_ = ""[0 /* ERROR "index .* out of bounds" */ ]

	_ = s[1<<30] // no compile-time error here

	// issue 4913
	type mystring string
	var ss string
	var ms mystring
	var i, j int
	ss = "foo"[1:2]
	ss = "foo"[i:j]
	ms = "foo" /* ERROR "cannot assign" */ [1:2]
	ms = "foo" /* ERROR "cannot assign" */ [i:j]
}

type T struct {
	x int
}

func (*T) m() {}

func method_expressions() {
	_ = T /* ERROR "no single field or method" */ .a
	_ = T /* ERROR "has no method" */ .x
	_ = T.m
	var f func(*T) = (*T).m
	var g func(*T) = ( /* ERROR "cannot assign" */ T).m
}

func struct_literals() {
	type T0 struct {
		a, b, c int
	}

	type T1 struct {
		T0
		a, b int
		u float64
		s string
	}

	// keyed elements
	_ = T1{}
	_ = T1{a: 0, 1 /* ERROR "mixture of .* elements" */ }
	_ = T1{aa /* ERROR "unknown field" */ : 0}
	_ = T1{1 /* ERROR "invalid field name" */ : 0}
	_ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
	_ = T1{a: "foo" /* ERROR "cannot use" */ }
	_ = T1{c /* ERROR "unknown field" */ : 0}
	_ = T1{T0: { /* ERROR "missing type" */ }}
	_ = T1{T0: T0{}}
	_ = T1{T0 /* ERROR "invalid field name" */ .a: 0}

	// unkeyed elements
	_ = T0{1, 2, 3}
	_ = T0{1, b /* ERROR "mixture" */ : 2, 3}
	_ = T0{1, 2} /* ERROR "too few values" */
	_ = T0{1, 2, 3, 4  /* ERROR "too many values" */ }
	_ = T0{1, "foo" /* ERROR "cannot use" */, 3.4  /* ERROR "cannot use" */}
}

func array_literals() {
	type A0 [0]int
	_ = A0{}
	_ = A0{0 /* ERROR "index .* out of bounds" */}
	_ = A0{0 /* ERROR "index .* out of bounds" */ : 0}

	type A1 [10]int
	_ = A1{}
	_ = A1{0, 1, 2}
	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	_ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /* ERROR "index .* out of bounds" */ }
	_ = A1{- /* ERROR "index .* negative" */ 1: 0}
	_ = A1{8: 8, 9}
	_ = A1{8: 8, 9, 10 /* ERROR "index .* out of bounds" */ }
	_ = A1{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
	_ = A1{5: 5, 6, 7, 3: 3, 4}
	_ = A1{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
	_ = A1{10 /* ERROR "index .* out of bounds" */ : 10, 10 /* ERROR "index .* out of bounds" */ : 10}
	_ = A1{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
	_ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
	_ = A1{2.0}
	_ = A1{2.1 /* ERROR "cannot use" */ }
	_ = A1{"foo" /* ERROR "cannot use" */ }

	a0 := [...]int{}
	assert(len(a0) == 0)
	
	a1 := [...]int{0, 1, 2}
	assert(len(a1) == 3)
	var a13 [3]int
	var a14 [4]int
	a13 = a1
	a14 = a1 /* ERROR "cannot assign" */
	
	a2 := [...]int{- /* ERROR "index .* negative" */ 1: 0}

	a3 := [...]int{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
	assert(len(a3) == 5) // somewhat arbitrary

	a4 := [...]complex128{0, 1, 2, 1<<10-2: -1i, 1i, 400: 10, 12, 14}
	assert(len(a4) == 1024)

	// from the spec
	type Point struct { x, y float32 }
	_ = [...]Point{Point{1.5, -3.5}, Point{0, 0}}
	_ = [...]Point{{1.5, -3.5}, {0, 0}}
	_ = [][]int{[]int{1, 2, 3}, []int{4, 5}}
	_ = [][]int{{1, 2, 3}, {4, 5}}
	_ = [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
	_ = [...]*Point{{1.5, -3.5}, {0, 0}}
}

func slice_literals() {
	type S0 []int
	_ = S0{}
	_ = S0{0, 1, 2}
	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	_ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	_ = S0{- /* ERROR "index .* negative" */ 1: 0}
	_ = S0{8: 8, 9}
	_ = S0{8: 8, 9, 10}
	_ = S0{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
	_ = S0{5: 5, 6, 7, 3: 3, 4}
	_ = S0{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
	_ = S0{10: 10, 10 /* ERROR "duplicate index" */ : 10}
	_ = S0{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
	_ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
	_ = S0{2.0}
	_ = S0{2.1 /* ERROR "cannot use" */ }
	_ = S0{"foo" /* ERROR "cannot use" */ }

	// indices must be resolved correctly
	// (for details, see comment in go/parser/parser.go, method parseElement)
	index1 := 1
	_ = S0{index1: 1}
	_ = S0{index2: 2}
	_ = S0{index3 /* ERROR "undeclared name" */ : 3}
}

var index2 int = 2

func map_literals() {
	type M0 map[string]int
	type M1 map[bool]int
	type M2 map[*int]int

	_ = M0{}
	_ = M0{1 /* ERROR "missing key" */ }
	_ = M0{1 /* ERROR "cannot use .* as string key" */ : 2}
	_ = M0{"foo": "bar" /* ERROR "cannot use .* as int value" */ }
	_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }

	// map keys must be resolved correctly
	// (for details, see comment in go/parser/parser.go, method parseElement)
	key1 := "foo"
	_ = M0{key1: 1}
	_ = M0{key2: 2}
	_ = M0{key3 /* ERROR "undeclared name" */ : 2}

	_ = M1{true: 1, false: 0}
	_ = M2{nil: 0, &index2: 1}
}

var key2 string = "bar"

type I interface {
	m()
}

type I2 interface {
	m(int)
}

type T1 struct{}
type T2 struct{}

func (T2) m(int) {}

func type_asserts() {
	var x int
	_ = x /* ERROR "not an interface" */ .(int)

	var e interface{}
	var ok bool
	x, ok = e.(int)

	var t I
	_ = t /* ERROR "use of .* outside type switch" */ .(type)
	_ = t.(T)
	_ = t.(T1 /* ERROR "missing method m" */ )
	_ = t.(T2 /* ERROR "wrong type for method m" */ )
	_ = t.(I2 /* ERROR "wrong type for method m" */ )
}

func f0() {}
func f1(x int) {}
func f2(u float32, s string) {}
func fs(s []byte) {}
func fv(x ...int) {}
func fi(x ... interface{}) {}

func g0() {}
func g1() int { return 0}
func g2() (u float32, s string) { return }
func gs() []byte { return nil }

func _calls() {
	var x int
	var y float32
	var s []int

	f0()
	_ = f0 /* ERROR "used as value" */ ()
	f0(g0 /* ERROR "too many arguments" */ )

	f1(0)
	f1(x)
	f1(10.0)
	f1 /* ERROR "too few arguments" */ ()
	f1(x, y /* ERROR "too many arguments" */ )
	f1(s /* ERROR "cannot assign" */ )
	f1(x ... /* ERROR "cannot use ..." */ )
	f1(g0 /* ERROR "used as value" */ ())
	f1(g1())
	// f1(g2()) // TODO(gri) missing position in error message

	f2 /* ERROR "too few arguments" */ ()
	f2 /* ERROR "too few arguments" */ (3.14)
	f2(3.14, "foo")
	f2(x /* ERROR "cannot assign" */ , "foo")
	f2(g0 /* ERROR "used as value" */ ())
	f2 /* ERROR "too few arguments" */ (g1 /* ERROR "cannot assign" */ ())
	f2(g2())

	fs /* ERROR "too few arguments" */ ()
	fs(g0 /* ERROR "used as value" */ ())
	fs(g1 /* ERROR "cannot assign" */ ())
	// fs(g2()) // TODO(gri) missing position in error message
	fs(gs())

	fv()
	fv(1, 2.0, x)
	fv(s /* ERROR "cannot assign" */ )
	fv(s...)
	fv(1, s /* ERROR "can only use ... with matching parameter" */ ...)
	fv(gs /* ERROR "cannot assign" */ ())
	fv(gs /* ERROR "cannot assign" */ ()...)

	fi()
	fi(1, 2.0, x, 3.14, "foo")
	fi(g2())
	fi(0, g2)
	fi(0, g2 /* ERROR "2-valued expression" */ ())
}
