(57)【特許請求の範囲】
【請求項１】
関数型言語で記述されたプログラムを手続型言語に変換する言語変換装置であって、
前記プログラムの変換を行う変換手段であって、該変換に伴って関数式に対しては任意の仮変数を生成して割当てる変換手段と有し、
前記変換手段は、前記プログラムにおいて選択構造またはループ構造の条件節に複数の関数式が記述されている場合、最後の関数式に対してのみ前記仮変数の割当てを行うことを特徴とする言語変換装置。
【請求項２】
前記プログラムにおいては、ＰＲＯＧＮ関数によって、前記選択構造またはループ構造の条件節に複数の式が記述されることを特徴とする請求項１記載の言語変換装置。
【請求項３】
前記変換手段は、前記プログラムにおいて前記ＰＲＯＧＮ関数があった場合、該ＰＲＯＧＮ関数に係わる全ての関数式について、仮変数の割当てを行うことなく前記手続型言語に変換した後に、最後の関数式に対してのみ前記仮変数の割当てを行うことを特徴とする請求項２記載の言語変換装置。
【請求項４】
前記変換手段は、前記プログラムにおいて選択構造で条件式が不成立時の選択肢が省略されていた場合、条件不成立時の選択肢を追加すると共に、最新の仮変数に対して０を代入する実行節を、変換結果プログラムに追加することを特徴とする請求項１記載の言語変換装置。
【請求項５】
前記関数型言語で記述されたプログラムにおける関数又はオペランドの各要素の配列を記憶した関数型言語記憶手段と、
前記配列の各要素を順次取得し、該各要素に応じたノードと該ノード間のリンクから成るツリー構造を生成するツリー構造作成手段とを更に有し、
前記変換手段は、該ツリー構造に基づいて、前記プログラムの変換を行うことを特徴とする請求項１〜４の何れかに記載の言語変換装置。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、関数型言語で記述されたプログラムを、関数型言語処理に不向きな演算処理装置において実行可能な形に変換する言語変換装置に関する。
【背景技術】
【０００２】
プログラマブルコントローラ（Programmable Logic Controller；以下、単に「ＰＬＣ」という場合があるものとする）は、シーケンス制御プログラムを実行し、制御対象機器を制御するものである。
【０００３】
このプログラマブルコントローラが実行するシーケンス制御プログラムとしては、図６に示すように、例えばＰＬＣ用言語としての表現依存部とマシン語としての機械依存部との間に中間言語としての関数型制御言語がある。尚、上記ＰＬＣ用言語としては、例えは図示のように、ニーモニック記述、ラダー図、ファンクションブロック図、ＳＦＣ図（Sequential Function Chart）、ディシジョンテーブル、等がある。また、上記関数型制御言語は、Functional Control Languageであり、これを略して以下「ＦＣＬ」という場合もあるものとする。関数型制御言語を、関数型言語と記す場合もある。
【０００４】
ＦＣＬについては特許文献１、特許文献２等で説明されているが、ここで簡単にＦＣＬを説明する。
上記ＦＣＬは、シーケンス制御プログラムを関数型のプログラム構造で表現した言語である。
【０００５】
図７は、関数型制御言語の基本構造の一例を示す図である。
ＦＣＬでは、図７に示すように、一つの機能を、引数Ａｒ１、Ａｒ２、Ａｒ３、・・・を持つ関数式Ｆで表している。引数は例えばオペランド（変数など）等であるが、別の関数式を関数式Ｆの引数とすることもできる。つまり、関数式自身を別の関数式の引数とすることができる。よって、ある関数式と、この関数式の引数（この中には別の関数式も含まれる場合もある）との関係を、ツリー構造（機能構造）として二次元的に表現することができる。
【０００６】
図８に、関数型制御言語の二次元機能構造（ツリー構造）の一例を示す。
例えば、図８の例では、関数Ａが関数Ｂと関数Ｃとを引数とし、関数Ｂはオペランドｖ及びオペランドｗを引数として有し、関数Ｃはオペランドｘ及び関数Ｄを引数として有し、関数Ｄはオペランドｙおよびオペランドｚを引数として有する。つまり、図８には、下記の式に対する２次元構造（ツリー構造）が表現されている。
（Ａ （Ｂ ｖ ｗ） （Ｃ ｘ （Ｄ ｙ ｚ）））
【０００７】
尚、図８に一例を示すような二次元機能構造（ツリー構造）では、各関数やオペランド（変数など）をノード（図示の四角形）とし、任意のノード間の直線は該ノード間のリンクを示す。例えば、ノードＡは、上記関数Ａを意味し、ノードＡはノードＢ（関数Ｂ）とノードＣ（関数Ｃ）とリンクしている。これは、ノードＡが、ノードＢとノードＣの親ノードであるものとする。換言すれば、ノードＡの子ノードは、ノードＢとノードＣであると言える。同様に、例えば、ノードＢの子ノードは、ノードｖとノードｗであると言える。他のノードについては特に説明しないが、図示の直線で示すリンクにより、上記親子関係が示されている。
【０００８】
上記のように、関数型制御言語は、例えば図８に示すように言語の２次元的な表現を行う事ができ、記述性の高いものとなり、以って図６に示すような、ＰＬＣプログラムの表現依存部と機械依存部をつなぐ中間言語としての役割を果たすことができる。
【０００９】
ここで、上記特許文献１、２や特許文献３には、関数型言語のプログラムの実行方式として、命令スタックとデータスタックを用いて演算を実行する方式が示されている。このような命令スタックとデータスタックを用いて演算を実行する方式の場合、当然のこととして、命令スタックとデータスタックという手段が必要となる。よって、この様な手段を持たない装置（例えば、手続き型の命令処理を実行する装置）では、プログラム実行が困難あるいはエミュレーションするために処理性能が低下するという問題がある。
【００１０】
この様な問題を解決するために、関数型言語を手続型言語に変換して、汎用の手続型言語（たとえばＣ言語）で実行する方式が、提案されている（特許文献４）。
あるいは、本出願人は、以前に、特許文献５に記載の発明を提案している。
【００１１】
特許文献５の発明は、上記特許文献４の発明に係わり、下記の課題を解決するものである。
まず、上記関数型言語は全ての関数に値を持ち、関数の引数に関数を記述することが可能であるため、条件分岐（たとえばIF〜THEN〜ELSE〜END_IF）を行ない、その結果をさらに、条件に用いる記述を簡単に行うことが可能である。また、条件分岐がネスト（入れ子）になったプログラムは、よく知られているものである。ここで、条件分岐処理は、実行条件によって選択された一方の式（THEN部またはELSE部）だけが実行されるべきであるのに対して、従来の変換処理による変換結果では、THEN部とELSE部の両方を実行し、その結果を選択する処理になってしまい、余計な処理実行を行うという問題が発生する。
【００１２】
上記課題に対して、特許文献５の発明は、関数型制御言語プログラムを手続型言語プログラムに変換することができ、命令スタックとデータスタックを待たない手続き形の命令処理を行うことができると共に、特に条件分岐を有する関数型制御言語プログラムについて、関数型制御言語の条件分岐命令を適切な構文に変換することができ、余分な実行や一時変数を作成することもなく効率的な実行が実現できる言語変換装置を、提供するものである。
【先行技術文献】
【特許文献】
【００１３】
【特許文献１】特開平１−２９８４４４号公報
【特許文献２】特開平２−２３０４２６号公報
【特許文献３】特開平１−２４３１２６号公報
【特許文献４】特開２０１２−１０４０６５号公報
【特許文献５】特開２０１４−５９８４８号公報
【発明の概要】
【発明が解決しようとする課題】
【００１４】
ここで、上記関数型制御言語（ＦＣＬ）は、全ての関数に値を持ち、関数の引数にPROGN関数を記述することが可能である。よく知られているように、ＰＲＯＧＮ関数を使用すると、複数の式を評価でき、戻り値が、最後に評価した式の結果となる。これより、ＰＲＯＧＮ関数を使用すると、選択構造（例えばIF〜THEN〜ELSE〜END_IF）やループ構造（例えばWHILE〜DO〜ENDWHIL）の条件節に、実質的に複数の式を記述することが可能である。
【００１５】
図９に、ＦＣＬでＰＲＯＧＮ関数を使用した選択構造文の一例を示す。
図示のプログラム例では、ＰＲＯＧＮ関数によって以下の２つの式を評価することになる。
（：＝（＋  ｂ  ａ）  ｃ）
（：＝（−  ｄ  ｅ）  ｆ）
【００１６】
そして、戻り値が、最後に評価した式、すなわち（：＝（−  ｄ  ｅ）  ｆ）の結果となり、この戻り値が‘１０’である場合、（：＝（−  ｃ  ａ）  ａ）を実行するものである。
【００１７】
図１０には、上記図９に示すＦＣＬプログラム文を、例えば上記特許文献４、５等の既存技術によって手続型言語に変換した結果を示す。この変換処理や変換結果については、殆どは、後に記載する本手法による変換処理や変換結果の説明において説明するので、ここでは特に説明しないが、この例では問題となるのは図示の“ＩＮＳＴ＿５：＝”であり、これについて説明する。
【００１８】
まず、図１０に示す変換結果における“ＩＮＳＴ＿５”や“ＩＮＳＴ＿６”等は、変換処理の際に全ての関数（リーフ以外のノード）に対して任意に割当てられる仮変数であり、ここでは仮変数の生成ルールは「“ＩＮＳＴ＿”＋任意の整数」となっているものとする。尚、“仮変数”（仮変数名）は、上記特許文献４、５における“インスタンス名”に相当すると見做しても構わない。
【００１９】
そして、図１０に示す例では、図示のように、２行目にある“ＩＮＳＴ＿５”は、その後の３行目以降で何等使用されておらず、意味が無いものとなっている。つまり、“ＩＮＳＴ＿５”は実質的に必要がないものとなっている。これは、上記の通り、ＰＲＯＧＮ関数では戻り値が最後に評価した式の結果となるので、条件節が複数の式からなるとき、実行条件は最後の式の実行結果で判断される為である。
【００２０】
尚、図９では、ＰＲＯＧＮ関数に係わる関数式が２つであるので、実質的に無用となる仮変数は上記“ＩＮＳＴ＿５”の１つだけとなるが、例えばＰＲＯＧＮ関数に係わる関数式が１０個あったならば、実質的に無用となる仮変数は９個となり、無駄が大きいものとなる。
【００２１】
尚、特許文献４、５では「関数名−インスタンス名作成部１４」によって二次元機能構造（ツリー構造）におけるノードのなかでリーフ（末端ノード）以外のノード全てに対して、“インスタンス名”（仮変数）を割当てている。つまり、全ての関数（命令）に対して、“インスタンス名”（仮変数）を割当てている。
【００２２】
この様に、従来の変換処理では全ての関数式の実行結果に仮変数を割り当てるため、ＰＲＯＧＮ関数がある場合には余分な仮変数を生成してしまうことになり、変換後のプログラム実行環境を圧迫してしまう問題が発生する。換言すれば、メモリの使用量が増大することになる。
【００２３】
また、上記図９、図１０の例では、以下の問題も発生することになる。
まず、上記関数型制御言語（ＦＣＬ）では、選択構造で条件式が不成立時の選択肢（ELSE節やOTHERW節）を省略することが可能である。
【００２４】
すなわち、例えばｉｆ文は一般的に下記のように記述される。
ｉｆ（条件式（条件節））
ｔｈｅｎ節
ｅｌｓｅ
ｅｌｓｅ節
図９には、選択構造のELSE節がない例を示している。尚、勿論、ELSE節だけでなく上記ｅｌｓｅ自体も無いが、これは言うまでもないことである。ELSE節がない場合、従来の変換処理では、何も変換されず、図１０に示すように、最後の閉じ括弧“｝”の後には何もない。尚、図では、何もないことを斜線で示している。何も変換されないため、当然、仮変数も割り当てられない。
【００２５】
尚、上記ｉｆ文に関して、上記条件節以外の部分を、実行節と呼ぶものとする。つまり、上記の例では、実行節にはｔｈｅｎ節やｅｌｓｅ節等が含まれていることになる。
ＦＣＬの場合、条件不成立時の選択肢を省略したとき、条件不成立時は実行結果＝０となる。
【００２６】
これに対して、汎用の手続型言語（たとえばＣ言語やＰＡＳＣＡＬなど）で図１０のようにELSE節がないプログラム文を実行すると、実行結果が不定になるという問題が発生する。
【００２７】
本発明の課題は、関数型言語を手続型言語に変換する言語変換装置において、ＰＲＯＧＮ関数を含む選択構造を含むプログラム文の変換の際に、実質的に無用となる仮変数の生成・割り当てが行われないようにできる言語変換装置などを提供することである。
【課題を解決するための手段】
【００２８】
本発明の言語変換装置は、関数型言語で記述されたプログラムを手続型言語に変換する言語変換装置であって、前記プログラムの変換を行う変換手段であって、該変換に伴って関数式に対しては任意の仮変数を生成して割当てる変換手段と有し、前記変換手段は、前記プログラムにおいて選択構造またはループ構造の条件節に複数の関数式が記述されている場合、最後の関数式に対してのみ前記仮変数の割当てを行うことを特徴とする。
【発明の効果】
【００２９】
本発明の言語変換装置などによれば、関数型言語を手続型言語に変換する言語変換装置において、ＰＲＯＧＮ関数を含む選択構造を含むプログラム文の変換の際に、実質的に無用となる仮変数の生成・割り当てが行われないようにできる。あるいは、変換元のプログラム文にELSE節がない場合であっても、変換したプログラム実行結果が不定になるという問題を回避できる。
【図面の簡単な説明】
【００３０】
【図１】（ａ）は言語変換装置の機能ブロック図、（ｂ）はその概略フロー図である。
【図２】図９のプログラム例に応じた配列を示す図である。
【図３】図２の配列に応じた二次元構造（ツリー）を示す図である。
【図４】変換部の処理フローチャート図である。
【図５】図９のプログラム例に応じた本手法による変換結果を示す図である。
【図６】ＰＬＣ用言語について説明する為の図である。
【図７】関数型制御言語の基本構造の一例を示す図である。
【図８】関数型制御言語の二次元機能構造の一例を示す。
【図９】ＰＲＯＧＮ関数を用いた選択構造文の一例を示す図である。
【図１０】図９のプログラム文を従来手法によって変換した結果を示す図である。
【発明を実施するための形態】
【００３１】
以下、図面を参照して、本発明の実施の形態について説明する。
図１（ａ）は、本例の言語変換装置の機能ブロック図である。
本例の言語変換装置１０は、関数型言語で記述されたプログラムを、関数型言語処理に不向きな演算処理装置において実行可能な形に変換する言語変換装置であり、特に、関数型言語で記述されたプログラムを手続型言語（Ｃ言語やＰＡＳＣＡＬなど）に変換する言語変換装置である。
【００３２】
図１（ａ）に示す例の言語変換装置１０は、関数型言語（ＦＣＬ）格納部１１、二次元構造（ツリー）変換部１２、二次元構造格納部１３、変換部１４、手続型言語格納部１５等を有する。
【００３３】
関数型言語（ＦＣＬ）格納部１１には、変換対象となるＦＣＬプログラム文を格納する。ここでは、このプログラムの格納形式は、上記特許文献１，２，３、４，５等と同様、例えば後述する図２の例のような配列とする。つまり、プログラムの各関数（命令）や各オペランド（変数等）を、配列の各要素として格納している。尚、関数型言語（ＦＣＬ）格納部１１自体は、上記従来の特許文献４、５の関数型言語（ＦＣＬ）格納装置と同様であって構わない。
【００３４】
ここで本実施例の説明では、変換対象となるＦＣＬプログラム文が、上記図９に示すものである場合を例にして説明するものとする。そして、図２に、図９のプログラム例に応じた配列を示す。つまり、本例の場合、関数型言語（ＦＣＬ）格納部１１には、図２に示す配列の形式で、変換対象となるＦＣＬプログラム文が、格納されていることになる。
【００３５】
この配列の各要素については、特許文献４、５等と同様であり、関数は開き括弧“（”と共に配列の１要素として格納され、オペランド（変数など）や関数終了子（閉じ括弧“）”）は、そのまま配列の１要素として格納される。よって、例えば、ＩＦやＰＲＯＧＮ等の関数（命令）は、図示のように“（ＩＦ”や“（ＰＲＯＧＮ”等の形でそれぞれ配列の１要素として格納される。
【００３６】
二次元構造（ツリー）変換部１２は、関数型言語（ＦＣＬ）格納装置１１に記憶された配列の内容を、その配列の各要素を節（以下、「ノード」という）としてツリー構造化する。二次元構造（ツリー）変換部１２も、特許文献４、５等に開示されている既存機能であるので、ここでは簡単に説明するならば、配列の各要素を順次取得し、該各要素に応じたノードと該ノード間のリンクから成るツリー構造を生成するものである。二次元構造（ツリー）変換部１２によって、例えば図２の例の配列の場合、図３に示す二次元構造（ツリー）が生成されることになる。生成された二次元構造（ツリー）データは、二次元構造格納部１３に格納される。
【００３７】
尚、図３にはツリー構造について概略的に示すが、その各ノードのデータ構造は、例えば特許文献４の図３や、特許文献５の図３、図４、図１４等のように“子供ノードへのポインタ”や“次のノードへのポインタ”等の他ノードへのリンクを示すポインタを有するものである。但し、この例に限らない。図３では、この様なポインタ等に基づく各ノード間の親子関係を、図示の直線で示してある。例えば、図３の左下に示す“ｂ”ノードと“ａ”ノードの親ノードは、何れも、“（＋”ノードである。換言すれば、“（＋”ノードの子ノードは、“ｂ”ノードと“ａ”ノードであると言える。これは、ノードが上記特許文献４の図３のデータ構造の場合では、“（＋”ノードにおける“子供ノードへのポインタ”が“ｂ”ノードを指しており、“ｂ”ノードにおける“次のノードへのポインタ”が“ａ”ノードを指していることになる。
【００３８】
二次元構造（ツリー）の各ノードのデータ構造は、上記のように特許文献４、５等とほぼ同様であってよいが、本例の場合にはインスタンス名（本例では仮変数とする）は無い。また、本例では、特許文献４、５における「関数名−インスタンス名作成部」が無く、ツリー構造においてインスタンス名（仮変数名）が割当てられることはない。特許文献４の場合、「関数名−インスタンス名作成部」によって、リーフ以外の全てのノードにインスタンス名（仮変数名）を付与していた為、上記図１０の例のように、不必要な仮変数ＩＮＳＴ＿５”が付与されてしまっていた。
【００３９】
これに対して、本手法では、上記のようにリーフ以外の全てのノードに一律にインスタンス名（仮変数）を付与する代わりに、変換部１４において後述する処理によって仮変数を付与する。これについては後述する。尚、上記リーフとは、特許文献４、５に記載のように、ツリー構造の末端部のノードすなわち子ノードを持たないノードである。
【００４０】
また、尚、本例においても、ある関数は、別の関数や変数を引数（子ノード）とすることができる。例えば、図３に示す例では、例えば図示の“（＋”ノードの親ノードとしての“（：＝”ノードは、その引数（子ノード）として、当該“（＋”ノードと図示の“ｃ”ノードを有する。尚、“：＝”は代入の関数であり、“＋”は加算の関数であり、ｃはオペランド（変数など）である。
【００４１】
尚、図３のような二次元構造（ツリー構造）を表現するのに、ＸＭＬ（Extensible Markup Language）で記述されたテキストによるデータ構造を使用することができる。ＸＭＬの場合、ツリー構造データの追加／削除／検索などの操作を容易に行なうことができる。
【００４２】
上記変換部１４の処理について、以下、説明する。
まず、図１（ｂ）には、変換部１４の概略処理フローを示す。
変換部１４は、上記二次元構造格納部１３に格納される二次元構造（ツリー）データに基づいて、上記変換対象となるＦＣＬプログラム文を手続型言語のプログラムに変換する。この処理は、概略的には、図１（ｂ）に示すように、ツリー構造に従ってＦＣＬプログラムを順次変換するなかで、ｉｆ文があった場合には（ステップＳ１，ＹＥＳ）、まず、このｉｆ文に係わる条件節の関数式の変換を行う（ステップＳ２）。そして、この条件節にＰＲＯＧＮがあった場合には、このＰＲＯＧＮに係わる複数の関数式のなかで１つの関数式だけを仮変数の割り当て対象に決定し（ステップＳ３）、決定した関数式に対して任意の仮変数を割当てる（ステップＳ４）。そして、この割当てた仮変数を用いて条件分岐部分（ｔｈｅｎ節など）を作成する（ステップＳ５）。
【００４３】
上記変換処理によって作成された手続型言語のプログラムは、手続型言語格納部１５に格納される。
尚、図１（ａ）、（ｂ）に示す構成、処理は、一例を示すものであり、この例に限らない。例えば、変換部１４は、二次元構造格納部１３ではなく関数型言語（ＦＣＬ）格納部１１に格納される上記配列を用いて、上記プログラム変換処理を行うようにしてもよい。
【００４４】
ここで、上記ステップＳ３の処理は、ＰＲＯＧＮに係わる複数の関数式の変換結果のなかで、最後の関数式のみに対して、仮変数を割当てる処理である。上記の通り、ＰＲＯＧＮ関数の戻り値は、最後に評価した式の結果となるからである。そして、ｉｆ文に係わりＰＲＯＧＮ関数がある場合には、この戻り値が条件分岐判定に用いられることになる。
【００４５】
従来では、例えば上記「関数名−インスタンス名作成部」によって全ての関数に対して仮変数が付与されるので、ＰＲＯＧＮに係わる複数の関数式に対しても全て仮変数が付与されることになった。これに対して、本手法では上記のように、ＰＲＯＧＮに係わる全ての関数式の変換結果に仮変数を割り当てるのではなく、条件判定に必要な関数式にのみ仮変数を割り当てるようにすることで、余分な仮変数を作成することもなく効率的な実行が可能である。この様な仮変数の割り当て処理の具体例は、後にフローチャート図を参照して説明する。
【００４６】
例えば、後述する具体例のように、本手法では上記図９のＦＣＬプログラム文を、後述する図５の手続型言語プログラム文に変換するので、図５に示すようにＰＲＯＧＮに係わる複数の関数式の中で最後の関数式だけに仮変数を割り当てるので、仮変数は３個（INST6、INST7、INST8）で済み、変換後のプログラムのメモリ使用量を削減でき、メモリ使用量の圧迫を回避できるようになる。
【００４７】
尚、条件節内部にさらに選択構造がある場合、つまり例えば所謂“ｉｆ文の入れ子”となっている場合等には、選択した後に実行される最後の関数式の実行結果が、選択構造の実行結果として条件判定に用いられる。そのため、それぞれの選択肢ごとに、最後の式の変換結果に対してのみ仮変数に割り当てる。
【００４８】
あるいは、変換対象となるＦＣＬプログラム文に、条件式が不成立時の選択肢（ELSE節やOTHERW節）がない場合であっても、当該選択肢を追加して実行結果を割り当てる。本手法では、例えば図９のＰＬＣプログラム文を手続型言語に変換する際に、図５の最後に示すｅｌｓｅ文を自動的に追加する処理を行う。すなわち、条件式不成立時の選択肢を自動的に追加して仮変数＝０とする処理を行う。これについて詳しくは後述するが、これによって、変換後のプログラムの実行結果が不定になる事態を避けられる。
【００４９】
上述した本手法の特徴を実現する為の具体的処理例は、図４に示し後に詳細に説明するが、以下、簡単に説明する。尚、以下の説明における“選択構造”は上述したように例えばIF〜THEN〜ELSE〜END_IF等であり、“ループ構造”は例えばWHILE〜DO〜ENDWHIL等である。そして、ＰＲＯＧＮ関数を使用すると、これらの各構造の条件節に、複数の式を記述することが可能である。
【００５０】
仮変数の無駄な割当てを避ける為に、例えば下記の（ａ）、（ｂ）等の操作を行う。
（ａ）PROGN関数に係わる複数の関数式を手続型命令に変換した後、当該PROGN関数に係わる複数の関数式（変換後）のなかで最後の関数式を検索する。
【００５１】
（ｂ）最後の関数式が選択構造やループ構造でなければ、仮変数を生成して当該最後の関数式に割り当てる。例えば、PROGN関数に係わり変換した手続型言語の命令コードの末尾から遡り、最後の関数式と一致する箇所に仮変数を挿入する。
【００５２】
（ｃ）一方、最後の関数式が選択構造やループ構造の場合、それぞれの実行節で割り当てられた仮変数をそのまま使用し、新たに仮変数を生成することはしない。
上記操作により、条件節が複数の関数式からなるときは、最後の関数式に割り当てる仮変数しか生成しない。
【００５３】
（ｄ）また、選択構造の実行節に条件不成立時の選択肢がない場合、つまり例えばＴｈｅｎ節はあるがｅｌｓｅ節が無い場合、条件不成立時の選択肢を追加して、仮変数に０を代入する実行節を追加する。
【００５４】
上記操作により、条件不成立時の選択肢がない場合でも、変換結果のプログラムの実行結果が不定にならなくなる。
上記（ａ）〜（ｄ）について、以下、更に説明する。
【００５５】
まず、上記の様に、ＰＲＯＧＮ関数等によって、選択構造の条件節に複数の関数式を使用することができる。また、一般的に、条件節内部にさらに選択構造を使用することができる。選択肢それぞれに仮変数を挿入する必要があるが、条件節に使用された際に全ての選択肢を検索するのは手間が多い。本手法では、選択構造の手続型言語への変換時に、各選択肢の最後の式に常に仮変数を挿入することにする。
【００５６】
選択構造では条件式が不成立時の選択肢（ELSE文やOTHERW文）がない場合がある。本手法では、選択構造の手続型言語への変換時にELSE文やOTHERW文の有無をチェックし、これらがない場合には自動的に”else”や”default:”を追加し、更に“（仮変数） ：＝ 0”を追加する。
【００５７】
図４のフローチャート図について上記図９の例に応じた上記図３のツリー構造を参照して説明する。
図４は、「ノード処理」のフローチャート図である。
【００５８】
図４の処理は、基本的に、処理対象ノードを基準にして処理を実行する。処理対象ノードは、最初はツリー構造の先頭となり、図３の例では“（ＩＦ”ノードとなる。但し、図４の処理中、ステップＳ１３、Ｓ１６等の処理は、図４の処理自体（「ノード処理」のプログラム）を再帰的に呼び出す処理である。その際、基本的には処理対象ノードの子ノードを示す情報をパラメータとして渡すことで、呼び出される「ノード処理」における処理対象ノードは当該子ノードということになる。
【００５９】
図４の処理は、処理対象ノードの種別によって、概略的には４つの処理に分岐する。つまり、処理対象ノードがｉｆ文であるか（ステップＳ１１，ＹＥＳ）、ＰＲＯＧＮ文であるか（ステップＳ３１，ＹＥＳ）、これら以外の任意の関数であるか（ステップＳ４１，ＹＥＳ）、変数（オペランド）であるか（ステップＳ４１，ＮＯ）によって、処理が４つに分岐する。
【００６０】
上記の通り最初は処理対象ノードが“（ＩＦ”であり、すなわちｉｆ文であるので、ステップＳ１１の判定がＹＥＳとなり、ステップＳ１２〜Ｓ２０の処理を実行することになる。尚、この処理は、ネスト１の「ノード処理」であるものとする。そして、ネスト１の「ノード処理」から呼び出す「ノード処理」は、ネスト２の「ノード処理」であるものとする。同様にして、ネスト２の「ノード処理」から呼び出す「ノード処理」は、ネスト３の「ノード処理」であるものとする。このようにして、「ノード処理」を再帰的に呼び出すことで、ネストが１段ずつ深くなっていく。
【００６１】
尚、上記ネスト１、ネスト２等における‘１’や‘２’は、ネストの深さを示すものであり、数値が大きいほどネストが深いことになる。
また、尚、以下の説明における子ノードの取り出し（子ノードの認識）は、例えば各ノードに含まれる上述した“子供ノードへのポインタ”や“次のノードへのポインタ”を参照することで実現できる。
【００６２】
まず、ｉｆ文における条件節を取り出し（ステップＳ１２）、この条件節に係わる「ノード処理」を実行させる（ステップＳ１３）。尚、ステップＳ１２の処理は、例えば、“処理対象ノードである（ＩＦ”ノードの子ノードの一方を、認識するものである。よって、図３例では、“（ＩＦ”ノードの一方の子ノードである“（＝”ノードが認識されて、ステップＳ１３ではこの“（＝”ノードをパラメータとして「ノード処理」を呼び出す。
【００６３】
これによって、呼び出される「ノード処理」では、“（＝”ノードが処理対象ノードとなる。つまり、処理対象ノードの種別は関数ということになる。よって、当該“（＝”ノードの「ノード処理」（ネスト２）においては、まず、ステップＳ１１、Ｓ３１がＮＯでＳ４１がＹＥＳとなり、これより、この“（＝”の子ノード（引数）を順次取り出して（ステップＳ４２）、これら子ノード毎に「ノード処理」を呼び出す（ステップＳ４３）処理を、全ての子ノードについて実行するまで繰り返す。
【００６４】
ここで、“（＝”の子ノードの１つは、“（PROGN”ノードであるので、ステップＳ４３においてＰＲＯＧＮ文の「ノード処理」を実行させる場合があることになる。これは、階層的にはネスト３の処理と言える。
【００６５】
よって、当該“（PROGN”ノードのノード処理（ネスト３）が開始されると、まず、ステップＳ１１がＮＯでステップＳ３１がＹＥＳになり、この“（PROGN”ノードの子ノード（引数）を順次取り出して（ステップＳ３２）、これら子ノード毎に「ノード処理」を呼び出す（ステップＳ３３）処理を、全ての子ノードについて実行するまで繰り返す。
【００６６】
“（PROGN”ノードには複数の子ノードがあり、図３の例では最初の子ノードは“（：＝”ノードであるので、これに応じてステップＳ３３で呼び出される「ノード処理」では、処理対象ノードが“（：＝”ノードとなり、“（：＝”（代入関数）の処理となる。これは、階層的には、ネスト４の処理と言える。
【００６７】
“（：＝”ノードの「ノード処理」（ネスト４）では、ステップＳ１１、Ｓ３１がＮＯとなりステップＳ４１がＹＥＳとなる。これより、この“（：＝”の子ノード（引数）を順次取り出して（ステップＳ４２）、これら子ノード毎に「ノード処理」を呼び出す（ステップＳ４３）処理を、全ての子ノードについて実行するまで繰り返す。
【００６８】
図３の例では“（：＝”の最初の子ノードは“（＋”ノードであるので、これに応じてステップＳ４３で呼び出される「ノード処理」は、“（＋”（加算関数）の処理となる。これは、階層的には、ネスト５の処理と言える。
【００６９】
“（＋”ノードの「ノード処理」（ネスト５）では、ステップＳ１１、Ｓ３１がＮＯでＳ４１がＹＥＳとなり、これより、この“（＋”ノードの子ノード（引数）を順次取り出して（ステップＳ４２）、これら子ノード毎に「ノード処理」を呼び出す（ステップＳ４３）処理を、全ての子ノードについて実行するまで繰り返す。
【００７０】
図３の例では“（＋”ノードの最初の子ノードは“ｂ”ノードであるので、これに応じてステップＳ４３で呼び出される「ノード処理」は、“ｂ”（変数）の処理となる。これは、階層的には、ネスト６の「ノード処理」と言える。
【００７１】
“ｂ”ノードの「ノード処理」（ネスト６）では、ステップＳ１１、Ｓ３１、Ｓ４１が全てＮＯとなり、これより、変数処理（ステップＳ４６）を実行する。この変数処理は、単に、処理対象ノード“ｂ”を、構文リストに出力するものである。構文リストは、変換結果の出力先ファイル等であり、本処理によって様々な出力が成されることで、最終的には例えば図５に示す変換結果を有する構文リスト生成されることになる。
【００７２】
尚、上記手続型言語格納部１５の一例が、上記構文リストであると見做しても構わない。
ステップＳ４６の処理を実行したら、“ｂ”ノードの「ノード処理」（ネスト６）は終了し、これより呼出元の処理（“（＋”ノードの「ノード処理」；ネスト５）に戻ることになる。これより、“（＋”ノードの「ノード処理」におけるステップＳ４３の処理が終了することになり、ステップＳ４４で全ての子ノードについて処理実施したか否かを判定する。ここでは、“（＋”ノードに関して、未処理の子ノード（“ａ”ノード）が残っているので、ステップＳ４２に戻る。
【００７３】
そして、ステップＳ４２において今度は“ａ”ノードを取り出し、これより、これに応じてステップＳ４３で呼び出される「ノード処理」は、“ａ”（変数）の処理となる。
“ａ”ノードの「ノード処理」では、ステップＳ１１、Ｓ３１、Ｓ４１が全てＮＯとなり、これより、変数処理（ステップＳ４６）を実行する。つまり、処理対象ノード“ａ”を、構文リストに出力する。これより、この段階では、“ｂ”と“a”のみが、構文リストに記述されている状態となっている。そして、呼出元の処理（“（＋”ノードの「ノード処理」）に戻ると、今度はステップＳ４４の判定はＮＯとなるので、ステップＳ４５の処理を実行する。
【００７４】
ステップＳ４５では、処理対象ノードの関数を構文リスト出力する。ここでは、関数“＋”を構文リスト出力することになる。ここで、対象となる関数が、＋（加算）、−（減算）、＊（乗算）、／（除算）の四則演算である場合には、出力先は、この関数の子ノードに係わる上記構文リストへの出力結果の間とする。つまり、上記の例では“ｂ”と“a”が出力されているので、この間に“＋”を出力する。これによって、構文リストには“ｂ＋ａ”が記述された状態となる。
【００７５】
ステップＳ４５では、更に、上記記述“ｂ＋ａ”に対して仮変数を割当てる処理を実行する。仮変数は、予め決められたルールに従って生成すればよく、ここでは仮変数＝「“ＩＮＳＴ＿”＋任意の数値」を生成ルールとする。任意の数値は、重複しなければ何でもよく、ここでは‘６’であるものとし、仮変数＝“ＩＮＳＴ＿６”が割当てられるものとする。この割当ては、“：＝”（代入）を意味し、従ってこの処理によって構文リストには下記の記述がある状態となる。すなわち、図５の構文リストにおける１行目のみが記述された状態となる。
ＩＮＳＴ＿６  ；＝  ｂ＋ａ；
【００７６】
上記ステップＳ４５を実行完了したら、“（＋”ノードの「ノード処理」（ネスト５）が終了することになり、これによって、呼出元である上記“（：＝”ノードの「ノード処理」（ネスト４）に戻ることになる。これより、“（：＝”ノードの「ノード処理」（ネスト４）におけるステップＳ４３の処理が終了することになり、続いてステップＳ４４の処理を実行すると、“（：＝”ノードには未処理の子ノード“ｃ”があるので判定はＮＯとなり、ステップＳ４２に戻る。
【００７７】
そして、ステップＳ４２において今度は子ノード“ｃ”を取り出し、これより、これに応じてステップＳ４３で呼び出される「ノード処理」は、“ｃ”（変数）の処理（ネスト５）となる。
【００７８】
“ｃ”ノードの「ノード処理」では、ステップＳ１１、Ｓ３１、Ｓ４１が全てＮＯとなり、これより、変数処理（ステップＳ４６）を実行する。つまり、処理対象ノード“ｃ”を、構文リストに出力する。そして、この「ノード処理」が終了することで呼出元の“（：＝”ノードの「ノード処理」に戻ると、今度はステップＳ４４の判定はＮＯとなるので、ステップＳ４５の処理を実行する。
【００７９】
ステップＳ４５では、処理対象ノードの関数を構文リスト出力する。ここでは、関数“：＝”を構文リスト出力することになる。ここで、対象となる関数が、“：＝”（代入関数）である場合には、上記記述された“ｃ”を代入先とすると共に、代入元は最新の仮変数とする。ここでは既存の最新の仮変数は上記“ＩＮＳＴ＿６”であるので、構文リストには下記の記述が加わることになる。つまり、図５における２行目の記述が生成されることになる。
ｃ：＝ＩＮＳＴ＿６
【００８０】
尚、対象となる関数が、“：＝”（代入関数）である場合には、新たな仮変数の割り当ては行わない。この場合には、上記の通り、既存の仮変数を用いるものである。
【００８１】
上記ステップＳ４５を実行完了したら、“（：＝”ノードの「ノード処理」（ネスト４）が終了することになり、これによって、呼出元である上記“（PROGN”ノードのノード処理（ネスト３）に戻ることになる。これより、上記ステップＳ３３の処理が終了することになり、続いて、“（PROGN”ノードの子ノード全てについて処理実行済みか否かを判定する（ステップＳ３４）。上記一例では、この段階では未処理の子ノードが残っているので判定はＮＯとなり、ステップＳ３２に戻ることになる。
【００８２】
そして、上記図３の例では、ステップＳ３３で“（：＝”ノードの「ノード処理」（ネスト４）が呼び出され、この「ノード処理」のステップＳ４３で“（−”ノードの「ノード処理」(ネスト５)が呼び出され、この「ノード処理」のステップＳ４３で“ｄ”ノードの「ノード処理」（ネスト６）や“ｅ”ノードの「ノード処理」（ネスト６）が、順次、呼び出されることになる。
【００８３】
これらの処理については、上記変数“ｂ”や“ａ”や“＋”に関する処理と略同様であるので、特に説明しないが、これらの処理によって、「ｄ−ｅ」が生成され、更に仮変数ＩＮＳＴ＿８が割当てられることになる。つまり、図５における３行目の記述（下記の記述）が、生成されることになる。
ＩＮＳＴ＿８  ：＝  ｄ−ｅ；
【００８４】
更に、上記“（：＝”の「ノード処理」（ネスト４）に戻ることで、そのステップＳ４５の処理によって、上記と同様に代入元は最新の仮変数とすることで、構文リストには下記の記述が加わることになる。つまり、図５における４行目の記述の一部が生成されることになる。
ｆ：＝ＩＮＳＴ＿８
【００８５】
そして、呼出元である上記“（PROGN”ノードのノード処理（ネスト３）に戻ると、図３の例の場合には今度は上記ステップＳ３４の判定はＹＥＳとなるので、ステップＳ３５〜Ｓ３７の処理を実行する。
【００８６】
ステップＳ３５〜Ｓ３７の処理は、“（PROGN”ノードの全ての子ノードに関して上記のように構文リスト上に生成された記述（関数式）のなかで、最後に記述された関数式を検索して（ステップＳ３５）、最後に記述された関数式についてのみ仮変数を割当てる（ステップＳ３７）処理である。但し、最後に記述された関数式が、選択構造やループ構造の場合には（ステップＳ３６，ＹＥＳ）、仮変数を割当てる処理（ステップＳ３７の処理）は行わない。最後に記述された関数式が、選択構造やループ構造以外である場合に（ステップＳ３６，ＮＯ）、仮変数を割当てる処理（ステップＳ３７の処理）が行われる。
【００８７】
尚、ステップＳ３６がＹＥＳの場合、例えば、上記選択構造やループ構造の実行節で割り当てられた仮変数をそのまま使用するものであってもよいが、この例に限らない。
上記の例では、図５における４行目の関数式についてのみ、任意の仮変数を割当てることになり、図５の例では、仮変数ＩＮＳＴ＿７が割当てられることになる。これによって、図５における４行目の記述が、以下のように生成されることになる。
ＩＮＳＴ＿７  ：＝  （ｆ：＝ＩＮＳＴ＿８）
【００８８】
尚、上記ステップＳ３５〜Ｓ３７の処理を、例えばステップＳ３５等の処理と記す場合もあるものとする。
【００８９】
ここで、比較の為に、図１０の従来手法の場合の変換結果も参照して説明するものとする。
従来の方法では、上述したように、“（PROGN”ノードの全ての子ノードに関して仮変数を割当てることになっていた。つまり、上記“ｃ”ノードに対しても仮変数（ここではＩＮＳＴ＿５であったものとする）が割当てられ、この為、図１０に示すように、２行目の記述は下記のようになる。
ＩＮＳＴ＿５  ：＝  （ｃ：＝ＩＮＳＴ＿６）
【００９０】
これに対して、本手法では、上記の通り、ＰＲＯＧＮ文に関しては上記ステップＳ３５等の処理を行うことで、最後の関数式に対してのみ仮変数が割当てられるので、図５に示すように、「ＩＮＳＴ＿５  ：＝」の記述は無いものとなる。
【００９１】
上述したように、従来技術では、変換結果においては全ての関数式の実行結果に仮変数を割り当て、そのために余分な仮変数が存在することになり、変換後のプログラム実行環境を圧迫（メモリの使用など）してしまう問題が発生する。これに対して、本手法では、上記の通り、変換結果において余分な仮変数が存在しないようにできる。
【００９２】
図４の処理の説明を続ける。
図４の処理に関して、上述したように、“（PROGN”ノードの「ノード処理」（ネスト３）の最後の処理（ステップＳ３５等）まで説明した。そして、この「ノード処理」が終了することで、呼出元の「ノード処理」に戻ることになる。つまり、ネスト２の“（＝”の「ノード処理」に戻り、ステップＳ４４の判定を行うと、未処理の子ノードがあるので判定はＮＯとなり、ステップＳ４２に戻る。そして、ステップＳ４３で、未処理の子ノードである“１０”ノードの「ノード処理」を、実行させることになる。
【００９３】
‘１０’はオペランドであるので、“１０”ノードの「ノード処理」では、ステップＳ１１、Ｓ３１、Ｓ４１が全てＮＯとなり、これより、変数処理（ステップＳ４６）を実行する。つまり、処理対象ノードのオペランド“１０”を、構文リストに出力する。そして、この「ノード処理」が終了することで呼出元の処理（“（＝”の「ノード処理」；ネスト２）に戻ると、今度はステップＳ４４の判定はＮＯとなるので、ステップＳ４５の処理を実行する。
【００９４】
ここで、処理対象ノードの関数が、“＝”（イコール関数）である場合には、上記記述された“１０”と、既存の最新の仮変数とを、“＝”で結んだ式を、構文リストに追加出力する。これによって、構文リストには下記の記述が加わることになる。つまり、図５における５行目の記述の一部が生成されることになる。
ＩＮＳＴ＿７  ＝  １０
【００９５】
尚、イコール関数の場合も、上記代入関数と同様、ステップＳ４５において新たな仮変数の割当ては行わない。
【００９６】
上記処理実行を以って“（＝”ノードの「ノード処理」（ネスト２）が終了するので、呼出元の「ノード処理」に戻ることになる。つまり、“（ＩＦ”ノードの「ノード処理」（ネスト１）に戻ることになる。ここで、これまでの処理は、上記ステップＳ１２で取り出したｉｆ文の条件部である上記“（＝”に係わる処理であり、この時点でステップＳ１３の処理が完了したことになり、続いてステップＳ１４の処理を実行する。
【００９７】
ステップＳ１４の処理は、構文リストにおける現在の最後の行に対して、if文を追加する処理である。上記一例では、上記「ＩＮＳＴ＿７  ＝  １０」に対して、ｉｆ文を追加することになる。これによって、図５に示す５行目の式が、ほぼ完成することになる。但し、５行目の式の最後の括弧“{”は、未だ記述されていない。この“{”は後述するステップＳ１７の処理で記述されるものであり、これについては後述する。
【００９８】
上記のようにステップＳ１４の処理によって、上記一例の場合、図５に示す５行目の式における下記の記述が、生成されることになる。
ｉｆ（ＩＮＳＴ＿７  ＝  １０）
そして、今度は、ｉｆ文におけるＴｈｅｎ部を取り出して（ステップＳ１６）、このＴｈｅｎ部に係わる「ノード処理」を実行させる（ステップＳ１６）。上記一例の場合、“ｉｆ”ノードのもう一方の子ノードである“（：＝”ノードに係わるノード処理を実行させることになる。
【００９９】
この“（：＝”ノードの「ノード処理」（ネスト２）では、まず、ステップＳ１１、Ｓ３１がＮＯでステップＳ４１がＹＥＳとなり、これより、この“（：＝”ノードの子ノード（引数）を順次取り出して（ステップＳ４２）、これら子ノード毎に「ノード処理」を呼び出す（ステップＳ４３）処理を、全ての子ノードについて実行するまで繰り返す。この処理については、図５の１行目、２行目の式を作成した際の処理と、略同様であり、ここでは説明を省略するものとする。この処理結果として、図５における６行目、７行目の下記の式が、生成されることになる。
ＩＮＳＴ＿１０  ；＝  ｃ−ａ；
ＩＮＳＴ＿９  ：＝  （ａ：＝ＩＮＳＴ＿１０）
【０１００】
そして、“ｉｆ”ノードの「ノード処理」（ネスト１）に戻り、ステップＳ１７の処理を実行する。ステップＳ１７の処理は、構文リストにおける上記Ｔｈｅｎ部に係わる変換結果を、括弧“｛｝”で挟む記述を、構文リストに追加する。上記一例の場合、上記図５における６行目、７行目の式を挟むように、開き括弧“｛”と閉じ括弧“｝”を、追加記述する。
【０１０１】
以上の処理によって、図５の１行目〜８行目の変換結果が、得られることになる。
続いて、変換対象にｅｌｓｅ部があるか否かを判定する（ステップＳ１８）。そして、ｅｌｓｅ部がある場合には（ステップＳ１８，ＹＥＳ）、その変換処理を実行する（ステップＳ１９）。これは、既存の処理であるので、ここでは特に説明しないものとする。
【０１０２】
一方、例えば図９の例のようにｅｌｓｅ部がない場合には（ステップＳ１８、ＮＯ）、従来では何も行わなかったが、本例ではステップＳ２０の処理を実行する。尚、従来では何も処理しないので、例えば図９の例に対しては、図１０に示すように、上記８行目までの変換結果のみであり、９行目以降は存在しない。一方、本手法では、ステップＳ２０の処理によって、図５に示す９行目〜１１行目の記述が、生成されることになる。
【０１０３】
ステップＳ２０の処理は、下記の３行分の１文を、構文リストの最後に追加記述する処理である。
ｅｌｓｅ  {
最新の（最後の）仮変数  ：＝  ０；
｝
【０１０４】
上記一例の場合、最新の仮変数は、図５の７行目の式を生成する際に割当てられていたＩＮＳＴ＿９である。よって、上記一例の場合、図５に示す９行目〜１１行目の記述が、追加されることになる。
ｅｌｓｅ  {
ＩＮＳＴ＿９  ：＝  ０；
｝
【０１０５】
従来の場合、図１０に示すように変換結果にｅｌｓｅ文が無いので、実行結果が不定になるという問題が発生する。これに対して、本手法では、上記の通り、変換元にｅｌｓｅ文が無い場合であっても、変換結果には強制的にｅｌｓｅ文が追加されているので、実行結果が不定になることはない。尚、上記‘０’は一例であり、この例に限らず、任意の数値を用いればよい。つまり、強制的に所定の数値を割当てれば、実行結果が不定となることはない。
【０１０６】
換言すれば、本手法では、ＦＣＬプログラムにおいて選択構造で条件式が不成立時の選択肢が省略されていた場合、変換結果プログラムに条件不成立時の選択肢を追加すると共に、最新の（最後の）仮変数に対して０を代入する実行節を、変換結果プログラムに追加する。
【０１０７】
尚、図３には示されていないが、例えば図３の例において更に別の“ｉｆ”ノード（不図示）が存在する場合、この“ｉｆ”ノードに関しても上記ステップＳ１２〜Ｓ２０の処理が行われることになる。
【０１０８】
また、図３に示すＰＲＯＧＮ関数に係わる複数の関数式の１つとして、ｉｆ文がある場合もあり得る。この場合には、上記の通り、新たな仮変数は生成しない。
以上説明したように、本例の言語変換装置１０によれば、関数型言語を手続型言語に変換する言語変換装置において、ＰＲＯＧＮ関数を含む選択構造を含むプログラム文の変換の際に、実質的に無用となる仮変数の生成・割り当てが行われないようにできる。あるいは、変換元のプログラム文にELSE節がない場合であっても、変換したプログラム実行結果が不定になるという問題を回避できる。
【符号の説明】
【０１０９】
１０  言語変換装置
１１  関数型言語（ＦＣＬ）格納部
１２  二次元構造（ツリー）変換部
１３  二次元構造格納部
１４  変換部
１５  手続型言語格納部
【図１】
0006402639.tif 000002
【図２】
0006402639.tif 000003
【図３】
0006402639.tif 000004
【図４】
0006402639.tif 000005
【図５】
0006402639.tif 000006
【図６】
0006402639.tif 000007
【図７】
0006402639.tif 000008
【図８】
0006402639.tif 000009
【図９】
0006402639.tif 000010
【図１０】
0006402639.tif 000011