golang/test/range4.go

352 lines
5.1 KiB
Go

// run -goexperiment rangefunc
// Copyright 2023 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 the 'for range' construct ranging over functions.
package main
var gj int
func yield4x(yield func() bool) {
_ = yield() && yield() && yield() && yield()
}
func yield4(yield func(int) bool) {
_ = yield(1) && yield(2) && yield(3) && yield(4)
}
func yield3(yield func(int) bool) {
_ = yield(1) && yield(2) && yield(3)
}
func yield2(yield func(int) bool) {
_ = yield(1) && yield(2)
}
func testfunc0() {
j := 0
for range yield4x {
j++
}
if j != 4 {
println("wrong count ranging over yield4x:", j)
panic("testfunc0")
}
j = 0
for _ = range yield4 {
j++
}
if j != 4 {
println("wrong count ranging over yield4:", j)
panic("testfunc0")
}
}
func testfunc1() {
bad := false
j := 1
for i := range yield4 {
if i != j {
println("range var", i, "want", j)
bad = true
}
j++
}
if j != 5 {
println("wrong count ranging over f:", j)
bad = true
}
if bad {
panic("testfunc1")
}
}
func testfunc2() {
bad := false
j := 1
var i int
for i = range yield4 {
if i != j {
println("range var", i, "want", j)
bad = true
}
j++
}
if j != 5 {
println("wrong count ranging over f:", j)
bad = true
}
if i != 4 {
println("wrong final i ranging over f:", i)
bad = true
}
if bad {
panic("testfunc2")
}
}
func testfunc3() {
bad := false
j := 1
var i int
for i = range yield4 {
if i != j {
println("range var", i, "want", j)
bad = true
}
j++
if i == 2 {
break
}
continue
}
if j != 3 {
println("wrong count ranging over f:", j)
bad = true
}
if i != 2 {
println("wrong final i ranging over f:", i)
bad = true
}
if bad {
panic("testfunc3")
}
}
func testfunc4() {
bad := false
j := 1
var i int
func() {
for i = range yield4 {
if i != j {
println("range var", i, "want", j)
bad = true
}
j++
if i == 2 {
return
}
}
}()
if j != 3 {
println("wrong count ranging over f:", j)
bad = true
}
if i != 2 {
println("wrong final i ranging over f:", i)
bad = true
}
if bad {
panic("testfunc3")
}
}
func func5() (int, int) {
for i := range yield4 {
return 10, i
}
panic("still here")
}
func testfunc5() {
x, y := func5()
if x != 10 || y != 1 {
println("wrong results", x, y, "want", 10, 1)
panic("testfunc5")
}
}
func func6() (z, w int) {
for i := range yield4 {
z = 10
w = i
return
}
panic("still here")
}
func testfunc6() {
x, y := func6()
if x != 10 || y != 1 {
println("wrong results", x, y, "want", 10, 1)
panic("testfunc6")
}
}
var saved []int
func save(x int) {
saved = append(saved, x)
}
func printslice(s []int) {
print("[")
for i, x := range s {
if i > 0 {
print(", ")
}
print(x)
}
print("]")
}
func eqslice(s, t []int) bool {
if len(s) != len(t) {
return false
}
for i, x := range s {
if x != t[i] {
return false
}
}
return true
}
func func7() {
defer save(-1)
for i := range yield4 {
defer save(i)
}
defer save(5)
}
func checkslice(name string, saved, want []int) {
if !eqslice(saved, want) {
print("wrong results ")
printslice(saved)
print(" want ")
printslice(want)
print("\n")
panic(name)
}
}
func testfunc7() {
saved = nil
func7()
want := []int{5, 4, 3, 2, 1, -1}
checkslice("testfunc7", saved, want)
}
func func8() {
defer save(-1)
for i := range yield2 {
for j := range yield3 {
defer save(i*10 + j)
}
defer save(i)
}
defer save(-2)
for i := range yield4 {
defer save(i)
}
defer save(-3)
}
func testfunc8() {
saved = nil
func8()
want := []int{-3, 4, 3, 2, 1, -2, 2, 23, 22, 21, 1, 13, 12, 11, -1}
checkslice("testfunc8", saved, want)
}
func func9() {
n := 0
for _ = range yield2 {
for _ = range yield3 {
n++
defer save(n)
}
}
}
func testfunc9() {
saved = nil
func9()
want := []int{6, 5, 4, 3, 2, 1}
checkslice("testfunc9", saved, want)
}
// test that range evaluates the index and value expressions
// exactly once per iteration.
var ncalls = 0
func getvar(p *int) *int {
ncalls++
return p
}
func iter2(list ...int) func(func(int, int) bool) {
return func(yield func(int, int) bool) {
for i, x := range list {
if !yield(i, x) {
return
}
}
}
}
func testcalls() {
var i, v int
ncalls = 0
si := 0
sv := 0
for *getvar(&i), *getvar(&v) = range iter2(1, 2) {
si += i
sv += v
}
if ncalls != 4 {
println("wrong number of calls:", ncalls, "!= 4")
panic("fail")
}
if si != 1 || sv != 3 {
println("wrong sum in testcalls", si, sv)
panic("fail")
}
}
type iter3YieldFunc func(int, int) bool
func iter3(list ...int) func(iter3YieldFunc) {
return func(yield iter3YieldFunc) {
for k, v := range list {
if !yield(k, v) {
return
}
}
}
}
func testcalls1() {
ncalls := 0
for k, v := range iter3(1, 2, 3) {
_, _ = k, v
ncalls++
}
if ncalls != 3 {
println("wrong number of calls:", ncalls, "!= 3")
panic("fail")
}
}
func main() {
testfunc0()
testfunc1()
testfunc2()
testfunc3()
testfunc4()
testfunc5()
testfunc6()
testfunc7()
testfunc8()
testfunc9()
testcalls()
testcalls1()
}