AI22-0158-1

!standard 4.4(2)                                    26-02-10  AI22-0158-1/01

!class Amendment 26-02-10

!status work item 26-02-10

!status received 25-08-19

!assigned author Tucker Taft

!submitter Tucker Taft

!priority Low

!difficulty Easy

!subject Range equivalent to two-component record aggregate

!summary

The ".." operation used in defining a range is treated as equivalent to a two-component record aggregate if it is used where an expression is expected. The expected type shall be a single record type with exactly two components.

!issue

There are places where it would be natural to define a subprogram that took a range as a parameter, such as a function that returned a slice of a vector. Currently the syntax for a range uses a notation that the user has no ability to connect to a user-defined operation.

It would be useful to provide a way for this notation to be used as a parameter to a user-defined subprogram.

!recommendation

A range appearing where an expression is expected is interpreted as equivalent to a two-component record aggregate, requiring a single expected type that is a record with two components. That is, we propose to allow ranges any place that an expression is permitted, interpreting A .. B as equivalent to (A, B)  and M'Range as equivalent to (M'First, M'Last).

!wording

Replace 4.4(2):

expression ::=

     relation {and relation}  | relation {and then relation}

   | relation {or relation}  | relation {or else relation}

   | relation {xor relation}

with:

expression ::=

     relation {and relation}  | relation {and then relation}

   | relation {or relation}  | relation {or else relation}

   | relation {xor relation}

   | range

Further wording is TBD.

!discussion

Ada's range notation, of A .. B, could be useful for a variety of operations, such as a function that returns a slice of a vector, or an iterator that iterates over a range of integers. It could also be used as a way of defining an upper and lower bound of a constraint of some sort on an abstract type, such as a range of Big Integers or Big Reals, or the first and last String associated with some part of a dictionary.

The simplest way of allowing this notation to be useful for abstract types seems to interpret it as a two-component record aggregate. We considered generalizing this to be usable with two-component arrays as well as records, but this could lead to ranges unintentionally appearing in places where they might make no sense, but might nevertheless happen to be semantically legal, potentially confusing the reader. So as an initial step we suggest requiring the expected type be a record type with exactly two components. This would seem to minimize the chance of unintentional use.

An alternative approach would be to have an aspect (say, Is_Range) that could only be applied to two component record types which would enable such aggregates. That would avoid the notation from being used on unexpected types, but otherwise would just be noise.[a]

!example

type Bounds is record
    Low : Positive;
    High : Natural;
end record;

type Vec is private
   with Constant_Indexing => Element;

function Element(V : Vec; B : Bounds) return Vec;
-- Return a slice of V

...
X : Vec := ...
Y : Vec := X(2 .. 5);  -- Invokes "Element" implicitly

-- X(2 .. 5) is equivalent to Element (X, (2, 5))

 

!ACATS test

An ACATS B-Test is needed that verifies that the expected type must be a single, two-component, record type when the range notation is used in expression context. An ACATS C-Test is needed to check that the notation is supported.

!appendix

This addresses ARG GitHub issue #142 and addresses ARG GitHub issue #141 for reading of slices. (Writing of slices is problematic for reasons beyond just describing ranges.)

[a]I slightly prefer this approach because I don't want to see certain Claw types written as ranges:

type Size_Type is record

Height, Width : Claw.Int;

end record;

(Position is similar.) A call like:

Create (Window, Size => 10..20, Position => 3..3, ...);

would be legal with the original proposed rules, but hardly sensible.