Sorry, can you elaborate? I'm skimming through the documentation and I can't find a section on having "the storage type determined at compile time", except for the section on arbitrary-range integers.
Example 1:
type Byte_Count is range 1 .. 4
with Static_Predicate => Byte_Count in 1 | 2 | 4; -- Aspects are Ada 2012
type Component_Count is range 1 .. 4;
V1 : Byte_Count := 3; -- compiler error: expression fails predicate check
V2 : Component_Count := V1; -- compiler error: requires explicit conversion
For these two types I'm not really concerned about how they are represented by the hardware, but I could if I needed to.Example 2:
Extra constraints added to some pre-defined types:
subtype String8 is String
with Dynamic_Predicate => String8'Length <= 8;
subtype Even_Integer is Integer
with Dynamic_Predicate => Even_Integer mod 2 = 0,
Predicate_Failure => "Even_Integer must be a multiple of 2";
Example 3:Use big-endian for some network packets:
type Packet_Type is record
Header : Header_Type;
Data : Data_Type;
end record;
Low-level representation (placed in the private part of a package spec): for Packet_Type use record
Header at 0 range 0 .. 255;
Data at 0 range 256 .. 1855;
end record;
for Packet_Type'Bit_Order use System.High_Order_First;
for Packet_Type'Scalar_Storage_Order use System.High_Order_First;
for Packet_Type'Size use 232 * System.Storage_Unit;Overall, working with Ada was quite pleasant. The type system is nice. The module system is nice. Writing concurrent code was really nice. The Algol like syntax somewhat reminded me of my day working in Ocaml. I did miss true variant types however.
[1] https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/r...