1// run
2
3// Copyright 2009 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Test the behavior of closures.
8
9package main
10
11import "runtime"
12
13var c = make(chan int)
14
15func check(a []int) {
16	for i := 0; i < len(a); i++ {
17		n := <-c
18		if n != a[i] {
19			println("want", a[i], "got", n, "at", i)
20			panic("fail")
21		}
22	}
23}
24
25func f() {
26	var i, j int
27
28	i = 1
29	j = 2
30	f := func() {
31		c <- i
32		i = 4
33		g := func() {
34			c <- i
35			c <- j
36		}
37		g()
38		c <- i
39	}
40	j = 5
41	f()
42}
43
44// Accumulator generator
45func accum(n int) func(int) int {
46	return func(i int) int {
47		n += i
48		return n
49	}
50}
51
52func g(a, b func(int) int) {
53	c <- a(2)
54	c <- b(3)
55	c <- a(4)
56	c <- b(5)
57}
58
59func h() {
60	var x8 byte = 100
61	var x64 int64 = 200
62
63	c <- int(x8)
64	c <- int(x64)
65	f := func(z int) {
66		g := func() {
67			c <- int(x8)
68			c <- int(x64)
69			c <- z
70		}
71		g()
72		c <- int(x8)
73		c <- int(x64)
74		c <- int(z)
75	}
76	x8 = 101
77	x64 = 201
78	f(500)
79}
80
81func newfunc() func(int) int { return func(x int) int { return x } }
82
83func main() {
84	runtime.GOMAXPROCS(1)
85	var fail bool
86
87	go f()
88	check([]int{1, 4, 5, 4})
89
90	a := accum(0)
91	b := accum(1)
92	go g(a, b)
93	check([]int{2, 4, 6, 9})
94
95	go h()
96	check([]int{100, 200, 101, 201, 500, 101, 201, 500})
97
98	memstats := new(runtime.MemStats)
99	runtime.ReadMemStats(memstats)
100	n0 := memstats.Mallocs
101
102	x, y := newfunc(), newfunc()
103	if x(1) != 1 || y(2) != 2 {
104		println("newfunc returned broken funcs")
105		fail = true
106	}
107
108	runtime.ReadMemStats(memstats)
109	if n0 != memstats.Mallocs {
110		println("newfunc allocated unexpectedly")
111		fail = true
112	}
113
114	ff(1)
115
116	if fail {
117		panic("fail")
118	}
119}
120
121func ff(x int) {
122	call(func() {
123		_ = x
124	})
125}
126
127func call(func()) {
128}
129