| Feature | Ada |
| Garbage Collection | No |
| Functions | |
| Function Delegates | No |
| Function Overloading | Yes |
| Out function parameters | Yes* |
| Nested functions | Yes |
| Function literals | No |
| Dynamic closures | Yes |
| Arrays | |
| Lightweight arrays | No |
| Resizable arrays | No |
| Arrays of bits | Yes |
| Built-in strings | Yes |
| Array slicing | Yes |
| Array bounds checking | Yes |
| Associative arrays | No |
| Strong typedefs | Yes* |
| String switches | No |
| Aliases | Yes |
| OOP | |
| Object Oriented | Yes |
| Multiple inheritance | No |
| Interfaces | Yes |
| Operator Overloading | Yes |
| Modules | Yes |
| Dynamic class loading | No |
| Inner classes | Yes |
| Covariant return types | Yes |
| Properties | No |
| Performance | |
| Inline assembler | Yes |
| Direct access to hardware | Yes |
| Lightweight objects | Yes |
| Explicit memory allocation control | Yes |
| Independent of VM | Yes |
| Direct native code gen | Yes |
| Generic Programming | |
| Templates | Yes* |
| typeof | No |
| foreach | Yes* |
| Generic formal subprogram parameters | Yes |
| Generic formal package parameters | Yes |
| Generic formal discrete type parameters | Yes |
| Generic formal floating-point type parameters | Yes |
| Generic formal enumeration type parameters | Yes |
| Generic formal array type parameters | Yes |
| Generic formal modular integer type parameters | Yes |
| Generic formal fixed point type parameters | Yes |
| Generic formal access type parameters | Yes |
| Reliablity | |
| Design by contract | No* |
| Unit testing | No |
| Static construction order | Yes* |
| Guaranteed initialization | No |
| RAII | Yes |
| Exception handling | Yes |
| Try-catch-finally blocks | No* |
| Thread Primitives | |
| Task creation primitives | Yes |
| Direct synchronized task communication primitives | Yes |
| Asynchronous data access primitives | Yes |
| Integration of tasking with interrupts | Yes |
| Asynchronous transfer of control | Yes |
| Per-task control of blocking during calls to synchronized blocks | Yes |
| Compatibility | |
| C-stype syntax | No |
| Enumerated types | Yes |
| Support all C types | Yes |
| 80 bit floating point | Yes |
| Complex and Imaginary | Yes |
| Direct access to C | Yes |
| Direct accesss to Fortran | Yes |
| Direct access to Cobol | Yes |
| Use existing debuggers | Yes |
| Struct member alignment control | Yes* |
| Generates standard object files | Yes |
| Macro text preprocessor | No |
| Other | |
| Conditional compilation | No |
| Unicode source text | Yes |
Ada provides two kinds of subprograms; procedures and functions. Procedure parameters may have the modes IN, OUT, or IN OUT. Procedures have no return type, similar to D, C, C++, and Java functions returning void. Function parameters may only have the mode IN. You may, however, pass an access value (similar to a reference) to an Ada function. Functions always have a non-void return type. Function return values cannot be ignored.
Ada is a very strongly typed language. Ada provides a distinction between type definitions and subtype definitions. For example, Ada provides a pre-defined integer type called integer. You may create another integer type as follows:
type Beauty_Scale is range 1..10;
There is no implicit conversion between a value of type Beauty_Scale and any other type in Ada.
You may also declare a subtype:
subtype Column_Count is Integer range
0..79;
Since Column_Count is a subtype of Integer, any instance of Column_Count is also an instance of Integer and can be used wherever an Integer is expected.
Ada provides generic programming capabilties, but there is no template reserved word. Ada uses the reserved word generic instead. You can define generic packages or generic subprograms (functions or procedures). A generic package would be used to create a generic ADT such as a linked list. A generic subprogram would be used for simpler algorithmic programming, such as defining a swap procedure.
generic Item_Type is private; procedure Swap(Left, Right : in out Item_Type); procedure Swap(Left, Rigth : in out Item_Type) is Temp : Item_Type := Left; begin Left := Right; Right := Temp; end Swap;
The Ada for loop always iterates through a discrete range of values. The range of values can either be explicitly stated, or it can be an expression evaluated from type attributes including 'First, 'Last, and 'Range.
type Vector is array (Natural range <>) of Float; -- An unbounded array type definition function Total (Item : Vector) return Float is Sum : Float := 0.0; begin for I in Item'Range loop Sum := Sum + Item(I); end loop; return Sum; end Total;
The above example will work with any size instance of type Vector, including a slice of a Vector instance.
Ada does not have constructors. Ada does have an elaboration phase prior to its normal execution phase. Elaboration order is controllable by the programmer. Variable, module and constant initialization are performed during the elaboration phase.
Ada does provide a block-centered exception creation and handling mechanism. It does not provide any equivalent to a finally block.
The following example demonstrates a simple producer-consumer program using many of the Ada threading features.
--------------------------------------------------------------------- -- Prodcon --------------------------------------------------------------------- with Ada.Text_Io; use Ada.Text_Io with Ada.Integer_Text_Io; use Ada.Integer_Text_Io; with Ada.Command_Line; use Ada.Command_Line; with Ada.Calendar; use Ada.Calendar; procedure Prodcon is protected Buffer is entry Put(Item : in Integer); entry Get(Item : out Integer); private Buf : Natural; Is_Valid : Boolean := False; end Buffer; protected body Buffer is entry Put(Item : in Integer) when not Is_Valid is begin Buf := Item; Is_Valid := True; end Put; entry Get(Item : out Integer) when Is_Valid is Item := Buf; Is_Valid := False; end Get; end Buffer; Prod_Count : Natural := 0; pragma Atomic (Prod_Count); Cons_Count : Natural := 0; pragma Atomic(Cons_Count); End_Of_Data : constant Integer := Integer'First; task Producer is entry Start(Num : in Positive); end Producer; task Consumer is entry Stop; end Consumer; task body Producer is Iterations : Positive; begin accept Sart(Num : in Positive) do Iterations := Num; end Start; for I in 1..Iterations loop Buffer.Put(I); Prod_Count := Prod_Count + 1; end loop; Buffer.Put(End_Of_Data); end Producer; task body Consumer is Value : Integer; begin loop Buffer.Get(Value); exit when Value = End_Of_Data; Cons_Count := Cons_Count + 1; end loop; accept Stop; end Consumer; Num : Positive; Start : Time := Clock; Done : Time; begin --prodcon begin -- Anonymous block for exception handling Num := Positive'Value(Argument(1)); exception when others => Num := 1; end; Producer.Start(Num); Consumer.Stop; Done := clock; Put(Item => Prod_Count, Width => 8); Put(Item => Cons_Count, Width => 8); New_Line; Put_Line("Elapsed time: " & Duration'Image(Done - Start) & " seconds."); end prodcon;
The Ada equivalent of a C, or D struct is a record. The
following example of specifying a record layout is extracted from
the Ada Language Reference Manual.
Example of specifying the layout of a record type: Word : constant := 4; -- storage element is byte, 4 bytes per word
type State is (A,M,W,P);
type Mode is (Fix, Dec, Exp, Signif);
type Byte_Mask is array (0..7) of Boolean;
type State_Mask is array (State) of Boolean;
type Mode_Mask is array (Mode) of Boolean;
type Program_Status_Word is
record
System_Mask : Byte_Mask;
Protection_Key : Integer range 0 .. 3;
Machine_State : State_Mask;
Interrupt_Cause : Interruption_Code;
Ilc : Integer range 0 .. 3;
Cc : Integer range 0 .. 3;
Program_Mask : Mode_Mask;
Inst_Address : Address;
end record;
for Program_Status_Word use
record
System_Mask at 0*Word range 0 .. 7;
Protection_Key at 0*Word range 10 .. 11; -- bits 8,9 unused
Machine_State at 0*Word range 12 .. 15;
Interrupt_Cause at 0*Word range 16 .. 31;
Ilc at 1*Word range 0 .. 1; -- second word
Cc at 1*Word range 2 .. 3;
Program_Mask at 1*Word range 4 .. 7;
Inst_Address at 1*Word range 8 .. 31;
end record;
for Program_Status_Word'Size use 8*System.Storage_Unit; for Program_Status_Word'Alignment use 8;
Note on the example: The record_representation_clause defines the record layout. The Size clause guarantees
that (at least) eight storage elements are used for objects of
the type. The Alignment clause guarantees that aliased, imported,
or exported objects of the type will have addresses divisible by
eight.
Ada does not provide full design by contract including
pre-conditions, post-conditions, and invariants. Ada does provide
some aspects of design by contract through its strong typing
coupled with the ability to define scalar types with a specific
range of values. This capability provides partial pre-condition
and post-condition capability.
type Voltage is digits 15 range -5.0..5.0; -- A floating point number with 15 decimal digits -- of precision and a limited range of values type Voltage_Sample is array(Natural range <>) of Voltage; -- An unconstrained array of Voltage function Mean(Item : Voltage_Sample) return Voltage is Sum : Long_Float := 0.0; Num_Values : Long_Float := 1.0; begin for I in Item'Range loop Sum := Sum + Long_Float(Item(I)); end loop; if Item'Length > 0 then Num_Values := Long_Float(Item'Length); end if; return Voltage(Sum / Num_Values); end Mean;
All elements of an instance of Voltage_Sample must satisfy the
range requirements of type Voltage. Similarly, the return value
from function Mean will always satisfy the range requirements of
type Voltage.