<3> プログラムヘッダと宣言部 (標準 Pascal 範囲内での Delphi 入門)

# 3. プログラムヘッダと宣言部
プログラムは**ヘッダ**と**ブロック**で構成されています。ブロックは宣言部と実行部で構成されており、実行部は複合文で構成されています。

```
プログラム = 
　[プログラムヘッダ (program)]
　プログラムブロック.

プログラムブロック =
　[uses 句]
　ブロック.

ブロック = 
　[ラベル宣言部 (label)]
　[定数定義部 (const)]
　[型定義部 (type)]
　[変数宣言部 (var)]
　[手続き・関数宣言部 (procedure / function)]
　実行部 (begin～end).

実行部 =
  複合文. 
```

Delphi の場合、ブロック内にある実行部以外の節 (宣言部 / 定義部) は、順序を入れ替えたり、同じ節を複数回記述する事ができますが、**標準 Pascal では記述順序が決まっています**。Delphi のコードを標準 Pascal で動作させる際に忘れがちなので注意してください。

## 3.1. プログラムヘッダ (Program heading )
プログラムヘッダはプログラムと外部環境とのコミュニケーションのためにあります。

```
プログラムヘッダ = 
　PROGRAM 識別子 ["(" パラメータリスト ")"] ";".
パラメータリスト =
  識別子 { "," 識別子}. 
```

プログラム名は殆どの環境でファイル名です。例えば `Hello.pas` のプログラム名は `Hello` となります。

```pascal:Hello.pas
program Hello(output);
begin
  Writeln('Hello, World.');
end.
```

パラメータリストに書かれた識別子はプログラムのブロックの変数宣言部 ([3.5. 節](#35-%E5%A4%89%E6%95%B0%E5%AE%A3%E8%A8%80%E9%83%A8)) で局所変数と同じように宣言する必要があります。

C 言語の main() 関数の argc / \*\*argv をご存知でしたら**一旦完全に忘れてください**。あれを想定していると混乱すると思います。

さらに混乱させてしまうかもしれませんが、**Delphi 等のモダンな Pascal はこのプログラムヘッダを無視します**。つまり記述する必要はありません。しかしながら、標準 Pascal での存在意義を知ることも大事だと思いますので、プログラムヘッダはあるものとして話を続けます。

**See also:**

 - [program ヘッダー (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A8%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%EF%BC%88Delphi%EF%BC%89#program_.E3.83.98.E3.83.83.E3.83.80.E3.83.BC)
 - [Delphi で最少のソースコードを書いてみる (Qiita)](https://qiita.com/ht_deko/items/c81a8bacd7e299c45340)

## 3.2. ラベル宣言部 (Label declaration part)
プログラムの文には [goto](https://qiita.com/ht_deko/items/05af01a81f7c3bb5eeb4#47-goto-%E6%96%87) 文で参照できるように `ラベル + ':'` を書きます。ラベルは使用する前に**ラベル宣言部**で宣言しておく必要があります。ラベルはカンマ区切りで複数登録できます。

```
ラベル宣言部 = 
  label (符号なし整数 | 識別子) {"," (符号なし整数 | 識別子)} ";".
```

符号なし整数は 0～9999 (Delphi の場合 0～4294967295) の範囲内の値です。

```pascal:labeltest.pas
program labeltest(output);
label 
  1;
begin
1:
  goto 1;
end.
```

Delphi の場合にはラベルに識別子が使えます。

```pascal:labeltest.pas
program labeltest(output);
label 
  loop;
begin
loop:
  goto loop;
end.
```

## 3.3. 定数定義部 (Constant declaration part)
**定数定義部**では定数の同義語となる名前を定義します。

```
定数定義部 = 
  const 識別子 "=" 定数 ";" {識別子 "=" 定数 ";"}.

定数 = 
  (数値 | 文字列 | 定数名).
```

定数の右辺には前方で定義した定数名を指定する事もできます。

```pascal:consttest.pas
program consttest(output);
const
  STR = 'Hello,world.';
  INT = 60;
  INT2 = INT; // 60
begin
end.
```

**See also:**

 - [宣言された定数 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%AE%A3%E8%A8%80%E3%81%95%E3%82%8C%E3%81%9F%E5%AE%9A%E6%95%B0)

### (3.3.1.) 定数式 (Constant Expressions)
Delphi の場合、**定数式**も使えます。

```pascal:consttest.pas
program consttest(output);
const
  STR = 'Hello,’ + ’world.';
  INT = 20 * 30;
begin
end.
```

定数式には次の関数も利用可能です。

|関数|パラメータ|説明|
|:---|:---|:---|
|[Abs()](http://docwiki.embarcadero.com/Libraries/ja/System.Abs)|単純型の定数または<br>単純値|値の絶対値を返す|
|[Chr()](http://docwiki.embarcadero.com/Libraries/ja/System.Chr)|順序型の定数または<br>順序数|順序数をもつ文字を返す|
|[Hi()](http://docwiki.embarcadero.com/Libraries/ja/System.Hi)|整数型の定数または<br>整数値|上位バイトを<br>符号なしの値として返す|
|[High()](http://docwiki.embarcadero.com/Libraries/ja/System.High)|順序型の定数または<br>順序数|型の範囲内での最大値を返す|
|[Length()](http://docwiki.embarcadero.com/Libraries/ja/System.Length)|文字列または配列|文字の数や配列の要素数を返す|
|[Lo()](http://docwiki.embarcadero.com/Libraries/ja/System.Lo)|整数型の定数または<br>整数値|下位バイトを<br>符号なしの値として返す|
|[Low()](http://docwiki.embarcadero.com/Libraries/ja/System.Low)|順序型の定数または<br>順序数|型の範囲内での最小値を返す|
|[Odd()](http://docwiki.embarcadero.com/Libraries/ja/System.Odd)|順序型の定数または<br>順序値|値が奇数のときに <br>True を返す|
|[Ord()](http://docwiki.embarcadero.com/Libraries/ja/System.Ord)|文字型の定数または<br>文字定数|現在の文字集合での<br>順序数を返す|
|[Pred()](http://docwiki.embarcadero.com/Libraries/ja/System.Pred)|整数型の定数|値の一つ前の値を返す|
|[Round()](http://docwiki.embarcadero.com/Libraries/ja/System.Round)|実数型の定数または<br>実数値|値を丸めた整数を返す|
|[Succ()](http://docwiki.embarcadero.com/Libraries/ja/System.Succ)|整数型の定数または<br>整数値|値の一つ次の値を返す|
|[Swap()](http://docwiki.embarcadero.com/Libraries/ja/System.Swap)|整数型の定数または<br>整数値|整数値（ワード）の上位バイトと<br>下位バイトを入れ替える|
|[Trunc()](http://docwiki.embarcadero.com/Libraries/ja/System.Trunc)|実数型の定数または<br>実数値|値の整数部を返す|

**See also:**

 - [定数式 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%AE%A3%E8%A8%80%E3%81%95%E3%82%8C%E3%81%9F%E5%AE%9A%E6%95%B0#.E5.AE.9A.E6.95.B0.E5.BC.8F)

### (3.3.2.) 型付きの定数 (Typed Constants)
Delphi の場合、**型付きの定数**も定義できます。

```
定数定義部 = 
  const 識別子 ":" 型識別子 "=" 定数 ";" {識別子 ":" 型識別子 "=" 定数 ";"}.
```

```pascal:consttest.pas
program consttest(output);
const
  STR: string = 'Hello,world.';
  INT: Integer = 60;
begin
end.
```

但し、型付きの定数を定数式の中に含める事はできません。

```pascal
const
  INT1 = 60;          // 真の定数
  INT2: Integer = 60; // 型付き定数
  INT3 = INT1 + 10;   // OK: 真の定数を使った定数式
  INT4 = INT2 + 10;   // NG: 型付き定数を使った定数式
```

**See also:**

 - [型付き定数 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/Rio/ja/%E5%AE%A3%E8%A8%80%E3%81%95%E3%82%8C%E3%81%9F%E5%AE%9A%E6%95%B0#.E5.9E.8B.E4.BB.98.E3.81.8D.E5.AE.9A.E6.95.B0)

## 3.4. 型定義部 (Type definition part)
**型定義部**ではユーザー定義の型を定義します。

```
型定義部 = 
  type 識別子 "=" 型 ";" {識別子 "=" 型 ";"}.

型 = 
  (単純型 | 構造型 | ポインタ型).
```

**See also:**

 - [型の宣言 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%9E%8B%E3%81%AE%E5%AE%A3%E8%A8%80)

## 3.5. 変数宣言部 (Variable declaration part)
**変数宣言部**では変数を使えるように宣言します。

```
変数宣言部 = 
  var 識別子 {"," 識別子} ":" 型 ";" {識別子 {"," 識別子} ":" 型 ";"}.
```

こんな感じです。

```pascal
var
  i, l: Integer;
  c: Char; 
```

Delphi ではグローバル変数に限り、変数の宣言と同時に初期化を行うことができます。

```pascal
var 
  i: Integer = 7;
```

グローバル変数宣言が初期値を伴わない場合、その変数が占有するメモリはゼロで初期化されます。

**See also:**

 - [変数（Delphi）(DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E5%A4%89%E6%95%B0%EF%BC%88Delphi%EF%BC%89)

### (3.5.1.) プログラムヘッダのパラメータ
プログラムヘッダのパラメータリストに書かれたパラメータは**外部実体**であり、通常はファイルです。

定義済み変数である **Input** と **Output** は例外的に変数宣言部に記述する必要はありませんが、それ以外のパラメータはこの変数宣言部で宣言する必要があります。

|変数|型|説明|
|:---:|:---:|:---:|
|[Input](http://docwiki.embarcadero.com/Libraries/ja/System.Input)|[テキストファイル](https://qiita.com/ht_deko/items/986fa01c9e6cfc3fd673#92-%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)|標準入力|
|[Output](http://docwiki.embarcadero.com/Libraries/ja/System.Output)|[テキストファイル](https://qiita.com/ht_deko/items/986fa01c9e6cfc3fd673#92-%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)|標準出力|

例えば標準出力を使いたい場合にはプログラムヘッダのパラメータに **Output** が必要で、標準入力を使いたい場合にはプログラムヘッダのパラメータに **Input** が必要です。

例えば標準入出力を使うにはプログラムヘッダのパラメータを次のように指定します。**Input** と **Output** の並びは逆でも構いません。

```pascal
program Console(Input, Output);
begin

end.
```

次の例ではパラメータ **ABC** と **DEF** を宣言しています。

```pascal
program Console(ABC, Output, Input, DEF);
var
  ABC: file of Text;
  DEF: file of Text;
begin

end.
```

さて、

> Delphi 等のモダンな Pascal はこのプログラムヘッダを無視します。つまり記述する必要はありません。

と書きましたが、Delphi で標準出力や標準入力を使いたい場合にはどうすればいいのでしょうか？

```pascal
program Console;
{$APPTYPE CONSOLE}
begin

end.
```

Delphi では `{$APPTYPE CONSOLE}` 指令を記述するか、プロジェクトオプションでコンソールアプリケーションを生成するように指定すると、**Output** 変数が標準出力に、**Input** 変数が標準入力に割り当てられるようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21785/a8a00118-bb49-9178-f94a-2fb38ac2343a.png)

**See also:**

 - [System.Input (DocWiki)](http://docwiki.embarcadero.com/Libraries/ja/System.Input)
 - [System.Output(DocWiki)](http://docwiki.embarcadero.com/Libraries/ja/System.Out)

### (3.5.2) インライン変数宣言 (Inline Variable Declaration)
Pascal ではブロック中で変数を宣言することはできないのですが、Delphi は 10.3 Rio から型推論可能なインライン変数宣言が可能になりました。

 - [インライン変数宣言 (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E5%A4%89%E6%95%B0%E5%AE%A3%E8%A8%80)

例えば従来このように記述していた **for** 文は、

```pascal
var
  i: Integer;
begin
  for i := 0 to 9 do
    writeln(i);
end;
```

インライン変数宣言と型推論のおかげで次のように記述可能になっています。

```pascal
begin
  for var i := 0 to 9 do
    writeln(i);
end;
```

## 3.6. 手続き・関数宣言部 (Procedure and Function declaration part)

**手続き**や**関数**はこの**手続き・関数宣言部**で使用前に宣言する必要があります。**手続き・関数宣言部**は基本的にプログラムと同じ形式です。

```
手続き・関数宣言部 = 
  手続き・関数 {手続き・関数}.

手続き・関数 = 
　手続き・関数 (procedure | function) [指令]
　手続き・関数ブロック.

手続き・関数ブロック = 
　[ラベル宣言部 (label)]
　[定数定義部 (const)]
　[型定義部 (type)]
　[変数宣言部 (var)]
　[手続き・関数宣言部 (procedure / function)]
　実行部 (begin～end).

実行部 =
  複合文. 
```

手続きと関数は、まとめて**ルーチン**と呼ばれます。

## 3.7. 識別子とラベルの有効範囲
同じレベルかつ同じ有効範囲 (スコープ) の中では同じ識別子 (やラベル値) を 2 回以上宣言できません。

# 索引
[ [← 2. データの概念: 単純データ型](https://qiita.com/ht_deko/items/5c04bb2b42947e29d94b) ] [ [↑ 目次へ](https://qiita.com/ht_deko/items/e2796788c65c2cda1de5) ] [ [→ 4. 記法: 動作の概念](https://qiita.com/ht_deko/items/05af01a81f7c3bb5eeb4) ] [:sushi:](https://qiita.com/ht_deko/items/26e37c293ee14c43238e)