【文献】
太田 裕,C++コンパイラの中間コード生成と最適化技報,第52回(平成8年前期)全国大会講演論文集(5),社団法人情報処理学会,1996年 3月 8日,第5-3頁-第5-4頁
【文献】
齊藤 正伸,C言語とreconfigurable computerとの相性に関する一考察,情報処理学会研究報告,日本,社団法人情報処理学会 Information Processing Society of Japan,1997年 8月22日,第97巻, 第78号,第121-126頁
【文献】
田中春樹, 吉田裕, 石橋景二,制御用中間言語FCL,富士時報,日本,富士電機株式会社,1987年12月,Vol.60, No.12,第15-19頁,URL,http://www.fujielectric.co.jp/company/jihou_archives/contents_60-12.html
【文献】
パー テレンス,言語実装パターン,日本,株式会社オライリー・ジャパン,2011年12月22日,第1版,第245-272頁
(58)【調査した分野】(Int.Cl.,DB名)
関数型言語で記述された制御処理プログラムを、手続型の命令処理を行う装置で実行可能な言語形式のプログラムである手続型言語プログラムに変換する言語変換装置において、
前記関数型言語で記述された制御処理プログラムにおける関数又はオペランドの各要素の配列を記憶した関数型言語記憶手段と、
前記配列の各要素を順次取得し、該各要素に応じたノードと該ノード間のリンクから成るツリー構造を生成するツリー構造作成手段と、
前記ツリー構造中のノードは、子供ノードを持たないノードであるリーフと、該リーフ以外のノードである子持ノードとから成り、該ツリー構造中の各ノードのうち該子持ノードにユニークな識別子を付与すると共に、条件分岐の関数に係わるノードの子供ノードには、同一の識別子を付与する識別子付与手段と、
前記識別子を付与後の前記ツリー構造の各ノードに基づいて前記手続型言語への変換を行う手段であって、変換対象ノードが前記条件分岐の関数に係わるノードである場合には、予め登録されている条件分岐処理に係る所定の雛形を用いて前記手続型言語プログラムの生成を行う変換手段と、
を有することを特徴とする言語変換装置。
前記識別子付与手段は、前記条件分岐の関数に係わるノードの複数の子供ノードのうちの2番目と3番目のノードに、同一の識別子を付与することを特徴とする請求項1〜3の何れかに記載の言語変換装置。
前記変換手段は、前記一時的に記憶された各命令文を、前記条件分岐の関数に係わるノードの各子供ノードに係わる前記手続型言語への変換結果として、前記所定の雛形の該当箇所に当て嵌めると共に、前記一時的に記憶された命令文全てを消去することを特徴とする請求項5記載の言語変換装置。
関数型言語で記述された制御処理プログラムを、手続型の命令処理を行う装置で実行可能な言語形式のプログラムである手続型言語プログラムに変換する言語変換装置のコンピュータを、
前記関数型言語で記述された制御処理プログラムにおける関数又はオペランドの各要素の配列を記憶した関数型言語記憶手段と、
前記配列の各要素を順次取得し、該各要素に応じたノードと該ノード間のリンクから成るツリー構造を生成するツリー構造作成手段と、
前記ツリー構造中のノードは、子供ノードを持たないノードであるリーフと、該リーフ以外のノードである子持ノードとから成り、該ツリー構造中の各ノードのうち該子持ノードにユニークな識別子を付与すると共に、条件分岐の関数に係わるノードの子供ノードには、同一の識別子を付与する識別子付与手段と、
前記識別子を付与後の前記ツリー構造の各ノードに基づいて前記手続型言語への変換を行う手段であって、変換対象ノードが前記条件分岐の関数に係わるノードである場合には、予め登録されている所定の雛形を用いて前記手続型言語プログラムの生成を行う変換手段、
として機能させる為のプログラム。
【背景技術】
【0002】
プログラマブルコントローラ(PLC:Programmable Logic Controller)の制御プログラムを関数型のプログラム構造で表した関数型制御言語(FCL:Functional Control Language;尚、関数型言語という場合もあるものとする)が使用されている。
【0003】
FCLについては特許文献1,特許文献2等で説明されているが、ここで簡単にFCLについて説明する。FCLは、一つの機能を
図10に示す形式の関数式で表し、更に
図11の図上上側に示すように関数式自身を別の関数式の引数とすることができるものである。従って、
図11の図上下側に示すように言語の2次元的な表現(2次元構造ツリー表現)を行う事ができ、記述性が高くなる。これより、例えば、
図12に示すような、PLCプログラムの表現依存部と機械依存部をつなぐ中間言語としての役割を果たすことができる。
【0004】
関数型言語の実行方式として命令スタックとデータスタックを用いて演算を実行する方式がある(上記特許文献1,2や特許文献3など)。
しかし、上記方式により演算を行うには、命令スタックとデータスタックという構成が必要となり、これらの構成と備えない装置では実行が困難、または、前記方式をエミュレーションするため性能が低下するという問題があった。その問題を解決するために、関数型言語を手続型言語に変換して、手続型言語(たとえばC言語)で実行する方式が提案されていた(特許文献4)。
【0005】
特許文献4では、例えば
図11の図上上側に示す関数型言語の関数式を、
図13に示すような配列にして、これに基づいて
図14に示すような二次元構造(ツリー構造)を生成し、このツリー構造に基づいて手続型言語プログラムへの変換を行うものである、
図14に示すツリー構造は、
図13に示す配列順に従って、順次、この配列の各要素から
図14に示す各ノードを生成していくことで作成される。
図14に示す各ノードは、“ノードの名称”、“インスタンス名”、“子供ノードへのポインタ”、“次のノードへのポインタ”の各データ項目から成る。
【0006】
“ノードの名称”には、配列の要素に格納されている関数またはオペランド等が格納される。尚、「開き括弧“(”+任意の名称)」の形式のものが関数であり、それ以外は(閉じ括弧を除いて)オペランド(変数など)である。また、配列の要素が閉じ括弧“)”である場合には、ノードを生成することなく、この閉じ括弧に対応する開き括弧のノードに処理対象を戻す。“インスタンス名”は、リーフ以外のノードに付与される、ツリー構造内におけるノード識別子である。尚、リーフとは子供ノードを持たないノード(末端のノード)である。
【0007】
また、尚、以下の説明では、各ノードをその“ノードの名称”を用いて区別して記述する場合があるものとする。例えば、“ノードの名称”が“(A”であるノードは、ノード“(A”等と呼ぶものとする。
【0008】
ここで、関数は、別の関数およびオペランド(変数など)を引数とすることができる。関数のノードからその引数のノードをポイント(リンク)するときは、“子供ノードへのポインタ”に、リンクの為のポインタを設定する。つまり、呼び出し元の関数のノードにおける“子供ノードへのポインタ”に、その引数のノード(複数ある場合には何れか1つ)を指定するためのポインタ値を設定する。
【0009】
一方、呼び出し元の関数のノードが同一である引数のノード(複数ノード)には、“次ノードへのポインタ”に所定のポインタ値を設定することで、自分に続く引数を指定する。
【0010】
図14に示す例では、例えば、ノード“(B”における“子供ノードへのポインタ”には、その引数ノードの1つである“v”ノードを指定(リンク)するポインタが格納されている。更に、関数Bの引数はvとwであるので、“v”ノードの“次ノードへのポインタ”には、自ノードに続く引数のノードである“w”ノードを指定(リンク)するポインタが格納されている。
【0011】
そして、
図14に示すツリー構造に基づいて、
図11の図上上側に示す関数型言語のプログラムを、手続型言語プログラム(不図示;尚、後述する
図15(a)に示す例については、
図15(b)に一例を示してある)へ変換する。
【0012】
この変換処理は、
図14に示すツリー構造から“子供ノードがリーフしかないノード”(該当ノードというものとする)を見つける毎に、該当ノードの関数とその子供ノードの引数などから、該当ノードのインスタンス名を代入先とする代入文(命令文)を生成する。これが手続型言語プログラムである。そして、該当ノードの子供ノードを全て削除する。これを、ノードが1つになるまで繰り返す。
【発明を実施するための形態】
【0026】
以下、図面を参照して本発明の実施の形態について説明する。
図1は、本例の言語変換装置の構成・機能ブロック図である。
図示の本例の言語変換装置10によれば、関数型制御言語(FCL)を手続型言語(C言語など)に変換することができ、命令スタックとデータスタックを待たない手続き形の命令処理を行うことができると共に、特に条件分岐を有するFCLプログラム等について、FCLの条件分岐命令を適切な構文に変換することができ、余分な処理実行を行うことが無くなり、余分な一時変数を作成することもなく、効率的な実行が実現できるようにすることが可能となる。
【0027】
図1に示す例の言語変換装置10は、関数型言語(FCL)格納部11、二次元構造(ツリー)変換部12、二次元構造格納部13、関数名−インスタンス名作成部14、インスタンス名管理部15、命令並び換え部(変換部)16、手続型言語格納部17の各機能部を有する。
【0028】
尚、関数名−インスタンス名作成部14とインスタンス名管理部15とを、まとめて“識別子付与部”と呼ぶものとしてもよい。“識別子付与部”は、ツリー構造中の各ノードのうち、リーフ以外のノードにユニークな識別子を付与すると共に、条件分岐の関数に係わるノードの子供ノードには(例えば、各子供ノードのうちの一部に(例えば3つのうちの2つに))、同一の識別子を付与するものである。
【0029】
言語変換装置10は、例えば汎用のパソコンやサーバ装置等で実現されるので、特に図示しないが、CPU、記憶装置(ハードディスク等)、メモリ、入力部、表示部、通信部等の一般的なコンピュータ装置の構成を有している。
【0030】
上記不図示の記憶装置には、予め所定のアプリケーションプログラムが記憶されており、上記CPUがこのアプリケーションプログラムを読出し・実行することにより、上記各種機能部の処理機能が実現される。すなわち、関数型言語(FCL)格納部11、二次元構造(ツリー)変換部12、二次元構造格納部13、関数名−インスタンス名作成部14、インスタンス名管理部15、命令並び換え部16、手続型言語格納部17等は、上記CPUが上記アプリケーションプログラムを読出し・実行することにより実現される。
【0031】
また、本発明は、上記言語変換装置10の形態に限らず、その各種機能をコンピュータ等により実現させる為の上記アプリケーションプログラム自体として構成することもできる。
【0032】
尚、これらの各種機能部のうち、関数型言語(FCL)格納部11、二次元構造(ツリー)変換部12、「関数名−インスタンス名作成部」14は、上記従来の特許文献4における、関数型言語(FCL)格納装置11、二次元構造(ツリー)変換部12、関数名−インスタンス名作成部14と同じであっても構わない。また、二次元構造格納部13は、生成された二次元構造(ツリー構造)を格納するという点では、特許文献4の二次元構造格納装置13と略同様であってよいが、格納内容は異なる。また、手続型言語格納部17も、手続型言語に変換したプログラムを格納するという点では、特許文献4の手続型言語格納装置16と略同様であってよいが、格納内容は異なる。
【0033】
上述したことから、本例の言語変換装置10は、例えば一例としては、特許文献4の言語変換装置に対して、インスタンス名管理部15が追加されると共に、命令並び換え部16の処理内容が異なるものと見做すこともできるが、この例に限るものではない。
【0034】
関数型言語(FCL)格納部11は、関数型言語の任意のプログラム(FCLプログラム)を格納するものであり、更にこのFCLプログラムの命令(関数)/オペランド(変数など)等の各要素を配列として格納したものである。ここでは、FCLプログラムの一例として上記
図15(a)に示した例を用いるものとするならば、このプログラム例に対応する上記配列は、
図2に示すものとなる。このような配列生成自体は、例えば上記
図13に示すように従来より行われていたものであり、ここでは特に説明しない。
【0035】
二次元構造(ツリー)変換部12と「関数名−インスタンス名作成部」14は、上記の通り既存の機能であってよく、二次元構造(ツリー)変換部12は、上記関数型言語(FCL)格納部11に格納された上記配列に基づいて、FCLプログラムを例えば上記
図14に示したような二次元構造(ツリー構造)表現で表したデータ(二重の親子関係を持ったリンク構造である)を生成する。
【0036】
また、「関数名−インスタンス名作成部」14は、上記ツリー構造の末端部(リーフ)以外のノード(子持ノードと呼ぶものとする)に対して、ツリー内でのユニークなノード識別子(本例ではインスタンス名とするがこの例に限らない)を付与するものである。
【0037】
上記
図2に示した例に対しては、特許文献4の従来手法の場合には
図3に示すツリー構造が生成されることになる。但し、本例では、更にインスタンス名管理部15によって複数のノードに同一のインスタンス名が付与される場合があり、その結果、二次元構造格納部13には、
図4に示すツリー構造が生成・格納されることになる。尚、上述したように、リーフとは子供ノードを持たないノード(末端のノード)である。
【0038】
尚、上記ツリー構造は、上記配列の各要素(関数やオペランド等)を順次読み出して各要素に応じたノードを生成すると共に、ノード間のリンク(ポインタなど)を生成することで作成される(詳細は特許文献4など参照;尚、特許文献4における
図5のS7の処理とS8の処理とを逆にしてもよい)。
【0039】
ここで、ノードにおける“子供ノードへのポインタ”と“次のノードへのポインタ”について簡単に説明する。まず、基本的に、「(IF」等のような開き括弧“(”で始まる要素については(つまり、関数については)、閉じ括弧“)”までがその引数となるので、閉じ括弧“)”の次の要素に係るノードが“次のノード”ということになる。また、上記引数となるノードは全て子供ノードとなるが、そのうちの最初のノードのみが“子供ノードへのポインタ”によってポイント(リンク)されることになる。
【0040】
一方、開き括弧“(”も閉じ括弧“)”も無い要素のノードについては(つまり、オペランドのノードについては)、その子供ノードは存在しない。よって、その“子供ノードへのポインタ”は常にNULLが設定される。
【0041】
尚、本説明では、関数に応じたノードは関数ノード、オペランド(変数など)に応じたノードを変数ノードと呼ぶ場合もあるものとする。
図3と
図4とを比較すれば明らかなように、両者の相違はインスタンス名である。すなわち、
図3に示すように(そして、特許文献4に記載のように)、従来ではインスタンス名はユニークな存在であり、従って複数のノードに同一のインスタンス名が付与されるようなことはない。これに対して、
図4に示すように、本例の場合、複数のノードに同一のインスタンス名が付与されることも有り得る。
【0042】
例えば、
図3においては、図上中央付近の「ノード名称が“(−”」である2つのノードのインスタンス名は、一方が“INST_5”、他方が“INST_6”となっている。これに対して、
図4におけるこれら2つのノードのインスタンス名は、両方とも“INST_5”となっている。
【0043】
これは、インスタンス名管理部15によって、所定の条件に該当する複数のノードに対して同一のインスタンス名が付与されるものである(例えば、インスタンス名付与処理中において、条件分岐(IF等)の関数に係るノードを検出した場合、その子供ノードのうちの2つのノードに、同一のインスタンス名を付与する場合がある)。インスタンス名管理部15は、例えば、条件分岐の関数(IF等)の関数ノードがあった場合には、例えば、その子供ノードのうちの2番目のノードと3番目のノードに対して、同一のインスタンス名を付与するようにする。
【0044】
尚、上記のような二次元構造のデータを表すためには、本データ構造だけである、XML(Extensible Markup Language)で記述されたテキストによるデータ構造であってもよい。XMLであれば、ツリー構造データの追加/削除/検索などの操作手段の作成は容易である。
【0045】
命令並び換え部16は、基本的には特許文献4の命令並び換え部15と略同様の処理を行うものであってもよいが、更に、条件分岐に関しては後述する処理を行うものであり、それによって例えば
図5に示すプログラムを生成するものである。詳しくは後述する。
【0046】
手続型言語格納部17には、命令並び換え部16によって生成された手続型言語のプログラム(例えば
図5に示すもの)が格納される。
以下、上述した各種機能部について、具体例も参照しながら、更に詳細に説明する。
【0047】
まず、上記二次元構造(ツリー)変換部12及び関数名−インスタンス名作成部14による二次元構造(ツリー構造)生成処理について、以下、説明する。尚、これらは上記の通り既存技術であってよいので、簡単に説明するものとする。また、具体例として、上述した
図15(a)に示すプログラム例を用いる。
【0048】
既に述べたように、特許文献4の場合と略同様に、二次元構造(ツリー)変換部12は、関数型言語(FCL)格納部11に格納されているプログラム(FCLプログラムという)から、ツリー構造を生成する。これは、例えば、FCLプログラムの内容(配列)をそのままツリー構造化する。この時、例えば、関数部を親の節(ノード)、引数部を子供のノードにする。例えば、
図15(a)に示すFCLプログラム例の場合、まず
図2に示す配列を生成し、この配列に基づいて
図3に示すツリー構造を生成する。
【0049】
この様なツリー構造生成処理については、特許文献4に記載されているが、以下、簡単に説明するものとする。
二次元構造(ツリー)変換部12は、関数型言語(FCL)格納部11に格納される上記配列の各要素(本例ではFCLコード)を順次読み出して、上記ツリー構造を生成する(但し、未だインスタンス名は無い)。本処理は、例えば特許文献4に記載のように、関数開始子(開き括弧“(”)、関数終了子(閉じ括弧“)”)、オペランド(括弧以外)等に基づいて、例えば下記の手法により実現できる。
【0050】
つまり、最初にルートノード(一番上位の要素:処理を再帰的に実行する為のダミーノード)を作成し、“現在処理中ノード”として記録する。そして、配列のFCLコードを順次読み出して、基本的には、それが関数またはオペランドであるならば(換言すれば、閉じ括弧以外であるならば)、それに対応するノードを新規生成すると共に、この新規ノードとそのときの上記“現在処理中ノード”との間のリンク(ポインタ)を生成する。これは、“子供ノードへのポインタ”または“次のノードへのポインタ”によってリンクする。そして、新規ノードを新たな上記“現在処理中ノード”とする。
【0051】
つまり、配列から取得した要素(FCLコードなど)が任意の関数である場合には、該関数の名称を“ノード名称”とするノードを新規作成すると共に、現在処理中ノードから該新規ノードをポイントするポインタを、該現在処理中ノードにおける“子供ノードへのポインタ”または“次のノードへのポインタ”の何れかに設定し、更に、該新規ノードを新たな前記現在処理中ノードとする。
【0052】
また、配列から取得した要素が任意のオペランドである場合には、該オペランドの名称を“ノード名称”とするノードを新規作成すると共に、現在処理中ノードから該新規ノードをポイントするポインタを、該現在処理中ノードにおける“子供ノードへのポインタ”または“次のノードへのポインタ”の何れかに設定し、更に、該新規ノードにおける“子供ノードへのポインタ”を無効化し、更に、該新規ノードを新たな前記現在処理中ノードとする。
【0053】
尚、上記配列から読み出したFCLコードが上記閉じ括弧である場合には、上記の通りノードを作成しないと共に、この場合には上記“現在処理中ノード”を、当該閉じ括弧に対応する開き括弧(関数)のノードに設定する。
【0054】
上記“現在処理中ノード”から新規ノードへのポインタは、“現在処理中ノード”における上記“子供ノードへのポインタ”と“次のノードへのポインタ”の何れかに格納される。例えば特許文献4に記載のように、変数ノードの“子供ノードへのポインタ”には常にNULLが格納される。従って、“現在処理中ノード”が変数ノードである場合には、常に、その“次のノードへのポインタ”に上記新規ノードへのポインタが格納される。
【0055】
一方、“現在処理中ノード”が変数ノードである場合には、最初の新規ノードに関しては“子供ノードへのポインタ”にこの新規ノードへのポインタが格納され、2番目の新規ノードがある場合には“次のノードへのポインタ”にこの新規ノードへのポインタが格納される。換言すれば、“子供ノードへのポインタ”にポインタ設定済みであれば“次のノードへのポインタ”に新規ノードへのポインタを設定し、そうでければ“子供ノードへのポインタ” に新規ノードへのポインタを設定する。
【0056】
尚、“子供ノードへのポインタ”が示すノードは、文字通り、そのノードの子供ノードである。また、“次のノードへのポインタ”が示すノードは、そのノードと親ノードが同一である他のノードである。例えば、
図3に示すインスタンス名がINST_4、INST_5、INST_6の3つのノードの親ノードは、全て同じである(何れも、INST_3のノードが親ノード)。
【0057】
例えば、
図3において、図示の上の真ん中に示す“(>”のノード(INST_4)が“現在処理中ノード”である場合、図上その右側に示す“a”のノードが新規ノードとして作成され、これによって“(>”のノードの“子供ノードへのポインタ”に、“a”のノードへのポインタが格納される(尚、図上では、この様なポインタを矢印で示している)。また、“a”のノードは変数ノードであるので、その“子供ノードへのポインタ”にNULLが格納される。
【0058】
次に、“a”のノードが新たな“現在処理中ノード”となり、その右側の“b”のノードが新規ノードとして作成され、これによって“現在処理中ノード”(“a”のノード)の“次のノードへのポインタ”に、“b”のノードへリンクするポインタが格納される。また、“b”のノードは変数ノードであるので、その“子供ノードへのポインタ”にNULLが格納される。
【0059】
そして、次に読み出されるFCLコードは閉じ括弧“)”であるので、“現在処理中ノード”(“b”のノード)の“次のノードへのポインタ”にNULLが格納されると共に、この閉じ括弧“)”に対応する開き括弧“(”のノード(“(>”のノード(INST_4))が(換言すれば、“現在処理中ノード”の親ノードが)、新たな“現在処理中ノード”となる。
【0060】
この状態で、次に読み出されるFCLコードは“(−”であるので、図示の“(−”のノード(INST_5)が新規作成されると共に、“現在処理中ノード”(“(>”のノード)の“次のノードへのポインタ”に、当該“(−”のノードへリンクするポインタが格納されることになる。そして、当該“(−”のノードが、新たな“現在処理中ノード”となる。
【0061】
他のノードも上記一例と略同様にして作成され、それによって
図2の配列に対しては従来手法の場合には
図3に示すツリー構造が生成されることになる。
尚、NULLの設定方法は、一例を上記したが、他の例については特許文献4に記載されており、ここでは省略する。尚、
図3、
図4において、斜線がNULLを意味している。よって、例えば図上右上角に示す“b”のノードの場合には、“インスタンス名”、“子供ノードへのポインタ”、“次のノードへのポインタ”の3つの項目にNULLが設定されていることになる。
【0062】
「関数名−インスタンス名作成部」14は、上記ツリー構造の末端部(リーフ)以外のノードに対して、ツリー内でのユニークなノード識別子(本例ではインスタンス名)を付与する。リーフは具体的な変数オペランドとなるので、そのままにする。
【0063】
換言すれば、「関数名−インスタンス名作成部」14は、各関数ノードに対して、順次、ユニークな(重複しない)名称/記号/番号等を生成・付与する。本例では”INST_”を接頭辞としたシリアル番号を割り付けている。割り付け順序は、関数ノードの出現順序である。換言すれば、「関数名−インスタンス名作成部」14だけの場合には、各ノードは全て異なるインスタンス名が割り付けられることになり、複数のノードに同一のインスタンス名が割り付けられるようなことはない。
【0064】
ここで、上記「関数名−インスタンス名作成部」14によるインスタンス名の割り付け処理の際に、インスタンス名管理部15によって、所定の条件に該当する複数のノードがある場合には、当該複数のノードに同一のインスタンス名を割り当てる。
【0065】
上記所定の条件とは、第一に、親ノードが条件分岐であるノード、換言すれば条件分岐ノードの子供ノードであることである。この第一の条件に加えて、更に条件があるが、これについては後述する。
【0066】
換言すれば、インスタンス名管理部15は、ノードに記述された関数が条件分岐などである場合(値を持たない構文に対する関数である場合)に、分岐して実行する内容に対して同一のインスタンスが割り当てられるように、インスタンス名の管理を行う(条件によりどちらか一方しか実行しない為、条件によらず実行結果を同一のインスタンス変数に格納する)。
【0067】
命令並び換え部16は、二次元構造格納部13に格納されたツリー構造の先頭から末端に向かう方向に順次辿って、子供ノードがリーフしかないノードを検索する。この検索の結果として、子供ノードがリーフしかないノードが検出される毎に、当該子供ノードがリーフしかないノードについて、ノードに記述された関数が呼び出されて、その関数の値を代入する代入文が、代入先をそのノードのインスタンス名(インスタンス変数というものとする)として作成されて、手続型言語格納部17に格納される。そして、上記処理で手続型言語格納部17に格納したノードの子供ノードがすべて削除される。これらの処理を、ツリー構造上のノードの数が1つになるまで繰り返し実行する。
【0068】
関数型言語の命令(関数)/変数(オペランド)の各要素の配列から生成されたツリー構造を用いて、ネストされた子供の関数が命令の実行順序で親関数の前に、命令並び換え部16による以上の操作によって並び換えられ、親関数は、子供関数の実行結果が代入されたオペランド(インスタンス名が付けられた変数)を用いて実行される。
【0069】
このような並び換えにより、命令スタックとデータスタックを持たない装置(例えば、手続き型の命令処理を実行する装置)において、関数型制御言語を実行することが可能となる。
【0070】
但し、上記の命令並び換え部16の処理は、特許文献4における命令並び換え部15と略同様の処理機能と見做してもよい。本例の命令並び換え部16では、更に、条件分岐の関数ノードを検出した場合に、後述する処理を行うことで、FCLの条件分岐命令を、変換先の手続型言語における適切な条件分岐の構文へと変換することが可能となる。
【0071】
一般に変換先の手続型言語では適切な条件分岐の構文があり、FCLの条件分岐命令を適切な構文に変換することができれば、余分な処理実行や一時変数を作成することもなく、効率的な実行が可能である。
【0072】
上記のように、命令並び換え部16は、上記ツリー構造を順にたどり、子供ノードがリーフしかないノード(変換対象ノードとする)を見つける毎に、手続型言語プログラムへの変換を行うと共に、必要に応じて変換結果を手続型言語格納部17に格納する。
【0073】
この変換は、基本的には、上記特許文献4と略同様に、変換対象ノードに記述された関数呼び出し(記述された関数に対応する変換先の関数等と、子供ノードに記述された引数等を用いて作成)と、その結果の代入文を作成する。代入先は変換対象ノードのインスタンス名とする(インスタンス変数を代入先とする)。
【0074】
但し、本手法の場合、変換対象ノードに記述された関数が条件分岐である場合、代入文ではなく、対応する手続型言語条件分岐構文に変換する。これについては詳しくは後述する。
【0075】
上述した各種処理により、ネストされた子供の関数が親関数の前に並び換えられ、子供関数の実行後に、この実行結果を用いて親関数が実行されるので、命令スタックとデータスタックが無くても、問題なく実行できる形式へと変換されることになる(この点は、特許文献4と略同様)。
【0076】
これに加えて、本手法では、条件分岐関数によって実行制御される部分は、対応する手続型言語条件分岐構文に変換されるのであって、特に、条件分岐の結果に応じて一方の処理だけが実行される形式となるので、無駄な処理が行われることが無くなる。更に、上記のように、条件分岐関数に係る子供ノードに同一のインスタンス名を付与されることで、インスタンス変数の数を削減することもできる。
【0077】
図6〜
図9に、本例の言語変換装置10の処理フローチャート図を示す。
図6は全体フローチャート図、
図7〜
図9は
図6の各処理の詳細フローチャート図である。
【0078】
図6において、まず、二次元構造(ツリー)変換部12が、上記のように既存の処理によって、関数型言語格納部11に格納されているFCLプログラムを、二次元構造(ツリー構造)に変換する(ステップS1)。
【0079】
このツリー構造の各ノード(但し、リーフは除く)に対して、関数名−インスタンス名作成部14によって、ツリー内でのユニークなノード識別子(本例ではインスタンス名)を割り当てる。但し、その際、インスタンス名管理部15によって、複数のノードに同じインスタンス名が割り当てられる場合も有り得る(ステップS2)。ステップS2の処理の詳細は、
図7に示し、後に説明する。
【0080】
尚、上記作成されたツリー構造は、二次元構造格納部13に格納される。
そして、上記ツリー構造の先頭ノードに、走査位置(例えば上記“現在処理中ノード”を示すポインタ等)をセットする(ステップS3)。そして、この走査位置を末端方向へ向けて順次移動させながら(“現在処理中ノード”を順次変えながら)、子供ノードがリーフだけであるノードを探索する(ステップS4)。ステップS4の処理の詳細は、
図8に示し、後に説明する。
【0081】
上記ステップS4で探し出したノード(変換対象ノード)に関して、手続型言語に変換する処理を行う(ステップS5)。ステップS5の処理の詳細は、
図9に示し、後に説明する。
【0082】
そして、変換対象ノードの子供ノード(リーフ)を全て削除する(ステップS6)。この削除によってツリー構造上のノードが1個だけの状態となったら(ステップS7,YES)本処理は終了する。一方、未だ2個以上のノードが残っているならば(ステップS7,NO)、上記走査位置を変換対象ノードの親ノードにセットして(当該親ノードを新たな“現在処理中ノード”にして)(ステップS8)ステップS4の処理に戻る。
【0083】
図7は、上記ステップS2のインスタンス名割当て処理の詳細フローチャート図である。
図7の処理では、ツリー構造の先頭から各ノードを順次“現在処理中ノード”として、現在の“現在処理中ノード”が、条件分岐の関数(ここでは“(IF”)に係るノードである場合には(ステップS21,YES)、このノードの子供ノードの数をカウントし(ステップS22)、子供ノードが2個であるか否かを判定する(ステップS23)。
【0084】
ここで、“現在処理中ノード”の関数が条件分岐ではない場合(ステップS21,NO)もしくは条件分岐であるが子供ノードが2個である場合には(ステップS21、S23がYES)、上記特許文献4のような従来通りの方法で各子供ノードにユニークな(異なる)インスタンス名を付与する(勿論、従来手法の通り、子供ノードがリーフの場合にはインスタンス名の付与は行われない)(ステップS25)。
【0085】
一方、“現在処理中ノード”の関数が条件分岐であり(ステップS21,YES)、且つ、その子供ノードが2個ではない場合には(ステップS23,NO)、これは基本的には子供ノードが3個であることを想定しており、3個の子供ノードのうち1番目と2番目に関しては上記従来手法によりユニークな(異なる)インスタンス名を割り当てる(勿論、リーフの場合には付与しない)。更に、3番目の子供ノードに対しては、2番目の子供ノードと同一のインスタンス名を割り当てる(ステップS24)。
【0086】
上述した処理によって、例えば
図4に示す例におけるインスタンス名=“INST_3”のノードが“現在処理中ノード”であるときには、その子供ノードは3個(ノードの名称が“(>”と“(−”と“(−”の3個)であるのでステップS23の判定はNOとなる。そして、これら3個のノードは何れもリーフではないので、S24の処理によって、上記1番目のノード(“(>”のノード)と2番目のノード(1つ目の“(−”のノード)とには、ユニークなインスタンス名が割り当てられると共に(それぞれ、“INST_4”、“INST_5”が付与される)、3番目のノード(2つ目の“(−”のノード)には、2番目のノードと同じインスタンス名(=“INST_5”)が付与される。
【0087】
これによって、
図4に示すように、3番目のノードのインスタンス名は、
図3に示す従来例とは異なるものとなる。また、これに伴って、それ以降のノードへのインスタンス名割当ても、(数値が1つ繰り上がるので)
図3とは異なることになる。
【0088】
図8は、上記ステップS4の「子供ノードがリーフだけのノードを探索する」処理の詳細フローチャート図である。
図8の処理では、現在、走査位置があるノード(“現在処理中ノード”)について、この“現在処理中ノード”の最初の子供ノード(“子供ノードへのポインタ”が示すノード)に走査位置をセットした後(つまり、当該最初の子供ノードを、新たな“現在処理中ノード”とする)(ステップS41)、ステップS42以降の処理を繰り返す。
【0089】
すなわち、まず、現在の上記“現在処理中ノード”(上記の通り、現在は、上記最初の子供ノードが“現在処理中ノード”)が、リーフであるか否かを判定し(ステップS42)、リーフではない場合には(ステップS42,NO)、この“現在処理中ノード”の最初の子供ノード(“子供ノードへのポインタ”が示すノード)に、走査位置を移動させて(新たな“現在処理中ノード”にして)(ステップS46)、ステップS42に戻る。
【0090】
この様にして、リーフが見つかるまでツリーの末端方向へ順次、走査位置を移動させていき、リーフが見つかったら(ステップS42,YES)、これが(現在の“現在処理中ノード”が)最後のノード(“次のノードへのポインタ”がNULLであるノード)であるか否かを判定し(ステップS43)、最後のノードではない場合には(ステップS43,NO)、上記現在の“現在処理中ノード”における“次のノードへのポインタ”が示すノードに、走査位置を移動させて(ステップS44、ステップS42に戻る。
【0091】
そして、途中でステップS42の判定がNOとなることなく、走査位置が上記最後のノードにある状態となったら(ステップS43,YES)、現在の“現在処理中ノード”の親ノードは、その子供ノードが全てリーフであることになるので、現在の“現在処理中ノード”の親ノードを探索結果(つまり、上記変換対象ノードである)として返して(ステップS45)、本処理を終了する。
【0092】
上記ステップS5では、上記ステップS45で返された探索結果を用いて、処理実行することになる。
図9は、上記ステップS5の「検索されたノード位置を手続型言語に変換する」処理の詳細フローチャート図である。
【0093】
図9の処理は、上記識別子(インスタンス名)を付与後のツリー構造の各ノードに基づいて、手続型言語への変換を行う処理であって、特に、変換対象ノードが条件分岐の関数に係わるノードである場合には、予め登録されている所定の雛形を用いて手続型言語プログラムの生成を行う処理である。
【0094】
上記所定の雛形は、例えば、if〜then〜else文である。そして、上記条件分岐の関数に係わるノードの各子供ノードに係わる手続型言語への変換結果(一時的に記憶している)を、上記所定の雛形の該当箇所(後述する“条件部”や“then部”など)に当て嵌めることで、上記手続型言語プログラムの生成を行うものである。これについて、詳細な一例を、
図9と下記の説明に示す。
【0095】
図9の処理は、上記ステップS4で検索された変換対象ノード(子供ノードがリーフだけのノード)について、当該変換対象ノードの“ノードの名称”が「(IF」であるか否かを判定する(ステップS51)。つまり、条件分岐の関数ノードであるか否かを判定する。
【0096】
対象ノードが「(IF」ではない場合には(ステップS51,NO)、従来(特許文献4など)と同様の変換処理を行う(ステップS55)。これは、例えば上記
図15(b)に関する説明で述べたように、例えば、基本的には、各変換対象ノード毎に、変換対象ノードに係る関数について、該変換対象ノードの各子供ノードに係る各オペランドまたは識別子を引数として用いて、該変換対象ノードの識別子(インスタンス名)を代入先とする命令文(代入文)を生成するものである。
【0097】
但し、本例の場合、変換処理は行うが、変換結果を直ちに手続型言語格納部17に出力するのではなく、一時的に記憶する。そして、ステップS51がYESになったときに、一時的に記憶されていた変換処理結果を上記所定の雛形に当て嵌めることで、手続型言語の適切な条件分岐処理を生成する(ステップS52)。そして、この生成結果を手続型言語格納部17に出力すると共に、上記一時的に記憶されていた変換処理結果を全て消去する。但し、ステップS51が一度もYESとならずに処理終了する場合には、終了する前に、一時的に記憶してあった変換処理結果を全て、手続型言語格納部17に出力する。
【0098】
図4の例の場合、最初は
図15(b)に示す先頭から3行目までの3行分(但し、3行目は、INST6→INST5になる)が、上記変換処理結果として一時的に記憶されることになる。尚、上記の通り、
図15(b)に示すfuncGT等は、変換先の言語の関数を便宜上表しているものであり、実際には例えばfuncGT(a,b)は例えば「a>b」、funcSub(a,b)は例えば「a−b」等であるものとする。
【0099】
上記従来の変換処理によれば、そのときの変換対象ノードの子供ノード(リーフ)は全て削除されるので、上記3行分の変換処理後は、
図4に示すインスタンス名がINST_3のノードが、変換対象ノードとなり、ステップS51の判定がYESとなることになる。
【0100】
この場合、この変換対象ノードの最初の子供ノードに係る上記一時的に記憶されている変換結果(すなわち、最初に記録された変換結果)を“条件部”、2番目の子供ノードに係る上記一時的に記憶されている変換結果((すなわち、2番目に記録された変換結果)を“then部”として、これらを予め登録されている下記の第1の雛形に当て嵌める(ステップS52の処理)。
【0101】
『 if(条件部){
then部;
} 』
これによって、上記の例の場合、下記の変換結果が得られて、これが手続型言語格納部17に出力されて書き込まれることになる。尚、上記一時的に記憶してあった変換結果は、手続型言語格納部17に出力したら削除する。
【0102】
『 if(a>b){
INST_5 := a−b
}
そして、変換対象ノードに3番目の子供ノードが無い場合には(ステップS53、NO)、そのまま本処理を終了する(但し、未処理部分があるならばステップS51に戻る)。
【0103】
一方、変換対象ノードに3番目の子供ノードがある場合には(ステップS53、YES)、3番目の子供ノードに係る上記一時的に記憶されている変換結果を“子供ノードの内容”として、これを予め登録されている下記の第2の雛形に当て嵌める(ステップS54)。
【0104】
『 else{
子供ノードの内容
} 』
これによって、上記の例の場合、下記の変換結果が得られて、これが手続型言語格納部17に出力されて書き込まれることになる。
【0105】
『 else{
INST_5 := b−a
} 』
尚、ステップS52、S54の処理において、任意の変換結果を雛形に当て嵌めた直後に、更に、次の変換結果も参照して、当該次の変換結果に、上記雛形に当て嵌めた変換結果における代入先のインスタンス名が含まれている場合には、更に当該次の変換結果も続型言語格納部17に出力して書き込むようにしてもよい。
【0106】
これは、例えば、
図9のステップS51の処理で2つ目の「(IF」が検出され、その最初の子供ノードに係わる上記変換結果である「INST_5 = 10」が上記“条件部”として出力されることで、
図5に示す例における
if(INST_5 = 10)
の部分が生成されるが、その際、更に、2番目の子供ノードに係わる上記変換結果である「INST_7 := a*a」を参照して、これに上記INST_5が含まれているか否かを判定する。この場合は、含まれていないので、何も行わない。
【0107】
そして、続いて、上記2番目の子供ノードに係わる上記変換結果である「INST_7 := a*a」が、上記“then部”として出力されることで、
図5に示す例における
INST_7 := a*a;
の部分が生成されるが、その際、更に、その次の変換結果である「INST_6 := (c:=INST_7)」を参照して、これに上記INST_7が含まれているか否かを判定する。この場合は含まれているので、「INST_6 := (c:=INST_7)」も更に出力する。
【0108】
これによって、この場合にはステップS52の処理によって
図5に示す例における
if(INST_5 = 10){
INST_7 := a*a;
INST_6 := (c:=INST_7);
の部分が、生成されることになる。
【0109】
これは、ステップS54の処理においても同様であり、その結果、
図5に示すように、elseに関して、2つの変換結果が出力されることになる。
尚、この場合、上記ステップS53の「変換対象ノードに3番目の子供ノードがある場合には(ステップS53,YES)」は、例えば、それまでにn番目の子供ノードに係わる変換結果を出力した場合に、「変換対象ノードにn+1番目の子供ノードがある場合には(ステップS53,YES)」に置き換えるものとする。
【0110】
図15(a)のプログラムの変換に関しても、
図5のように手続型言語の条件分岐を使用した構文に変換できれば、変数は3個(INST5, INST6, INST7)でよく、プログラム実行時に実行される部分も枠で囲んだ5個の実行文(実際には条件分岐の結果次第で別の部分が実行される場合がある)で済み、効率的になる。
【0111】
尚、勿論、本発明では、特許文献4の発明と略同様に、関数型制御言語で記述されたプログラム内容を並び換え、並び替えにより必要となる一時変数を生成、管理する手段を設けることにより、命令スタックとデータスタックを待たない手続き形の命令処理を行なう装置(代入および処理の呼び出しで構成される装置)で関数型制御言語を実行できるようになるという効果も得られる。