﻿`` T := Tensor.From(Range(12));
`` T2 := T->Reshape(3, 4);
`` n := Null(0i8);
`` full := (n, n, n);
`` N1 := -1;

T
(T[full], T[4:10], T[2:9:2], T[2:9:3], T[9:2:3], T[2:9:100], T[100:20], T[^2:^9:3], T[^2:^9:-3], T[^100:^2], T[^2:^100])
(T[1:10:0], T[10:1:0], T[^1:^10:0], T[^10:^1:0])

T[1:*2:2]
T[11:*2:-3]
T[1:^*2:2]
T[11:*^1:-3]
T[11:*^N1:-3]

// Steps are clamped at run-time to 7 bytes.
T[::0x8000_0000_0000_0000L]
T[::0x7FFF_FFFF_FFFF_FFFFL]

// Coverage of indexing into empty dimension as part of slice.
T2[1:1][3, :]

// Nullability tests.
`` q1  := Opt(1i8);
`` q7  := Opt(7i8);
`` q10 := Opt(10i8);
(T[3:q7], T[3:^q1], T[^10:q7], T[10:^q1:0], T[10:q7:0])
(T[q7:10], T[^q7:12], T[^q7:^1], T[^q7:10:0], T[q10:7:0])
(T[q7:q10], T[^q7:q10], T[^q7:^q1], T[^q7:q10:0], T[q10:q7:0])

// Each line should contain the same four elements.
(T[0:10:1], T[n:10:1], T[:10:1],  T[0:10:0])
(T[7:12:1], T[7:n:1],  T[7::1],   T[7:12:0])
(T[7:10:1], T[7:10:n], T[7:10:1], T[7:10:0])

(T[7:^13:-1], T[7:n:-1], T[7::-1], T[7:^13:0])
(T[11:7:-1],  T[n:7:-1], T[:7:-1], T[11:7:0])
(T[10:7:-1],  T[10:7:n], T[10:7:], T[10:7:0])

(T[0:12:1],    T[n:n:1],  T[::1],  T[0:12:0])
(T[11:^13:-1], T[n:n:-1], T[::-1], T[11:^13:-0])

// Tuple tests.
(T[(4,10, null)], T[(2, 9, 2)])

// REVIEW: How should the tuple form support "back" mode?
`` tups0 := [(4, 10, null), (2, 9, 2), (2, 9, 3), (9, 2, 3), (2, 9, 100), (100, 20, null), (-2, -9, 3), (-2, -9, -3), (-100, -2, null), (-2, -100, null)];
`` tups1 := [(4, false, 10, false, null), (2, false, 9, false, 2), (2, false, 9, false, 3), (9, false, 2, false, 3), (2, false, 9, false, 100), (100, false, 20, false, null),
``           (2, true, 9, true, 3), (2, true, 9, true, -3), (100, true, 2, true, null), (2, true, 100, true, null)];
tups0->(T[it])
tups1->(T[it])

`` tups := [(1, false, 10, false, 0), (10, false, 1, false, 0), (1, true, 10, true, 0), (10, true, 1, true, 0)];
tups->(T[it])

`` tup0 := (q1, q7, 2);
`` tup1 := (q1, 7, 2);
`` tup2 := (1, q7, 2);
(T[tup0], T[tup1], T[tup2])

// Reference types with null default values.
`` T := Tensor.From(Range(12)->ToText())
T
(T[0], T[-2], T[^2], T[-100], T[^100], T[12], T[100])
(T[:], T[3:7], T[^1:^4])

`` T := Tensor.From(Range(4*4)->ToText(), 4, 4)
T
(T[0,0], T[^1,^1], T[^100, ^100], T[100,100])
(T[:], T[1:3, 0], T[^1:^3, 0], T[1:3, ^100], T[^1:^3, 100])

`` T := Tensor.From(Range(12)->({A:it} if it mod 2 = 0 else null))
T
(T[0], T[^2], T[^100], T[12], T[100])
(T[:], T[3:7], T[^1:^4])

`` T := Tensor.From(Range(4*4)->({A:it} if it mod 2 = 0 else null), 4, 4)
T
(T[0,0], T[^1,^1], T[^100, ^100], T[100,100])
(T[:], T[1:3, 0], T[^1:^3, 0], T[1:3, ^100], T[^1:^3, 100])

`` T := Tensor.From(Range(12)->([it]))
T
(T[0], T[^1], T[^100], T[12], T[100])
(T[:], T[3:7], T[^1:^4])

`` T := Tensor.From(Range(4*4)->([it]), 4, 4)
T
(T[0,0], T[^1,^1], T[^100, ^100], T[100,100])
(T[:], T[1:3, 0], T[^1:^3, 0], T[1:3, ^100], T[^1:^3, 100])

// Types whose default values differ from C#'s default value semantics.
`` T := Tensor.From(Range(12)->{A:it})
T
(T[0], T[^1], T[^100], T[12], T[100])
(T[:], T[3:7], T[^1:^4])

`` T := Tensor.From(Range(4*4)->{A:it}, 4, 4)
T
(T[0,0], T[^1,^1], T[^100, ^100], T[100,100])
(T[:], T[1:3, 0], T[^1:^3, 0], T[1:3, ^100], T[^1:^3, 100])

`` T := Tensor.From(Range(12)->(it,))
T
(T[0], T[^1], T[^100], T[12], T[100])
(T[:], T[3:7], T[^1:^4])

`` T := Tensor.From(Range(4*4)->(it,), 4, 4)
T
(T[0,0], T[^1,^1], T[^100, ^100], T[100,100])
(T[:], T[1:3, 0], T[^1:^3, 0], T[1:3, ^100], T[^1:^3, 100])

// Extra rank tests.

`` T := Tensor.From(Range(16), 4, 4)
T
(T[:], T[full], T[1, 2:4], T[2:4, 1], T[1:3, 2:4], T[::2, 1::2], T[100:2, 1:2], T[1:2, 100:^100], T[5, 2:9:100], T[^2:^9:3, 1], T[^2:^9:-3, ^1], T[^100:^2, ^2], T[^2, ^100:^2], T[^5, 1:3], T[1:3, ^5], T[1:3, 5])
(T[0, 0:3:0], T[0, 3:0:0], T[^1:^3:0, 0], T[^3:^1:0, 0])
(T[2:1:, 1], T[2:1:0, 1])

`` T := Tensor.From(Range(3*4*4), 3, 4, 4)
T
(T[:], T[full], T[2, 2, 2:4], T[2, 2:4:2, 1], T[0, 2:4:2, 1:4:2], T[1:3, 1, 3], T[1:3, 2, 0:4:2], T[1:3:2, 0:3:2, 2], T[1:3:2, 0:3:2, 3:1:-1])
(T[^1:^3, 1, 2], T[1, ^1:^3, 2], T[1, 2, ^1:^3], T[1, 2, ^100:^1], T[^100:^1, 1, 2], T[1,^100:^1, 2], T[1, 2, ^1:^100], T[100:^100, 1, 2], T[1, 2, 100:^100], T[1, 100:^100, 2])
(T[1:2, 0, ^5], T[1:2, ^5, 0], T[^5, 1:2, 0], T[1:2, 0, 5], T[1:2, 5, 0], T[5, 1:2, 0])
(T[0, 1, 0:3:0], T[0, 3:0:0, 1], T[^1:^3:0, 0, 1], T[^3:^1:0, 0, 1])
(T[2:1:, 1], T[2:1:0, 1])

`` T := Tensor.From(Range(3*3*4*4), 3, 3, 4, 4)
T
(T[:], T[full], T[1, 2, 2, 2:4], T[1, 2, 2:4:2, 1], T[2, 0, 2:4:2, 1:4:2], T[1, 1:3, 1, 3], T[^2, 1:3, 2, 0:4:2], T[^2, 1:3:2, 0:3:2, 2], T[^1, 1:3:2, 0:3:2, 3:1:-1])
(T[::2, ^2, ^2, ^1], T[1:3:2, 2, 2, 2:4], T[^3:2, 2, 2:4:2, 1], T[1:2, 0, 2:4:2, 1:4:2], T[1:3, 1:3, 1, 3], T[^2:^3, 1:3, 2, 0:4:2], T[^2:^3, 1:3:2, 0:3:2, 2], T[^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[^1:^3, 2:4, 1, 2], T[2:4, ^1:^3, 1, 2], T[2:4, 1, ^1:^3, 2], T[2:4, 1, 2, ^1:^3], T[1, 2, 2:4, ^100:^1], T[1, 2, ^100:^1, 2:4], T[1,^100:^1, 2, 2:4], T[^100:^1, 1, 2, 2:4], T[100:^100, 1, 2, 2:4], T[1, 100:^100, 2, 2:4], T[1, 2, 100:^100, 2:4], T[1, 2, 2:4, 100:^100])
(T[1:2, 2:3, 0, ^5], T[1:2, ^5, 2:3, 0], T[1:2, 2:3, ^5, 0], T[^5, 1:2, 2:3, 0], T[1:2, 2:3, 0, 5], T[1:2, 5, 2:3, 0], T[1:2, 2:3, 5, 0], T[5, 1:2, 2:3, 0])
(T[0, 1, 2, 0:3:0], T[0, 1, 3:0:0, 2], T[0, ^1:^3:0, 1, 2], T[^3:^1:0, 0, 1, 2])
(T[2:1:, 1], T[2:1:0, 1])

`` T := Tensor.From(Range(4*3*3*4*4), 4, 3, 3, 4, 4)
T
(T[:], T[full], T[3, 1, 2, 2, 2:4], T[3, 1, 2, 2:4:2, 1], T[3, 2, 0, 2:4:2, 1:4:2], T[3, 1, 1:3, 1, 3], T[3, ^2, 1:3, 2, 0:4:2], T[3, ^2, 1:3:2, 0:3:2, 2], T[3, ^1, 1:3:2, 0:3:2, 3:1:-1])
(T[^3, ::2, ^2, ^2, ^1], T[^3, 1:3:2, 2, 2, 2:4], T[^3:2, 2, 2:4:2, 1], T[^3, 1:2, 0, 2:4:2, 1:4:2], T[^3, 1:3, 1:3, 1, 3], T[^3, ^2:^3, 1:3, 2, 0:4:2], T[^3, ^2:^3, 1:3:2, 0:3:2, 2], T[^3, ^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[1:4, 1, 2, 2, 2:4], T[1:4, 1, 2, 2:4:2, 1], T[1:4, 2, 0, 2:4:2, 1:4:2], T[1:4, 1, 1:3, 1, 3], T[1:4, ^2, 1:3, 2, 0:4:2], T[1:4, ^2, 1:3:2, 0:3:2, 2], T[1:4, ^1, 1:3:2, 0:3:2, 0:2:4])
(T[0:4:2, ::2, ^2, ^2, ^1], T[0:4:2, 1:3:2, 2, 2, 2:4], T[0:4:2, ^3:2, 2, 2:4:2, 1], T[0:4:2, 1:2, 0, 2:4:2, 1:4:2], T[0:4:2, 1:3, 1:3, 1, 3], T[0:4:2, ^2:^3, 1:3, 2, 0:4:2], T[0:4:2, ^2:^3, 1:3:2, 0:3:2, 2], T[0:4:2, ^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[^1:^3, 2:4, 1, 1:3, 2], T[2:4, ^1:^3, 1, 1:3, 2], T[2:4, 1, ^1:^3, 1:3, 2], T[2:4, 1, 1:3, ^1:^3, 2], T[2:4, 1, 1:3, 2, ^1:^3], T[1, 1:3, 2, 2:4, ^100:^1], T[1, 1:3, 2, ^100:^1, 2:4], T[1,1:3, ^100:^1, 2, 2:4], T[1, ^100:^1, 1:3, 2, 2:4], T[^100:^1, 1, 1:3, 2, 2:4], T[100:^100, 1, 1:3, 2, 2:4], T[1, 100:^100, 1:3, 2, 2:4], T[1, 1:3, 100:^100, 2, 2:4], T[1, 1:3, 2, 100:^100, 2:4], T[1, 1:3, 2, 2:4, 100:^100])
(T[1:2, 1, 2:3, 0, ^5], T[1:2, 1, 2:3, ^5, 0], T[1:2, 1, ^5, 2:3, 0], T[1:2, ^5, 1, 2:3, 0], T[^5, 1:2, 1, 2:3, 0], T[1:2, 1, 2:3, 0, 5], T[1:2, 1, 2:3, 5, 0], T[1:2, 1, 5, 2:3, 0], T[1:2, 5, 1, 2:3, 0], T[5, 1:2, 1, 2:3, 0])
(T[0, 1, 2, 3, 0:3:0], T[0, 1, 2, 3:0:0, 3], T[0, 1, 3:0:0, 2, 3], T[0, ^1:^3:0, 1, 2, 3], T[^3:^1:0, 0, 1, 2, 3])
(T[2:1:, 1], T[2:1:0, 1])

`` T := Tensor.From(Range(4*4*3*3*4*4), 4, 4, 3, 3, 4, 4)
T
(T[:], T[full], T[0, 3, 1, 2, 2, 2:4], T[0, 3, 1, 2, 2:4:2, 1], T[0, 3, 2, 0, 2:4:2, 1:4:2], T[0, 3, 1, 1:3, 1, 3], T[0, 3, ^2, 1:3, 2, 0:4:2], T[0, 3, ^2, 1:3:2, 0:3:2, 2], T[0, 3, ^1, 1:3:2, 0:3:2, 3:1:-1])
(T[^1, ^3, ::2, ^2, ^2, ^1], T[^1, ^3, 1:3:2, 2, 2, 2:4], T[^1, ^3:2, 2, 2:4:2, 1], T[^1, ^3, 1:2, 0, 2:4:2, 1:4:2], T[^1, ^3, 1:3, 1:3, 1, 3], T[^1, ^3, ^2:^3, 1:3, 2, 0:4:2], T[^1, ^3, ^2:^3, 1:3:2, 0:3:2, 2], T[^1, ^3, ^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[2, 1:4, 1, 2, 2, 2:4], T[2, 1:4, 1, 2, 2:4:2, 1], T[2, 1:4, 2, 0, 2:4:2, 1:4:2], T[2, 1:4, 1, 1:3, 1, 3], T[2, 1:4, ^2, 1:3, 2, 0:4:2], T[2, 1:4, ^2, 1:3:2, 0:3:2, 2], T[2, 1:4, ^1, 1:3:2, 0:3:2, 0:2:4])
(T[^2, 0:4:2, ::2, ^2, ^2, ^1], T[^2, 0:4:2, 1:3:2, 2, 2, 2:4], T[^2, 0:4:2, ^3:2, 2, 2:4:2, 1], T[^2, 0:4:2, 1:2, 0, 2:4:2, 1:4:2], T[^2, 0:4:2, 1:3, 1:3, 1, 3], T[^2, 0:4:2, ^2:^3, 1:3, 2, 0:4:2], T[^2, 0:4:2, ^2:^3, 1:3:2, 0:3:2, 2], T[^2, 0:4:2, ^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[0:4:2, 3, 1, 2, 2, 2:4], T[0:4:2, 3, 1, 2, 2:4:2, 1], T[0:4:2, 3, 2, 0, 2:4:2, 1:4:2], T[0:4:2, 3, 1, 1:3, 1, 3], T[0:4:2, 3, ^2, 1:3, 2, 0:4:2], T[0:4:2, 3, ^2, 1:3:2, 0:3:2, 2], T[0:4:2, 3, ^1, 1:3:2, 0:3:2, 0:2:4])
(T[1:4:2, ^1, ^3, ::2, ^2, ^1], T[1:4:2, ^3, 1:3:2, 2, 2, 2:4], T[1:4:2, ^3:2, 2, 2:4:2, 1], T[1:4:2, ^3, 1:2, 0, 2:4:2, 1:4:2], T[1:4:2, ^3, 1:3, 1:3, 1, 3], T[1:4:2, ^3, ^2:^3, 1:3, 2, 0:4:2], T[1:4:2, ^3, ^2:^3, 1:3:2, 0:3:2, 2], T[1:4:2, ^3, ^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[^1:^3, 1:4, 1, 2, 2, 2:4], T[^1:^3, 1:4, 1, 2, 2:4:2, 1], T[^1:^3, 1:4, 2, 0, 2:4:2, 1:4:2], T[^1:^3, 1:4, 1, 1:3, 1, 3], T[^1:^3, 1:4, ^2, 1:3, 2, 0:4:2], T[^1:^3, 1:4, ^2, 1:3:2, 0:3:2, 2], T[^1:^3, 1:4, ^1, 1:3:2, 0:3:2, 0:2:4])
(T[^2:^4, 0:4:2, ::2, ^2, ^2, ^1], T[^2:^4, 0:4:2, 1:3:2, 2, 2, 2:4], T[^2:^4, 0:4:2, ^3:2, 2, 2:4:2, 1], T[^2:^4, 0:4:2, 1:2, 0, 2:4:2, 1:4:2], T[^2:^4, 0:4:2, 1:3, 1:3, 1, 3], T[^2:^4, 0:4:2, ^2:^3, 1:3, 2, 0:4:2], T[^2:^4, 0:4:2, ^2:^3, 1:3:2, 0:3:2, 2], T[^2:^4, 0:4:2, ^1:^3, 1:3:2, 0:3:2, 0:2:4])
(T[^1:^3, 2:4, 1, 1:3, 2, 0], T[2:4, ^1:^3, 1, 1:3, 2, 0], T[2:4, 1, ^1:^3, 1:3, 2, 0], T[2:4, 1, 1:3, ^1:^3, 2, 0], T[2:4, 1, 1:3, 2, ^1:^3, 0], T[2:4, 1, 1:3, 2, 0, ^1:^3], T[1, 1:3, 2, 2:4, 0, ^100:^1], T[1, 1:3, 2, 2:4, ^100:^1, 0], T[1, 1:3, 2, ^100:^1, 2:4, 0], T[1, 1:3, ^100:^1, 2, 2:4, 0], T[1, ^100:^1, 1:3, 2, 2:4, 0], T[^100:^1, 1, 1:3, 2, 2:4, 0], T[100:^100, 1, 1:3, 2, 2:4, 0], T[1, 100:^100, 1:3, 2, 2:4, 0], T[1, 1:3, 100:^100, 2, 2:4, 0], T[1, 1:3, 2, 100:^100, 2:4, 0], T[1, 1:3, 2, 2:4, 100:^100, 0])
(T[2, 1:2, 1, 2:3, 0, ^5], T[2, 1:2, 1, 2:3, ^5, 0], T[2, 1:2, 1, ^5, 2:3, 0], T[2, 1:2, ^5, 1, 2:3, 0], T[2, ^5, 1:2, 1, 2:3, 0], T[^5, 2, 1:2, 1, 2:3, 0], T[2, 1:2, 1, 2:3, 0, 5], T[2, 1:2, 1, 2:3, 5, 0], T[2, 1:2, 1, 5, 2:3, 0], T[2, 1:2, 5, 1, 2:3, 0], T[2, 5, 1:2, 1, 2:3, 0], T[5, 2, 1:2, 1, 2:3, 0])
(T[0, 1, 2, 1, 0, 0:3:0], T[0, 1, 2, 1, 0:3:0, 0], T[0, 1, 2, 3:0:0, 1, 0], T[0, 1, 3:0:0, 2, 1, 0], T[0, ^1:^3:0, 1, 2, 1, 0], T[^3:^1:0, 0, 1, 2, 1, 0])
(T[2:1:, 1], T[2:1:0, 1])
