Ada: Difference between revisions

Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content deleted Content added
No edit summary
m Bot: Replace deprecated source tag with syntaxhighlight
Line 11: Line 11:
In addition to being a strongly typed language, Ada allows for the definition of new scalar, enumerated and record types. Custom primitive types can also be constrained to a predefined range of values. The example below demonstrates the definition of a new integer type based upon Ada's native <tt>Natural</tt> type, restricted to a predefined range. The use of the <tt>subtype</tt> directive informs the compiler that other variables of the <tt>Natural</tt> type are compatible with the newly defined subtype.
In addition to being a strongly typed language, Ada allows for the definition of new scalar, enumerated and record types. Custom primitive types can also be constrained to a predefined range of values. The example below demonstrates the definition of a new integer type based upon Ada's native <tt>Natural</tt> type, restricted to a predefined range. The use of the <tt>subtype</tt> directive informs the compiler that other variables of the <tt>Natural</tt> type are compatible with the newly defined subtype.


<source lang="ada">
<syntaxhighlight lang="ada">
VGA_COL_COUNT : constant := 80;
VGA_COL_COUNT : constant := 80;
VGA_ROW_COUNT : constant := 24;
VGA_ROW_COUNT : constant := 24;
Line 17: Line 17:
subtype Col is Natural range 0 .. VGA_COL_COUNT - 1;
subtype Col is Natural range 0 .. VGA_COL_COUNT - 1;
subtype Row is Natural range 0 .. VGA_ROW_COUNT - 1;
subtype Row is Natural range 0 .. VGA_ROW_COUNT - 1;
</syntaxhighlight>
</source>


The below example illustrates the creation of incompatible custom integer types. While their base type and range constraints are identical, Ada treats both as separate, incompatible types. An assignment of a variable of one type to the value of another is illegal, and will trigger a compile-time error.
The below example illustrates the creation of incompatible custom integer types. While their base type and range constraints are identical, Ada treats both as separate, incompatible types. An assignment of a variable of one type to the value of another is illegal, and will trigger a compile-time error.
<source lang="ada">
<syntaxhighlight lang="ada">
type Integer_1 is range 1 .. 10;
type Integer_1 is range 1 .. 10;
type Integer_2 is range 1 .. 10;
type Integer_2 is range 1 .. 10;
A : Integer_1 := 8;
A : Integer_1 := 8;
B : Integer_2 := A; -- illegal!
B : Integer_2 := A; -- illegal!
</syntaxhighlight>
</source>


The following example demonstrates the creation of a custom enumerated type. It also demonstrates a subtype of an enumerated type with a constrained range of values.
The following example demonstrates the creation of a custom enumerated type. It also demonstrates a subtype of an enumerated type with a constrained range of values.


<source lang="ada">
<syntaxhighlight lang="ada">
type Day_Of_Week is (Monday, Tuesday,
type Day_Of_Week is (Monday, Tuesday,
Wednesday, Thursday, Friday, Saturday, Sunday);
Wednesday, Thursday, Friday, Saturday, Sunday);


subtype Work_Day is Day_Of_Week range Monday .. Friday;
subtype Work_Day is Day_Of_Week range Monday .. Friday;
</syntaxhighlight>
</source>


A variable with the type of <tt>Work_Day</tt> is restricted to its constrained range. Any attempt to assign a value outside of this range to a variable of this type will raise a <tt>Constraint_Error</tt> exception at runtime.
A variable with the type of <tt>Work_Day</tt> is restricted to its constrained range. Any attempt to assign a value outside of this range to a variable of this type will raise a <tt>Constraint_Error</tt> exception at runtime.
Line 43: Line 43:
Ada allows for explicitly defining the in-memory representation of scalar and compound types. The following example demonstrates the definition of a record type (equivalent to structures in C), as well as its associated representation in memory.
Ada allows for explicitly defining the in-memory representation of scalar and compound types. The following example demonstrates the definition of a record type (equivalent to structures in C), as well as its associated representation in memory.


<source lang="ada">
<syntaxhighlight lang="ada">
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- The format of the System Table Descriptor pointer used by the processor
-- The format of the System Table Descriptor pointer used by the processor
Line 59: Line 59:
Offset at 0 range 16 .. 47;
Offset at 0 range 16 .. 47;
end record;
end record;
</syntaxhighlight>
</source>


The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>System_Table_Descriptor</tt> type must be 48 bits in size. The ''record representation clause'' instructs the compiler as to the required layout of this record type in memory. This example specifies that the <tt>Size</tt> member should occupy bits 0 to 15, and the <tt>Offset</tt> member should occupy bits 16 to 47. This feature is analogous to C's bit-fields.
The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>System_Table_Descriptor</tt> type must be 48 bits in size. The ''record representation clause'' instructs the compiler as to the required layout of this record type in memory. This example specifies that the <tt>Size</tt> member should occupy bits 0 to 15, and the <tt>Offset</tt> member should occupy bits 16 to 47. This feature is analogous to C's bit-fields.
Line 65: Line 65:
The following example demonstrates defining the in-memory representation of an enumerated type.
The following example demonstrates defining the in-memory representation of an enumerated type.


<source lang="ada">
<syntaxhighlight lang="ada">
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- The privilege level for a particular descriptor.
-- The privilege level for a particular descriptor.
Line 84: Line 84:
Ring_3 => 3
Ring_3 => 3
);
);
</syntaxhighlight>
</source>


The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>Descriptor_Privilege_Level</tt> type must be 2 bits in size. The ''representation clause'' instructs the compiler as to required representation of each possible value of the enumerated type in memory. In this example the value of <tt>Ring_0</tt> will be represented by a value of <tt>0x0</tt> in memory, the value of <tt>Ring_1</tt> will be represented by <tt>0x1</tt>, and so on.
The <tt>Size</tt> ''aspect specifier'' instructs the compiler that the <tt>Descriptor_Privilege_Level</tt> type must be 2 bits in size. The ''representation clause'' instructs the compiler as to required representation of each possible value of the enumerated type in memory. In this example the value of <tt>Ring_0</tt> will be represented by a value of <tt>0x0</tt> in memory, the value of <tt>Ring_1</tt> will be represented by <tt>0x1</tt>, and so on.
Line 91: Line 91:
The following example, and accompanying comparison with C, demonstrates the configuration of a hypothetical [[UART]] device by interfacing with an 8-bit memory-mapped configuration register. This example has been adapted from a presentation by AdaCore viewable at: https://www.youtube.com/watch?v=qvmDqbuQe-M
The following example, and accompanying comparison with C, demonstrates the configuration of a hypothetical [[UART]] device by interfacing with an 8-bit memory-mapped configuration register. This example has been adapted from a presentation by AdaCore viewable at: https://www.youtube.com/watch?v=qvmDqbuQe-M


<source lang="ada">
<syntaxhighlight lang="ada">
with System.Storage_Elements; use System.Storage_Elements;
with System.Storage_Elements; use System.Storage_Elements;


Line 158: Line 158:
end Main;
end Main;


</syntaxhighlight>
</source>


Contrast this with the same functionality implemented in C. Despite being shorter in length, the register cannot be altered without using bitwise operators to manipulate the individual fields. This approach is generally considered more error-prone than using a record in Ada overlaid at the register's memory-mapped address. It is possible to define a <tt>struct</tt> type in C with bit-fields for the individual elements, however the C standard does not guarantee the layout and order of the individual fields (refer to section 6.7.2.1 paragraph 11 of the C1X standard).
Contrast this with the same functionality implemented in C. Despite being shorter in length, the register cannot be altered without using bitwise operators to manipulate the individual fields. This approach is generally considered more error-prone than using a record in Ada overlaid at the register's memory-mapped address. It is possible to define a <tt>struct</tt> type in C with bit-fields for the individual elements, however the C standard does not guarantee the layout and order of the individual fields (refer to section 6.7.2.1 paragraph 11 of the C1X standard).