Ada Addition to D Language Comparison Table

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

Out function Parameters

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.

Strong typedefs

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.

Templates

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;

foreach

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.

Static Construction Order

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.

try-catch-finally blocks

Ada does provide a block-centered exception creation and handling mechanism. It does not provide any equivalent to a finally block.

Threading Example

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;

Struct Member Alignment Control

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.

Design By Contract

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.