このドキュメントでは、ルーチン、つまり下位プログラムとして呼び出すことができるオブジェクトタイプについて説明します。
ヘルプルーチンとマップは他のオブジェクトからも呼び出されますが、厳密にはルーチンではないため、個別のドキュメントで説明しています。「ヘルプルーチン」および「マップ」を参照してください。
このドキュメントでは、次のトピックについて説明します。
一般に、Natural アプリケーションは単一の巨大なプログラムで構成されるのではなく、複数のモジュールに分割されます。 これらの各モジュールは、管理可能なサイズの機能ユニットであり、各モジュールは明確に定義された方法でアプリケーションの他のモジュールに接続されています。 これにより、適切に構造化されたアプリケーションが提供されるため、開発およびその後のメンテナンスが大幅に容易かつ迅速に行うことができるようになります。
メインプログラムの実行中には、他のプログラム、サブプログラム、サブルーチン、ヘルプルーチン、およびマップを呼び出すことができます。 続いてこれらのオブジェクトが他のオブジェクトを呼び出すことができます。例えば、サブルーチンが別のサブルーチンを呼び出すこともできます。 したがって、アプリケーションのモジュラー構造は非常に複雑になり、複数のレベルに拡張される可能性があります。
呼び出される各オブジェクトは、それを呼び出したオブジェクトのレベルの 1 つ下のレベルになります。つまり、下位オブジェクトを呼び出すたびに、レベル番号は 1 つ増加します。
直接実行されるプログラムはすべてレベル 1 です。メインプログラムによって直接呼び出されるサブプログラム、サブルーチン、マップ、ヘルプルーチンはレベル 2 になります。このサブルーチンがサブルーチンを呼び出すと、呼び出されたサブルーチンはレベル 3 になります。
別のオブジェクト内から FETCH
ステートメントで呼び出されたプログラムは、メインプログラムとして分類され、レベル 1 から動作します。 ただし、FETCH RETURN
で呼び出されたプログラムは、下位プログラムとして分類され、呼び出し元オブジェクトの 1 つ下のレベルが割り当てられます。
次の図は、呼び出されるオブジェクトの複数レベルの例と、これらのレベルがどのように数えられるかを示しています。
現在実行中のオブジェクトのレベル番号を確認する場合は、システム変数 *LEVEL
を使用できます。詳細については『システム変数』ドキュメントを参照してください。
このドキュメントでは、ルーチン、つまり下位プログラムとして呼び出すことができる次の Natural オブジェクトタイプについて説明します。
プログラム
ファンクション
サブルーチン
サブプログラム
ヘルプルーチンとマップは他のオブジェクトからも呼び出されますが、厳密にはルーチンではないため、個別のドキュメントで説明しています。「ヘルプルーチン」および「マップ」を参照してください。
基本的に、プログラム、サブプログラムおよびサブルーチンは、データの受け渡し方法やお互いのデータエリアを共有できるかどうかなどがそれぞれ異なります。 したがって、どのオブジェクトタイプをどの目的に使用するかの決定は、アプリケーションのデータ構造に大きく依存します。
プログラムは単独で実行し、テストできます。
プログラムは、他のオブジェクトから FETCH
または FETCH RETURN
ステートメントで呼び出すこともできます。 呼び出し元オブジェクトは、別のプログラム、サブプログラム、ファンクション、サブルーチン、またはヘルプルーチンのいずれでもかまいません。
プログラムが FETCH RETURN
で呼び出されると、呼び出し元オブジェクトの実行は終了されるのではなく中断され、FETCH
されたプログラムは下位プログラムとしてアクティブになります。 FETCH
されたプログラムの実行が終了すると、呼び出し元オブジェクトが再びアクティブになり、その実行は FETCH RETURN
ステートメントの次のステートメントから継続します。
プログラムが FETCH
で呼び出されると、呼び出し元オブジェクトの実行は終了し、FETCH
されたプログラムがメインプログラムとしてアクティブになります。 呼び出し元オブジェクトが、FETCH
されたプログラムの終了時に再びアクティブになることはありません。
以下では次のトピックについて説明します。
FETCH RETURN
で呼び出されるプログラムは、呼び出し元オブジェクトが使用するグローバルデータエリアにアクセスできます。
また、あらゆるプログラムには独自のローカルデータエリアがあり、その中にはそのプログラム内だけで使用されるフィールドが定義されます。
ただし、FETCH RETURN
で呼び出されたプログラムが独自のグローバルデータエリアを持つことはできません。
メインプログラムとして FETCH
で呼び出されるプログラムは、上記の図に示したように、通常は独自のグローバルデータエリアを設定します。 ただし、呼び出し元オブジェクトが設定したものと同じグローバルデータエリアを使用することもできます。
注意:
ソースプログラムは、RUN
ステートメントで呼び出すこともできます。『ステートメント』ドキュメントの RUN
ステートメントを参照してください。
"ファンクション" タイプのオブジェクトには、単一のファンクションの定義が含まれ、次のコーディング例で示されるような構造が可能です。
DEFINE FUNCTION ... DEFINE SUBROUTINE ... END-SUBROUTINE ... END-FUNCTION
DEFINE FUNCTION
と END-FUNCTION
の間のステートメントブロックには、ファンクションが呼び出されたときに実行されるすべてのステートメントを含める必要があります。
ファンクション定義内に内部サブルーチンを定義することは可能です。
ファンクションはファンクションコール構文を使用して呼び出されます。
オブジェクト内で繰り返し実行されるコードブロックがある場合は、インラインサブルーチンを使用すると便利です。 次に、DEFINE SUBROUTINE
ステートメントブロック内でこのブロックを 1 度だけコードし、いくつかの PERFORM
ステートメントで呼び出すだけです。
呼び出し元オブジェクトのグローバルデータエリア(例:GDA1)は、ファンクション定義内では参照できません。 また、ファンクションを入力すると、ランタイム環境によって新しいグローバルデータエリアが作成されるため、ファンクションによって呼び出されるオブジェクトは、このファンクションを呼び出すオブジェクトのグローバルデータエリア(GDA1)を参照できません。
パラメータデータエリア(例:PDA1)は、パラメータ変更時の管理工数を最小限にするために、ファンクションコールおよびファンクション定義のパラメータにアクセスするために使用できます。
プロトタイプ定義を含むコピーコードオブジェクトは、必要に応じて、ファンクションコール参照の戻り変数のタイプを決定してパラメータをチェックするのみの目的で、コンパイル時に使用されます。
サブルーチンを構成するステートメントは、DEFINE SUBROUTINE
... END-SUBROUTINE
ステートメントブロック内に定義する必要があります。
サブルーチンは PERFORM
ステートメントによって呼び出されます。
サブルーチンには、インラインサブルーチンと外部サブルーチンがあります。
インラインサブルーチン
インラインサブルーチンは、このサブルーチンを呼び出す PERFORM
ステートメントが含まれるオブジェクト内に定義されるものです。
外部サブルーチン
外部サブルーチンは、このサブルーチンを呼び出すオブジェクトの外部にある別のサブルーチンタイプのオブジェクト内に定義されるものです。
1 つのオブジェクト内で繰り返し実行されるコードブロックがある場合は、インラインサブルーチンを使用すると便利です。 次に、DEFINE SUBROUTINE
ステートメントブロック内でこのブロックを 1 度だけコードし、いくつかの PERFORM
ステートメントで呼び出すだけです。
以下では次のトピックについて説明します。
インラインサブルーチンは、タイプがプログラム、ファンクション、サブプログラム、サブルーチン、またはヘルプルーチンのプログラミングオブジェクト内に含めることができます。
インラインサブルーチンが非常に大きく、それを含むオブジェクトの読みやすさが損なわれる場合は、アプリケーションの読みやすさが改善されるように、外部サブルーチンに置き換えることを検討できます。
インラインサブルーチンは、ローカルデータエリアと、このサブルーチンを含むオブジェクトが使用するグローバルデータエリアにアクセスできます。
外部サブルーチン、つまりサブルーチンタイプのオブジェクトは単独では実行できません。 これは、他のオブジェクトから呼び出す必要があります。 呼び出し元オブジェクトは、プログラム、関数、サブプログラム、サブルーチン、またはヘルプルーチンのいずれでもかまいません。
外部サブルーチンは、呼び出し元オブジェクトが使用するグローバルデータエリアにアクセスできます。
また、PERFORM
ステートメントを使用して、呼び出し元オブジェクトから外部サブルーチンにパラメータを渡すことができます。 これらのパラメータは、サブルーチンの DEFINE DATA PARAMETER
ステートメント、またはサブルーチンが使用するパラメータデータエリアに定義する必要があります。
また、外部サブルーチンは、そのサブルーチン内のみで使用するフィールドを定義するローカルデータエリアを持つことができます。
ただし、外部サブルーチンが独自のグローバルデータエリアを持つことはできません。
通常、サブプログラムには、アプリケーション内のさまざまなオブジェクトに使用される一般に使用可能な標準ファンクションが含まれています。
サブプログラムは単独では実行できません。 これは、他のオブジェクトから呼び出す必要があります。 呼び出し元オブジェクトは、プログラム、関数、サブプログラム、サブルーチン、またはヘルプルーチンのいずれでもかまいません。
サブプログラムは、CALLNAT
ステートメントを使用して呼び出されます。
CALLNAT
ステートメントが実行されると、呼び出し元オブジェクトの実行は中断され、サブプログラムが実行されます。 このサブプログラムの実行後は、呼び出し元オブジェクトの実行が CALLNAT
ステートメントの次のステートメントから続行されます。
CALLNAT
ステートメントを使用して、パラメータを呼び出し元オブジェクトからサブプログラムに渡すことができます。 これらのパラメータは、呼び出し元オブジェクトからサブプログラムが使用できる唯一のデータです。 これらのパラメータは、サブプログラムの DEFINE DATA PARAMETER
ステートメント、またはサブプログラムが使用するパラメータデータエリアに定義する必要があります。
また、サブプログラムは、その中で使用するフィールドを定義する独自のローカルデータエリアを持つことができます。
サブプログラムがサブルーチンやヘルプルーチンを呼び出す場合は、そのようなサブルーチンやヘルプルーチンと共有する独自のグローバルデータエリアを設定することもできます。
ルーチン、つまりサブプログラム、外部サブルーチンまたはプログラムをそれぞれ呼び出す CALLNAT
、PERFORM
、または FETCH RETURN
ステートメントが実行されると、呼び出し元オブジェクトの実行は中断され、該当するルーチンの実行が始まります。
ルーチンの実行は、END
ステートメントに到達するまで、または ESCAPE ROUTINE
ステートメントの実行によってルーチンの処理が停止されるまで継続します。
いずれの場合も、呼び出し元オブジェクトの処理は、ルーチンを呼び出すために使用された CALLNAT
、PERFORM
または FETCH RETURN
ステートメントの次のステートメントから続行します。