GNAT

Implementation of programming language Ada

GNAT is one of the most popular Ada compilers nowadays. The name is short for GNU NYU Ada compiler (the full name is not used any more). It is written in Ada itself. GNAT supports all three dialects of the language — Ada 83, Ada 95 and Ada 2005.

The first prototype of this compiler was NYU Ada/Ed translator, historically first Ada compiler written in SETL and released in 1983. The work on the modern version started in 1992, when USA Air Forces contracted New York University to build an open-source compiler for Ada to encourage work on Ada 9X standard. The contract required that all development was done under GNU GPL, and the copyright was assigned to Free Software Foundation. The first official validation of GNAT took place in 1995.

Currently the main company associated with GNAT is AdaCore, created in 1994 and merged in 2004. Nowadays it distributes two main versions of the compiler:

  • GNAT/Pro — a paid version, available for over 30 platforms and shipped with IDE, lots of development tools and support.
  • GNAT/GPL — a free version, available for only a couple of platforms for “hobbyist” use: 32bit x86 Linux glibc2.3, 32bit x86 MS-Windows 2000, XP and PowerPC & x86 Mac OS X (Panther, Tiger and Leopard).

It is licensed under GNU GPL.

GCC logo
GCC logo

Examples:

Hello, World!:

Example for versions gnat 3.4.5, gnat 4.3.2
with Ada.Text_IO; 
 
procedure HelloWorld is
begin
  Ada.Text_IO.Put_Line("Hello, World!");
end HelloWorld;

Factorial:

Example for versions gnat 3.4.5, gnat 4.3.2

This example uses recursive factorial definition.

Note that there are different packages for printing text, integers and long integers. put command generally accepts several arguments: Item is the number/string to print, Width is the number of positions to use, Fore and Aft are the numbers of decimal digits to be printed before and after decimal separator etc. If there is only one argument, it is considered to be Item. Setting Width to a number which is less than the actual length of the number prints it without leading spaces (which is the default for Ada).

Another thing to note is that Ada doesn’t support implicit data type conversions, so to calculate N*Fact(N-1) one has to convert N to Long_Long_Integer explicitly first.

with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Long_Long_Integer_Text_IO;

procedure Factorial is
begin
   declare 
      function Fact (N: Integer) return Long_Long_Integer is
      begin
         if N=0 then
            return 1;
         else 
            return Long_Long_Integer(N)*Fact(N-1);
         end if;
      end Fact;
   i: Integer := 0;
   begin
      loop
         Ada.Integer_Text_IO.Put (Item => i, Width => 1);
         Ada.Text_IO.Put ("! = ");
         Ada.Long_Long_Integer_Text_IO.Put (Item => Fact(i), Width => 1);
         Ada.Text_IO.New_Line;
         i := i + 1;
         exit when i=17;
      end loop;
   end;
end Factorial;

Fibonacci numbers:

Example for versions gnat 3.4.5, gnat 4.3.2

This example uses recursive definition of Fibonacci numbers.

with Ada.Text_IO, Ada.Integer_Text_IO;

procedure Fibonacci is
begin
   declare 
      function Fib (N: Integer) return Integer is
      begin
         if N<3 then
            return 1;
         else 
            return Fib(N-1) + Fib(N-2);
         end if;
      end Fib;
   i: Integer := 1;
   begin
      loop
         Ada.Integer_Text_IO.Put (Item => Fib(i), Width => 1);
         Ada.Text_IO.Put (", ");
         i := i + 1;
         exit when i=17;
      end loop;
      Ada.Text_IO.Put ("...");
   end;
end Fibonacci;

Quadratic equation:

Example for versions gnat 3.4.5, gnat 4.3.2

Ada provides complex datatype, which requires using packages Generic_Complex_Types and Generic_Complex_Elementary_Functions and instantiating them with the type of complex number to use (in this case — floating-point numbers). Ada doesn’t support implicit data type conversions, so all casts are done explicitly.

with Ada.Text_IO, 
     Ada.Integer_Text_IO,
     Ada.Float_Text_IO,
     Ada.Numerics.Elementary_Functions,
     Ada.Text_IO.Complex_IO, 
     Ada.Numerics.Generic_Complex_Types,
     Ada.Numerics.Generic_Complex_Elementary_Functions;
use Ada.Text_IO, Ada.Integer_Text_IO, Ada.Float_Text_IO;

procedure QuadraticEquation is
    package Complex_Types is new Ada.Numerics.Generic_Complex_Types (Float);
    package Complex_Functions is new Ada.Numerics.Generic_Complex_Elementary_Functions(Complex_Types);
    package Complex_IO is new Ada.Text_IO.Complex_IO (Complex_Types);

    use Complex_Types, Complex_Functions, Complex_IO;

    A,B,C,D: Integer;
    A2f, Bf, S: Float;
    Dc: Complex;
begin
    Put("A = ");
    Get(Item => A);
    if A = 0 then
        Put_Line("Not a quadratic equation.");
        return;
    end if;
    Put("B = ");
    Get(B);
    Put("C = ");
    Get(C);
    A2f := Float(2*A);
    Bf := Float(B);

    D := B*B-4*A*C;
    if D = 0 then
        Put("x = ");
        Put(-Bf/A2f);
    elsif D > 0 then
        S := Ada.Numerics.Elementary_Functions.Sqrt(Float(D));
        Put("x1 = ");
        Put((-Bf+S)/A2f);
        Put_Line("");
        Put("x2 = ");
        Put((-Bf-S)/A2f);
    else
        Dc := Compose_From_Cartesian (Re => Float(D), Im => 0.0);
        Put("x1 = ");
        Put((-Bf+Complex_Functions.Sqrt(Dc))/A2f);
        Put_Line("");
        Put("x2 = ");
        Put((-Bf-Complex_Functions.Sqrt(Dc))/A2f);
    end if;
end QuadraticEquation;

CamelCase:

Example for versions gnat 3.4.5, gnat 4.3.2
with Ada.Text_IO,
     Ada.Characters.Handling; 
 use Ada.Text_IO,
     Ada.Characters.Handling;

procedure CamelCase is
   Text: String(1..100);
   Length: Natural;
   Was_Space: Boolean := True;
   I: Integer := 1;
begin
   Get_Line(Text, Length);
   Text := To_Lower(Text);
   loop
      if Character'Pos(Text(I)) > 96 and Character'Pos(Text(I)) < 123 then
         if Was_Space then
            Put(To_Upper(Text(I)));
         else
            Put(Text(I));
         end if;
         Was_Space := False;
      else
         Was_Space := True;
      end if;
      I := I + 1; 
      exit when I > Length;
   end loop;
end;