更新履歴(初版のみ・2026年11月01日公開)
- 初版公開
この記事を引用する(DOI: 10.5281/zenodo.23855025)
この記事はZenodoにアーカイブされています。常に最新版へ解決されるDOIと、いま表示している版に固定されたDOIの両方を下に示します。
小村 豪(2026)「Ada 2022 の新しい機能 ── GNAT で動くものと、まだ書けない並列構文」合同会社小村ソフト. https://doi.org/10.5281/zenodo.23855025 https://comcomponent.com/blog/ada-2022-new-features/
- DOI(最新版)
- 10.5281/zenodo.23855025
- DOI(この版)
- 10.5281/zenodo.23855026
Ada 2022 は Ada の国際規格 ISO/IEC 8652 の第4版で、2023年5月に ISO/IEC 8652:2023 として発行されました1。この記事では追加された機能のうち普段のコードで使いやすいものを、GNAT で実際にコンパイルして動かした結果とともに説明します。取り上げるのは、宣言式、差分集成体(delta aggregate)、どの型にも使える 'Image、角括弧の集成体と @ と反復子のフィルタ、'Reduce、任意精度整数の Big_Integers、Jorvik プロファイル、並列ブロックと並列ループです。
試した環境は Ubuntu 上の GNAT 13.3.0(apt のパッケージ)と GNAT 15.3.0(Alire で取得した gnat_native 15.3.1)です。Windows では試していません。結果を先に書くと、並列の構文以外は2つのバージョンとも同じように動き、並列の構文はどちらのバージョンでも受け付けられませんでした。
Ada の基本はAda言語の魅力、契約と証明はSPARKによる形式検証入門で扱っています。Alire でのプロジェクトの作り方はAlire で Ada のプロジェクトを始めるにまとめています。
Ada 2022 を有効にするコンパイラの指定
GNAT で Ada 2022 の機能を使うには、コンパイラに -gnat2022 を渡すか、ソースの先頭に pragma Ada_2022; を書きます23。試した2つのバージョンはどちらも、指定しないと Ada 2022 の構文をエラーにしました。次は後で出てくる宣言式と @ を、指定なしでコンパイルしたときのメッセージです。
decl_delta.adb:19:07: error: declare expression is an Ada 2022 feature
decl_delta.adb:19:07: error: unit must be compiled with -gnat2022 switch
misc22.adb:22:13: error: target name is an Ada 2022 feature
misc22.adb:22:13: error: unit must be compiled with -gnat2022 switch
角括弧の集成体は、指定がないと illegal character, replaced by "(" という別のエラーになります。メッセージから Ada 2022 の機能だとは読み取りにくいので、このエラーが出たら -gnat2022 の指定を確かめます。
gprbuild でビルドするときは、プロジェクトファイルの Compiler パッケージに書きます。
project Demo is
for Source_Dirs use ("src");
for Object_Dir use "obj";
for Main use ("misc22.adb");
package Compiler is
for Default_Switches ("Ada") use ("-gnat2022");
end Compiler;
end Demo;
この記事の例はすべて -gnat2022 を付けてコンパイルしています。
flowchart TB
accTitle: Ada 2022の機能とGNATでの結果
accDescr: この記事で試したAda 2022の機能を、GNAT 13.3と15.3で動いたものと受け付けられなかったものに分けて示す。
A["試したAda 2022の機能"] --> B{"GNAT 13.3と15.3で動いたか"}
B -->|"動いた"| C["式と集成体の追加"]
B -->|"動いた"| D["Big_Integers・Jorvik"]
B -->|"受け付けられない"| G["並列の構文"]
C --> C1["宣言式・差分集成体"]
C --> C2["'Image・'Reduce・@・フィルタ"]
G --> G1["parallel do・parallel for"]
G --> G2["'Parallel_Reduce"]
図1: この記事で試した機能のうち、並列の構文だけがGNAT 13.3と15.3で受け付けられなかった。
図の実線は常に成り立つ関係、破線は条件付きの関係です(成立条件は詳細ページの各関係の説明に記載)。関係すべての一覧(全12件、根拠・確度つき)と主要概念の定義は知識マップ詳細ページにまとめています。データ: JSON-LD / Turtle
式の中で名前を置く宣言式
宣言式(declare expression)は、式の中で定数を宣言したり名前を付け替えたりする構文です4。(declare 宣言 begin 式) の形で、丸括弧で囲めば式を書ける場所ならどこにでも置けます。式関数や、事前条件・事後条件の中でも使えます。
-- 宣言式: 式の中で一時的な名前を置ける
function Percent (Done, Total : Natural) return Natural is
(declare
Ratio : constant Natural :=
(if Total = 0 then 0 else Done * 100 / Total);
begin
Natural'Min (Ratio, 100));
Percent (3, 4) は ` 75、Percent (5, 0) は 0` を返しました。式関数は本体が1つの式なので、途中の計算に名前を付けたいときに宣言式が使えます。
宣言できるのは、制限型(limited type)でない型の定数と、名前の付け替え(renaming)だけです。変数は宣言できません。RM は制限型を除く理由として、式の評価の途中でタスクを待たせることになるのを避けるためだと説明しています4。
flowchart TB
accTitle: 宣言式の評価の流れ
accDescr: 宣言式ではdeclareの後に置いた定数をbeginの後の式で使い、その式の値が宣言式全体の値になることを示す。
A["declare"] --> B["定数か名前の付け替えを宣言する"]
B --> C["begin"]
C --> D["宣言した名前を使って式を評価する"]
D --> E["その値が宣言式の値になる"]
B -.-> F["変数と制限型の定数は宣言できない"]
図2: 宣言式はdeclareで置いた定数をbeginの後の式で使い、その式の値を返す。
一部だけ変えた値を作る差分集成体
差分集成体(delta aggregate)は、ある値をもとに、一部の成分だけを変えた新しい値を作る式です5。(元の値 with delta 成分 => 新しい値, ...) と書き、挙げなかった成分は元の値のまま写されます。配列にも使えます。
type Config is record
Port : Natural;
Timeout : Duration;
Verbose : Boolean;
end record;
Default : constant Config :=
(Port => 8080, Timeout => 5.0, Verbose => False);
-- 差分集成体: 元の値から一部の成分だけ変えた値を作る
Debug : constant Config :=
(Default with delta Verbose => True, Timeout => 30.0);
Debug'Image の出力は次のとおりで、Port は Default の値のまま残っています。
(PORT => 8080,
TIMEOUT => 30.000000000,
VERBOSE => TRUE)
差分集成体は式なので、契約の中にも書けます。AdaCore の解説も、仮の変数を用意してから成分を書き換えるやり方は契約の中では使えないことを、差分集成体の動機に挙げています6。次の事後条件は「Verbose だけが True に変わり、ほかの成分は呼び出し前のまま」という意味です。C'Old は呼び出し前の C の値です。
-- Verbose だけが True に変わり、ほかの成分は呼び出し前のまま
procedure Enable_Verbose (C : in out Config)
with Post => C = (C'Old with delta Verbose => True);
procedure Enable_Verbose (C : in out Config) is
begin
C.Verbose := True;
C.Timeout := 30.0; -- 事後条件にない変更(誤り)
end Enable_Verbose;
本体は事後条件にない Timeout まで書き換えています。表明の検査を有効にする -gnata7 を付けて実行すると、事後条件の違反として止まりました。
raised ADA.ASSERTIONS.ASSERTION_ERROR : failed postcondition from contracts.adb:12
-gnata を付けないと事後条件は検査されず、Timeout が 30.0 に変わったまま正常に終わりました。実行時に確かめたいときは、このスイッチを忘れないようにします。実行せずに証明する方法はSPARKによる形式検証入門とAIが書いたコードを SPARK で証明するで扱っています。
flowchart TB
accTitle: 差分集成体を使った事後条件の検査
accDescr: 呼び出し前の値から差分集成体で期待する値を作り、呼び出し後の値と比べて、一致しなければ事後条件の違反になることを示す。
A["呼び出し前の値 C'Old"] --> B["差分集成体で Verbose だけ変える"]
B --> C["期待する値"]
D["呼び出し後の値 C"] --> E{"期待する値と等しいか"}
C --> E
E -->|"等しい"| F["事後条件を満たす"]
E -->|"等しくない"| G["Assertion_Error(-gnata のとき)"]
図3: 差分集成体で作った期待値と呼び出し後の値を比べ、ほかの成分の変更を事後条件で検出する。
どの型にも使える ‘Image と Put_Image
Ada 2012 までの 'Image 属性はスカラー型にしか使えませんでした。Ada 2022 ではレコードや配列を含むどの型にも使えます8。'Image は型の Put_Image という手続きを通して定義されていて、結果は Put_Image がバッファに書いた文字列です。Put_Image は型ごとにアスペクトで差し替えられ、'Image そのものは差し替えられません。
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Text_Buffers;
procedure Put_Image_Demo is
package Temps is
type Celsius is record
Value : Integer;
end record
with Put_Image => Put_Celsius;
procedure Put_Celsius
(Buffer : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class;
Item : Celsius);
end Temps;
package body Temps is
procedure Put_Celsius
(Buffer : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class;
Item : Celsius) is
begin
Buffer.Put (Item.Value'Image & " C");
end Put_Celsius;
end Temps;
type Reading is record
Sensor : Positive;
Temp : Temps.Celsius;
end record;
R : constant Reading := (Sensor => 3, Temp => (Value => 21));
begin
Put_Line (R.Temp'Image);
Put_Line (R'Image);
end Put_Image_Demo;
出力は次のとおりです。Reading には Put_Image を指定していませんが、成分の Temp は Celsius の Put_Image で書かれています。
21 C
(SENSOR => 3,
TEMP => 21 C)
GNAT の既定の出力では次の2点に気づきました。
- レコードと配列の
'Imageは、GNAT 13.3 と 15.3 のどちらでも改行で始まりました。上の出力の空行はそのためです。 - RM は、配列の既定の
Put_Imageは名前付きの集成体の形([1 => ..., 2 => ...])で書くと定めています8。GNAT 13.3 と 15.3 の出力は、次の節のとおり[ 1, 4, 9, 16, 25]という位置による形でした。
整数の 'Image が先頭に空白か負号を1文字置くのは、以前と同じです8。既定の 'Image はログやデバッグで値を見るのに使い、ほかのプログラムが読む形式には使わないほうが無難です。形式を決めたいときは、Put_Image を自分で指定します。
flowchart TB
accTitle: 'ImageとPut_Imageの関係
accDescr: 'Imageは型のPut_Imageを呼び、指定があればそれを、なければ既定の書き方を使い、レコードの既定の書き方は成分ごとに成分の型のPut_Imageを呼ぶことを示す。
A["X'Image"] --> B["型の Put_Image を呼ぶ"]
B --> C{"Put_Image を指定しているか"}
C -->|"している"| D["指定した手続きで書く"]
C -->|"していない"| E["既定の書き方で書く"]
E --> F["レコードは成分ごとに成分の型の Put_Image を呼ぶ"]
D --> G["バッファの文字列が 'Image の結果"]
F --> G
図4: ‘ImageはPut_Imageを通して文字列を作るので、成分の型に指定したPut_Imageは外側のレコードの’Imageにも使われる。
書き方を短くする角括弧の集成体、@、フィルタ、’Reduce
普段のコードでよく使う小さな追加を、次の例にまとめました。
with Ada.Text_IO; use Ada.Text_IO;
procedure Misc22 is
type Int_Array is array (Positive range <>) of Integer;
-- 角括弧の配列集成体。空の配列も [] で書ける
Values : constant Int_Array := [3, 8, 1, 6, 5];
Empty : constant Int_Array := [];
-- 反復子付きの配列集成体
Squares : constant Int_Array (1 .. 5) := [for I in 1 .. 5 => I * I];
Count : Natural := 0;
Total : Integer := 0;
-- 簡約式: 'Reduce で畳み込む
Sum : constant Integer := Values'Reduce ("+", 0);
Max : constant Integer := Values'Reduce (Integer'Max, Integer'First);
Sum_Sq : constant Integer := [for V of Values => V * V]'Reduce ("+", 0);
begin
-- 対象名 @: 左辺と同じ名前を右辺で繰り返さない
Count := @ + 1;
-- 反復子のフィルタ: when の条件を満たす要素だけを回す
for V of Values when V mod 2 = 0 loop
Total := @ + V;
end loop;
Put_Line ("Count =" & Count'Image);
Put_Line ("Even total =" & Total'Image);
Put_Line ("Empty length =" & Empty'Length'Image);
Put_Line ("Squares =" & Squares'Image);
Put_Line ("Sum =" & Sum'Image);
Put_Line ("Max =" & Max'Image);
Put_Line ("Sum of squares =" & Sum_Sq'Image);
end Misc22;
Count = 1
Even total = 14
Empty length = 0
Squares =
[ 1, 4, 9, 16, 25]
Sum = 23
Max = 8
Sum of squares = 135
- 角括弧の集成体: 配列の集成体を
[ ]で書けます。空の配列は[]と書け、[for I in 1 .. 5 => I * I]のように反復子で要素を作れます5。 @(対象名): 代入文の右辺で、左辺の変数を@と書けます9。Statistics.Total_Count := Statistics.Total_Count + 1;のように長い名前を繰り返さずに済みます。- 反復子のフィルタ:
for ... when 条件 loopと書くと、条件を満たす要素だけでループの本体を実行します10。 'Reduce(簡約式): 配列などの値の列を、2項の演算と初期値で1つの値に畳み込みます4。Values'Reduce ("+", 0)は和、Integer'Maxを渡すと最大値です。
フィルタは 'Reduce の値の列にも書けます。次の式は偶数だけを2乗して足します。8 と 6 の2乗の和で、結果は ` 100` でした。
Even_Sq : constant Integer :=
[for V of Values when V mod 2 = 0 => V * V]'Reduce ("+", 0);
なお、[for V of Values => V * V]'Reduce ("+", 0)'Image のように 'Reduce の結果に続けて 'Image を付けると、GNAT 13.3 と 15.3 のどちらも prefix of attribute must be a name というエラーを出しました。上の例ではいったん定数に入れてから 'Image を付けています。
flowchart TB
accTitle: 簡約式の評価の流れ
accDescr: 値の列から反復子のフィルタで要素を選び、各要素を変換し、初期値と2項の演算で1つの値に畳み込む流れを示す。
A["値の列 Values"] --> B["フィルタ when V mod 2 = 0"]
B --> C["各要素を V * V に変換"]
C --> D["初期値 0 から + で畳み込む"]
D --> E["結果 100"]
図5: 簡約式は値の列を選び、変換し、初期値と演算で1つの値に畳み込む。
桁あふれしない整数 Big_Integers
Ada.Numerics.Big_Numbers.Big_Integers は、桁数の上限がない整数の型 Big_Integer を定めるパッケージです11。次の例は 30 の階乗を計算します。この値は 64 ビットの整数にも収まりません。
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Big_Numbers.Big_Integers;
use Ada.Numerics.Big_Numbers.Big_Integers;
procedure Big_Demo is
F : Big_Integer := 1;
begin
for I in 1 .. 30 loop
F := @ * To_Big_Integer (I);
end loop;
Put_Line ("30! =" & F'Image);
end Big_Demo;
30! = 265252859812191058636308480000000
F : Big_Integer := 1; と、整数のリテラルをそのまま Big_Integer に代入できています。これは Ada 2022 で加わったユーザー定義リテラルの仕組みによるものです12。RM の Big_Integer の宣言には Integer_Literal => From_Universal_Image が指定されていて、リテラルはこの関数で Big_Integer に変換されます11。同じ宣言には Put_Image も指定されているので、F'Image が10進の数字を返します。
flowchart TB
accTitle: Big_Integerのリテラルと'Image
accDescr: 整数リテラルはInteger_Literalアスペクトの関数でBig_Integerになり、'ImageはBig_IntegerのPut_Imageで10進の文字列になることを示す。
A["整数リテラル 1"] --> B["Integer_Literal の From_Universal_Image"]
B --> C["Big_Integer の値"]
C --> D["F'Image"]
D --> E["Big_Integer の Put_Image"]
E --> F["10進の文字列"]
図6: Big_Integerはユーザー定義リテラルでリテラルを受け取り、Put_Imageで’Imageの文字列を作る。
Ravenscar より制限の少ない Jorvik プロファイル
Jorvik は Ada 2022 で標準に加わったタスク機能のプロファイルで、Ravenscar の制限の一部を外したものです13。Ravenscar の内容と使いどころはAdaによるリアルタイムシステムプログラミングで説明しているので、ここでは差分だけを扱います。
RM によると、Jorvik は Ravenscar から次の6つの制限を外しています13。
No_Implicit_Heap_AllocationsNo_Relative_Delay(相対遅延のdelay文を禁止する)Max_Entry_Queue_Length => 1Max_Protected_Entries => 1(保護オブジェクトのエントリを1つに限る)No_Dependence => Ada.CalendarNo_Dependence => Ada.Synchronous_Barriers
さらに、エントリのバリアに対する Simple_Barriers を、より弱い Pure_Barriers に置き換えています。Ravenscar を満たすユニットは、すべて Jorvik も満たします13。
試したのは、エントリを2つ持つ保護オブジェクトと、相対遅延の delay を使う次のプログラムです。mailboxes.ads、mailboxes.adb、main.adb の3つのファイルに分けて置きます。
package Mailboxes is
protected Mailbox is
entry Put (Item : Integer);
entry Get (Item : out Integer);
private
Value : Integer := 0;
Count : Natural := 0;
end Mailbox;
end Mailboxes;
package body Mailboxes is
protected body Mailbox is
-- Count = 0 は Ravenscar の Simple_Barriers では書けない
entry Put (Item : Integer) when Count = 0 is
begin
Value := Item;
Count := 1;
end Put;
entry Get (Item : out Integer) when Count > 0 is
begin
Item := Value;
Count := 0;
end Get;
end Mailbox;
end Mailboxes;
with Ada.Text_IO; use Ada.Text_IO;
with Mailboxes; use Mailboxes;
procedure Main is
X : Integer;
begin
delay 0.01; -- 相対遅延。Ravenscar では No_Relative_Delay で禁止
Mailbox.Put (42);
Mailbox.Get (X);
Put_Line (X'Image);
end Main;
gnat.adc に pragma Profile (Jorvik); と書いてビルドすると、エラーなくコンパイルでき、 42 を出力しました。同じコードを pragma Profile (Ravenscar); でビルドすると、次のエラーになりました。
main.adb:7:04: error: violation of restriction "No_Relative_Delay"
main.adb:7:04: error: from profile "Ravenscar" at gnat.adc:1
mailboxes.ads:3:07: error: violation of restriction "Max_Protected_Entries = 1"
mailboxes.ads:3:07: error: from profile "Ravenscar" at gnat.adc:1
gnatmake は仕様部のエラーで止まるので、バリアの違反は本体を gcc -c -gnatc mailboxes.adb で検査して確かめました。2つのバリアがどちらも違反になります。
mailboxes.adb:4:45: error: violation of restriction "Simple_Barriers"
mailboxes.adb:4:45: error: from profile "Ravenscar" at gnat.adc:1
mailboxes.adb:10:49: error: violation of restriction "Simple_Barriers"
mailboxes.adb:10:49: error: from profile "Ravenscar" at gnat.adc:1
最初は保護オブジェクトを手続きの中に置いていたので、どちらのプロファイルでも No_Local_Protected_Objects の違反になりました。この制限は Jorvik にも残っているので、保護オブジェクトはパッケージに置きます。試したのはデスクトップ向けの通常のランタイムで、組み込み向けのランタイムでは試していません。
flowchart TB
accTitle: RavenscarとJorvikの関係
accDescr: JorvikはRavenscarから6つの制限を外し、Simple_BarriersをPure_Barriersに置き換えたプロファイルで、Ravenscarを満たすユニットはJorvikも満たすことを示す。
A["Ravenscar プロファイル"] --> B["6つの制限を外す"]
A --> C["Simple_Barriers を Pure_Barriers に置き換える"]
B --> D["Jorvik プロファイル"]
C --> D
B -.-> E["複数エントリ・相対遅延・Ada.Calendar など"]
A -.-> F["Ravenscar を満たすユニットは Jorvik も満たす"]
図7: JorvikはRavenscarの制限を一部外したプロファイルで、Ravenscarの要件を満たすユニットはJorvikの要件も満たす。
GNAT ではまだ書けない並列ブロックと並列ループ
Ada 2022 には、処理を並列に実行する構文として並列ブロック(parallel do)と並列ループ(parallel for)が加わりました1410。並列ブロックは and で区切った複数の文の並びを、それぞれ独立した論理的な制御の流れとして並行に進めます。並列ループはループの各回を並列に実行できるものとして書く構文です。parallel (4) for ... のように、まとめて実行する単位(チャンク)の数の上限も指定できます。
並列の構文には、データ競合を避けるための規則があります。RM 9.10.1 は衝突しうる読み書きをどこまで禁止するかを衝突検査の方針(pragma Conflict_Check_Policy)として定めています。既定の方針(All_Parallel_Conflict_Checks)では、並列の構文の中から外側の変数を読み書きすることを、コンパイル時に禁止します15。例外は同期オブジェクト(synchronized object)と、並列ループの中でループの変数を添字にした配列の要素です。そのため、次の並列ループは規則上許されますが、並列ブロックの各枝から外側の変数 A と B に代入するコードは禁止されます。
parallel for I in V'Range loop
V (I) := I * I;
end loop;
ただし、GNAT 13.3 と 15.3 はどちらも、この構文を受け付けませんでした。上の並列ループをコンパイルすると次のエラーになります。
par_loop.adb:7:12: error: missing ":"
par_loop.adb:9:04: error: "end loop parallel;" expected
parallel do も missing ":=" などの構文エラーになり、並列版の簡約式である 'Parallel_Reduce は unrecognized attribute "Parallel_Reduce" になりました。GNAT リファレンスマニュアルの「Implementation of Ada 2022 Features」は実装済みの Ada 2022 の機能を一覧にした章ですが、並列ブロックと並列ループを定めた AI12-0119 は載っていません3。
外側の変数への読み書きをコンパイル時に検査する点が、RM の上でのこの構文の特徴です。今の GNAT で並列に動かしたい処理は、タスクと保護オブジェクトで書きます。書き方はAdaにおける安全な並行処理で説明しています。
flowchart TB
accTitle: 並列の構文とGNATでの扱い
accDescr: Ada 2022の並列ブロックと並列ループはRMの衝突検査で外側の変数の読み書きが制限されるが、GNAT 13.3と15.3では構文エラーになるので、タスクと保護オブジェクトで書くことを示す。
A["parallel do / parallel for"] --> B["既定の衝突検査で外側の変数の読み書きを禁止"]
B -.-> C["例外: 同期オブジェクト・ループ変数を添字にした要素"]
A --> D{"GNAT 13.3 と 15.3 で使えるか"}
D -->|"構文エラー"| E["タスクと保護オブジェクトで書く"]
図8: 並列の構文はRM上はデータ競合を防ぐ規則を持つが、試したGNATでは受け付けられないため、タスクと保護オブジェクトで書く。
機能ごとの結果のまとめ
| 機能 | RM の箇所 | GNAT 13.3 / 15.3 |
|---|---|---|
| 宣言式 | 4.5.9 | 動いた |
| 差分集成体 | 4.3.4 | 動いた |
どの型にも使える 'Image、Put_Image |
4.10 | 動いた(配列の形は位置による形) |
| 角括弧の集成体、反復子付きの集成体 | 4.3.3 | 動いた |
@(対象名) |
5.2.1 | 動いた |
| 反復子のフィルタ | 5.5 | 動いた |
'Reduce |
4.5.10 | 動いた |
Big_Integers |
A.5.6 | 動いた |
| Jorvik プロファイル | D.13 | 動いた |
並列ブロック、並列ループ、'Parallel_Reduce |
5.6.1、5.5、4.5.10 | 受け付けられない |
ここで挙げなかった追加には、コンテナの集成体、列挙型の表現値を扱う 'Enum_Rep と 'Enum_Val、C の可変長引数の関数の取り込みなどがあります2。
関連記事
- Ada言語の魅力 ── 型で設計を語り、数十年動き続けるソフトウェアを支える言語
- SPARKによる形式検証入門 ── Adaの契約から数学的証明へ
- Adaにおける安全な並行処理 ── タスクと保護オブジェクトの実践ガイド
- Adaによるリアルタイムシステムプログラミング ── 優先度・周期・実行時間制御の実践
- Adaのジェネリックプログラミング ── 型で契約を書き、再利用をゼロコストで実現する
- Alire で Ada のプロジェクトを始める
- AIが書いたコードを SPARK で証明する
参考リンク
-
ISO, ISO/IEC 8652:2023 Programming languages — Ada. Ada 2022 の規格。第4版で、2023年5月の発行。 ↩
-
AdaCore Learn, What’s New in Ada 2022: Introduction. Ada 2022 の機能の紹介と、GNAT での有効化の方法。 ↩ ↩2
-
AdaCore, GNAT Reference Manual: Implementation of Ada 2022 Features. GNAT が実装した Ada 2022 の機能の一覧と、
-gnat22スイッチまたはpragma Ada_2022による有効化。 ↩ ↩2 -
Ada Reference Manual (Ada 2022), 4.5 Operators and Expression Evaluation. 4.5.9 の宣言式(宣言できるのは制限型でない定数と名前の付け替え)と、4.5.10 の簡約式。 ↩ ↩2 ↩3
-
Ada Reference Manual (Ada 2022), 4.3 Aggregates. 4.3.3 の配列集成体(角括弧と反復子付きの形)と、4.3.4 の差分集成体。 ↩ ↩2
-
AdaCore Learn, What’s New in Ada 2022: Delta Aggregates. 差分集成体の動機と、仮の変数を使うやり方が契約の中では使えないこと。 ↩
-
AdaCore, GNAT User’s Guide: Alphabetical List of All Switches. 表明の検査を有効にする
-gnata(Pre と Post の検査も含む)。 ↩ -
Ada Reference Manual (Ada 2022), 4.10 Image Attributes. Put_Image の既定の動作、’Image が Put_Image を通して定義されること、配列とレコードの既定の形。 ↩ ↩2 ↩3
-
Ada Reference Manual (Ada 2022), 5.2 Assignment Statements. 5.2.1 の対象名
@。 ↩ -
Ada Reference Manual (Ada 2022), 5.5 Loop Statements. 並列ループの構文、チャンクの指定、反復子のフィルタ。 ↩ ↩2
-
Ada Reference Manual (Ada 2022), A.5 The Numerics Packages. A.5.6 の Big_Integers と、Big_Integer に指定された Integer_Literal と Put_Image。 ↩ ↩2
-
Ada Reference Manual (Ada 2022), 4.2 Literals. 4.2.1 のユーザー定義リテラルと Integer_Literal アスペクト。 ↩
-
Ada Reference Manual (Ada 2022), D.13 The Ravenscar and Jorvik Profiles. 両プロファイルの制限の一覧と、Jorvik が外した制限。 ↩ ↩2 ↩3
-
Ada Reference Manual (Ada 2022), 5.6 Block Statements. 5.6.1 の並列ブロック。 ↩
-
Ada Reference Manual (Ada 2022), 9.10 Shared Variables. 9.10.1 の衝突検査の方針と、既定の方針 All_Parallel_Conflict_Checks の内容。 ↩
関連する記事
同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。
Adaのメモリ管理 ── アクセス型・Controlled型・ストレージプールの使い分け
AdaはGCに頼らず、まず値をスタックに置き、ヒープが要るときはアクセス型で寿命の規則を型に書きます。解放の危うさ、Controlled型での後始末、ストレージプールでの確保先の制御を、GNATで動かした例で説明します。
Alire で Ada のプロジェクトを始める ── プロジェクト作成、依存の追加、ビルドプロファイル、GNATproveまで
AdaのパッケージマネージャーAlireで、プロジェクトの作成、GNATの自動取得、依存クレートの追加、ビルドプロファイルの切り替え、GNATproveによる証明までを、alr 2.1で実行した出力とともに説明します。
Ada と Rust の安全性の考え方の違い ── 型・オーバーフロー・所有権・データ競合・形式検証を実際に動かして比べる
Ada と Rust はどちらも安全性を重視する言語ですが、誤りを止める場所が違います。値の範囲、整数オーバーフロー、メモリ、データ競合、検査を外す仕組み、形式検証の6点を、GNAT・GNATprove・rustc で実際に動かして比べます。
Ada と C / C# をつなぐ ── DLL を作って呼び出す
Adaで共有ライブラリを作り、CとC#から呼ぶ手順を実際に動かして説明します。Interfaces.CとConvention => C、gprbuildの設定、初期化、文字列とメモリの持ち主、例外の扱い、AdaからWindowsのDLLを呼ぶ方法まで扱います。
Adaのジェネリックプログラミング ── 型で契約を書き、再利用をゼロコストで実現する
Adaのジェネリックプログラミングを、総称サブプログラム、総称パッケージ、仮サブプログラム、型カテゴリ、実務上の設計指針まで体系的に解説します。型安全な再利用とゼロコスト抽象化の考え方を整理します。
関連トピック
このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。
Windows技術トピック
Windows 開発、不具合調査、既存資産活用の技術トピックをまとめた入口です。
このテーマがつながるサービス
この記事は次のサービスページにつながります。近い入口からご覧ください。
技術相談・設計レビュー
Adaの既存コードにAda 2022の機能を取り入れるか、どのバージョンのコンパイラで何が使えるかを確かめたい場合に、技術相談・設計レビューとして扱えます。
既存Windowsソフトの改修・保守
Adaで書かれた既存のソフトを新しいGNATでビルドし直し、保守を続けたい場合は、既存ソフトの改修・保守として相談できます。
よくある質問
この記事のテーマについて、相談時によくある質問をまとめています。
- GNATでAda 2022の機能を使うには、何を指定すればよいですか?
- コンパイラに -gnat2022 を渡すか、ソースに pragma Ada_2022; を書きます。GNAT 13.3と15.3のどちらも、指定しないと宣言式などが「Ada 2022 feature」としてエラーになりました。gprbuildを使う場合は、プロジェクトファイルのCompilerパッケージに -gnat2022 を書きます。
- Ada 2022の並列ブロック(parallel do)はGNATで使えますか?
- この記事で試したGNAT 13.3と15.3では使えませんでした。parallel do と parallel for はどちらも構文エラーになり、'Parallel_Reduce は未知の属性として扱われました。GNATリファレンスマニュアルの、実装済みのAda 2022機能の一覧にも並列ブロックのAIは載っていません。いま並列に動かしたい処理は、タスクと保護オブジェクトで書きます。
- JorvikプロファイルとRavenscarプロファイルはどう違いますか?
- JorvikはRavenscarの制限のうち6つを外し、エントリのバリアの制限を緩めたプロファイルです。保護オブジェクトに複数のエントリを置くこと、相対遅延のdelay文、Ada.Calendarの利用などが許されます。Ravenscarを満たすユニットはJorvikも満たします。