]]> ]]>

GNAT

Реализация языка программирования Ada

GNAT — один из самых популярных компиляторов языка Ada. Изначально его название было аббревиатурой GNU NYU Ada Translator. Фронтэнд и библиотека времени исполнения написаны на Аде. GNAT поддерживает все четыре диалекта языка — Ada 83, Ada 95, Ada 2005 и Ada 2012.

Проект был начат в 1992 году, когда ВВС США заключили контракт с университетом Нью Йорка (NYU) на создание компилятора Ады с открытыми исходниками, чтобы помочь стандартизировать Ada 9X. Контракт требовал использования GNU GPL для всех разработок и передачи копирайта Free Software Foundation. Первая официальная валидация GNAT была проведена в 1995 г. Этот компилятор основан на исторически первом компиляторе Ada (Ada/Ed translator), написанном на SETL.

В 1994 и 1996 годах создатели GNAT организовали две родственные компании, Ada Core Technologies в Нью–Йорке и ACT-Europe в Париже, с целью обеспечить продолжение разработки и коммерческую поддержку GNAT. Обе компании были объединены и переименованы в AdaCore в 2004 г.

В настоящее время существует две основные версии компилятора GNAT:

  • GNAT Pro — свободная (но не бесплатная) версия от AdaCore, доступен для 30 платформ, в комплект входит среда разработки и обширный инструментарий.
  • GNAT GPL — свободная версия, также предоставляющаяся компанией AdaCore, доступна для ограниченного количества платформ, которые считаются платформами любительской разработки: Linux (x64 и x86), Windows x86, Mac OS X (x64 и PowerPC), Raspberry Pi 2 (ARM 32-bit), Java VM, .NET, “голое железо” (ARM, AVR), LEGO Mindstorms NXT.
  • FSF GNAT — свободная версия, входящая в официальное дерево FSF GCC. Может быть установлена, например, из дистрибутива Linux, или, на Windows, из дистрибутивов Cygwin и TDM-GCC. Последний поддерживает платформу Windows x64. Патчи AdaCore попадают в FSF GCC с задержкой, а такие утилиты, как gprbuild, входящие в состав GNAT Pro и GNAT GPL, нужно устанавливать отдельно.

Версия GNAT для Java VM также известна как JGNAT, а версия GNAT для .NET известна как A# или MGNAT. Эти специальные версии не входят в ветку FSF GCC.

GNAT изначально выпускался отдельно от исходных текстов GNU Compiler Collection. 2 октября 2001 исходные тексты GNAT были отправлены в репозиторий GCC CVS. Последней версией, выпущенной отдельно, был GNAT 3.15p, на базе GCC 2.8.1, 2 октября 2002. Начиная с GCC 3.4, на основных платформах официальные выпуски GCC проходят 100% тестов Ada ACATS.

Компилятор лицензируется на условиях GNU General Public License. Библиотека времени выполнения лицензируется либо под GNU GPL (“GNAT GPL Edition” от AdaCore), либо под GNAT Modified General Public License (FSF GNAT, GNAT Pro). GNAT входит в большинство дистрибутивов GNU/Linux и BSD.

Примеры:

Hello, World!:

Пример для версий gnat 3.4.5
with Ada.Text_IO; 
 
procedure HelloWorld is
begin
  Ada.Text_IO.Put_Line("Hello, World!");
end HelloWorld;

Факториал:

Пример для версий gnat 3.4.5

В этом примере используется рекурсивное определение факториала.

Следует отметить, что для вывода на печать текста, целых и длинных целых чисел используются разные пакеты. Команда put в общем случае принимает несколько аргументов, изменяющих формат вывода: Item — это число, которое выводится на печать, Width — количество позиций, которые следует использовать при выводе, Fore и Aft — количества десятичных цифр, которые следует вывести до и после запятой и т.д. Если передается только один аргумент, он считается значением Item. Установив Width равным 1 или другому числу, меньшему, чем количество цифр в выводимом числе, можно вывести его без пробелов в начале (что является умолчательным способом для языка Ada).

Кроме того, отметим, что Ada не поддерживает неявные преобразования типов, так что для вычисления N*Fact(N-1) сначала следует явно преобразовать N к типу Long_Long_Integer.

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;

Числа Фибоначчи:

Пример для версий gnat 3.4.5

В этом примере используется рекурсивное определение чисел Фибоначчи.

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;

Квадратное уравнение:

Пример для версий gnat 3.4.5

Ada предоставляет тип данных для работы с комплексными числами, который требует использования пакетов Generic_Complex_Types и Generic_Complex_Elementary_Functions с предварительной инициализацией их типом данных для хранения комплексных чисел (в данном случае — Float). Ada не поддерживает неявные преобразования типов, поэтому все преобразования выполняются в явном виде.

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:

Пример для версий gnat 3.4.5
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;

Комментарии

]]>

blog comments powered by Disqus

]]>

Работа программистам