バージョン 6.3.3
 —  プログラミングガイド  —

プログラム、関数、サブプログラム、およびサブルーチン

このドキュメントでは、ルーチン、つまり下位プログラムとして呼び出すことができるオブジェクトタイプについて説明します。

ヘルプルーチンとマップは他のオブジェクトからも呼び出されますが、厳密にはルーチンではないため、個別のドキュメントで説明しています。「ヘルプルーチン」および「マップ」を参照してください。

このドキュメントでは、次のトピックについて説明します。


モジュラーアプリケーション構造

一般に、Natural アプリケーションは単一の巨大なプログラムで構成されるのではなく、複数のモジュールに分割されます。 これらの各モジュールは、管理可能なサイズの機能ユニットであり、各モジュールは明確に定義された方法でアプリケーションの他のモジュールに接続されています。 これにより、適切に構造化されたアプリケーションが提供されるため、開発およびその後のメンテナンスが大幅に容易かつ迅速に行うことができるようになります。

メインプログラムの実行中には、他のプログラム、サブプログラム、サブルーチン、ヘルプルーチン、およびマップを呼び出すことができます。 続いてこれらのオブジェクトが他のオブジェクトを呼び出すことができます。例えば、サブルーチンが別のサブルーチンを呼び出すこともできます。 したがって、アプリケーションのモジュラー構造は非常に複雑になり、複数のレベルに拡張される可能性があります。

Top of page

呼び出されるオブジェクトの複数レベル

呼び出される各オブジェクトは、それを呼び出したオブジェクトのレベルの 1 つ下のレベルになります。つまり、下位オブジェクトを呼び出すたびに、レベル番号は 1 つ増加します。

直接実行されるプログラムはすべてレベル 1 です。メインプログラムによって直接呼び出されるサブプログラム、サブルーチン、マップ、ヘルプルーチンはレベル 2 になります。このサブルーチンがサブルーチンを呼び出すと、呼び出されたサブルーチンはレベル 3 になります。

別のオブジェクト内から FETCH ステートメントで呼び出されたプログラムは、メインプログラムとして分類され、レベル 1 から動作します。 ただし、FETCH RETURN で呼び出されたプログラムは、下位プログラムとして分類され、呼び出し元オブジェクトの 1 つ下のレベルが割り当てられます。

次の図は、呼び出されるオブジェクトの複数レベルの例と、これらのレベルがどのように数えられるかを示しています。

現在実行中のオブジェクトのレベル番号を確認する場合は、システム変数 *LEVEL を使用できます。詳細については『システム変数』ドキュメントを参照してください。

このドキュメントでは、ルーチン、つまり下位プログラムとして呼び出すことができる次の Natural オブジェクトタイプについて説明します。

ヘルプルーチンとマップは他のオブジェクトからも呼び出されますが、厳密にはルーチンではないため、個別のドキュメントで説明しています。「ヘルプルーチン」および「マップ」を参照してください。

基本的に、プログラム、サブプログラムおよびサブルーチンは、データの受け渡し方法やお互いのデータエリアを共有できるかどうかなどがそれぞれ異なります。 したがって、どのオブジェクトタイプをどの目的に使用するかの決定は、アプリケーションのデータ構造に大きく依存します。

Top of page

プログラム

プログラムは単独で実行し、テストできます。

プログラムは、他のオブジェクトから FETCH または FETCH RETURN ステートメントで呼び出すこともできます。 呼び出し元オブジェクトは、別のプログラム、サブプログラムファンクションサブルーチン、またはヘルプルーチンのいずれでもかまいません。

以下では次のトピックについて説明します。

FETCH RETURN で呼び出されるプログラム

FETCH RETURN で呼び出されるプログラムは、呼び出し元オブジェクトが使用するグローバルデータエリアにアクセスできます。

また、あらゆるプログラムには独自のローカルデータエリアがあり、その中にはそのプログラム内だけで使用されるフィールドが定義されます。

ただし、FETCH RETURN で呼び出されたプログラムが独自のグローバルデータエリアを持つことはできません。

FETCH で呼び出されるプログラム

メインプログラムとして FETCH で呼び出されるプログラムは、上記の図に示したように、通常は独自のグローバルデータエリアを設定します。 ただし、呼び出し元オブジェクトが設定したものと同じグローバルデータエリアを使用することもできます。

注意:
ソースプログラムは、RUN ステートメントで呼び出すこともできます。『ステートメント』ドキュメントの RUN ステートメントを参照してください。

Top of page

ファンクション

"ファンクション" タイプのオブジェクトには、単一のファンクションの定義が含まれ、次のコーディング例で示されるような構造が可能です。

DEFINE FUNCTION
   ...
   DEFINE SUBROUTINE
   ...
   END-SUBROUTINE
   ...
END-FUNCTION

DEFINE FUNCTIONEND-FUNCTION の間のステートメントブロックには、ファンクションが呼び出されたときに実行されるすべてのステートメントを含める必要があります。

ファンクション定義内に内部サブルーチンを定義することは可能です。

ファンクションはファンクションコール構文を使用して呼び出されます。

オブジェクト内で繰り返し実行されるコードブロックがある場合は、インラインサブルーチンを使用すると便利です。 次に、DEFINE SUBROUTINE ステートメントブロック内でこのブロックを 1 度だけコードし、いくつかの PERFORM ステートメントで呼び出すだけです。

呼び出し元オブジェクトのグローバルデータエリア(例:GDA1)は、ファンクション定義内では参照できません。 また、ファンクションを入力すると、ランタイム環境によって新しいグローバルデータエリアが作成されるため、ファンクションによって呼び出されるオブジェクトは、このファンクションを呼び出すオブジェクトのグローバルデータエリア(GDA1)を参照できません。

パラメータデータエリア(例:PDA1)は、パラメータ変更時の管理工数を最小限にするために、ファンクションコールおよびファンクション定義のパラメータにアクセスするために使用できます。

プロトタイプ定義を含むコピーコードオブジェクトは、必要に応じて、ファンクションコール参照の戻り変数のタイプを決定してパラメータをチェックするのみの目的で、コンパイル時に使用されます。

Top of page

サブルーチン

サブルーチンを構成するステートメントは、DEFINE SUBROUTINE ... END-SUBROUTINE ステートメントブロック内に定義する必要があります。

サブルーチンは PERFORM ステートメントによって呼び出されます。

サブルーチンには、インラインサブルーチン外部サブルーチンがあります。

1 つのオブジェクト内で繰り返し実行されるコードブロックがある場合は、インラインサブルーチンを使用すると便利です。 次に、DEFINE SUBROUTINE ステートメントブロック内でこのブロックを 1 度だけコードし、いくつかの PERFORM ステートメントで呼び出すだけです。

以下では次のトピックについて説明します。

インラインサブルーチン

インラインサブルーチンは、タイプがプログラム、ファンクション、サブプログラム、サブルーチン、またはヘルプルーチンのプログラミングオブジェクト内に含めることができます。

インラインサブルーチンが非常に大きく、それを含むオブジェクトの読みやすさが損なわれる場合は、アプリケーションの読みやすさが改善されるように、外部サブルーチンに置き換えることを検討できます。

インラインサブルーチンで使用できるデータ

インラインサブルーチンは、ローカルデータエリアと、このサブルーチンを含むオブジェクトが使用するグローバルデータエリアにアクセスできます。

外部サブルーチン

外部サブルーチン、つまりサブルーチンタイプのオブジェクトは単独では実行できません。 これは、他のオブジェクトから呼び出す必要があります。 呼び出し元オブジェクトは、プログラム、関数、サブプログラム、サブルーチン、またはヘルプルーチンのいずれでもかまいません。

外部サブルーチンで使用できるデータ

外部サブルーチンは、呼び出し元オブジェクトが使用するグローバルデータエリアにアクセスできます。

また、PERFORM ステートメントを使用して、呼び出し元オブジェクトから外部サブルーチンにパラメータを渡すことができます。 これらのパラメータは、サブルーチンの DEFINE DATA PARAMETER ステートメント、またはサブルーチンが使用するパラメータデータエリアに定義する必要があります。

また、外部サブルーチンは、そのサブルーチン内のみで使用するフィールドを定義するローカルデータエリアを持つことができます。

ただし、外部サブルーチンが独自のグローバルデータエリアを持つことはできません。

Top of page

サブプログラム

通常、サブプログラムには、アプリケーション内のさまざまなオブジェクトに使用される一般に使用可能な標準ファンクションが含まれています。

サブプログラムは単独では実行できません。 これは、他のオブジェクトから呼び出す必要があります。 呼び出し元オブジェクトは、プログラム、関数、サブプログラム、サブルーチン、またはヘルプルーチンのいずれでもかまいません。

サブプログラムは、CALLNAT ステートメントを使用して呼び出されます。

CALLNAT ステートメントが実行されると、呼び出し元オブジェクトの実行は中断され、サブプログラムが実行されます。 このサブプログラムの実行後は、呼び出し元オブジェクトの実行が CALLNAT ステートメントの次のステートメントから続行されます。

サブプログラムで使用可能なデータ

CALLNAT ステートメントを使用して、パラメータを呼び出し元オブジェクトからサブプログラムに渡すことができます。 これらのパラメータは、呼び出し元オブジェクトからサブプログラムが使用できる唯一のデータです。 これらのパラメータは、サブプログラムの DEFINE DATA PARAMETER ステートメント、またはサブプログラムが使用するパラメータデータエリアに定義する必要があります。

また、サブプログラムは、その中で使用するフィールドを定義する独自のローカルデータエリアを持つことができます。

サブプログラムがサブルーチンやヘルプルーチンを呼び出す場合は、そのようなサブルーチンやヘルプルーチンと共有する独自のグローバルデータエリアを設定することもできます。

Top of page

ルーチンを呼び出すときの処理フロー

ルーチン、つまりサブプログラム、外部サブルーチンまたはプログラムをそれぞれ呼び出す CALLNATPERFORM、または FETCH RETURN ステートメントが実行されると、呼び出し元オブジェクトの実行は中断され、該当するルーチンの実行が始まります。

ルーチンの実行は、END ステートメントに到達するまで、または ESCAPE ROUTINE ステートメントの実行によってルーチンの処理が停止されるまで継続します。

いずれの場合も、呼び出し元オブジェクトの処理は、ルーチンを呼び出すために使用された CALLNATPERFORM または FETCH RETURN ステートメントの次のステートメントから続行します。

例:

Top of page