This post is a part of the Ada 2020 series.
You can launch this notebook with Jupyter Ada Kernel by clicking this button:
Firstly, let's activate Ada 2020 support in the compiler.
Usually we do this by -gnat2020
option in compiler command line or in the project file
(preferred). But in this notebook we will do this by the pragma Ada_2020
.
Also we will need some predefined packages.
pragma Ada_2020;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Unchecked_Conversion;
Enumeration types in Ada are represented as integers on the machine level. But, actually, there are two mappings from enumeration to integer: a literal position and a representation value.
Each enumeration literal has corresponding position in the type declaration. We can get it easily through Type'Pos (Enum)
attribute.
Ada.Text_IO.Put ("Pos(False) =");
Ada.Integer_Text_IO.Put (Boolean'Pos (False));
Ada.Text_IO.New_Line;
Ada.Text_IO.Put ("Pos(True) =");
Ada.Integer_Text_IO.Put (Boolean'Pos (True));
Pos(False) = 0
Pos(True) = 1
For reverse mapping we use Type'Val (Int)
:
Ada.Text_IO.Put_Line (Boolean'Val (0)'Image);
Ada.Text_IO.Put_Line (Boolean'Val (1)'Image);
FALSE
TRUE
The representation value defines internal code. It is used to store enumeration value in the memory or a CPU register. By default, enumeration representation values are the same as corresponding literal positions, but you can redefine them:
type My_Boolean is new Boolean;
for My_Boolean use (False => 3, True => 6);
Here we created a copy of Boolean type and assigned it a custom representation.
In Ada 2020 we can get an integer value of the representation with Type'Enum_Rep(Enum)
attribute:
Ada.Text_IO.Put ("Enum_Rep(False) =");
Ada.Integer_Text_IO.Put (My_Boolean'Enum_Rep (False));
Ada.Text_IO.New_Line;
Ada.Text_IO.Put ("Enum_Rep(True) =");
Ada.Integer_Text_IO.Put (My_Boolean'Enum_Rep (True));
Enum_Rep(False) = 3
Enum_Rep(True) = 6
And for the reverse mapping we can use Type'Enum_Val (Int)
:
Ada.Text_IO.Put_Line (My_Boolean'Enum_Val (3)'Image);
Ada.Text_IO.Put_Line (My_Boolean'Enum_Val (6)'Image);
FALSE
TRUE
NOTE. The 'Val(X)/'Pos(X)
behaviour still is the same:
Ada.Text_IO.Put ("Pos(False) =");
Ada.Integer_Text_IO.Put (My_Boolean'Pos (False));
Ada.Text_IO.New_Line;
Ada.Text_IO.Put ("Pos(True) =");
Ada.Integer_Text_IO.Put (My_Boolean'Pos (True));
Pos(False) = 0
Pos(True) = 1
Custom representation could be useful for integration with a low level protocol or a hardware.
This looks like not a big deal, but let see how it works with Ada 2012 and before. Firstly we need an integer type of matching size, then we should instantiate Ada.Unchecked_Conversion
.
type My_Boolean_Int is range 3 .. 6;
for My_Boolean_Int'Size use My_Boolean'Size;
function To_Int is new Ada.Unchecked_Conversion (My_Boolean, My_Boolean_Int);
function From_Int is new Ada.Unchecked_Conversion (My_Boolean_Int, My_Boolean);
Now we call To_Int/From_Int
to work with representation values. And an extra type conversion needed:
Ada.Text_IO.Put ("To_Int(False) =");
Ada.Integer_Text_IO.Put (Integer (To_Int (False)));
Ada.Text_IO.New_Line;
Ada.Text_IO.Put ("To_Int(True) =");
Ada.Integer_Text_IO.Put (Integer (To_Int (True)));
To_Int(False) = 3
To_Int(True) = 6
But this solution doesn't work for generic formal type (because T'Size should be a static value)!
Do you like this? Support us on patreon!