それ自体から呼び出される、または別のアクティブのプロシージャーから 呼び出されるアクティブのプロシージャーは、 再帰的 プロシージャーです。 そのような呼び出しは、再帰と呼ばれます。
再帰的に呼び出されたプロシージャーは、PROCEDURE ステートメントで 指定された RECURSIVE 属性を持たなければなりません。
|
再帰プロシージャーの呼び出しごとの環境 (自動変数の値など) は、 被制御変数の割り振りのスタッキングと類似した方法で 保存されます (被制御ストレージとその属性を参照)。 環境は、再帰的呼び出し時に、最後に記憶された環境がスタックに入れられ、 その呼び出しの終了時にスタックから除去される と考えてください。 現行ブロック内のラベル定数は、常に、そのラベルが入っているブロックの現行呼び出しへの参照になります。
ラベル定数が特定呼び出しのラベル変数に割り当てられ、 ラベル変数が再帰的プロシージャー内部で宣言されていない場合には、 別の呼び出しでその変数を指定する GO TO ステートメントが、 現行および介在するプロシージャーや開始ブロックを終了し、 割り当てが行われたときの環境を復元します。
再帰的プロシージャー内から入り口変数を通して呼び出された別の プロシージャーの環境は、その入り口定数がその変数に 割り当てられたときに存在していた環境です。 次の例を考えてみてください。
I=1;
call A; /* First invocation of A */
A: proc recursive;
declare Ev entry variable static;
if I=1 then
do;
I=2;
Ev=B;
call A; /* 2nd invocation of A */
end;
else call Ev; /* Invokes B with environment */
/* of first invocation of A */
B: proc;
go to Out;
end B;
Out: end A;
プロシージャー B の中の GO TO ステートメントは、 1 回目に呼び出された A 内の END A ステートメントに 制御を移し、B を終了させるほかに、2 つの A を終了させます。
再帰的プロシージャーの 1 回の活動化時に割り振られた変数の値は、次にそのプロシージャーが活動化されたときに変更されないようにしなければなりません。 これは、変数のスタッキングによって解決されます。 スタッキングは後入れ先出し法で処理されるため、 自動変数の最も新しい世代だけを参照することができます。 静的変数は、再帰の影響を受けないので、 再帰的に呼び出されたプロシージャー相互間の連絡に使用できます。 これは、再帰的プロシージャーを含んでいるプロシージャー内で宣言された自動変数にも、被制御変数と基底付き変数にも適用されます。 次に例を示します。
A: proc; dcl X;
·
·
·
B: proc recursive; dcl Z,Y static; call B;
·
·
·
end B; end A;
変数 X の世代は 1 つであり、 プロシージャー B の呼び出しのつど代わることはありません。 変数 Z の世代は、プロシージャー B の呼び出しのつど代わります。 変数 Y は、プロシージャー B の中でだけ 参照することができ、呼び出しのつど再割り振りされることは ありません (変数のスタッキングという概念は、被制御ストレージとその属性の被制御変数の説明でも重要です)。