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

// builtin calls

package builtins

import "unsafe"

func _append() {
	var x int
	var s []byte
	_0 := append /* ERROR "argument" */ ()
	_1 := append("foo" /* ERROR "not a typed slice" */)
	_2 := append(nil /* ERROR "not a typed slice" */, s)
	_3 := append(x /* ERROR "not a typed slice" */, s)
	_4 := append(s)
	append /* ERROR "not used" */ (s)
}

func _cap() {
	var a [10]bool
	var p *[20]int
	var s []int
	var c chan string
	_0 := cap /* ERROR "argument" */ ()
	_1 := cap /* ERROR "argument" */ (1, 2)
	_2 := cap(42 /* ERROR "invalid" */)
	const _3 = cap(a)
	assert(_3 == 10)
	const _4 = cap(p)
	assert(_4 == 20)
	_5 := cap(c)
	cap /* ERROR "not used" */ (c)

	// issue 4744
	type T struct{ a [10]int }
	const _ = cap(((*T)(nil)).a)
}

func _close() {
	var c chan int
	var r <-chan int
	close /* ERROR "argument" */ ()
	close /* ERROR "argument" */ (1, 2)
	close(42 /* ERROR "not a channel" */)
	close(r /* ERROR "receive-only channel" */)
	close(c)
}

func _complex() {
	var i32 int32
	var f32 float32
	var f64 float64
	var c64 complex64
	_ = complex /* ERROR "argument" */ ()
	_ = complex /* ERROR "argument" */ (1)
	_ = complex(true /* ERROR "invalid argument" */ , 0)
	_ = complex(i32 /* ERROR "invalid argument" */ , 0)
	_ = complex("foo" /* ERROR "invalid argument" */ , 0)
	_ = complex(c64 /* ERROR "invalid argument" */ , 0)
	_ = complex(0, true /* ERROR "invalid argument" */ )
	_ = complex(0, i32 /* ERROR "invalid argument" */ )
	_ = complex(0, "foo" /* ERROR "invalid argument" */ )
	_ = complex(0, c64 /* ERROR "invalid argument" */ )
	_ = complex(f32, f32)
	_ = complex(f32, 1)
	_ = complex(f32, 1.0)
	_ = complex(f32, 'a')
	_ = complex(f64, f64)
	_ = complex(f64, 1)
	_ = complex(f64, 1.0)
	_ = complex(f64, 'a')
	_ = complex(f32 /* ERROR "mismatched types" */, f64)
	_ = complex(f64 /* ERROR "mismatched types" */, f32)
	_ = complex(1, 1)
	_ = complex(1, 1.1)
	_ = complex(1, 'a')
	complex /* ERROR "not used" */ (1, 2)
}

func _copy() {
	copy /* ERROR "not enough arguments" */ ()
	copy /* ERROR "not enough arguments" */ ("foo")
	copy([ /* ERROR "copy expects slice arguments" */ ...]int{}, []int{})
	copy([ /* ERROR "copy expects slice arguments" */ ]int{}, [...]int{})
	copy([ /* ERROR "different element types" */ ]int8{}, "foo")

	// spec examples
	var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	var s = make([]int, 6)
	var b = make([]byte, 5)
	n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
	n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
	n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
}

func _delete() {
	var m map[string]int
	var s string
	delete /* ERROR "argument" */ ()
	delete /* ERROR "argument" */ (1)
	delete /* ERROR "argument" */ (1, 2, 3)
	delete(m, 0 /* ERROR "not assignable" */)
	delete(m, s)
}

func _imag() {
	var f32 float32
	var f64 float64
	var c64 complex64
	var c128 complex128
	_ = imag /* ERROR "argument" */ ()
	_ = imag /* ERROR "argument" */ (1, 2)
	_ = imag(10 /* ERROR "must be a complex number" */)
	_ = imag(2.7182818 /* ERROR "must be a complex number" */)
	_ = imag("foo" /* ERROR "must be a complex number" */)
	const _5 = imag(1 + 2i)
	assert(_5 == 2)
	f32 = _5
	f64 = _5
	const _6 = imag(0i)
	assert(_6 == 0)
	f32 = imag(c64)
	f64 = imag(c128)
	f32 = imag /* ERROR "cannot assign" */ (c128)
	f64 = imag /* ERROR "cannot assign" */ (c64)
	imag /* ERROR "not used" */ (c64)
}

func _len() {
	const c = "foobar"
	var a [10]bool
	var p *[20]int
	var s []int
	var m map[string]complex128
	_ = len /* ERROR "argument" */ ()
	_ = len /* ERROR "argument" */ (1, 2)
	_ = len(42 /* ERROR "invalid" */)
	const _3 = len(c)
	assert(_3 == 6)
	const _4 = len(a)
	assert(_4 == 10)
	const _5 = len(p)
	assert(_5 == 20)
	_ = len(m)
	len /* ERROR "not used" */ (c)

	// esoteric case
	var t string
	var hash map[interface{}][]*[10]int
	const n = len /* ERROR "not constant" */ (hash[recover()][len(t)])
	assert /* ERROR "failed" */ (n == 10)
	var ch <-chan int
	const nn = len /* ERROR "not constant" */ (hash[<-ch][len(t)])
	_ = nn // TODO(gri) remove this once unused constants get type-checked

	// issue 4744
	type T struct{ a [10]int }
	const _ = len(((*T)(nil)).a)
}

func _make() {
	n := 0

	_ = make /* ERROR "argument" */ ()
	_ = make(1 /* ERROR "not a type" */)
	_ = make(int /* ERROR "cannot make" */)

	// slices
	_ = make/* ERROR "arguments" */ ([]int)
	_ = make/* ERROR "arguments" */ ([]int, 2, 3, 4)
	_ = make([]int, int /* ERROR "not an expression" */)
	_ = make([]int, 10, float32 /* ERROR "not an expression" */)
	_ = make([]int, "foo" /* ERROR "must be an integer" */)
	_ = make([]int, 10, 2.3 /* ERROR "must be an integer" */)
	_ = make([]int, 5, 10.0)
	_ = make([]int, 0i)
	_ = make([]int, - /* ERROR "must not be negative" */ 1, 10)
	_ = make([]int, 0, - /* ERROR "must not be negative" */ 1)
	_ = make([]int, - /* ERROR "must not be negative" */ 1, - /* ERROR "must not be negative" */ 1)
	_ = make([]int, 1<<100, 1<<100)  // run-time panic
	_ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100 + 1, 1<<100)
	_ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100, 12345)

	// maps
	_ = make /* ERROR "arguments" */ (map[int]string, 10, 20)
	_ = make(map[int]float32, int /* ERROR "not an expression" */)
	_ = make(map[int]float32, "foo" /* ERROR "must be an integer" */)
	_ = make(map[int]float32, 10)
	_ = make(map[int]float32, n)
	_ = make(map[int]float32, int64(n))

	// channels
	_ = make /* ERROR "arguments" */ (chan int, 10, 20)
	_ = make(chan int, int /* ERROR "not an expression" */)
	_ = make(chan<- int, "foo" /* ERROR "must be an integer" */)
	_ = make(<-chan float64, 10)
	_ = make(chan chan int, n)
	_ = make(chan string, int64(n))

	make /* ERROR "not used" */ ([]int, 10)
}

func _new() {
	_ = new /* ERROR "argument" */ ()
	_ = new /* ERROR "argument" */ (1, 2)
	_ = new("foo" /* ERROR "not a type" */)
	p := new(float64)
	_ = new(struct{ x, y int })
	q := new(*float64)
	_ = *p == **q
	new /* ERROR "not used" */ (int)
}

func _panic() {
	panic /* ERROR "arguments" */ ()
	panic /* ERROR "arguments" */ (1, 2)
	panic(0)
	panic("foo")
	panic(false)
}

func _print() {
	print()
	print(1)
	print(1, 2)
	print("foo")
	print(2.718281828)
	print(false)
}

func _println() {
	println()
	println(1)
	println(1, 2)
	println("foo")
	println(2.718281828)
	println(false)
}

func _real() {
	var f32 float32
	var f64 float64
	var c64 complex64
	var c128 complex128
	_ = real /* ERROR "argument" */ ()
	_ = real /* ERROR "argument" */ (1, 2)
	_ = real(10 /* ERROR "must be a complex number" */)
	_ = real(2.7182818 /* ERROR "must be a complex number" */)
	_ = real("foo" /* ERROR "must be a complex number" */)
	const _5 = real(1 + 2i)
	assert(_5 == 1)
	f32 = _5
	f64 = _5
	const _6 = real(0i)
	assert(_6 == 0)
	f32 = real(c64)
	f64 = real(c128)
	f32 = real /* ERROR "cannot assign" */ (c128)
	f64 = real /* ERROR "cannot assign" */ (c64)
	real /* ERROR "not used" */ (c64)
}

func _recover() {
	_ = recover()
	_ = recover /* ERROR "argument" */ (10)
	recover()
}

// assuming types.DefaultPtrSize == 8
type S0 struct{      // offset
	a bool       //  0
	b rune       //  4
	c *int       //  8
	d bool       // 16
	e complex128 // 24
}                    // 40

type S1 struct{   // offset
	x float32 //  0
	y string  //  8
	z *S1     // 24
	S0        // 32
}                 // 72

type S2 struct{ // offset
	*S1     //  0
}               //  8

func _Alignof() {
	var x int
	_ = unsafe /* ERROR "argument" */ .Alignof()
	_ = unsafe /* ERROR "argument" */ .Alignof(1, 2)
	_ = unsafe.Alignof(int /* ERROR "not an expression" */)
	_ = unsafe.Alignof(42)
	_ = unsafe.Alignof(new(struct{}))
	unsafe /* ERROR "not used" */ .Alignof(x)

	var y S0
	assert(unsafe.Alignof(y.a) == 1)
	assert(unsafe.Alignof(y.b) == 4)
	assert(unsafe.Alignof(y.c) == 8)
	assert(unsafe.Alignof(y.d) == 1)
	assert(unsafe.Alignof(y.e) == 8)
}

func _Offsetof() {
	var x struct{ f int }
	_ = unsafe /* ERROR "argument" */ .Offsetof()
	_ = unsafe /* ERROR "argument" */ .Offsetof(1, 2)
	_ = unsafe.Offsetof(int /* ERROR "not an expression" */)
	_ = unsafe.Offsetof(x /* ERROR "not a selector" */)
	_ = unsafe.Offsetof(x.f)
	_ = unsafe.Offsetof((x.f))
	_ = unsafe.Offsetof((((((((x))).f)))))
	unsafe /* ERROR "not used" */ .Offsetof(x.f)

	var y0 S0
	assert(unsafe.Offsetof(y0.a) == 0)
	assert(unsafe.Offsetof(y0.b) == 4)
	assert(unsafe.Offsetof(y0.c) == 8)
	assert(unsafe.Offsetof(y0.d) == 16)
	assert(unsafe.Offsetof(y0.e) == 24)

	var y1 S1
	assert(unsafe.Offsetof(y1.x) == 0)
	assert(unsafe.Offsetof(y1.y) == 8)
	assert(unsafe.Offsetof(y1.z) == 24)
	assert(unsafe.Offsetof(y1.S0) == 32)

	assert(unsafe.Offsetof(y1.S0.a) == 0) // relative to S0
	assert(unsafe.Offsetof(y1.a) == 32)   // relative to S1
	assert(unsafe.Offsetof(y1.b) == 36)   // relative to S1
	assert(unsafe.Offsetof(y1.c) == 40)   // relative to S1
	assert(unsafe.Offsetof(y1.d) == 48)   // relative to S1
	assert(unsafe.Offsetof(y1.e) == 56)   // relative to S1

	var y2 S2
	assert(unsafe.Offsetof(y2.S1) == 0)
	_ = unsafe.Offsetof(y2 /* ERROR "embedded via pointer" */ .x)
}

func _Sizeof() {
	var x int
	_ = unsafe /* ERROR "argument" */ .Sizeof()
	_ = unsafe /* ERROR "argument" */ .Sizeof(1, 2)
	_ = unsafe.Sizeof(int /* ERROR "not an expression" */)
	_ = unsafe.Sizeof(42)
	_ = unsafe.Sizeof(new(complex128))
	unsafe /* ERROR "not used" */ .Sizeof(x)

	// basic types have size guarantees
	assert(unsafe.Sizeof(byte(0)) == 1)
	assert(unsafe.Sizeof(uint8(0)) == 1)
	assert(unsafe.Sizeof(int8(0)) == 1)
	assert(unsafe.Sizeof(uint16(0)) == 2)
	assert(unsafe.Sizeof(int16(0)) == 2)
	assert(unsafe.Sizeof(uint32(0)) == 4)
	assert(unsafe.Sizeof(int32(0)) == 4)
	assert(unsafe.Sizeof(float32(0)) == 4)
	assert(unsafe.Sizeof(uint64(0)) == 8)
	assert(unsafe.Sizeof(int64(0)) == 8)
	assert(unsafe.Sizeof(float64(0)) == 8)
	assert(unsafe.Sizeof(complex64(0)) == 8)
	assert(unsafe.Sizeof(complex128(0)) == 16)

	var y0 S0
	assert(unsafe.Sizeof(y0.a) == 1)
	assert(unsafe.Sizeof(y0.b) == 4)
	assert(unsafe.Sizeof(y0.c) == 8)
	assert(unsafe.Sizeof(y0.d) == 1)
	assert(unsafe.Sizeof(y0.e) == 16)
	assert(unsafe.Sizeof(y0) == 40)

	var y1 S1
	assert(unsafe.Sizeof(y1) == 72)

	var y2 S2
	assert(unsafe.Sizeof(y2) == 8)
}

// self-testing only
func _assert() {
	var x int
	assert /* ERROR "argument" */ ()
	assert /* ERROR "argument" */ (1, 2)
	assert("foo" /* ERROR "boolean constant" */ )
	assert(x /* ERROR "boolean constant" */)
	assert(true)
	assert /* ERROR "failed" */ (false) 
}

// self-testing only
func _trace() {
	// Uncomment the code below to test trace - will produce console output
	// _ = trace /* ERROR "no value" */ ()
	// _ = trace(1)
	// _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
}
