Ada
このAdaチュートリアルは、Adaプログラミング
このチュートリアルでは、Ada
このチュートリアルを
Adaの概要
[[Adaがどのようなプログラミング
Adaは、1980
Adaの
強 い型付 け:変数 や関数 などのデータ型 が厳密 に定義 され、コンパイル時 に型 エラーを検出 できるため、バグの発生 を防止 できます。相互 排除 機能 :タスク間 の相互 排除 機能 が強力 で、デッドロックやライブロックなどの問題 が少 なく、安全 な並行 処理 を実現 できます。- メモリ
管理 :Adaにはガベージコレクション機能 があるため、メモリリークや二 重 解放 のような問題 が起 こりにくく、安全 なメモリ管理 が可能 です。 大 規模 なプログラムの開発 に適 した機能 :Adaには、パッケージ、抽象 型 、ジェネリック、タスクなど、大 規模 なプログラムの開発 に必要 な機能 が豊富 にあります。- ドキュメント
生成 :Adaには、コードから自動的 に文書 を生成 する機能 があり、ソフトウェア開発 における文書 作成 の手間 を省 くことができます。
Adaの
環境 の設定
[[Adaの
Adaの
Debian linux へのインストール
[- ターミナルを
開 きます。 sudo apt update
コマンドを実行 して、パッケージリストを更新 します。sudo apt-get install gnat
コマンドを実行 して、GNATパッケージをインストールします。- インストールが
完了 したら、gnat --version
コマンドを実行 して、GNATのバージョンを確認 します。
MSYS2/Windows へのインストール
[MSYS2にGNATをインストールする
- MSYS2をインストールします。
公式 サイトからダウンロードして、指示 に従 ってインストールしてください。 - MSYS2を
開 きます。開 いたコンソールで以下 のコマンドを実行 して、パッケージリストを更新 します。pacman -Syu
- GNATをインストールするために、
以下 のコマンドを実行 して必要 なパッケージをインストールします。 このコマンドは、GNATのパッケージに含 まれているmingw-w64-x86_64-gcc-adaパッケージをインストールします。pacman -S mingw-w64-x86_64-gcc-ada
- インストールが
完了 したら、gnat --version
コマンドを実行 して、GNATのバージョンを確認 します。
macOS へのインストール
[macOSにGNATをインストールする
- Homebrewをインストールします。ターミナルを
開 いて、以下 のコマンドを実行 します。/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
- GNATをインストールするために、
以下 のコマンドを実行 します。 このコマンドは、GNATのパッケージをHomebrewからインストールします。brew install gnat
- インストールが
完了 したら、gnat --version
コマンドを実行 して、GNATのバージョンを確認 します。
FreeBSD へのインストール
[FreeBSDにGNATをインストールする
- pkgを
更新 します。ターミナルを開 いて、以下 のコマンドを実行 します。% sudo pkg update
- GNATをインストールするために、
以下 のコマンドを実行 します。 このコマンドは、GNATのパッケージに含 まれているgcc-adaパッケージをインストールします。% sudo pkg install gcc-ada
- インストールが
完了 したら、gnat --version
コマンドを実行 して、GNATのバージョンを確認 します。
トップレベルのプログラム構造
[Adaプログラムのトップレベルの
with パッケージ
名 ; use パッケージ名 ; プログラム名 is --定数 、型 、変数 、サブプログラム、タスクなどの宣言 begin -- プログラムの実行 部分 end プログラム名 ;
with
use
プログラム
begin
キーワードの
ソースコードのファイル
- ファイル
名 は、プログラム名 と同 じにする必要 があります。 - Adaのソースファイルは、
.adb
(本体 )と.ads
(仕様 )の2つの拡張子 を持 つことができます。 .adb
ファイルと.ads
ファイルのペアは、同 じ名前 を持 つ必要 があります。- ただし、プログラムが
一 つの.adb
ファイルで完結 している場合 、.ads
ファイルは不要 です。
my_program.adb -- プログラムの
本体 my_program.ads -- プログラムの仕様
コメント
[Adaのコメントは、ダブルハイフン(--)ではじまり、どの
-- これはコメントです。
コメントは、コードの
コメントは、コードをより
データ型 と変数
[Adaには、さまざまなデータ
データ型
[Adaには、
整数 型 (Integer)実数 型 (Float)文字 型 (Character)真偽 値 型 (Boolean)列挙 型 (Enumeration)配列 型 (Array)- レコード
型 (Record) 構造 体型 (Access)
これらのデータ
整数 型 (Integer)
[- integer_example.adb
with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; procedure Integer_Example is age : Integer := 25; begin Put("I am "); Put(age, 2); Put(" years old."); end Integer_Example;
実数 型 (Float)
[- float_example.adb
with Ada.Text_IO; use Ada.Text_IO; with Ada.Float_Text_IO; use Ada.Float_Text_IO; procedure Float_Example is pi : Float := 3.14159; begin Put("The value of Pi is "); Put(pi, 1, 5); end Float_Example;
文字 型 (Character)
[- character_example.adb
with Ada.Text_IO; use Ada.Text_IO; procedure Character_Example is letter : Character := 'A'; begin Put("The first letter of the alphabet is "); Put(letter); end Character_Example;
真偽 値 型 (Boolean)
[- boolean_example.adb
with Ada.Text_IO; use Ada.Text_IO; procedure Boolean_Example is is_raining : Boolean := True; begin if is_raining then Put("Bring an umbrella."); else Put("Leave your umbrella at home."); end if; end Boolean_Example;
列挙 型 (Enumeration)
[- enumeration_example.adb
with Ada.Text_IO; use Ada.Text_IO; procedure Enumeration_Example is type Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); today : Day := Tuesday; begin Put("Today is "); case today is when Monday => Put("Monday"); when Tuesday => Put("Tuesday"); when Wednesday => Put("Wednesday"); when Thursday => Put("Thursday"); when Friday => Put("Friday"); when Saturday => Put("Saturday"); when Sunday => Put("Sunday"); end case; end Enumeration_Example;
配列 型 (Array)
[- erray_example.adb
with Ada.Text_IO; use Ada.Text_IO; procedure Array_Example is --
配列 を宣言 する type My_Array is array(1..5) of Integer; A : My_Array := (1, 2, 3, 4, 5); begin --配列 の要素 にアクセスする Put_Line("A(1) = " & Integer'Image(A(1))); Put_Line("A(2) = " & Integer'Image(A(2))); --配列 の要素 を変更 する A(1) := 10; A(2) := 20; --変更 された要素 を出力 する Put_Line("A(1) = " & Integer'Image(A(1))); Put_Line("A(2) = " & Integer'Image(A(2))); --配列 の全 要素 にアクセスする for I in A'range loop Put_Line("A(" & Integer'Image(I) & ") = " & Integer'Image(A(I))); end loop; end Array_Example;
レコード型 (Record)
[レコード
- record_example.adb
with Ada.Text_IO; use Ada.Text_IO; procedure Record_Example is type Person is record Name : String(1..20); Age : Integer; Is_Married : Boolean; end record; p : Person := ("John", 30, False); begin Put("Name: "); Put(p.Name); New_Line; Put("Age: "); Put(p.Age, 2); New_Line; Put("Married: "); if p.Is_Married then Put("Yes"); else Put("No"); end if; end Record_Example;
構造 体型 (Access)
[with Ada.Text_IO; use Ada.Text_IO; procedure Access_Example is type Person is record Name : String(1..20); Age : Integer; Is_Married : Boolean; end record; type Person_Ptr is access Person; p : Person_Ptr :== new Person'(Name ==> "John", Age ==> 30, Is_Married ==> False); begin Put("Name: "); Put(p.Name); New_Line; Put("Age: "); Put(p.Age, 2); New_Line; Put("Married: "); if p.Is_Married then Put("Yes"); else Put("No"); end if; end Access_Example;
変数 の宣言
[variable_name : data_type := initial_value;
x
を10
に
x : Integer := 10;
データの代入
[variable_name := new_value;
:=
の
x
に、20
を
x := 20;
式 と演算 子
[式
[Ada
with Ada.Text_IO; use Ada.Text_IO; procedure Main is x, y, z : Integer; begin x := 10; y := 20; z := x + y; Put_Line(z'Image); end Main;
演算 子
[Adaには、
算術 演算 子 : +、-、*、/、**(べき乗 )比較 演算 子 : =、/=、<、<=、>、>=論理 演算 子 : and、or、not- ビット
演算 子 : and、or、xor、not、shl(左 シフト)、shr(右 シフト)
Adaには、C
Adaに
また、Adaには、
with Ada.Text_IO; use Ada.Text_IO; procedure Main is X, Y, Z : Integer; begin X := 10; Y := 3; Z := X + Y; Put_Line("X + Y = " & Integer'Image(Z)); Z := X - Y; Put_Line("X - Y = " & Integer'Image(Z)); Z := X * Y; Put_Line("X * Y = " & Integer'Image(Z)); Z := X / Y; Put_Line("X / Y = " & Float'Image(Z)); Z := X ** Y; Put_Line("X ** Y = " & Integer'Image(Z)); end Main;
出力 X + Y = 13 X - Y = 7 X * Y = 30 X / Y = 3.333333 X ** Y = 1000
+ | |
---|---|
- | |
* | |
/ | |
mod | |
** | べき |
= | |
---|---|
/= | |
< | |
<= | |
> | より |
>= |
and | |
---|---|
or | |
not |
and | ビットごとの |
---|---|
or | ビットごとの |
xor | ビットごとの |
not | ビットごとの |
shl | |
shr |
& | |
---|---|
:= | |
[] | |
() | |
. | レコードのフィールドの |
.. |
制御 構造
[条件 分岐 (if文 )
[単純 なif文 if
条件 then真 の場合 の処理 ; end if;上記 の構文 では、条件 が真 である場合 に真 の場合 の処理 が実行 されます。偽 である場合 は、何 も処理 されません。- if-else
文 if
条件 then真 の場合 の処理 ; else偽 の場合 の処理 ; end if;上記 の構文 では、条件 が真 である場合 に真 の場合 の処理 が実行 され、偽 である場合 には偽 の場合 の処理 が実行 されます。- if-elsif-else
文 if
条件 1 then条件 1が真 の場合 の処理 ; elsif条件 2 then条件 2が真 の場合 の処理 ; else条件 1も条件 2も偽 の場合 の処理 ; end if;上記 の構文 では、条件 1が真 の場合 には条件 1が真 の場合 の処理 が実行 され、条件 2が真 の場合 には条件 2が真 の場合 の処理 が実行 され、どちらも偽 の場合 には、else以下 の偽 の場合 の処理 が実行 されます。
case文
[Adaにおけるcase
case
case
case expression is when choice1 => -- choice1の
処理 when choice2 => -- choice2の処理 ... when choiceN => -- choiceNの処理 when others => -- どの条件 にも一致 しない場合 の処理 end case;
expression
にはchoice
にはwhen
キーワードのchoice
にwhen others
を
反復
[Adaにおけるループ(
- loopループ
- whileループ
- forループ
loopループ
[loopループは、
loop --
実行 する処理 end loop;
with Ada.Text_IO; use Ada.Text_IO; procedure Example is I : Integer := 1; begin loop Put_Line("I is " & Integer'Image(I)); I := I + 1; exit when I = 5; end loop; end Example;
この
whileループ
[whileループは、
while condition loop --
実行 する処理 end loop;
with Ada.Text_IO; use Ada.Text_IO; procedure Example is I : Integer := 1; begin while I <= 5 loop Put_Line("I is " & Integer'Image(I)); I := I + 1; end loop; end Example;
この
forループ
[forループは、
for variable in range loop --
実行 する処理 end loop;
with Ada.Text_IO; use Ada.Text_IO; procedure Example is begin for I in 1..5 loop Put_Line("I is " & Integer'Image(I)); end loop; end Example;
この
まとめ
[- control_structures.adb
with Ada.Text_IO, Ada.Integer_Text_IO; use Ada.Text_IO, Ada.Integer_Text_IO; procedure Control_Structures is I : Integer; Num : Integer; begin -- if-then-else statement Put("Enter a number: "); Get(Num); if Num > 0 then Put_Line("The number is positive."); elsif Num = 0 then Put_Line("The number is zero."); else Put_Line("The number is negative."); end if; -- case statement Put("Enter a number between 1 and 3: "); Get(I); case I is when 1 => Put_Line("You entered 1."); when 2 => Put_Line("You entered 2."); when 3 => Put_Line("You entered 3."); when others => Put_Line("You entered something else."); end case; -- for loop Put_Line("Printing numbers from 1 to 10:"); for I in 1..10 loop Put(I, 2); Put(" "); end loop; New_Line; -- while loop I := 1; Put_Line("Printing odd numbers from 1 to 10:"); while I <= 10 loop if I mod 2 = 1 then Put(I, 2); Put(" "); end if; I := I + 1; end loop; New_Line; -- exit statement Put_Line("Printing numbers from 1 to 10 until 6 is reached:"); for I in 1..10 loop if I = 6 then exit; end if; Put(I, 2); Put(" "); end loop; New_Line; end Control_Structures;
このプログラムでは、ユーザーからの
サブプログラム
[[
サブプログラムは、メインプログラムの
手続 きの宣言
[procedure Procedure_Name (parameter1, parameter2, ...) is -- Declaration statements begin -- Statements end Procedure_Name;
関数 の宣言
[function Function_Name (parameter1, parameter2, ...) return Return_Type is -- Declaration statements begin -- Statements return return_value; end Function_Name;
引数 の渡 し方
[Adaでは、
例 procedure Example (A : in Integer; B : out Integer; C : in out Integer) is begin B := A + 1; --
変数 Bには値 が代入 される C := C + 1; --変数 Cには値 が代入 され、呼 び出 し元 の変数 にも反映 される end Example;
戻 り値 の取 り扱 い
[例 function Add (A : Integer; B : Integer) return Integer is begin return A + B; end Add; -- メインプログラム X := Add(2, 3); -- Xには5が
代入 される
オブジェクト指向 プログラミング
[[Adaでのオブジェクト
オブジェクト
クラスの定義 方法
[クラスは、データ
-- Pointクラスを
定義 package Point_Class is type Point is tagged record X, Y : Integer; end record; procedure Set_Point(P : in out Point; X, Y : Integer); function Get_X(P : Point) return Integer; function Get_Y(P : Point) return Integer; end Point_Class;
クラスの
継承
[Adaは、
-- Circleクラスを
定義 package Circle_Class is type Circle is new Point with record Radius : Integer; end record; procedure Set_Circle(C : in out Circle; X, Y, R : Integer); function Get_Radius(C : Circle) return Integer; end Circle_Class;
type
Adaの
例外 処理
[[
Adaには
begin --
例外 が発生 する可能 性 のある処理 exception when Exception1 => -- Exception1が発生 した場合 の処理 when Exception2 => -- Exception2が発生 した場合 の処理 ... when others => --上記 以外 の例外 が発生 した場合 の処理 end;
ここで、Exception1やException2は、
others
キーワードは、
with Ada.Text_IO; use Ada.Text_IO; procedure Exception_Handling is A : Integer := 10; B : Integer := 0; Result : Integer; -- ゼロ
除算 を検出 する例外 処理 関数 function Divide(A, B : Integer) return Integer is begin if B = 0 then raise Program_Error; else return A / B; end if; end Divide; begin -- Divide関数 でゼロ除算 が発生 した場合 、 -- Program_Error例外 が発生 するため、例外 処理 が実行 される begin Result := Divide(A, B); Put_Line("Result: " & Result'Image); exception when Program_Error => Put_Line("Error: Division by zero."); end; Put_Line("End of program."); end Exception_Handling;
このDivide
B
が0であるProgram_Error
Program_Error
Divide
try-catch
Program_Error
タスク
[[タスクの
タスクとは、
タスクの
task Task_Name is entry Entry_Name (Parameter_List); end Task_Name;
ここで、Task_Name はタスクの
また、タスク
- セマフォ(Semaphore)
- ミューテックス(Mutex)
- リモート・リード、ローカル・マルチプル・ライト(Remote_Read, Local_Multiple_Write)
パッケージ
[[Adaでのパッケージの
パッケージは、Adaの
パッケージの
package Package_Name is -- インターフェース
部 end Package_Name; package body Package_Name is --実装 部 end Package_Name;
ファイル入出力
[[ファイルを
Adaにおけるファイル
with Ada.Text_IO; use Ada.Text_IO; procedure Main is F : File_Type; begin Create (F, Out_File, "output.txt"); --
出力 先 のファイルを "output.txt" に設定 end Main;
ファイルからの
デバッグとテスト
[[Adaのデバッグやテストの
Adaには、コンパイル
まず、コンパイル
ランタイム
また、Adaにはコードカバレッジツールも
附録
[チートシート
[with Ada.Text_IO; use Ada.Text_IO; procedure Subprogram_Cheat_Sheet is --
関数 の定義 function Add(a, b : Integer) return Integer is begin return a + b; end Add; --手続 きの定義 procedure Greet(name : in String) is begin Put("Hello, "); Put(name); Put_Line("!"); end Greet; --引数 の渡 し方 procedure Pass_By_Value(x : Integer) is begin x := 0; --値 を変更 しても呼 び出 し元 の変数 に影響 はない end Pass_By_Value; procedure Pass_By_Reference(x : in out Integer) is begin x := 0; --値 を変更 すると呼 び出 し元 の変数 にも影響 がある end Pass_By_Reference; --戻 り値 の取 り扱 い function Divide(a, b : Integer) return Float is Result : Float; begin if b = 0 then raise Constraint_Error with "Division by zero"; else Result := Float(a) / Float(b); end if; return Result; end Divide; --例外 処理 procedure Exception_Handling is begin Put("Enter an integer: "); declare Num : Integer := Integer'Value(Get_Line); begin if Num < 0 then raise Constraint_Error with "The number must be non-negative"; else Put("The square root of "); Put(Num, Width => 0); Put(" is "); Put(Float'Sqrt(Float(Num)), 2); New_Line; end if; exception when Constraint_Error => Put_Line("Error: " & Exception_Message); end; end Exception_Handling; begin -- テスト Put_Line("Add(1, 2) = " & Integer'Image(Add(1, 2))); Greet("Alice"); --引数 の渡 し方 declare x : Integer := 1; begin Pass_By_Value(x); Put_Line("x = " & Integer'Image(x)); -- 1 Pass_By_Reference(x); Put_Line("x = " & Integer'Image(x)); -- 0 end; --戻 り値 の取 り扱 い Put_Line("Divide(4, 2) = " & Float'Image(Divide(4, 2))); Put_Line("Divide(4, 0) = " & Float'Image(Divide(4, 0))); -- Constraint_Error --例外 処理 Exception_Handling; end Subprogram_Cheat
with Ada.Text_IO; use Ada.Text_IO; procedure OOP_Cheat_Sheet is -- クラスの
定義 type MyClass is tagged record x: Integer; end record; -- クラスの継承 type MySubclass is new MyClass with record y: Integer; end record; -- ポリモーフィズム type MyClass_Access is access all MyClass'Class; procedure MyProc (Obj : MyClass_Access'Class); -- クラスメソッド function Get_X (Obj : MyClass'Class) return Integer is begin return Obj.x; end Get_X; -- クラスの操作 procedure Set_X (Obj : in out MyClass'Class; Val : Integer) is begin Obj.x := Val; end Set_X; -- クラスの初期 化 overriding procedure Initialize (Obj : in out MyClass'Class) is begin Obj.x := 0; end Initialize; -- クラスの終了 処理 overriding procedure Finalize (Obj : in out MyClass'Class) is begin null; end Finalize; -- クラスの利用 例 Obj : MyClass'Class := new MyClass; begin Set_X (Obj, 42); Put_Line (Integer'Image (Get_X (Obj))); end OOP_Cheat_Sheet;
用語 集
[- パッケージ(package):
関連 するサブプログラムや型 、定数 などをひとまとめにした、独立 したコンパイル単位 。パッケージ仕様 とパッケージ本体 に分 かれる。 - タイプ(type):データの
種類 を定義 する。整数 型 、浮動 小数点 型 、文字 型 などがある。型 の定義 には、レコード型 や配列 型 なども使用 できる。 - モジュール(module):Adaプログラムの
構成 単位 。複数 のパッケージやサブプログラムから構成 され、単一 のコンパイル単位 となる。 - サブプログラム(subprogram):
繰 り返 し使 われる処理 をまとめた、関数 や手続 きなどの部品 。関数 は値 を返 し、手続 きは値 を返 さない。 引数 (parameter):サブプログラムに与 える入力 値 。サブプログラム内 でのみ使用 できる変数 であり、呼 び出 し元 の変数 に影響 を与 えない。例外 (exception):プログラムの実行 中 に発生 するエラーを処理 するためのメカニズム。例外 が発生 した場合 は、例外 処理 部分 に制御 が移 る。継承 (inheritance):オブジェクト指向 プログラミングにおける、新 しいクラスの定義 時 に既存 のクラスを基 にして新 たな機能 を追加 する仕組 み。- ポリモーフィズム(polymorphism):オブジェクト
指向 プログラミングにおける、異 なるクラスのオブジェクトを同 じインタフェースで扱 うことができる性質 。 - タスク(task):
並列 処理 を実現 するための機能 。Adaでは、タスクの生成 、同期 、通信 などを行 うことができる。 - ファイル(file):
外部 記憶 装置 に格納 されたデータを扱 うためのデータ型 。ファイルをオープンすることで、ファイルからの入力 やファイルへの出力 が可能 になる。 名前 空間 (namespace):名前 の衝突 を回避 するための仕組 み。パッケージの名前 空間 は、パッケージ内 で定義 されます。