Auto: abcip-1.3 — array-slice read addressing

Closes #227
This commit is contained in:
Joseph Doherty
2026-04-25 13:03:45 -04:00
parent 29edd835a3
commit 767ac4aec5
8 changed files with 480 additions and 6 deletions

View File

@@ -123,6 +123,61 @@ public sealed class AbCipTagPathTests
AbCipTagPath.TryParse("_private_tag")!.Segments.Single().Name.ShouldBe("_private_tag");
}
[Fact]
public void Slice_basic_inclusive_range()
{
var p = AbCipTagPath.TryParse("Data[0..15]");
p.ShouldNotBeNull();
p.Slice.ShouldNotBeNull();
p.Slice!.Start.ShouldBe(0);
p.Slice.End.ShouldBe(15);
p.Slice.Count.ShouldBe(16);
p.BitIndex.ShouldBeNull();
p.Segments.Single().Name.ShouldBe("Data");
p.Segments.Single().Subscripts.ShouldBeEmpty();
p.ToLibplctagName().ShouldBe("Data[0..15]");
// Slice array name omits the `..End` so libplctag sees an anchored read at the start
// index; pair with ElementCount to cover the whole range.
p.ToLibplctagSliceArrayName().ShouldBe("Data[0]");
}
[Fact]
public void Slice_with_program_scope_and_member_chain()
{
var p = AbCipTagPath.TryParse("Program:MainProgram.Motors.Data[3..7]");
p.ShouldNotBeNull();
p.ProgramScope.ShouldBe("MainProgram");
p.Segments.Select(s => s.Name).ShouldBe(["Motors", "Data"]);
p.Slice!.Start.ShouldBe(3);
p.Slice.End.ShouldBe(7);
p.ToLibplctagName().ShouldBe("Program:MainProgram.Motors.Data[3..7]");
p.ToLibplctagSliceArrayName().ShouldBe("Program:MainProgram.Motors.Data[3]");
}
[Fact]
public void Slice_zero_length_single_element_allowed()
{
// [5..5] is a one-element slice — degenerate but legal (a single read of one element).
var p = AbCipTagPath.TryParse("Data[5..5]");
p.ShouldNotBeNull();
p.Slice!.Count.ShouldBe(1);
}
[Theory]
[InlineData("Data[5..3]")] // M < N
[InlineData("Data[-1..5]")] // negative start
[InlineData("Data[0..15].Member")] // slice + sub-element
[InlineData("Data[0..15].3")] // slice + bit index
[InlineData("Data[0..15,1]")] // slice cannot be multi-dim
[InlineData("Data[0..15,2..3]")] // multi-dim slice not supported
[InlineData("Data[..5]")] // missing start
[InlineData("Data[5..]")] // missing end
[InlineData("Data[a..5]")] // non-numeric start
public void Invalid_slice_shapes_return_null(string input)
{
AbCipTagPath.TryParse(input).ShouldBeNull();
}
[Fact]
public void ToLibplctagName_recomposes_round_trip()
{