Skip to content

Commit eb012a8

Browse files
authored
Merge pull request #1210 from gusthoff/content/advanced_ada/new_content/types/universal_and_root_types/20250413
Adding section on universal and root types
2 parents d23d6cd + 4f397fb commit eb012a8

File tree

1 file changed

+187
-3
lines changed
  • content/courses/advanced-ada/parts/data_types

1 file changed

+187
-3
lines changed

content/courses/advanced-ada/parts/data_types/types.rst

Lines changed: 187 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ view because it's a private type. Finally, as expected, :ada:`Settings` has a
530530
variable view because it's a variable object.
531531

532532

533+
.. _Adv_Ada_Named_Numbers:
534+
533535
Named numbers
534536
~~~~~~~~~~~~~
535537

@@ -557,18 +559,21 @@ A named number is always known at compilation time. Also, it doesn't have a
557559
type associated with it. In fact, its type is called universal real or
558560
universal integer |mdash| depending on the number being a real or integer
559561
number. (In this specific case, :ada:`Pi` is a universal real number.) We talk
560-
about universal real and universal integer types in another chapter.
562+
about :ref:`universal types <Adv_Ada_Universal_Types>` later on in this
563+
chapter.
561564

562565
.. todo::
563566

564-
Add link to section on universal real and universal integer types
565-
(Adv_Ada_Universal_Real_Integer) once it's available.
567+
Add link to section on universal real, integer and fixed types
568+
(Adv_Ada_Universal_Real_Integer_Fixed) once it's available.
566569

567570
.. admonition:: In the Ada Reference Manual
568571

569572
- :arm22:`3.3.2 Number Declarations <3-3-2>`
570573

571574

575+
.. _Adv_Ada_Scalar_Types:
576+
572577
Scalar Types
573578
------------
574579

@@ -1483,6 +1488,185 @@ representation clause. We discuss this topic
14831488
:ref:`in another section <Adv_Ada_Enumeration_Representation_Clauses>`.
14841489

14851490

1491+
.. _Adv_Ada_Universal_And_Root_Types:
1492+
1493+
Universal and Root Types
1494+
------------------------
1495+
1496+
Previously, in the section about :ref:`scalar types <Adv_Ada_Scalar_Types>`,
1497+
we said that scalar types are the most basic types that we can get. However,
1498+
Ada has the concept of universal and root types, which could be
1499+
considered *more basic* than scalar types. In fact, universal and root types
1500+
are underlying scalar types used by the language designers to define the
1501+
language semantics. In this section, we briefly introduce this topic.
1502+
1503+
.. _Adv_Ada_Universal_Types:
1504+
1505+
Universal Types
1506+
~~~~~~~~~~~~~~~
1507+
1508+
The Ada standard defines four universal types:
1509+
1510+
#. universal integer types
1511+
1512+
#. universal real types
1513+
1514+
#. universal fixed types
1515+
1516+
#. universal access types
1517+
1518+
The first three are numeric types, and we discuss them in detail later on
1519+
in another chapter. The last one
1520+
is used for :ref:`anonymous access types <Adv_Ada_Anonymous_Access_Types>`.
1521+
1522+
.. todo::
1523+
1524+
Add link to section on universal real, integer and fixed types
1525+
(Adv_Ada_Universal_Real_Integer_Fixed) once it's available.
1526+
1527+
.. todo::
1528+
1529+
Add link to section on universal access types once it's available.
1530+
1531+
Universal types aren't types we can use directly, but rather via specific
1532+
languages constructs. In this sense, we cannot derive from universal types, but
1533+
only make use of them indirectly.
1534+
1535+
For instance, if we declare :ref:`named numbers <Adv_Ada_Named_Numbers>` using
1536+
a real value, we're indirectly using a universal real type. If we declare
1537+
another named number using an expression, the computation is performed based on
1538+
the universal types of the elements of that expression:
1539+
1540+
.. code:: ada compile_button project=Courses.Advanced_Ada.Data_Types.Types.Universal_And_Root_Types.Universal_Real_Integer
1541+
1542+
package Show_Universal_Real_Integer is
1543+
1544+
Pi : constant := 3.1415926535;
1545+
-- ^^^^^^^^^^^^
1546+
-- universal real type
1547+
1548+
Two_Pi : constant := Pi * 2.0;
1549+
-- ^^^^^^^^
1550+
-- operation on
1551+
-- universal real type
1552+
1553+
N : constant := 10;
1554+
-- ^^
1555+
-- universal integer type
1556+
1557+
N_10 : constant := N * 10;
1558+
-- ^^^^^^
1559+
-- operation on
1560+
-- universal integer type
1561+
1562+
end Show_Universal_Real_Integer;
1563+
1564+
In this example, the expression :ada:`Pi * 2.0` is computed using universal
1565+
real types, while the expression :ada:`N * 10` is computed using universal
1566+
integer types.
1567+
1568+
Similarly, for anonymous access types, the equality operator uses universal
1569+
access types for the comparison:
1570+
1571+
.. code:: ada run_button project=Courses.Advanced_Ada.Data_Types.Types.Universal_And_Root_Types.Universal_Access
1572+
1573+
with Ada.Text_IO; use Ada.Text_IO;
1574+
1575+
procedure Show_Universal_Access is
1576+
I : aliased Integer;
1577+
A : access Integer := I'Access;
1578+
B : access Integer := I'Access;
1579+
begin
1580+
if A = B then
1581+
Put_Line ("A = B");
1582+
else
1583+
Put_Line ("A /= B");
1584+
end if;
1585+
end Show_Universal_Access;
1586+
1587+
In this example, both :ada:`A` and :ada:`B` are variables of anonymous access
1588+
types. Because the type isn't a known named type, the equality operation
1589+
:ada:`=` uses the universal access type for the comparison.
1590+
1591+
.. admonition:: In the Ada Reference Manual
1592+
1593+
- :arm22:`3.3.2 Number Declarations <3-3-2>`
1594+
- :arm22:`4.5.2 Relational Operators and Membership Tests <4-5-2>`
1595+
1596+
1597+
.. _Adv_Ada_Root_Types:
1598+
1599+
Root Types
1600+
~~~~~~~~~~
1601+
1602+
The root types can be found on a level above the universal types. In this
1603+
category, we can find the same numeric types that we have for universal types,
1604+
namely the root real, root integer and root fixed types.
1605+
1606+
The term *root* is used in the context of type derivation. In fact, the root
1607+
type is the first type that we derive all other types from. In other words, if
1608+
we declare an integer range as a new type, that type is derived from the root
1609+
integer type. Similarly, if we declare a new floating-point type, that type is
1610+
derived from the root real type. For example:
1611+
1612+
.. code:: ada compile_button project=Courses.Advanced_Ada.Data_Types.Types.Universal_And_Root_Types.Root_Integer_Real
1613+
1614+
package Show_Root_Integer_Real is
1615+
1616+
type Score is range 0 .. 10;
1617+
-- Type Score is derived from
1618+
-- the root integer type.
1619+
1620+
type Real_Score is
1621+
digits 10 range 0.0 .. 10.0;
1622+
-- Type Real_Score is derived from
1623+
-- the root real type.
1624+
1625+
end Show_Root_Integer_Real;
1626+
1627+
Here, :ada:`Score` and :ada:`Real_Score` are derived from the root integer and
1628+
real types, respectively. Note that the derivation is always implicit, as we
1629+
cannot write something like
1630+
:ada:`type Score is new Root_Integer range 0 .. 10` or
1631+
:ada:`type Real_Score is new Root_Real digits 10 range 0.0 .. 10.0`.
1632+
1633+
In contrast, if we derive from an existing floating-point or integer type
1634+
defined by the Ada standard, we're not deriving directly from the root types:
1635+
1636+
.. code:: ada compile_button project=Courses.Advanced_Ada.Data_Types.Types.Universal_And_Root_Types.Standard_Integer_Float_Derivation
1637+
1638+
package Show_Standard_Derivation is
1639+
1640+
type Score is new Integer
1641+
range 0 .. 10;
1642+
-- Type Score is derived from
1643+
-- the Integer type.
1644+
1645+
type Real_Score is new Float
1646+
range 0.0 .. 10.0;
1647+
-- Type Real_Score is derived from
1648+
-- the Float type.
1649+
1650+
end Show_Standard_Derivation;
1651+
1652+
In this case, we're explicitly deriving from the standard Ada types
1653+
:ada:`Integer` and :ada:`Float`, which, on their turn, are derived from the
1654+
root integer and root real types, respectively.
1655+
1656+
.. admonition:: For further reading...
1657+
1658+
You might remember our discussion about the
1659+
:ref:`Base attribute <Adv_Ada_Base_Attribute>` and the fact that it
1660+
indicates the underlying subtype of a type. We said, for example, that
1661+
:ada:`Integer'Base` gives us the base type of :ada:`Integer`, i.e. the
1662+
the underlying hardware type representing the :ada:`Integer` type.
1663+
1664+
Although the concept of the base type *sounds* similar to the concept of
1665+
the root type, the focus of each one is different: while the base type
1666+
refers to the constraints of a type, the root type refers to the derivation
1667+
tree of a type.
1668+
1669+
14861670
.. _Adv_Ada_Definite_Indefinite_Subtypes:
14871671

14881672
Definite and Indefinite Subtypes

0 commit comments

Comments
 (0)