Version 1.2 of acs/ac-00282.txt

Unformatted version of acs/ac-00282.txt version 1.2
Other versions for file acs/ac-00282.txt

!standard 12.3(5)          16-08-18 AC95-00282/00
!class Amendment 16-08-18
!status received no action 16-08-18
!status received 16-07-30
!subject Allow the use of case statements in generic instantiations
!summary
!appendix

!topic Allow the usage of case in generic instantiation type-selection.
!reference Ada 202x RM 12.3
!from Edward Fish 16-07-30
!keywords generic instantiation
!discussion

It would be nice, at times, to have generics vary on constants/static
conditions; doing so would reduce the need for the use of multiple bodies
selected externally (e.g. via project-variables in GPS).

As a simple example:

with
Interfaces,
Constant_Test.Generic_Signed;
Package Constant_Test.Integers is
  new Constant_Test.Generic_Signed
    (case Cell_Size is
     when Word_16 => Interfaces.Integer_16,
     when Word_32 => Interfaces.Integer_32,
     when Word_64 => Interfaces.Integer_64
    ) with Pure;

where the generic's spec is:

Generic
    Type T is (<>);
Package Constant_Test.Generic_Signed with Pure is
    Subtype Internal is T;
End Constant_Test.Generic_Signed;

would allow the program to use Constant_Test.Integers.Internal transparently
across the program.

Syntactically the only change needed would be the insertion of another
production between generic_association and explicit_generic_actual_parameter
allowing the case-statement.

***************************************************************

From: Gautier de Montmollin
Sent: Sunday, July 31, 2016  12:32 AM

Where is Cell_Size defined in your example ? Depending on its meaning, you could
pass this integer type to the generic package:

its: constant:= System.Word_Size;

type Integer_Sys is range -2**(bits-1) .. 2**(bits-1) - 1;

or even this:


min_bits_32: constant:= Integer'Max(32, System.Word_Size);

type Integer_M32 is range -2**(min_bits_32-1) .. 2**(min_bits_32-1) - 1;

***************************************************************

From: Joey Fish
Sent: Sunday, July 31, 2016  12:39 AM

> Where is Cell_Size defined in your example ? ...

In another unit: something like

Package Constant_Test with Pure is

    Type Word_Size is ( Word_16, Word_32, Word_64 );

    Cell_Size : Constant Word_Size := Word_64;

    Bits : Constant := (case Cell_Size is
            when Word_16 => 16,
            when Word_32 => 32,
            when Word_64 => 64
               );
End Constant_Test;

***************************************************************

From: Randy Brukardt
Sent: Monday, August 1, 2016  4:38 PM

What you appear to be asking for here is a subtype-valued case expression.
It doesn't make sense to support such things ONLY in a generic instantiation;
there's nothing special about the actual parameters of an instance and it would
certainly be best to keep in that way.

The problem, of course, is that generally supporting subtype-valued expressions
is a big change to Ada. And it doesn't seem necessary to solve this problem, as
Gautier pointed out. Adding a type to your package solves the problem, and
without depending on anything predefined (always better to avoid predefined
things), and without using a junk generic (which would add runtime expense on a
generic sharing implementation):

	package Constant_Test with Pure is

	    type Word_Size is ( Word_16, Word_32, Word_64 );

	    Cell_Size : constant Word_Size := Word_64;

	    Bits : Constant := (case Cell_Size is
	            when Word_16 => 16,
	            when Word_32 => 32,
	            when Word_64 => 64);

            type Cell_Integer is range -(2**Bits) .. 2**Bits-1;

	end Constant_Test;

If you *absolutely* have to depend on a subtype of a type in Interfaces, that's
also best done in this package:

      with Interfaces;
      package Constant_Test with Pure is

	    type Word_Size is ( Word_16, Word_32, Word_64 );

	    Cell_Size : constant Word_Size := Word_64;

	    Bits : Constant := (case Cell_Size is
	            when Word_16 => 16,
	            when Word_32 => 32,
	            when Word_64 => 64);

            subtype Cell_Integer is Interfaces.Integer_64; -- Change if Cell_Size is changed.
            pragma Assert (Cell_Integer'Size = Bits, Message => "Cell_Integer must match Cell_Size");

	end Constant_Test;

Given the existence of good work-arounds for this problem, it's hard to see the
value of complex language support here. (Maybe you have a more compelling
problem??)

***************************************************************


Questions? Ask the ACAA Technical Agent