プロシージャ ブロックは、呼び出されるたびにアクティブになり、呼び出しから戻るまで (またはローカル以外の GOTO から包含するブロックの有効化に制御が移るまで) アクティブな状態となります。それらのプロシージャの有効化により、関連する記憶域ブロックがスタックに割り当てられます。この記憶域ブロックはスタック フレームと呼ばれ、それぞれのプロシージャの有効化に固有の情報 (制御が有効化から戻る位置など) を保持するために使用されます。
スタック フレームには、ブロック内で宣言された自動データ用の記憶域があります。そのため、ブロックが有効化されるたびに自動データの独自のコピーが格納されます。
プロシージャ A からプロシージャ B を呼び出すと、A の有効化に関連するスタック フレームが B の有効化に関連するスタック フレームによってプッシュダウンされます。B から制御が戻ると、B のスタック フレームがスタックから取り出され、A のスタック フレームが現在のスタック フレームになります。
プロシージャ A が呼び出す一連のプロシージャによって A が直接的または間接的に再度呼び出される場合、A のことを再帰プロシージャと呼びます。次に例を示します。
A: PROCEDURE RECURSIVE; . . . CALL A; . . . END A;
次の例は、ブロックの有効化および再帰の原則を使用してツリー構造のコピーを作成するプログラムを示しています。
. . NEW = COPY(OLD); . . COPY: PROCEDURE(IN) RETURNS(POINTER)| RECURSIVE; DECLARE (IN,OUT) POINTER; DECLARE 1 RECORD BASED, 2 FIELD1 FLOAT, 2 FIELD2 FLOAT, 2 DAUGHTER POINTER, 2 SON POINTER; DECLARE NULL BUILTIN; IF IN = NULL THEN RETURN(NULL); ALLOCATE RECORD SET(OUT); OUT->RECORD.FIELD1 = IN->RECORD.FIELD1; OUT->RECORD.FIELD2 = IN->RECORD.FIELD2; OUT->RECORD.DAUGHTER = COPY(IN->RECORD.DAUGHTER); OUT->RECORD.SON = COPY(IN->RECORD.SON); RETURN(OUT); END COPY;
この例で示すように、元のツリー構造の各レコードは SON レコードまたは DAUGHTER レコード (あるいはその両方) へのポインターを使用してリンクされます。SON フィールドと DAUGHTER フィールドは、いずれかが Null ポインター値であってもかまいません。COPY は、元のツリー構造のルートへのポインターを使用して呼び出され、そのコピーである新しいツリー構造のルートへのポインターを返します。COPY プロシージャが有効化されるたびに、変数 IN および OUT の独自のインスタンスが格納されます。
再帰プロシージャの詳細については、「データ型」の章の「エントリ データ」のセクションを参照してください。