Что нового в Аде 202х

wiki:/graphics/ada_202x.jpg

Стандарт языка Ада 2012 был опубликован, как официальный документ ISO/IEC 8652:2012, в декабре 2012 года. В феврале 2016 был опубликован стандарт с техническими правками ISO/IEC 8652:2012/Cor 1:2016. Этот последний документ и определяет действующий стандарт языка Ада.

С момента публикации началась работа над следующей версией языка. Будущий стандарт условно называется Ada 202x. Окончательное название и дата публикации пока не известны.

Черновик стандарта можно посмотреть на сайте ada-auth.org. А подробную информацию о ходе разработки новой версии можно почерпнуть на странице Ada Rapporteur Group. Там же можно найти подробности по каждому отдельному рассмотренному вопросу AI12-XXXX-X.

Что же будет в новом стандарте Ады? Вот, с моей точки зрения, наиболее интересные нововведения.

Числовые и строковые литералы для пользовательских типов

AI12-0249-1 AI12-0295-1

Новый аспект позволяет пользователю указать функцию преобразования числового литерала в данный тип. Это позволяет избежать явного вызова этой функции, например:

type Big_Integer is private
  with Integer_Literal => Big_Integer_Value;

function Big_Integer_Value (S : String)
  return Big_Integer;

...

Y : Big_Integer := -3;
--  Что эквивалентно записи:
--    Y : Big_Integer := - Big_Integer_Value ("3");

Аналогично аспект Real_Literal используется для дробных литералов, а String_Literal для строковых.

Итеративные ассоциации в агрегатах массивов

AI12-0061-1

Теперь можно будет писать так

 G : constant Matrix :=
    (for I in 1 .. 4 =>
       (for J in 1 .. 4 =>
          (if I = J then 1.0 else 0.0)));

Агрегаты контейнеров

Появилась возможность инициализировать контейнеры с помощью агрегатов специального вида. Поддерживаются почти все стандартные контейнеры (кроме Multiway_Trees) и определенные пользователем контейнеры, для которых указаны специальные аспекты. Для записи агрегата используются квадратные скобки:

X : My_Set := [1, 2, 3];

Что равнозначно:

X : My_Set := Empty_Set;
Include (X, 1);
Include (X, 2);
Include (X, 3);

Соответственно, если вы определяете собственный контейнер, вы можете указать какими операциями его инициализировать:

type Set_Type is private
  with Aggregate => (Empty       => Empty_Set,
                     Add_Unnamed => Include);

function Empty_Set return Set_Type;

procedure Include (S : in out Set_Type; N : Element);

Для контейнеров типа ключ‐значение используется агрегат с именованным сопоставлением:

M := [12 => "house", 14 => "beige"];

Внутри контейнеров можно использовать итераторы. Есть также сокращенная форма, когда не нужно отдельно записывать значение ключа, например:

M := [for Key of Keys use Key => Integer'Image (Key)];
--  сокращенная форма:
M := [for Key of Keys => Integer'Image (Key)];

Агрегат с квадратными скобками можно использовать и для массивов. Им проще записывать массивы без элементов и с одним элементом, т.к. нет необходимости указывать индекс:

Keys : constant array (Positive range <>) of Integer := [2, 3, 5, 7];
K1   : constant array (Positive range <>) of Integer := [2];
K0   : constant array (Positive range <>) of Integer := [];
--  Для Ады 2012:
K1   : constant array (Positive range <>) of Integer := (1 => 2);
K0   : constant array (Positive range <>) of Integer := (1 .. 0 => <>);

Параллельные циклы и блоки

AI12-0119-1 AI12-0251-1

Вводится новое ключевое слово parallel. Оно используется в написании двух новых операторов.

Параллельный блок:

procedure Traverse (T : Expr_Ptr) is
begin
  if T /= null
    and then
     T.all in Binary_Operation'Class -- see 3.9.1
  then -- recurse down the binary tree
    parallel do
      Traverse (T.Left);
    and
      Traverse (T.Right);
    and
      Ada.Text_IO.Put_Line
        ("Processing " & Ada.Tags.Expanded_Name (T'Tag));
    end do;
  end if;
end Traverse;

Параллельный цикл:

parallel for I in Grid'Range(1) loop
   Grid(I, 1) := (for all J in Grid'Range(2) => Grid(I,J) = True);
end loop;

Для параллельного цикла можно задать количество параллельно исполняемых отрезков указав его как выражение либо как спецификацию индекса:

parallel (Num_CPUs) for I in Arr'Range loop
   A(I) := B(I) + C(I);
end loop;

declare
   Partial_Sum : array (1 .. Num_CPUs) of Integer := (others => 0);
begin
   parallel (Chunk in Partial_Sum'Range) for I in Arr'Range loop
      --  Какие-то сложные манипуляции
      Partial_Sum (Chunk) := @ + some_complicated_computation;
   end loop;

   Sum := Partial_Sum'Reduce ("+", 0);
end;

Плюха @

AI12-0125-3

Вводится сокращение в операторах присваивания для обозначение левой части.

Board (1, 1) := @ + 1;  -- An abbreviation for
Board (1, 1) := Board (1, 1) + 1;

Дельта агрегат

AI12-0127-1

Новая форма агрегата для замены части компонент новыми значениями. Удобно использовать с постусловиями:

  procedure The_Answer (V : in out Vector; A, B : in Integer)
     with Post => V = (V'Old with delta A .. B => 42.0, V'First => 0.0);

Процедурные итераторы

AI12-0189-1

Вводится новый способ итерации по контейнеру. Контейнер определяет процедуру итерации принимающую на вход указатель на подпрограмму. Эта подпрограмма затем вызывается для нужных элементов контейнера. Чтобы упростить использование, вводится новый вид циклов. Тело такого цикла компилятор преобразует в анонимную подпрограмму и передаёт ссылку на неё в итератор.

   package Maps is
     ...
     procedure Iterate
      (Container : in Map;
       Process   : not null access procedure
                     (Key : in Key_Type; Element : in Element_Type));

   end Maps

   My_Map : Maps.Map;

   for (Key, Value) of My_Map.Iterate loop
      Put_Line (Key_Type'Image (Key) & " => " &
         Element_Type'Image (Value));
   end loop;

Анонимные функции

AI12-0190-1

Теперь можно создавать функции прямо в точке, где они необходимы. Анонимными могут быть только функции из одного выражения. Тип параметров можно не указывать, если они понятны компилятору из контекста.

    --  Замена управляющих символов на '?'
    Ada.Strings.Fixed.Translate
      (Str, (function (C) return (if C < ' ' then '?' else C)));

Упрощённое переименование объектов

AI12-0275-1

При переименовании объекта можно опустить тип, так как он известен и так.

declare
   X renames Get_My_Position.X;

Аспект Nonblocking

AI12-0064-2

На этапе описания подпрограммы можно указать, что она не содержит блокирующих операций. Работает и на уровне пакетов:

package Ada.Calendar with Nonblocking is
  type Time is private;

Контракты для параметров настраиваемых модулей

AI12-0272-1

Для подпрограмм параметров настройки можно задавать пре/пост условия, а для типов — аспект Default_Initial_Condition.

generic
   type Element is private
      with Default_Initial_Condition => Is_Empty (Element);

   with function Is_Empty (Value : Element) return Boolean;

   with function Hash (Value : Element) return Hash_Type
      with Post => Hash'Result in 0 .. 99;
package Maps is

Прочее

Множество вопросов носит технический либо узкоспециализированный характер. Для полноты приведу здесь лишь список таких изменений.

  • AI12-0002-1 Для Remote_Control_Interface типов нельзя определять свои процедуры чтения из потока и записи в поток.
  • AI12-0004-1 Ограничения на Unicode форму представления исходного кода.
  • AI12-0020-1 T'Image для всех типов с возможностью переопределения.
  • AI12-0021-1 Wide_String при именах файлов, директорий, командной строке и пр.
  • AI12-0058-1 Обновление интерфейса с Фортраном
  • AI12-0059-1 Новый атрибут S'Object_Size
  • AI12-0075-1 Новый аспект Static для функций‐выражений.
  • AI12-0079-1 Аспекты описания побочный эффектов подпрограмм.
  • AI12-0086-1 Ослабили ограничение на дискриминант в агрегатах
  • AI12-0111-1 Неизменяемый вид для контейнеров позволяет выполнять чтение из разных потоков и ускоряет итерацию.
  • AI12-0112-1 Для описания контейнеров использовали контракты. Добавили возможность отключить их проверку.
  • AI12-0128-1 Атомарность доступа к полям записи
  • AI12-0140-1 Уточнения об ограничениях на type-view
  • AI12-0143-1 Индекс входа в пре/пост‐условиях
  • AI12-0144-1 Упрощение использования функции Random
  • AI12-0155-1 О правилах заморозки неполных описаний типов
  • AI12-0156-1 Разрешили анонимные ссылочные типы в итераторах
  • AI12-0160-1 Исправили правила для аспектов индексирования контейнеров
  • AI12-0162-1 Переписали правила Unchecked_Unions
  • AI12-0163-1 Новая политика Ordered_FIFO_Queuing
  • AI12-0164-1 Новый аспект Max_Entry_Queue_Length для входов
  • AI12-0165-1 Исправили правила для формальных подпрограмм и типов
  • AI12-0166-1 Исправили правила для предусловий и параметров по умолчанию в защищённых типах
  • AI12-0167-1 Про дырки в инвариантах типов
  • AI12-0168-1 Про заморозку в теле настраиваемого модуля
  • AI12-0169-1 Добавили аспекты для тела входа
  • AI12-0170-1 Абстрактные функции в предусловиях надклассовых операций
  • AI12-0171-1 Про семантику Synchronous_Task_Control
  • AI12-0172-1 Разрешили выражения возбуждения исключений для limitied
  • AI12-0173-1 Переформулировали правила расширенного оператора возврата
  • AI12-0174-1 Переформулировали правила Unchecked_Unions агрегатов
  • AI12-0175-1 Упростили задание адресов в 'Address
  • AI12-0178-1 Поправили ошибки в примерах
  • AI12-0179-1 О постусловиях в стандартных пакетах
  • AI12-0180-1 О использовании входов в инвариантах
  • AI12-0181-1 О влиянии аспектов на заморозку
  • AI12-0182-1 О защищённых операциях в предусловиях
  • AI12-0183-1 Редакционные правки
  • AI12-0184-1 Новые long типы в Interfaces.C
  • AI12-0185-1 Переформулировали правила для F'Result
  • AI12-0186-1 О заморозке профиля атрибутом S'Access
  • AI12-0187-1 Новый аспект Stable_Properties
  • AI12-0192-1 О инициализации защищённых типов
  • AI12-0193-1 О срабатывании постусловий на задачных входах
  • AI12-0194-1 О аспектах языка для тела входа
  • AI12-0195-1 О наследуемых подпрограммах и пре/пост‐условиях
  • AI12-0196-1 Разрешили непересекающийся доступ к элементам контейнера из нескольких задач одновременно
  • AI12-0198-1 Поправили правила постусловий
  • AI12-0199-1 Поправили правила о надклассовых инвариантах
  • AI12-0200-1 Поправили правила о одновременном вызове стандартных подпрограмм
  • AI12-0201-1 Отнесли операции со строками к статическим операциям
  • AI12-0203-1 О переопределении аспектов
  • AI12-0204-1 О префиксных видах
  • AI12-0206-1 О переопределении аспектов
  • AI12-0207-1 О соглашениях о вызове для анонимных типов
  • AI12-0211-1 О наследовании аспектов от интерфейсов
  • AI12-0216-1 О передаче составных значений в параметрах подпрограмм
  • AI12-0217-1 Переформулировали правила для X'Old
  • AI12-0219-1 О 'in' параметрах импортируемых подпрограмм
  • AI12-0220-1 Пре/пост‐условия для ссылочных типов
  • AI12-0222-1 О аспектах приватного типа
  • AI12-0224-1 О взаимодействии с Фортраном через C механизм
  • AI12-0225-1 Об использовании универсальных типов в атрибутах
  • AI12-0226-1 Поправили правила о преобразованиях типов
  • AI12-0227-1 Об операциях над универсальными типами
  • AI12-0228-1 О свойствах квалифицированных выражений
  • AI12-0230-1 Deadline Floor Protocol — замена Stack Resource Protocol.
  • AI12-0231-1 Про результат Activation_Is_Complete (Null_Task_Id)
  • AI12-0232-1 О «чистых» телах настраиваемых модулей
  • AI12-0235-1 Пакет System.Storage_Pools теперь «чистый»
  • AI12-0237-1 Новые атрибуты Representation и Value_From_Representation
  • AI12-0241-1 Аспект Nonblocking для стандартных подпрограмм
  • AI12-0244-1 О подавлении Range_Check для атрибутов S'Value
  • AI12-0247-1 Про Detect_Blocking и вложенные вызовы
  • AI12-0252-1 Про прерывания в Ravenscar профиле
  • AI12-0254-1 Новый стандартный контейнер Bounded_Indefinite_Holders
  • AI12-0256-1 Новый аспект No_Controlled_Parts
  • AI12-0258-1 Про инициализацию контейнеров
  • AI12-0259-1 Про строки возвращаемые Ada.Command_Line
  • AI12-0260-1 Новые функции Is_Basic и To_Basic в Wide_Characters.Handling
  • AI12-0261-1 Поправили правила о «private with»
  • AI12-0263-1 Про ссылки на стандарт Unicode
  • AI12-0264-1 Про сдвиги и ротацию бит
  • AI12-0265-1 Новый аспект Default_Initial_Condition
  • AI12-0267-1 Новая прагма Conflict_Check_Policy для контроля за параллельным исполнением.
  • AI12-0269-1 Аспект No_Return для функций
  • AI12-0276-1 Новая прагма Admission_Policy для спинлоков
  • AI12-0277-1 Про accessibility level параметров
  • AI12-0278-1 О неявном преобразовании анонимных типов
  • AI12-0279-1 Новый аспект Yield для невытесняющей диспетчеризации
  • AI12-0283-1 Дистанционную подпрограмму и тип нельзя объявить Nonblocking
  • AI12-0285-1 Исправили синтаксис Stable_Properties
  • AI12-0286-1 Добавили аспект Allows_Exit в стандрантные пакеты
  • AI12-0287-1 О использовении not null в переименовании
  • AI12-0289-1 О неявном not null в анонимных типах
  • AI12-0290-1 Новое ограничение Pure_Barriers
  • AI12-0291-1 Новый профиль Jorvik, не такой жесткий, как Ravenscar
  • AI12-0292-1 Редакционные правки
  • AI12-0293-1 Новый пакет FIFO_Streams
  • AI12-0294-1 Редакционные правки На этом пока всё.

Август 2018 — Декабрь 2018