【テクニカル・上級編】DOループにおけるITERATEおよびLEAVE文の制御フロー – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの深淵:ITERATEとLEAVEが制御フローにもたらす「静かなる革命」

汎用機の世界に長く身を置いていると、「なぜPL/Iという言語が、これほどまでにしぶとく生き残っているのか」を自問することがある。JavaやC#のモダンな設計思想に慣れた若手エンジニアからすれば、PL/Iの「予約語が存在しない」という仕様は、まさに悪夢のように映るだろう。しかし、この自由度こそが、アセンブラに近い低レイヤーの制御と、高度な抽象化を両立させるPL/Iの真骨頂なのだ。

今日は、バッチ処理やCICSオンラインにおけるループ制御の要、`ITERATE`と`LEAVE`について、現場の「地雷」を踏み抜かないための知見を共有したい。

1. 予約語なき世界での制御フロー:ITERATEとLEAVE

PL/Iには明確な「予約語」が存在しない。`IF`や`DO`といったキーワードも、文脈によって変数名として定義できてしまう。これはコンパイラの字句解析エンジンが、常に複雑な先読みを行っていることを意味する。

ネストされたループ内での `ITERATE`(次周へのスキップ)や `LEAVE`(強制脱出)を使用する際、最も注意すべきは「どのラベルを対象にしているか」というスコープの明確化だ。

/i
/ ネストされたDOループの制御例 /
OUTER_LOOP: DO I = 1 TO 100;
INNER_LOOP: DO J = 1 TO 10;

/ ポインタを用いた動的メモリの異常検知時 /
IF Ptr -> DATA_AREA.STATUS = ‘E’ THEN DO;
/ 内部ループを抜けて、外部ループの次周へスキップ /
ITERATE OUTER_LOOP;
END;

/ 重大なエラー発生時に全処理を強制中断 /
IF Ptr -> DATA_AREA.FATAL_ERR THEN DO;
LEAVE OUTER_LOOP; / ラベル指定により一気に脱出 /
END;

END INNER_LOOP;
END OUTER_LOOP;

ここで重要なのは、`LEAVE`や`ITERATE`を多用した複雑な制御フローが、後続のマイグレーション担当者にとっての「迷宮」になるという点だ。特に、`ON-UNIT`(例外処理)がスタックされている状況下でこれらが発行されると、制御が予期せぬスタックフレームへ戻る可能性がある。

2. マイグレーション時の「爆弾」:パックデシマルの内部符号

JavaやC#への移行において、最も悲鳴が上がるのが「パックデシマル(COMP-3)」の扱いだ。PL/Iでは単なる型定義の一つに過ぎないが、内部的にはニブル単位の符号管理を行っている。

特に、`LEAVE`でループを脱出する際、残存するデータ領域に「符号が壊れたパックデシマル」が残っていると、それを後続のモジュールが読み込んだ瞬間に `S0C7` アベンド(データ例外)を叩き出す。マイグレーション設計時には、ループ脱出前に必ず「クリーンアップ・ルーチン」を挟むか、あるいはターゲット言語の `BigDecimal` の厳密なバリデーション・ロジックを生成させる必要がある。

3. CICSとDB2における動的メモリ操作のエッジケース

ポインタ(`PTR`)を用いた動的ストレージ操作は、PL/Iの醍醐味だが、CICS環境下では劇薬だ。`ALLOCATE`文で確保したメモリを`LEAVE`で放置してループを抜ければ、当然ながら「ストレージ・リーク」が発生する。

CICSのタスクが再利用される際、このリークが蓄積し、ある日突然 `STORAGE SHORTAGE` でトランザクションが全滅する。

  • 現場の鉄則:
  • `LEAVE`や`ITERATE`の直前には、必ず確保したストレージの`FREE`を配置せよ。
  • `ON ANYCONDITION` を活用し、ループ内での異常終了時にもメモリを解放する安全装置を組み込むこと。

4. コンパイラ最適化とダンプ解析の深淵

コンパイラオプションの `OPTIMIZE(3)` を指定すると、コンパイラは「冗長」と判断したコードを果敢にインライン化し、ループの構造を破壊する。この状態でアベンドが発生すると、ダンプ上の命令ポインタがソースコードのどの行を指しているのか、一見して判別不能になることが多い。

ダンプ解析の際、`LEAVE`による脱出経路が最適化で「ジャンプ先を直接計算する命令」に置き換えられている場合、`SYMDUMP`や`IPCS`を駆使しても、スタックフレームの追跡には相当の慣れが必要だ。

最後に:なぜレガシーを語るのか

PL/Iのコードをモダン言語に書き換える際、単に構文を変換するだけでは不十分だ。我々アーキテクトに求められているのは、「当時のプログラマが、限られたメモリとCPU資源の中で、どのような意図を持ってこのループを組んだのか」という文脈の継承である。

`ITERATE`の一行、`LEAVE`の一行に込められた「計算資源への敬意」と「処理速度への執着」。これらを理解せずにマイグレーションを行うことは、歴史ある大聖堂の設計図を読まずに、その壁を塗り替えることに等しい。

もし、今まさに移行の現場でPL/Iの迷宮に迷い込んでいるなら、まずはダンプを読み、そのコードの背後にある「生存戦略」に耳を傾けてみてほしい。答えは必ず、コンパイラが吐き出したバイナリの中に眠っている。

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