ブロックの有効化および再帰

プロシージャ ブロックは、呼び出されるたびにアクティブになり、呼び出しから戻るまで (またはローカル以外の 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 の独自のインスタンスが格納されます。

再帰プロシージャの詳細については、「データ型」の章の「エントリ データ」のセクションを参照してください。