【PL/I学習|豆知識】PL/Iプリプロセッサの深淵:マクロの「リスキャン」規則をマスターする

1. 導入:なぜマクロのリスキャンを理解すべきか

メインフレームのPL/I開発において、プリプロセッサによるマクロ展開は強力な武器ですが、意図せぬ動作に悩まされた経験はありませんか?特に「マクロが展開された結果、さらに別のマクロが含まれていた場合」の挙動、すなわち「リスキャン(再帰的展開)」を理解することは、コードの自動生成や複雑な条件コンパイルを制御する上で不可欠です。これを正しく理解することで、コードの保守性を高め、予期せぬ無限ループを回避できるようになります。

2. 基礎知識:リスキャンとは何か

PL/Iのプリプロセッサは、マクロの置換を一回行って終わりではありません。置換の結果生成された文字列に対して、さらにマクロ定義が残っていないかを「再度スキャン(リスキャン)」します。このプロセスは、置換すべきマクロが完全に消失するまで(不動点に達するまで)繰り返されます。現代的な言語の定数置換とは異なり、この再帰的な性質がPL/Iマクロの強力さと、同時に「不注意による無限ループ」という危険性を生んでいます。

3. 実装と解決策:多重置換の論理

リスキャンを利用すると、階層的な定義管理が可能です。例えば、環境設定値を段階的に解決させることで、保守性の高いコードを書くことができます。ただし、循環参照(AがBを呼び、BがAを呼ぶ)を作るとプリプロセッサが停止しなくなるため、定義の依存関係を単方向(A -> B -> C)に保つ設計が基本となります。

4. サンプルプログラム:リスカンの挙動確認

以下のコードは、マクロの連鎖的展開を示す実用的な例です。

/ プリプロセッサによる段階的置換のサンプル /
%REPLACE VER_MAJOR BY ‘2’;
%REPLACE VER_MINOR BY ‘0’;
/ マクロの中にマクロを含めることで、リスキャンによって合成される /
%REPLACE VERSION_STR BY ‘VER_MAJOR || “.” || VER_MINOR’;

/
コンパイル時、プリプロセッサはまずVERSION_STRを置換し、
次に内部のVER_MAJORとVER_MINORを置換して最終結果を得ます。
/
DCL SYS_VER CHAR(3) INIT(VERSION_STR);

5. 応用・注意点:現場でのトラブル回避

現場で最も陥りやすいのは、マクロ名と変数名を混同することです。
無限ループの回避: マクロ名と同じ文字列を置換後の文字列に含めないでください。デバッグ時には、プリプロセッサの出力結果(SYSINの展開後)を確認するのが一番の近道です。
不動点の考え方: 複雑なロジックを組む際は、「この置換はどこで収束するか」をフローチャートのように紙に書き出すと、バグの芽を早期に摘み取ることができます。
可読性の維持: リスキャンは便利ですが、多用しすぎると「どの値がどこで定義されているか」が追いづらくなります。ネストは最大でも3段階程度に留めるのが、堅牢なメインフレーム開発の秘訣です。

コメント

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