プログラムの構造
本章では、OpenFrame PL/Iのプログラムの構造と構成について説明します。
1. 概要
OpenFrame PL/Iは、パッケージ、プロシージャ、開始ブロック、ステートメント、式、組み込み関数で構成されたブロック構造の言語です。1つのOpenFrame PL/Iアプリケーションは、1つ以上の共有ライブラリーとオブジェクト・ファイルがリンクされ、また別の共有ライブラリーとして作成されます。1つのソース(コンパイル・ユニット)がコンパイルされ、オブジェクト・ファイルを作成します。
コンパイル・ユニット(Compilation unit)は、OpenFrame PL/Iのパッケージまたは外部プロシージャです。パッケージは、0個以上のプロシージャを含むことができます。プロシージャは0個以上のブロックで構成されます。OpenFrame PL/Iのブロックは、0個以上のステートメントまたはブロックを含むプロシージャもしくは開始ブロックです。
2. ブロック
OpenFrame PL/Iブロックは変数宣言を含むことができますが、特定のブロックで宣言された変数は、そのブロック内の有効範囲を持ちます。すなわち、宣言されたブロックの外のブロックからは当該変数を参照することができません。
以下は、ブロックの特性です。
-
変数の有効範囲を指定します。
-
自動変数を割り当てます。
-
DEFAULTステートメントの有効範囲を指定します。
以下は、ブロックの種類です。
-
パッケージ・ブロック
-
プロシージャ・ブロック
-
開始ブロック
ブロックは変数宣言を含むことができます。宣言された変数は、該当するブロックの外では参照または使用できません。
ブロックの有効化は、ブロックが有効になったら自動変数のストレージを割り当て、宣言された変数の初期化を行います。ブロックの終了は、ブロックが終了されるとき、ONユニット環境の該当するブロックで登録された条件の処理(条件ハンドラー)を削除します。
2.1. PACKAGEステートメント
PACKAGEステートメントは、変数の宣言、DEFAULTステートメント、プロシージャ・ブロックだけを含むことができます。現在のOpenFrame PL/Iは、プロシージャ・ブロックのみを含むことが可能であり、PACKAGEステートメントのオプションはサポートしていません。

項目 | 説明 |
---|---|
condition_prefix |
PACKAGEステートメントに記述された条件接頭語(Condition prefix)は、パッケージ内のすべてのプロシージャに適用されます。詳細については、条件の条件接頭語を参照してください。 |
package_name |
パッケージ名を記述します。 |
2.2. プロシージャ
プロシージャは、PROCEDUREステートメントとそれに対応するENDステートメントで区切られた連続したステートメントの集合です。プロシージャは、必ず名前を持つ必要があります。
プロシージャ・ブロックは、他のプロシージャ・ブロックや開始ブロック内でネストされることができます。このようなプロシージャを内部プロシージャと言い、ネストされていないプロシージャを外部プロシージャと言います。外部プロシージャは、他のコンパイル・ユニットの別のプロシージャから呼び出されることができます。プロシージャの呼び出しについての詳細は、プロシージャの呼び出しを参照してください。
プロシージャは、メイン・プロシージャ、サブルーチンまたは関数になることができます。OpenFrame PL/Iアプリケーションは、1つのOPTIONS(MAIN)を含む外部プロシージャを持つ必要があります。
以下の例において、FUNC1はプロシージャ名であり、かつプロシージャのエントリ・ポイント名です。
FUNC1: PROCEDURE; END FUNC1;
ENTRYステートメントは、プロシージャに2次エントリ・ポイントを定義することができます。
FUNC1: PROCEDURE; FUNC2: ENTRY; END FUNC1;
FUNC2は、FUNC1プロシージャに追加したエントリ・ポイントとなります。
2.2.1. PROCEDUREステートメント(略語: PROC)
以下は、PROCEDUREステートメントの文法についての説明です。

項目 | 説明 |
---|---|
entry-label |
プロシージャのエントリ・ポイント名です。 |
parameter-list |
プロシージャのパラメータを記述します。 |
returns-options |
プロシージャのRETURN属性を定義します。 |
OPTIONS |
MAINのみサポートします。OpenFrame PL/IプログラムのMAINプロシージャであることを指定します。 |
2.2.2. ENTRYステートメント
ENTRYステートメントを含むプロシージャは、すべての非ポインター・パラメータがBYADDR(pass by address)である必要があります。

項目 | 説明 |
---|---|
entry-label |
プロシージャの2次エントリ・ポイント名です。 |
parameter- list |
エントリ・ポイントのパラメータを記述します。 |
returns-options |
エントリ・ポイントのRETURN属性を定義します。 |
3. プロシージャの呼び出し
プロシージャは、別のプロシージャを呼び出すことができます。呼び出されるプロシージャは、戻り値の有無によってサブルーチンと関数に分けられます。
-
CALLステートメントを使用したサブルーチンの呼び出し
サブルーチンは、CALLステートメントによって呼び出される内部プロシージャまたは外部プロシージャとして、結果を返さないプロシージャです。
サブルーチンを呼び出す場合、以下の事項に注意します。
-
PROCEDUREステートメントにRETURNSオプションを持ってはなりません。
-
外部プロシージャの場合、RETURNS属性を持つENTRYで宣言されてはなりません。
-
CALLステートメントで呼び出される必要があります。関数参照を通じて呼び出されてはなりません。
-
RETURNステートメントを使用して結果を返してはなりません。
以下は、サブルーチン呼び出しの例です。SUB1がサブルーチンです。
TEST: PROCEDURE OPTIONS(MAIN); CALL SUB1( 20, 20 ); END TEST; SUB1: PROC( PARM1, PARM2 ); DECLARE PARM1 FIXED DEC (7); DECLARE PARM2 FIXED DEC (7); DISPLAY( PARM1 + PARM2 ); END SUB1;
-
-
関数参照の呼び出し
関数は式で関数参照を通じて呼び出されるプロシージャです。式を計算しながら、関数参照によってプログラムの実行が関数プロシージャに移され、関数の実行が終了されるとき、プログラムの実行が結果と一緒に呼び出し元に戻ります。以降、式の計算が続行されます。
関数で呼び出す場合、以下の事項に注意します。
-
PROCEDUREステートメントにRETURNSオプションを持っている必要があります。
-
外部プロシージャの場合、RETURNS属性を持つENTRYで宣言される必要があります。
-
関数参照によって呼び出されます。CALLステートメントで呼び出されることもできます。
-
PROCECUREやENTRYステートメントのRETURNSオプションとDECLAREステートメントでENTRYに宣言されたRETURNS属性が一致する必要があります。
-
RETURNステートメントを使用して結果を返します。
以下は、関数呼び出しの例です。FUNC1が関数です。
TEST: PROCEDURE OPTIONS(MAIN); DECLARE SUM FIXED DEC(7); SUM = FUNC1( 20, 20 ); END TEST; FUNC1: PROC( PARM1, PARM2 ) RETURNS ( FIXED DEC(7) ); DECLARE PARM1 FIXED DEC (7); DECLARE PARM2 FIXED DEC (7); DECLARE RESULT FIXED DEC (7); RESULT = PARM1 + PARM2; RETURN (RESULT); END FUNC1;
TESTプロシージャで「SUM = FUNC( 20, 20);」というASSIGNステートメントを処理する際、関数参照によってFUNC1が呼び出され、PARM1、PARM2に20が引数として渡されます。
FUNC1プロシージャではこれを足してRESULTに保存した後、RESULTを返します。返されたらTES1プロシージャのASSIGNステートメントを続行し、返されたRESULT値を「SUM = FUNC1( 20, 20);」に保存します。
-
3.1. プロシージャへの引数の引き渡し
関数またはサブルーチンが呼び出されると、パラメータは渡される引数と関連付けられます。
-
計算データの引数を計算データ・タイプのパラメータに渡すことができます。
たとえば、FIXED BIN、FIXED DEC、FLOAT DEC、FLOAT BIN、CHARACTREなどの計算データの引数を別の計算タイプのパラメータに渡すことができます。パラメータがCHARATER属性を持っており、これに対応する引数がCHARACTERではなくFIXED DEC、FIXED BINなどの別のタイプのデータであっても呼び出す際に渡されます。
-
プログラム制御データの引数は、同じタイプのパラメータに渡す必要があります。
ただし、以下の場合は例外となります。
-
ポインターとオフセットは、相互に渡されます。
-
ラベル定数の配列は、引数として使用することはできません。
-
関数またはサブルーチンが呼び出される前に、呼び出し側の引数リストの式が先に計算されます。パラメータにはメモリ・ストレージはありません。呼び出されたプロシージャが、呼び出し側のプロシージャのメモリ・ストレージにアクセスできるようにするだけに使用されます。
本節では、プロシージャに引数を引き渡す方法について説明します。
BYVALUEとBYADDR
BYVALUEは引数の値を呼び出されるプロシージャのパラメータに渡します。
BYVALUEを指定すると、仮引数は作成されません。呼び出されるプロシージャのパラメータが変更されても、呼び出したプロシージャの引数は変更されません。
BYVALUEは、コンパイル時に既知の長さとサイズを持つスカラー引数および、スカラー・パラメータに対してのみ指定できます。構造体や配列などのデータセットは使用できず、以下のデータ・タイプのみ使用できます。
-
REAL FIXED BIN
-
REAL FLOAT
-
CHAR(1)
BYADDRは、呼び出されるプロシージャのパラメータにアドレスの値を渡します。パラメータは対応する引数のアドレス値を参照して使用します。パラメータの値への変更は、実際には、対応する引数の値への変更になります。ただし、定数などを引数として使用する場合は、内部的に仮引数が作成され、渡されます。したがって、パラメータは仮引数のアドレス値を参照することになるので、元の引数は変更されません。
仮引数
仮引数は、引数が以下のいずれかの場合に作成されます。
-
定数
-
CHAR(1)
-
変数であり、データ属性、位置合わせ属性、接続属性がパラメータに宣言された属性と異なる場合
仮引数の属性は、以下の場合に決まります。
-
内部プロシージャの関連パラメータに宣言された属性
-
外部入り口宣言の関連パラメータのパラメータ記述子に指定された属性(入り口宣言のためのDECLAREステートメントに記述されたパラメータの属性をパラメータ記述子と言います)
-
宣言されたパラメータ属性にアスタリスク(*)が付けられている場合、引数の配列サイズ、文字列の長さ、区域のサイズなどで使用します。
仮引数は、以下の規則に従います。
-
パラメータがエレメント(構造体または配列のいずれでもない変数)である場合には、引数もエレメントである必要があります。
-
VARYINGまたはVARYINGZ文字列エレメントがアスタリスク(*)で指定され、長さが未定義であるNONVARYINGパラメータに渡された場合、元の引数の長さを持つ仮引数が作成されます。
-
パラメータがプログラム制御タイプ(パラメータがロケーター(ポインターまたはオフセット)を除く)である場合、引数とパラメータのデータ・タイプが同じである必要があります。
-
パラメータがロケーターである場合は、引数もロケーターでなければなりません。タイプが異なる場合には、仮引数が作成されます。オフセット・パラメータのパラメータ記述子で、関連区域を記述してはなりません。
-
パラメータが被制御状態のデータのときは、ENTRY宣言のパラメータ記述子にこれを記述しなければなりません。
また、被制御引数は以下の条件を満たす必要があります。
-
添え字が付いていない。
-
構造体のエレメントではない。
-
仮引数を作成しない。
-
3.2. 入り口データ
入り口データは、入り口定数と入り口変数の値です。
入り口定数は、PROCEDUREまたはENTRYステートメントにラベル接頭部として付けられた名前、または、DECLAREステートメントでVARIABLE属性ではなくENTRY属性で宣言された名前です。これは、入り口変数に割り当てられます。
-
入り口定数
-
PROCEDUREまたはENTRYステートメントにラベル接頭部を指定すると、入り口定数を明示的に宣言することになります。
-
パラメータ記述子リストは、PROCEDUREまたはENTRYステートメントに関連するパラメータ宣言から取得できます。
-
外部入り口定数(別のコンパイル・ユニットに存在するプロシージャまたは入り口名前)は、DECLAREステートメントを利用して明示的に宣言される必要があります。このような宣言は、外部プロシージャにエントリ・ポイントを宣言します。
-
オプションで、パラメータ記述子リストを記述することができます。入り口が関数の場合に、プロシージャによって戻り値の属性も記述できます。
-
-
入り口変数
-
ENTRY属性にVARIABLE属性が記述されています。
-
DECLAREステートメントで宣言された変数が、内部入り口値(PROCEDURE、ENTRYステートメントで宣言されたエントリ・ポイント)または外部入り口値(DECLAREステートメントによってENTRY属性を持つように宣言されたデータ)が保存できる変数として使用されます。
-
入り口変数は、データ集合体の一部になることができます。
-
以下の例において、TEST、ENT_CON1、ENT_CON2は入り口定数であり、ENT_VARは入り口変数です。
TEST: PROC; DECLARE ENT_VAR 入り口変数; DECLARE (ENT_CON1, ENT_CON2) ENTRY; ENT_VAR = ENT_CON2; CALL ENT_VAR; ENT_VAR = ENT_CON1; CALL ENT_VAR; END TEST;
最初のCALLステートメントからエントリ・ポイントENT_CON2がよ呼び出され、次のCALLステートメントからエントリ・ポイントENT_CON1が呼び出されます。
ENTRY属性
ENTRY属性は、DECLAREステートメントに記述され宣言された変数が、入り口定数または入り口変数のいずれかであることを指定します。

項目 | 説明 |
---|---|
parameter-descriptor |
外部入り口のパラメータの属性を記述します。この属性は、プログラムを呼び出すとき、引数とパラメータの突き合わせおよび仮引数の作成用に使用されます。 パラメータ記述子リストが指定されていない場合には、パラメータ属性と引数属性のデフォルトを突き合わせる必要があります。そのため、引数属性と異なるコンパイル・ユニットに記述された外部入り口の属性が異なる場合は、パラメータ記述子リストを指定しなければなりません。 アスタリスク(*)は、対応される位置のパラメータ属性を引数属性として使用することになります。 |
structure-descriptor |
パラメータが構造体の場合、構造体の属性を記述します。 レベル番号が指定できるので、メンバーの属性も記述できます。 |
VARIABLE |
DECLAREステートメントで宣言された変数が入り口変数であることを指定します。 VARIABLE属性が指定されていない場合は、入り口定数で使用されます。 |
RETURNS |
外部入り口の戻り値の属性を記述します。 |
attribute |
データ属性が指定できます。次元属性は最初に記述される必要があります。 |