【PL/I学習|実務向け】PL/Iにおける予約語の不在とデータ宣言の柔軟性

1. 導入: PL/Iの予約語不在がもたらす柔軟性と課題

メインフレームの世界では、COBOLと並んでPL/Iも現役で活躍しています。PL/Iの最大の特徴の一つに、多くのプログラミング言語とは異なり、予約語(RESERVED WORDS)が基本的に存在しないことが挙げられます。これは、`IF`や`THEN`、`DECLARE`といった、他の言語では命令やキーワードとして扱われる単語を、変数名やラベル名として自由に定義できることを意味します。この柔軟性はプログラマの記述自由度を大いに高めますが、一方で、コードの解析や移行ツールの開発においては、特有の難しさをもたらします。本稿では、PL/Iのこのユニークな仕様について、基礎知識から具体的な実装、そして現場での注意点までを解説します。

2. PL/Iの予約語不在の基礎知識

多くのプログラミング言語では、コンパイラやインタプリタがコードを解釈する際に、特定の単語(予約語)を特別な意味を持つものとして扱います。例えば、`IF`は条件分岐の開始、`THEN`はその条件が真の場合の処理の区切り、`DECLARE`は変数の宣言を表します。これらの単語を変数名などに使用しようとすると、通常はコンパイルエラーとなります。

しかし、PL/Iでは、これらの単語が「予約語」として固定されていません。コンパイラは、文脈を高度に解析することで、それらが命令として使われているのか、それとも識別子(変数名、ラベル名など)として使われているのかを判断します。例えば、以下のコード例を見てみましょう。

1
DCL IF FIXED BIN; / IF という名前の変数を固定小数点バイナリ型で宣言 /
IF IF = 1 THEN / 宣言された IF 変数が 1 と等しいかどうかを判定 /

この例では、最初の `IF` は `DECLARE` 文の中で変数名を宣言するために使われています。一方、二行目の `IF` は条件分岐の開始を示すキーワードとして機能しています。このように、PL/Iのコンパイラは、文脈に応じて同じ単語に異なる意味を与えます。この仕組みは、プログラマにとっては非常に強力な自由度を提供しますが、後述する解析ツールの開発者にとっては、その解析ロジックの複雑さを増大させる要因となります。

3. 実装/解決策: PL/Iにおけるデータ宣言と属性

PL/Iでは、変数は `DECLARE` (または `DCL`) 文によって明示的に宣言する必要があります。この宣言では、変数の名前だけでなく、そのデータ型や属性を細かく指定できます。

  • データ型: `FIXED` (固定小数点数), `FLOAT` (浮動小数点数), `CHARACTER` (文字), `BIT` (ビット), `POINTER` (ポインタ) など。
  • 属性: `BIN` (バイナリ), `DEC` (10進), `REAL` (実数), `COMPLEX` (複素数), `VARYING` (可変長), `CONTROLLED` (制御変数) など。

これらのデータ型と属性を組み合わせることで、非常に多様なデータ構造を表現することが可能です。前述の「予約語不在」の仕様と組み合わせることで、例えば `DECLARE CHARACTER VARYING IF BIT (1) THEN FIXED …` のような、一見すると読みにくい、しかしPL/Iの文法上は有効な宣言も理論上は可能です(ただし、可読性の観点からは推奨されません)。

4. サンプルプログラム: 変数宣言と簡単な処理

ここでは、PL/Iで「予約語」となりうる単語を変数名として使用し、基本的な処理を行うサンプルコードを示します。

1
/ ——————————————————————– /
/ サンプルプログラム: PL/Iにおける予約語不在とデータ宣言の例 /
/ ——————————————————————– /
SAMPLE_PROG: PROC OPTIONS(MAIN);

/ IF という名前の変数を固定小数点バイナリ型として宣言 /
DCL IF FIXED BIN;

/ THEN という名前の変数を文字型(可変長)として宣言 /
DCL THEN CHARACTER(10) VARYING;

/ DECLARE という名前の変数をビット型(固定長)として宣言 /
DCL DECLARE BIT(8);

/ THEN という名前の変数を初期化 /
THEN = ‘START’;

/ IF 変数に初期値 1 を代入 /
IF = 1;

/ THEN 変数に初期値 2 を代入 /
THEN = ‘SECOND’; / THEN 変数の値は ‘SECOND’ に上書きされる /

/ IF 変数の値を判定し、条件分岐を行う /
/ ここで使われる IF はキーワードとしての IF /
IF IF = 1 THEN / IF 変数が 1 ならこのブロックを実行 /
DO;
PUT SKIP LIST(‘IF Variable is 1.’); / IF 変数が 1 であることを表示 /

/ DECLARE 変数に値を代入 /
/ ここで使われる DECLARE は変数名としての DECLARE /
DECLARE = ‘ABCDEFGH’; / DECLARE 変数に文字列を代入 /

PUT SKIP LIST(‘THEN Variable is: ‘, THEN); / THEN 変数の現在の値を表示 /
PUT SKIP LIST(‘DECLARE Variable is: ‘, DECLARE); / DECLARE 変数の値を表示 /

END;
ELSE / IF 変数が 1 でないならこのブロックを実行 /
DO;
PUT SKIP LIST(‘IF Variable is NOT 1.’); / IF 変数が 1 でないことを表示 /
END;

/ THEN 変数に値を代入 /
THEN = ‘END’;

PUT SKIP LIST(‘Final THEN Variable: ‘, THEN); / THEN 変数の最終的な値を表示 /

END SAMPLE_PROG;

このサンプルでは、`IF`、`THEN`、`DECLARE` といった、他の言語では予約語となる単語を変数名として使用しています。コンパイラは、`DCL` の直後にある `IF`、`THEN`、`DECLARE` を変数名として認識し、それぞれのデータ型と属性を定義します。一方、条件分岐の `IF IF = 1 THEN` の部分では、最初の `IF` はキーワードとして、続く `IF` は変数名として正しく解釈されます。

5. 応用・注意点: 解析ツールの開発とコードの可読性

PL/Iの予約語不在の仕様は、特にレガシーシステムの解析や移行ツールを開発する際に、大きな課題となります。

  • 解析ツールの開発: 単純な文字列検索や正規表現によるパターンマッチングでは、文脈を正確に把握できません。例えば、`IF` という文字列が出現した場合、それが変数名なのか、それとも条件分岐の開始を示すキーワードなのかを判断するには、構文木(Abstract Syntax Tree, AST)を構築できるような、フルスペックのPL/Iパーサ(構文解析器)が必須となります。これは、ツールの開発コストを著しく上昇させる要因となります。
  • コードの可読性: プログラマの自由度が高い反面、意図的に、あるいは無意識に、予約語となりうる単語を変数名などに使用すると、コードの可読性が著しく低下する可能性があります。例えば、`IF` という変数名が多用されると、コードを読む際に「これは変数としてのIFか、それともキーワードとしてのIFか?」という判断を常に強いられることになります。
  • 規約の重要性: チーム開発や長期的な保守を考慮する場合、PL/Iにおいても命名規則やコーディング規約を厳格に定めることが非常に重要です。一般的には、他の言語で予約語となっている単語を変数名やラベル名として使用することは避けるのが賢明です。これにより、コードの可読性と保守性を保ち、誤解を防ぐことができます。

PL/Iの予約語不在という特性は、その言語の持つ柔軟性を示す一方で、開発者やツールの開発者にとっては常に意識すべき重要なポイントとなります。これらの特性を理解し、適切に管理することで、PL/Iでの開発はより効率的かつ安全に進めることができるでしょう。

コメント

タイトルとURLをコピーしました