Skip to content

Latest commit

 

History

History
175 lines (96 loc) · 4.36 KB

enum-val.md

File metadata and controls

175 lines (96 loc) · 4.36 KB

Ada 2020: Enumeration representation

This post is a part of the Ada 2020 series.

You can launch this notebook with Jupyter Ada Kernel by clicking this button:

Binder

Ada 2020 activation

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

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.

Literal positions

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

Representation values

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.

Before Ada 2020

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)!

References:


Do you like this? Support us on patreon!

Live discussions: Telegram, Matrix.