#!/usr/bin/ruby

assert_eq(
    gather {
        for i,j (1..2 ~X 1..2, 5..7 ~X 5..7, [3,4,5]) { take([i,j]) }
    },
    [[1, 1],[1, 2],[2, 1],[2, 2],[5, 5],[5, 6],[5, 7],[6, 5],[6, 6],[6, 7],[7, 5],[7, 6],[7, 7],[3, nil],[4, nil],[5, nil]]
)

assert_eq(
    gather {
        for i,j (1..2 ~X 1..2, 5..7 ~X 5..7, [3,4,5]) { take([i,j]); break }
    },
    [[1,1]]
);

assert_eq(
    gather {
        for i (1..3, 5..7) { take(i) }
    },
    [1,2,3,5,6,7]
)

assert_eq(
    gather {
        for a,*b in (1..2 ~X 'a'..'b') {
            take([a,b])
        }
    },
    [[1, ["a"]],[1, ["b"]], [2, ["a"]], [2, ["b"]]]
)

assert_eq(
    gather {
        for *a in (1..2 ~X 'a'..'b') {
            take(a)
        }
    },
    [[1, "a"],[1, "b"], [2, "a"], [2, "b"]]
)

assert_eq(
    gather {
        for :a in ('a'..'b' ~X 1..2) {
            take(a)
        }
    },
    [Hash(a => 1),Hash(a => 2), Hash(b => 1), Hash(b => 2)]
)

assert_eq(
    gather {
        for i (1..3, 5..7) { take(i); break }
    },
    [1]
)

assert_eq(
    gather {
        for i (1..3, 5..7) { take(i); i == 2 && break }
    },
    [1,2]
)

assert_eq(
    gather {
        for i (1..3, 5..7) {
            take(i);
            i == 2 && next;
            i == 3 && break
        }
    },
    [1,2,3]
)

assert_eq(
    gather {
        for i (1..3, [5,6,7]) {
            take(i);
            i == 2 && next;
            i == 6 && break
        }
    },
    [1,2,3,5,6]
)


assert_eq(
    gather {
        for i (1..3, [5,6,7]) {
            i == 1 && next;
            i == 5 && next;
            take(i);
            i == 2 && next;
            i == 6 && break
        }
    },
    [2,3,6]
)

assert_eq(
    gather {
        for i (1..3, [5,6,7]) {
            i == 3 && break
            take(i);
        }
    },
    [1,2]
)

assert_eq(
    gather {
        for i (1..3, [5,6,7]) {
            i == 5 && next
            i == 3 && next
            take(i);
        }
    },
    [1,2,6,7]
)

assert_eq(
    gather {
        for i ([5,6,7], 1..3) {
            i == 5 && next;
            take(i);
            i == 2 && break;
        }
    },
    [6,7,1,2]
)

assert_eq(
    gather {
        var hash = Hash(a => 1, b => 2, c => 3)
        for k,v in (hash) {
            take(v, hash{k})
        }
    }.sort,
    [1, 1, 2, 2, 3, 3]
)

assert_eq(
    gather {
        var hash = Hash(a => 1, b => 2, c => 3)
        for k,v in (hash) {
            take([\k, \v])
        }
    }.map {|p| [*p[0], *p[1]]}.sort_by {|p| p[1] }
    [[:a, 1], [:b, 2], [:c, 3]]
)

assert_eq(
    gather {
        for a in (1..4), b in (a..4) {
            take([a, b])
        }
    },
    [[1, 1], [1, 2], [1, 3], [1, 4], [2, 2], [2, 3], [2, 4], [3, 3], [3, 4], [4, 4]]
)

assert_eq(
    gather {
        for a in (1..4), b in (a..4), c in (b-a .. b+a) {
            take([a, b, c])
        }
    },
    [[1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 4], [1, 4, 3], [1, 4, 4], [1, 4, 5], [2, 2, 0], [2, 2, 1], [2, 2, 2], [2, 2, 3], [2, 2, 4], [2, 3, 1], [2, 3, 2], [2, 3, 3], [2, 3, 4], [2, 3, 5], [2, 4, 2], [2, 4, 3], [2, 4, 4], [2, 4, 5], [2, 4, 6], [3, 3, 0], [3, 3, 1], [3, 3, 2], [3, 3, 3], [3, 3, 4], [3, 3, 5], [3, 3, 6], [3, 4, 1], [3, 4, 2], [3, 4, 3], [3, 4, 4], [3, 4, 5], [3, 4, 6], [3, 4, 7], [4, 4, 0], [4, 4, 1], [4, 4, 2], [4, 4, 3], [4, 4, 4], [4, 4, 5], [4, 4, 6], [4, 4, 7], [4, 4, 8]],
)

assert_eq(
    gather {
        for a in (1..4), b in (a..4), c in (b-a .. b+a) {
            take([a, b, c])
            break if (c==5)
        }
    },
    [[1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 4], [1, 4, 3], [1, 4, 4], [1, 4, 5]]
)

assert_eq(
    gather {
        for a in (1..4), b in (a..4), c in (b-a .. b+a) {
            take([a, b, c])
            break if (b==3)
        }
    },
    [[1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 3, 2]]
)

assert_eq(
    gather {
        for a in (1..4), b in (a..4), c in (b-a .. b+a) {
            take([a, b, c])
            break if (a==2)
        }
    },
    [[1, 1, 0], [1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 4], [1, 4, 3], [1, 4, 4], [1, 4, 5], [2, 2, 0]]
)

assert_eq(
    gather {
        for a = (var t = 1..3), b = (var k = 1..5) {
            take([a, b])
        }

        assert_eq(t, 1..3)
        assert_eq(k, 1..5)
    },
    [[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [2, 1], [2, 2], [2, 3], [2, 4], [2, 5], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5]]
)

do {
    var z1 = (1..2)
    var z2 = (3..4)

    var arr = [z1, z2]

    assert_eq(gather {
        for a,b in (arr) {
            take [a,b]
        }
    }, [[1,2], [3,4]])

    assert_eq(z1, 1..2)
    assert_eq(z2, 3..4)

    assert_eq(arr, [z1, z2])
}

assert_eq(gather {
    for a in ([1,2]) {
        take [a,a+42]
    }
}, [[1,43],[2,44]])

assert_eq(gather {
    for a,b in ([1,2]) {
        take [a,b]
    }
}, [[1,nil],[2,nil]])

say "** Test passed!"