以下、実施形態について、図面を参照しながら詳細に説明する。説明は以下の順序で行う。
まず、種々の実施形態の利点の意義を明らかにするための説明を行う。次に、図1を参照して第1実施形態について説明する。その後、各種実施形態についての理解を助けるために、図2〜5を参照して第1〜第3比較例について説明する。続いて、図6〜16を参照して、第2〜第4実施形態について説明する。最後に、その他の実施形態についても説明する。
複数の自然言語で書かれており、かつ、互いに対応する意味を持つような複数の文字列の長さ同士は、異なり得る。他方、多言語アプリケーションが実際にどのような環境で実行されるのかは、アプリケーションのソースコードがコンパイルされる際には不明である。
よって、「長さが異なり得るような複数の言語の文字列リテラル(string literals)のうちのいずれが、アプリケーションが実際に実行されるロケールに適しているのか」ということは、ソースコードがコンパイルされる際には決まらない。このような不確定性は、多言語アプリケーションのライフサイクル中の少なくとも一つの段階において、広義のコストの増大を招く原因となり得るし、その結果として、何らかの問題または困難を引き起こし得る。
例えば、開発または保守を担当する人の手間という意味でのコストが、上記の不確定性のせいで増大することもあり得る。別の例として、アプリケーションの実行にともなう計算コスト(computational cost)が、上記の不確定性のせいで増大することもあり得る。コストの増大は、アプリケーションの多言語化を妨げる要因である。
詳しくは後述するとおり、各種実施形態によれば、多言語アプリケーションのライフサイクル中の開発・実行・保守等の段階のうちの、少なくとも一つの段階における何らかのコストを、第1〜第3比較例よりも減らすことが可能である。コストの削減は、アプリケーションの多言語化を促進するうえで有益である。したがって、各実施形態によるコンパイラは、アプリケーションの多言語化を促進するのに役立つと期待される。
基幹系システムを含む種々のアプリケーションの多言語化は、近年、重要性を増している。理由は以下のとおりである。
近年では、市場の成熟化などの理由により、日本国内の市場が伸び悩んでいる。そのため、海外への事業展開を目指す企業が増えている。具体的には、グローバル化に向けた企業の動き(例えば、ICT(Information and Communication Technology)分野での海外への投資を増やす、などの動き)が加速している。
従来、企業の海外拠点で使われる基幹系システムは、個々の海外拠点に任されるケースが多かった。しかし、クラウドサービスが本格的に使われる時代の到来により、基幹系システムのグローバル化(換言すれば国際化)が進められつつある。したがって、基幹系システムを含む種々のアプリケーションの国際化および多言語化の重要性が近年増してきている。
様々なプログラミング言語により実装された様々な基幹系システムが存在するが、中でもCOBOL(Common Business-Oriented Language)は、多くの基幹系システムの実装に使われている。よって、以下の説明では、主にCOBOLを例として取り上げる。しかし、例えばCなどの、COBOL以外の他の高級言語(high-level language)に対しても、各実施形態は適用可能である。
COBOLは、国際化対応(internationalization support)機能を有する。例えば、COBOLの仕様では、漢字などのマルチオクテット文字の扱いが規定されている。国際化対応機能により、様々な言語向け(または様々な文化圏向け)のCOBOLアプリケーションの開発が容易化され得る。
しかし、単にマルチオクテット文字の入出力を容易化する機能だけでは、アプリケーションの国際化には不十分である。アプリケーションの国際化のためには、複数の言語または文化圏における動作を規定するための、いわゆる「文化圏適応」(cultural adaptation)機能が有益である。
ところが、文化圏適応に関するCOBOLの規格は、通貨や時刻の変換などに関する限定的な範囲にとどまっている。COBOLの規格に定められた文化圏適応機能は、「ロケールに応じて、いくつかの国別文字定数(national literals)の中から、適宜の自然言語で書かれた国別文字定数を選んで出力する」といった機能を含まない。すなわち、COBOLの規格で定められている機能には限界がある。
そのため、COBOL開発環境のベンダにより提供されるCOBOLコンパイラは、国別文字定数を含むプログラムをコンパイルするとき、特定の一つの言語または文化圏向けのオブジェクトコードを出力するだけである。よって、アプリケーションに文化圏適応機能を持たせるためには、個々のアプリケーションの開発者が何らかの対処を迫られる。
例えば、「アプリケーション本体の実行ファイル(executable file)のほかに、ロケール別のリソースファイルをいくつか用意する」という方法が考えられ得る。この方法の詳細は、第1比較例として後述する。
別の例として、「複数のロケールに対応する複数のソースファイルを用意し、ロケール別にソースファイルをコンパイルし、それにより、複数のロケールに対応する複数の実行ファイルを生成する」という方法も考えられ得る。この方法の詳細は、第2比較例として後述する。
詳しくは後述するとおり、第1比較例も第2比較例も、アプリケーションのライフサイクル中で生じる広義のコストという点において、改善の余地が大いにある。つまり、アプリケーションの国際化および多言語化の重要性が上記のとおり近年増しているにも関わらず、アプリケーションに文化圏適応機能を持たせる(つまりアプリケーションを国際化および多言語化する)ためのコストは、現在ではまだ高い。
したがって、アプリケーションを国際化および多言語化するために生じるコストを減らす技術を提供することには、意義がある。とりわけ、コスト削減の役に立つ機能をコンパイラが提供することには、意義がある。なぜなら、コンパイラによって機能が提供されれば、個々のアプリケーション開発者のスキルや努力への依存度を減らせるからである。
下記の各種実施形態のコンパイラは、アプリケーションを国際化および多言語化するために生じ得るコストを減らす効果を有する。よって、各実施形態によるコンパイラは、アプリケーションの多言語化を促進するのに役立つと期待される。
さて、図1は、第1実施形態によるコンパイラが実行するコンパイル処理について説明する図である。図1に関する説明において、理解の助けとするために、後述の実施形態における具体例を参照することもある。
図1には、コンパイラ100と、コンパイル対象のソースコード101と、定義情報102が例示されている。以下では、複数の言語の間で互いに対応する意味を持つ複数の文字列リテラルの組み合わせを「リテラル組」(literal tuple)という。定義情報102は、リテラル組を定義する情報である。
定義情報102で定義されるリテラル組の数は、1以上である。図1の例では、M組のリテラル組が定義されている(1≦M)。例えば、i番目(1≦i≦M)のリテラル組は、N種類(1<N)の言語で書かれた、互いに対応する意味を持つN個の文字列リテラルLi1,……,LiNの組み合わせである。
図1には、コンパイラ100によってオブジェクトコード103(つまりマシン語で書かれたコード)が生成される例が示されている。実施形態によっては、コンパイラ100は、アセンブリ言語で書かれたアセンブリコードを生成してもよい。
なお、コンパイラ100は、コンピュータ(例えば後述の図8のコンピュータ700)により実行されるプログラムの一種である。コンピュータは、コンパイラ100のプログラムを実行することにより、コンパイル装置として動作する。以下では説明の簡単化のため、「コンピュータが、コンパイラ100のプログラムを実行することにより、オブジェクトコード103を生成する」と述べる代わりに、単に「コンパイラ100がオブジェクトコード103を生成する」のように述べることもある。
コンパイラ100がコンピュータに実行させるコンパイル処理は、ソースコード101と定義情報102を読み込むことを含む。また、コンパイル処理は、コード(具体的にはオブジェクトコード103またはアセンブリコード)を生成することも含む。
なお、ソースコード101が書かれたソースファイルの中に、定義情報102が含まれていてもよい。あるいは、ソースファイルとは別のファイル(例えば後述の図6のロケールリソースファイル502)に、定義情報102が含まれていてもよい。
ソースコード101は、複数の言語(図1の例ではN種類の言語)のうちの1つの言語で書かれた複数の文字列リテラルのそれぞれについて、当該文字列リテラルか、または、当該文字列リテラルへの参照を含んでもよい。例えば、ソースコード101は、複数の言語のうちの1つの言語で書かれた複数の文字列リテラル自体を含んでもよい。または、ソースコード101は、当該1つの言語で書かれた複数の文字列リテラルへの参照を含んでもよい。もちろん、ソースコード101が、1つ以上の文字列リテラル自体と、1つ以上の文字列リテラルへの参照とを含んでいてもよい。
文字列リテラルは、例えば、定数(constant)または変数(variable)に値を設定するためにソースコード101内に記述されてもよいし、関数のパラメタとしてソースコード101内に記述されてもよい。
文字列リテラルへの参照の形式は、プログラミング言語の仕様による。例えば、ソースコード101がC言語で書かれている場合、文字列リテラルを定義するマクロの名前が、文字列リテラルへの一種の参照として、ソースコード101内に含まれていてもよい。
便宜上、図1には、s番目(1≦s≦N)の言語で書かれたM個の文字列リテラルL1s,……,LMsがソースコード101に含まれる場合が図示されている。
オブジェクトコード103の中では、各リテラル組について、当該リテラル組に属する複数の文字列リテラルのそれぞれに対して、当該リテラル組のうちで最長の文字列リテラルのバイト長以上である「算出バイト長」が割り当てられている。例えば、i番目のリテラル組に属する文字列リテラルLi1,……,LiNのそれぞれに対して割り当てられる算出バイト長は、図1の例では、Biバイトである。
つまり、Biは、文字列リテラルLi1,……,LiNのうちで最長の文字列リテラルのバイト長以上の値である。したがって、各文字列リテラルLij(1≦j≦N)は、文字列リテラルLijに割り当てられたBiバイトの範囲内に収まる。よって、例えば、文字列リテラルの参照にともなってBiバイトの範囲外への不正なメモリアクセスを引き起こし得るような危険な命令の生成は、自然と防止される。
各リテラル組に対応する算出バイト長は、具体的には、当該リテラル組に属する複数の文字列リテラルのうちで最長の文字列リテラルのバイト長そのものでもよい。または、各リテラル組に対応する算出バイト長は、「メモリ管理の単位である所定のバイト長の倍数であり、かつ当該リテラル組に属する複数の文字列リテラルのうちで最長の文字列リテラルのバイト長以上である」という条件を満たす最小のバイト長でもよい。
また、オブジェクトコード103によれば、各文字列リテラルの開始アドレスが、実行時に指定されるロケール(例えば、実行環境においてOSに設定されているロケール)に応じて参照される。換言すれば、各文字列リテラルの開始アドレスが、実行時に指定されるロケールに応じて参照されるように、コンパイラ100は、適切なオブジェクトコード103を生成する。すなわち、オブジェクトコード103には、コンピュータ(具体的には、オブジェクトコード103から生成される実行ファイルを実行するコンピュータ)に各文字列リテラルの開始アドレスを実行時のロケールに応じて参照させるような複数の命令が含まれている。
なおここでの「各文字列リテラルの開始アドレス」とは、より具体的には、各リテラル組に属する複数の文字列リテラルのうち、実行時のロケールに応じた言語の文字列リテラルの開始アドレスのことである。
図1では便宜上、開始アドレスへの参照が矢印により表されている。矢印により表されているとおり、オブジェクトコード103には、実行時のロケールに応じて文字列リテラルLi1,……,LiNのうちの1つの開始アドレスを参照するための命令が含まれる。
コンパイラ100は、以上のような複数の命令を生成し、生成した複数の命令をオブジェクトコード103に含める。より具体的には、複数の命令の中には以下のような命令が含まれる。
・実行時に指定されるロケールを示すロケール識別情報を取得するための、1つ以上の命令。例えば、後述の図10の命令803〜805など。
・ロケール識別情報に応じた条件分岐のための、1つ以上の命令。例えば、後述の図10の命令807、808、810、812、813、815、817、818、820など。
・複数の言語の数に対応する複数個の数値(図1の例ではN個の異なる数値)のうちの1つを用いて、各文字列リテラルの開始アドレスを参照するための、1つ以上の命令。例えば、後述の図10〜11の命令809、814、819、822、825〜830、833、834、837、838、841、842や、図15の命令905〜908、911〜914、917〜920、923〜926など。
文字列リテラルの開始アドレスを参照するための1つ以上の命令の中には、開始アドレスを算出するための1つ以上の命令が含まれていてもよい。開始アドレスを算出するための命令は、例えば、加算命令や乗算命令などの算術命令でもよい。別の例として、開始アドレスを算出するための命令は、、あるレジスタに保持されている値と指定された数値との算術演算(加算など)を行うことがオペランドに指定されているような、他の種類の命令であってもよい。
例えば、後述の図10〜11には、命令809、814、819、822、825〜830、833、834、837、837、841、842が例示されている。これらの命令は、3つの言語に対応する、0、1、2という3つの数値のうちの1つを用いて、開始アドレスを算出および参照するための命令の例である。
他の例として、後述の図15には、命令905〜908、911〜914、917〜920、923〜926が例示されている。これらの命令は、3つの言語に対応する、0、1、2という3つの数値のうちの1つを用いて、開始アドレスを算出および参照するための命令の例である。
図10〜11と15の例では、上記の「複数個の数値」は、0、1、2という連続した整数である。しかし、実施形態によっては、例えば、0、Y、2Yなどの、連続しない複数個の数値が使われてもよい(Yの具体例は図6とともに後述する)。
さらに、実施形態によっては、α、β+Y、γ+2Yなどの、不等間隔の複数個の数値が使われてもよい。なお、α、β、γは、コンパイラ100が実装に応じて決める適宜の値であるものとする。
もちろん、定義情報102で文字列リテラルが定義される対象となる言語の数(図1ではN)に応じて、上記の「複数個の数値」の個数は、3以外の個数であってもよい。
ところで、複数の文字列リテラルのオブジェクトコード103内での配置には、2種類のものがあり得る。後述の第2実施形態は1種類目の配置が採用される例であり、後述の第3実施形態は2種類目の配置が採用される例である。
1種類目の配置によると、オブジェクトコード103の中では、言語ごとに文字列リテラルが配置され、かつ、各言語について、当該言語の複数の文字列リテラルは、リテラル組同士の間で定義される順序で配置される。例えば、1種類目の配置では、「L11,……,LM1,L12,……,LM2,……,L1N,……,LMN」という順序で、MN個の文字列リテラルがオブジェクトコード103内に配置されてもよい。
他方、2種類目の配置によると、オブジェクトコード103の中では、リテラル組ごとに文字列リテラルが配置され、かつ、各リテラル組について、当該リテラル組に属する複数の文字列リテラルは、複数の言語の間で定義される順序で配置される。例えば、2種類目の配置では、「L11,……,L1N,L21,……,L2N,……,LM1,……,LMN」という順序で、MN個の文字列リテラルがオブジェクトコード103内に配置されてもよい。
コンパイラ100は、1種類目と2種類目のいずれの配置を採用するかに応じて、適宜の命令を生成する。なお、1種類目と2種類目のいずれの配置が採用される場合でも、オブジェクトコード103の中では、各リテラル組について、当該リテラル組に属する複数の文字列リテラルのそれぞれに対して上記の「算出バイト長」が割り当てられる。
1種類目の配置が採用される場合、コンパイラ100は、算出バイト長を累積加算することによって、各リテラル組に対応するオフセットを算出してもよい。オフセットの具体例は図9とともに後述する。この場合、各文字列リテラルの開始アドレスを参照するための上記の1つ以上の命令は、オフセットを含むオペランドが指定された命令(例えば、後述の図11の命令829、833、837、841など)を含んでもよい。
また、1種類目の配置が採用される場合、コンパイラ100は、さらに、全リテラル組の算出バイト長の合計を算出してもよい。例えば、図1の例では、合計は(B1+……+Bi+……+BN)であり、後述の図11の例では合計はYである。この場合、各文字列リテラルの開始アドレスを参照するための上記1つ以上の命令は、複数の言語のうち実行時のロケールに対応する1つの言語の複数の文字列リテラルが配置された範囲の開始アドレスを合計に基づいて算出するための命令を含んでいてもよい。
例えば、実行時のロケールに対応する言語が、N個の言語のうちのj番目の言語であれば、上記範囲は、具体的には、文字列リテラルL1j,……,LMjが配置される範囲である。
例えば、コンパイラ100は、上記の複数個の数値(各文字列リテラルの開始アドレスを参照するための1つ以上の命令についての説明を参照)を、算出した合計に基づいて決めてもよい(0、Y、2Yが上記の複数個の数値として使われる例を参照)。
あるいは、上記の複数個の数値のうちの1つと算出した合計とを使って上記範囲の開始アドレスを算出するための命令を、コンパイラ100が生成してもよい。例えば、図10〜11の例では、0、1、2が上記の複数個の数値として使われており、算出される合計はYである。そして、3つの言語それぞれについての上記範囲の開始アドレスは、(StartAddr+Offset+X)、(StartAddr+Offset+X+Y)、(StartAddr+Offset+X+2Y)であり、これらは、命令825〜829、833、837、841の実行過程で算出され得る。
詳しくは第2実施形態とともに後述するが、例えば、命令825は、複数個の数値のうちの1つ(0、1、または2)と、算出された合計(Y)との積を所定のレジスタに記憶するための命令である。また、命令829、833、837、および841のオペランド内では、当該所定のレジスタの値を用いて上記範囲の開始アドレスを算出することが"BaseReg+Reg2"のように表現されている。
ところで、1種類目の配置における、上記の「リテラル組同士の間で定義される順序」は、1つの言語で書かれた文字列リテラル(または、当該文字列リテラルへの参照)がソースコード101内に出現する順序に基づくことが好ましい。なぜなら、ソースコード101内での出現順を入れ替える処理が不要なので、コンパイラ100が行う解析を簡素にすることができるからである。なお、リテラル組同士の間で定義される順序は、図1の例では、「1,……,i,……,M」というインデックスにより表されており、この順序は、ソースコード101での文字列リテラルの出現順と同じである。
他方、2種類目の配置における、上記の「複数の言語の間で定義される順序」は、例えば、定義情報102によって定義される順序であってもよい。例えば、図1の例では、複数の言語の間で定義される順序は、「1,……,s,……,M」というインデックスにより表されている。
2種類目の配置が採用される場合、コンパイラ100は、算出バイト長を累積加算することによって各リテラル組に対応する第1の値(例えば後述の図9における「オフセット」フィールドの値など)を算出してもよい。この場合、各文字列リテラルの開始アドレスを参照するための上記の1つ以上の命令は、複数の言語の数(図1の例ではN、図14〜15の例では3)と第1の値とに応じて決まる第2の値を含むオペランドが指定された命令を含んでいてもよい。
詳しくは第3実施形態とともに後述するが、例えば、後述の図15には、複数の言語の数である3と、図9にオフセットとして示される0という値とに応じて決まる値(具体的には3と0の積である0)を含むオペランドが指定された命令907が例示されている。同様に、図15には、3と12という2つの値に応じて決まる値(具体的には3と12の積である36)を含むオペランドが指定された命令913も例示されている。命令919と925も類似の命令である。
ところで、第1のロケールと第2のロケールで特定の自然言語が使われる場合がある。例えば、アメリカとイギリスでは英語が使われる。
第1と第2のロケールで特定の自然言語が使われる場合、複数の言語(図1ではN種類の言語)のうちの2つは、第1のロケールで使われる特定の自然言語と、第2のロケールで使われる特定の自然言語であってもよい。例えば、第1と第2のロケールが"en-us"と"en-gb"という名前でそれぞれ識別される場合、アメリカ英語とイギリス英語が2つの異なる言語として扱われてもよい。
このように第1のロケールで使われる特定の自然言語と、第2のロケールで使われる特定の自然言語が区別される実施形態では、コンパイラ100が生成する複数の命令の中には、次のような処理のための命令が含まれる。
・ロケール識別情報が第1のロケールを示す場合には、上記の複数個の数値(各文字列リテラルの開始アドレスを参照するための1つ以上の命令についての説明を参照)のうちの第1の数値を使って、開始アドレスを算出する。
・ロケール識別情報が第2のロケールを示す場合には、上記の複数個の数値のうちの第2の数値を使って、開始アドレスを算出する。
なお、第1の数値は、第1のロケールで使われる特定の自然言語に対応する。よって、第1の数値を使って算出される上記開始アドレスとは、第1のロケールで使われる特定の自然言語で書かれた文字列リテラルの開始アドレスのことである。また、第2の数値は、第2のロケールで使われる特定の自然言語に対応する。よって、第2の数値を使って算出される上記開始アドレスとは、第2のロケールで使われる特定の自然言語で書かれた文字列リテラルの開始アドレスのことである。
逆に、第1のロケールで使われる特定の自然言語と、第2のロケールで使われる特定の自然言語が区別されない実施形態も可能である。例えば、第1と第2のロケールが"en-us"と"en-gb"という名前でそれぞれ識別される場合、"en"という2文字で識別される言語(すなわち英語)が、第1と第2のロケールに共通の「特定の自然言語」に当たる。つまり、アメリカ英語とイギリス英語が区別されずに、同じ英語として扱われるような実施形態も可能である。
第1のロケールで使われる特定の自然言語と、第2のロケールで使われる特定の自然言語が区別されない場合、複数の言語(図1ではN種類の言語)のうちの1つは、第1のロケールと第2のロケールに共通の特定の自然言語であってもよい。この場合、コンパイラ100が生成する複数の命令の中には、次のような命令が含まれる。
すなわち、複数の命令の中には、ロケール識別情報が第1のロケールを示す場合と、ロケール識別情報が第2のロケールを示す場合のいずれにおいても、上記の複数個の数値のうちのある1つの数値を用いて、開始アドレスを算出するための命令が含まれる。このようにして算出される上記開始アドレスとは、第1と第2のロケールに共通の特定の自然言語で書かれた文字列リテラルの開始アドレスのことである。
ところで、実行時に指定されるロケールで使われる言語が、複数の言語(図1ではN種類の言語)のうちのいずれとも異なる場合もあり得る。そこで、コンパイラ100は、そのような場合に使われるデフォルト言語を、複数の言語のうちの1つに決定してもよい。デフォルト言語の決定方法の具体例については後述する。
ここで、説明の便宜上、上記の複数個の数値(各文字列リテラルの開始アドレスを参照するための1つ以上の命令についての説明を参照)のうちで、デフォルト言語に対応する1つの数値を、「デフォルト数値」という。コンパイラ100がデフォルト言語を決める場合、生成される複数の命令の中には、次のような命令が含まれる。すなわち、複数の言語のうちのいずれとも異なる言語を使うロケールをロケール識別情報が示している場合にデフォルト数値を用いて開始アドレスを算出するための命令が、複数の命令の中には含まれる。
例えば、後述の第2実施形態では、デフォルト言語が英語であり、デフォルト数値が0である。図10には、デフォルト数値を用いて開始アドレスを算出するための命令822が例示されている。
ところで、オブジェクトコード103を生成する処理は、以下のいずれか一方の処理を含んでいてもよい。
・各リテラル組について、当該リテラル組に属する複数の文字列リテラルのうち算出バイト長未満の長さの各文字列リテラルを所定の文字でパディングし、パディングした文字列リテラルをオブジェクトコード103内に配置する処理。例えば、後述の図13のステップS206〜S208など。
・各リテラル組に属する複数の文字列リテラルそれぞれの長さを示す数値をオブジェクトコード103内に埋め込み(例えば図16を参照)、長さを示す数値が埋め込まれたアドレスを参照するための命令を生成する処理。
また、ソースコード101は、ロケールによらずに共通に使われる言語非依存の文字列リテラルを含むか、または、言語非依存の文字列リテラルへの参照を含む場合があり得る。この場合、オブジェクトコード103を生成する処理は、言語非依存の文字列リテラルをオブジェクトコード103に含める処理を含む。例えば、後述の図6のように、すべての言語非依存の文字列リテラルが、複数の言語の文字列リテラルよりも前に配置されてもよい。実施形態によっては、言語非依存の文字列リテラルは、複数の言語の文字列リテラルよりも後に配置されてもよい。
続いて、上記の第1実施形態および後述の各種実施形態の利点についての理解を助けるために、第1〜第3比較例について説明する。
図2は、第1比較例について説明する図である。各種実施形態は、第1比較例と比べると、少なくとも以下の2つの点で優れている。ある側面では、各種実施形態は、第1比較例に対して以下のような優位性を持つことを1つの目的としている。
・実行時のオーバヘッドが少ない。換言すれば、実行時の計算コストが少ない。
・運用(service)開始後の保守コストが少ない。
図2のとおり、第1比較例の実行環境200では、実行ファイル201とリソース呼び出しDLL(Dynamic Link Library)202とリソースファイル群203が使われる。リソースファイル群203は、N個のリソースファイルの集まりである(1<N)。これらN個のリソースファイルは、N通りのロケールで使われるN種類の自然言語に対応する。図2の例では、N=3であり、リソースファイル群203は、英語リソースファイル204と日本語リソースファイル205と中国語リソースファイル206を含む。
英語リソースファイル204は、英語の文字列リテラルをM個含む(1≦M)。これらM個の文字列リテラルに対応する意味を有し、かつ、日本語で書かれたM個の文字列リテラルが、日本語リソースファイル205に含まれる。また、英語リソースファイル204内のM個の文字列リテラルに対応する意味を有し、かつ、中国語で書かれたM個の文字列リテラルが、中国語リソースファイル206に含まれる。
各リソースファイル内の各文字列リテラルは、コード番号などのID(identifier)により識別される。互いに対応する意味を持つ英語と日本語と中国語の3つの文字列リテラルには、同じIDが割り当てられる。
実行ファイル201には、少なくとも以下の命令列が含まれる。
・実行ファイル201が実行される実行環境200におけるロケールを認識するための命令列。例えば、実行環境200のOS(Operating System)に設定されているロケールを示す値を、OSにより提供されるAPI(Application Programming Interface)などを介して取得するための命令列。
・取得した値に応じて(つまり実行時のロケールに応じて)リソースファイルを選択し、選択したリソースファイルから、呼び出しDLL202を介して文字列リテラルを読み出すための命令列。
したがって、第1比較例によれば、実行ファイル201が実行されると、実行環境200のロケールに応じて、英語、日本語、または中国語の文字列リテラルが読み出される。実行ファイル201は、リソースファイルから読み出された文字列リテラルを表示するための命令列も含む。よって、実行環境200のロケールに応じた言語で、文字列リテラルが表示される。すなわち、第1比較例によれば、多言語化が実現される。
しかしながら、第1比較例では、実行時のオーバヘッドが大きい。換言すれば、第1比較例では、実行時の計算コストが高い。
なぜなら、リソースファイル群203内のいずれかのリソースファイルが、実行時に、リソース呼び出しDLL202を介してアクセスされるからである。具体的には、実行ファイル201からリソース呼び出しDLL202を呼び出すためのオーバヘッドが生じる。さらに、リソースファイルを参照するためのディスクアクセスによるオーバヘッドも生じる。このようにリソースファイルを実行時に参照するために生じるオーバヘッドは、実行効率の低下の原因となり得る。
また、第1比較例では、実行時にリソースファイル群203が使われる。よって、第1比較例では、運用開始後もリソースファイル群203内の各リソースファイルを適切に管理するための管理コストが生じ得る。例えば、リソースファイル群203がエンドユーザによって誤って削除、移動、または編集されないように、システム管理者が何らかの手作業を行うことが考えられる。
続いて、図3〜4を参照して第2比較例について説明する。第1比較例のような実行時のオーバヘッドは、第2比較例では生じない。また、第2比較例では、実行時にリソースファイル群203を使わないので、リソースファイル群203の管理コストも不要である。
しかし、第2比較例では、プログラマが、ロケール別にソースファイルを作成およびコンパイルし、ロケール別に実行ファイルをビルドする。したがって、第2比較例では、ソースファイルの作成およびコンパイルに第1比較例よりも手間がかかる。さらに、第2比較例では、実行ファイルのビルドにも、第1比較例よりも手間がかかる。
このように、第2比較例には、プログラマの負担が大きい(すなわち開発コストが高い)という欠点がある。詳しくは後述するとおり、各種実施形態は、第2比較例と比べて開発コストが低い。つまり、ある側面では、各種実施形態は、第2比較例よりも開発コストを下げることを1つの目的としている。
例えば、あるアプリケーションが、日本語が使われる実行環境と、英語が使われる実行環境と、中国語が使われる実行環境という、3つの実行環境(すなわち3つのロケール)で使われる可能性があるとする。この場合、第2比較例では、プログラマが3つの言語の開発環境で3つのソースファイルを作成する。
そして、各ソースファイルが、各開発環境内のコンパイラによりコンパイルされ、その結果、3つの言語に対応する3つのオブジェクトファイルが得られる。
各オブジェクトファイルは、リンカによって、適宜別のオブジェクトファイルとリンクされる。その結果、3つの言語に対応する3つの実行ファイルが得られる。エンドユーザは、3つの実行ファイルのうち、自分が使うコンピュータの環境に応じた実行ファイルを実行する。
具体的には、図3には、日本語向け開発環境300と日本語の実行環境310が例示されている。
プログラマは、日本語向け開発環境300において、日本語で書かれた文字列リテラルを含むソースファイル301を作成する。なお、説明の便宜上、ソースファイル301はCOBOLで書かれているものとする。COBOLの用語では、指定された各国文字集合(national character set)に属する文字の連なりにより表された文字列リテラルを、国別文字定数(national literal)という。
図3には、ソースファイル301中の6個の文字列リテラルが例示されている。
"20131226"および"G8-2"という2つの文字列リテラルは、英数字リテラル(alphanumeric literals)であり、言語に依存しない文字列リテラルである。つまり、これら2つの文字列リテラルは、日本語・英語・中国語の違いによらず使われる、共通の文字列リテラルである。
他方、"富士通太郎"と"基本給"と"職責給"と"勤続年数"という4つの文字列リテラルは、日本語で書かれた言語依存の文字列リテラルである。つまり、これら4つの文字列リテラルは国別文字定数(national literals)である。よって、これら4つの文字列リテラルを出力するための4つのDISPLAY文(DISPLAY statements)の各々では、国別文字定数を示す"N"が指定されている。
さて、プログラマは、ソースファイル301を日本語向け開発環境300内のコンパイラ302に入力として与える。コンパイラ302は、ソースファイル301をコンパイルすることでオブジェクトファイル303を生成する。
日本語向け開発環境300には、コンパイラ302だけでなくリンカ305も用意されている。リンカ305は、オブジェクトファイル303および他のオブジェクトファイル304から、実行ファイル311を生成する(つまりビルドする)。
実行ファイル311が日本語の実行環境310で実行されると、画面312には、"20131226"、"G8-2"、"富士通太郎"、"基本給"、"職責給"、"勤続年数"という6つの文字列リテラルが表示される。
ところで、図3にはオブジェクトファイル303の詳細も示されている。オブジェクトファイル303は、文字列リテラル用の記憶領域(storage area)であるRO領域(read-only section)306と、命令307〜309を少なくとも含む。RO領域306の詳細が図3の右端に示されている。
具体的には、RO領域306において、0〜7バイト目に"20131226"が配置され、8〜11バイト目に"G8-2"が配置される。また、RO領域306において、12〜21バイト目に"富士通太郎"が配置され、22〜27バイト目に"基本給"が配置され、28〜33バイト目に"職責給"が配置され、34〜41バイト目に"勤続年数"が配置される。
命令307は、ベースレジスタに、メモリ上でのオブジェクトコードの開始アドレスを読み込む(つまりロードする)ための命令である。なお、図3および後述の他の図では、ベースレジスタが"BaseReg"という名前で示されており、メモリ上でのオブジェクトコードの開始アドレスが"StartAddr"と表されている。
命令308は、ベースレジスタに保持されている値に、オブジェクトコードの開始アドレスに対するRO領域306の開始アドレスのオフセットを足して、その加算結果をベースレジスタに格納するための命令である。図3および後述の他の図では、オブジェクトコードの開始アドレスに対するRO領域の開始アドレスのオフセットが、"Offset"と表されている。
命令309は、ベースレジスタに保持されている値と34を足した値を、"Reg1"という名前のレジスタに格納するための命令である。つまり、命令309は、"勤続年数"という文字列リテラルのメモリ上での開始アドレスを、レジスタReg1に格納するための命令である。命令309は、画面312に"勤続年数"という文字列リテラルを出力するための命令列に含まれる複数の命令のうちの1つである。
なお、図3および後述の他の図では、説明の便宜上、オブジェクトコードをアセンブリ言語で表現している。しかし、実際には、オブジェクトコードは、図示されたアセンブリコードに対応するマシン語のコード(machine code)である。
ところで、第2比較例でプログラマは、英語向け開発環境(不図示)において、英語で書かれた文字列リテラルを含む、英語向けソースファイルを作成する。英語向けソースファイルでは、ソースファイル301内の日本語の文字列リテラルが英語の文字列リテラルに置換されるが、その他の点では両ソースファイルは同じである。
具体的には、英語向けソースファイルには、日本語向けソースファイル301と同じく、"20131226"および"G8-2"という2つの言語非依存文字列リテラルが含まれる。また、英語向けソースファイルには、ソースファイル301に含まれる日本語の4つの文字列リテラルに対応する意味を持つ、英語で書かれた4つの文字列リテラルも含まれる。すなわち、英語向けソースファイルには、"Fujitsu Taro"と"Base Salary"と"Responsibility Salary"と"Length of Service"という4つの文字列リテラルも含まれる。
プログラマは、英語向けソースファイルを、英語向け開発環境内のコンパイラに入力として与える。コンパイラは、英語向けソースファイルをコンパイルすることで、図4のオブジェクトファイル320を生成する。
オブジェクトファイル320はリンカによって他のオブジェクトファイルとリンクされる。その結果、英語の実行環境(不図示)用の実行ファイル(不図示)が生成される。この実行ファイルが実行されると、画面には、"20131226"、"G8-2"、"Fujitsu Taro"、"Base Salary"、"Responsibility Salary"、"Length of Service"という6つの文字列リテラルが表示される。
ところで、図4には、オブジェクトファイル320の詳細が示されている。オブジェクトファイル320は、RO領域321と、命令307および308と同じ2つの命令と、命令309とはオペランドが異なる命令322を含む。
具体的には、RO領域321において、0〜7バイト目に"20131226"が配置され、8〜11バイト目に"G8-2"が配置される。また、RO領域306において、12〜23バイト目には、"富士通太郎"に対応する意味を持つ"Fujitsu Taro"が配置される。そして、24〜34バイト目には、"基本給"に対応する意味を持つ"Base Salary"が配置される。また、35〜55バイト目には、"職責給"に対応する意味を持つ"Responsibility Salary"が配置される。さらに、56〜72バイト目には、"勤続年数"に対応する意味を持つ"Length of Service"が配置される。
命令322は、ベースレジスタに保持されている値と56を足した値を、レジスタReg1に格納するための命令である。つまり、命令322は、"Length of Service"という文字列リテラルのメモリ上での開始アドレスを、レジスタReg1に格納するための命令である。
さて、第2比較例でプログラマは、中国語向け開発環境(不図示)において、中国語で書かれた文字列リテラルを含む、中国語向けソースファイルを作成する。中国語向けソースファイルでは、ソースファイル301内の日本語の文字列リテラルが中国語の文字列リテラルに置換されるが、その他の点では両ソースファイルは同じである。
よって、中国語向けソースファイルにも、"20131226"および"G8-2"という2つの言語非依存文字列リテラルが含まれる。また、中国語向けソースファイルには、ソースファイル301に含まれる日本語の4つの文字列リテラルに対応する意味を持つ、中国語で書かれた4つの文字列リテラルも含まれる。すなわち、中国語向けソースファイルには、"富士通太郎"と
と
と
という4つの文字列リテラルも含まれる。なお、"富士通太郎"という人名は、たまたま日本語と中国語で同じ文字で表されているが、固有名詞の中には、日本語と中国語で異なる文字で表されるものもある。
プログラマは、中国語向けソースファイルを、中国語向け開発環境内のコンパイラに入力として与える。すると、コンパイラは、図4のオブジェクトファイル330を生成する。
オブジェクトファイル330リンカによって他のオブジェクトファイルとリンクされる。その結果、中国語の実行環境(不図示)用の実行ファイル(不図示)が生成される。この実行ファイルが実行されると、画面には、"20131226"、"G8-2"、"富士通太郎"、
、
、
という6つの文字列リテラルが表示される。
ところで、図4には、オブジェクトファイル330の詳細が示されている。オブジェクトファイル330は、RO領域331と、命令307および308と同じ2つの命令と、命令309とはオペランドが異なる命令332を含む。
具体的には、RO領域331において、0〜7バイト目に"20131226"が配置され、8〜11バイト目に"G8-2"が配置される。また、RO領域331において、12〜21バイト目には、日本語の"富士通太郎"に対応する意味を持つ中国語の"富士通太郎"が配置される。そして、22〜29バイト目には、"基本給"に対応する意味を持つ
が配置される。また、30〜37バイト目には、"職責給"に対応する意味を持つ
が配置される。さらに、38〜41バイト目には、"勤続年数"に対応する意味を持つ
が配置される。
命令332は、ベースレジスタに保持されている値と38を足した値を、レジスタReg1に格納するための命令である。つまり、命令332は、
という文字列リテラルのメモリ上での開始アドレスを、レジスタReg1に格納するための命令である。
以上の説明から分かるように、命令309と322と332は、オペランドが異なるだけである。命令309と322と332のオペランドが異なる理由は、互いに対応する意味を持つような複数の言語の文字列リテラル同士が、必ずしも同じ長さではないからである。結果として、オブジェクトファイル303と320と330は、文字列リテラル用のRO領域の内容において互いに異なるだけでなく、命令用の領域に含まれるいくつかの命令のオペランドにおいても互いに異なる。ある観点から見れば、「RO領域の内容も、命令のオペランドも、上記のように言語に依存してしまう」ということは、言語ごとに別々にコンパイル処理が行われることの帰結とも言える。
第2比較例では、言語ごとにプログラマがソースファイルを用意するので、ソースファイルの作成・保守・管理にかかる手間(つまりコスト)が大きい。また、第2比較例では、言語ごとに別々にコンパイル処理が行われるので、コンパイル処理の手間もかかる。
続いて、図5を参照して第3比較例について説明する。第3比較例は、第1比較例と第2比較例の欠点を克服するために考えられ得る方法の一例を示す。
しかし、第3比較例のような単純な方法では、コンパイルが失敗してしまう。つまり、第3比較例は非現実的である。ある側面では、各種実施形態は、第3比較例のような失敗を避けることを1つの目的としている。
実は、図3〜4に例示したようなRO領域を含むオブジェクトコードを生成するような種類のコンパイラには、優れた利点がある。具体的には、この種のコンパイラには、「コンパイル処理を簡素化することで、ソースファイルをコンパイルするのにかかる時間を短縮する」という効果がある(詳しくは後述する)。
しかし、この時間短縮効果が得られるようなコンパイルの仕方を変えずに(つまり時間短縮効果を維持したままで)、第1比較例と第2比較例の欠点を克服することには、困難がある。第3比較例は、この困難の克服(または回避)に失敗してしまう例である。
図5には、図3のソースファイル301と同じソースファイル401が例示されている。また、図5には、コンパイラ402とオブジェクトファイル403が図示されており、オブジェクトファイル403内のRO領域404の詳細も図示されている。
第3比較例での目標の1つは、第1比較例のように複数のリソースファイル204〜206を実行時に使う事態を避け、かつ、第2比較例のように複数種類のオブジェクトファイル303、320、および330を生成する事態も避けることである。この目標を達成するために考えられ得る方法は、1つのオブジェクトファイル403のRO領域404内に、複数の言語の文字列リテラルを含めることである。
図5には、言語非依存の文字列リテラルと、日本語の文字列リテラルと、英語の文字列リテラルと、中国語の文字列リテラルのすべてを含むRO領域404が例示されている。具体的には、上記の文字列リテラルが以下のように配置されたRO領域404が考えられ得る。
・ 0〜 7バイト目:"20131226"(言語非依存の文字列リテラル)
・ 8〜11バイト目:"G8-2"(言語非依存の文字列リテラル)
・12〜21バイト目:"富士通太郎"(日本語の文字列リテラル)
・22〜33バイト目:"Fujitsu Taro"(12〜21バイト目の文字列リテラルに対応する意味を持つ英語の文字列リテラル)
・34〜43バイト目:"富士通太郎"(12〜21バイト目の文字列リテラルに対応する意味を持つ中国語の文字列リテラル)
・44〜49バイト目:"基本給"(日本語の文字列リテラル)
・50〜60バイト目:"Base Salary"(44〜49バイト目の文字列リテラルに対応する意味を持つ英語の文字列リテラル)
・61〜68バイト目:
(44〜49バイト目の文字列リテラルに対応する意味を持つ中国語の文字列リテラル)
・69〜74バイト目:"職責給"(日本語の文字列リテラル)
・75〜95バイト目:"Responsibility Salary"(69〜74バイト目の文字列リテラルに対応する意味を持つ英語の文字列リテラル)
・96〜103バイト目:
(69〜74バイト目の文字列リテラルに対応する意味を持つ中国語の文字列リテラル)
・104〜111バイト目:"勤続年数"(日本語の文字列リテラル)
・112〜128バイト目:"Length of Service"(104〜111バイト目の文字列リテラルに対応する意味を持つ英語の文字列リテラル)
・129〜132バイト目:
(104〜111バイト目の文字列リテラルに対応する意味を持つ中国語の文字列リテラル)
もし、上記のごときRO領域404を含むオブジェクトファイル403をコンパイラ402が生成することが可能であれば、第3比較例は第1・第2比較例よりも有利であろう。しかし、単にオブジェクトファイル403が図5のようなRO領域404を含んでさえいれば十分、という訳ではない。もし、RO領域404内の文字列リテラルを参照するための適切な命令をコンパイラ402が生成することができなければ、図5のようなRO領域404は意味を持たない。
そして、「上述のような時間短縮効果を持つコンパイラを改造(modify)することで、RO領域404を含むオブジェクトファイル403の生成を可能にしよう」という試みは、失敗してしまう。つまり、第3比較例で想定した方法は、コンパイルの失敗にしかつながらない。
なぜなら、RO領域404内の文字列リテラルを参照するための適切な命令は、コンパイル時には定まらないからである。この失敗は、図5において、オペランドが定まらない命令405によって表現されている。以下に、より具体的に説明する。
上記のとおり、コンパイル処理を簡素化することで、ソースファイルをコンパイルするのにかかる時間を短縮することが可能となる。コンパイル処理の簡素化とは、コンパイラ(例えばコンパイラ302または402)が、ソースファイル(例えばソースファイル301または401)にリテラルが出現する順に、リテラルの種類によらない一律の操作を行うことを意味する。以下、第2比較例のコンパイラ302とソースファイル301を例にして、この時間短縮効果について説明する。
具体的には、コンパイラ302は、リテラルの種類によらず、単に、ソースファイル301にリテラルが出現する順にそれらのリテラルを解析する。そして、コンパイラ302は、解析した順にそれらのリテラルをオブジェクトファイル303のRO領域306内に連続的に配置する。
つまり、コンパイラ302は、リテラルの種類(数値リテラル、言語非依存の文字列リテラル、言語依存の文字列リテラル、など)に基づいてリテラルを解析する順序を変えることはない。コンパイラ302は、単に、ソースファイル301にリテラルが出現する順に、それらのリテラルを解析するだけである。
また、コンパイラ302は、RO領域306内でリテラルを配置する場所(換言すればRO領域306内での各リテラルの開始アドレス)を、リテラルの種類に基づいて決めることもない。コンパイラ302は、単に、ソースファイル301にリテラルが出現する順に、それらのリテラルをRO領域306内に連続的に配置するだけである。
例えば、ソースファイル301に10個のリテラルが含まれ、そのうち1番目と7番目のリテラルが数値リテラルであり、2番目と9番目が言語非依存の文字列リテラルであり、3〜6、8、10番目が言語依存の文字列リテラルであるとする。このような場合でも、例えば「1〜2番目に2つの数値リテラルを解析し、3〜4番目に2つの言語非依存の文字列リテラルを解析し、5〜10番目に6つの言語依存の文字列リテラルを解析する」といったような、解析順の入れ替えは行われない。また、このような場合でも、例えば「1〜2番目に2つの数値リテラルを配置し、3〜4番目に2つの言語非依存の文字列リテラルを配置し、5〜10番目に6つの言語依存の文字列リテラルを配置する」といったような、種類に応じた配置は行われない。上記の場合、コンパイラ302は、単に、ソースファイル301に出現するi番目のリテラルをi番目に解析し、このi番目のリテラルをRO領域306内でi番目に配置するだけである(1≦i≦10)。
以上のような、「コンパイラ302がリテラルの種類を考慮しないで、単にソースファイル301での出現順にのみ基づいて、リテラルを順に解析し、RO領域306内に順にリテラルを配置する」という方法によれば、コンパイル処理が簡素化される。なぜなら、リテラルを配置する順番やアドレスをリテラルの種類に応じて決める処理が不要だからである。そして、コンパイル処理の簡素化により、ソースファイル301をコンパイルするのにかかる時間が短縮される。
第3比較例のコンパイラ402も、以上のような時間短縮効果を狙って、リテラルの種類によらず、単に、ソースファイル401にリテラルが出現する順にそれらのリテラルを解析する。そして、コンパイラ402は、解析した順に、リテラルをRO領域404に配置しようとする。
より具体的には、ソースファイル401にi番目に出現するリテラルが言語に依存しない種類のリテラルであれば、コンパイラ402は、単に、i番目のリテラルをRO領域404内の次の位置に配置する。逆に、i番目のリテラルが、言語依存の文字列リテラルであれば、コンパイラ402は、i番目のリテラルをRO領域404内の次の位置に配置し、さらに、i番目のリテラルに対応する他の言語の文字列リテラルも、その後に連続して配置する。こうしてコンパイラ402は、複数の言語間で互いに対応するリテラルを含む複数のリテラルを、図5に示すようにRO領域404に配置することも可能である。
ところが、単にリテラルがRO領域404内に配置されているだけでは意味がない。リテラルにアクセスする(つまり、RO領域404内のリテラルを参照する)ための命令がオブジェクトファイル403に含まれてこそ、RO領域404内のリテラルは意味を持つ。しかし、第3比較例のコンパイラ402は、リテラルを参照するための命令をうまく決めることができない。
リテラルを参照するための命令の生成にコンパイラ402が失敗してしまうことが、図5では、オペランドが不定の命令405として表現されている。オペランドが正しく指定されていない命令405は、もちろん、不正であり、実行不能である。
このような第3比較例におけるコンパイル処理の失敗の原因は、第2比較例と第3比較例を比べることで、よりよく理解される。
第2比較例では、どの言語の文字列リテラルが実行時に参照されるのかについて、コンパイル時に一意に確定される。例えば、日本語向けソースファイル301がコンパイルされる場合は、「コンパイルにより得られるオブジェクトファイル303から生成される実行ファイル311が実行されると、日本語の文字列リテラルが参照される」ということがコンパイル時に確定される。同様に、英語向けのソースファイルがコンパイルされる場合には、「実行時には英語の文字列リテラルが参照される」ということがコンパイル時に確定する。同様に、中国語向けのソースファイルがコンパイルされる場合には、「実行時には中国語の文字列リテラルが参照される」ということがコンパイル時に確定する。
そのため、第2比較例のコンパイラ302は、RO領域内のリテラルを参照するための命令のオペランド(例えば、命令309における、34という数値を含むオペランド)をコンパイル時に確定することができる。したがって、第2比較例のコンパイラ302は、適切な命令(例えば命令309)を生成することもできる。
例えば、ソースファイル301は日本語の文字列リテラルを含むが、英語や中国語などの他の言語の文字列リテラルは含まない。よって、コンパイラ302は、ソースファイル301をコンパイルする際に、「実行時に参照されることになる文字列リテラルは、ソースファイル301に現れる日本語の文字列リテラルである」と確定することができる。つまり、第2比較例では、コンパイラ302がソースファイル301をコンパイルする際には、「実行ファイル311の実行時に、英語や中国語などの他の言語の文字列リテラルが参照される」という可能性は予め排除されている。
そのため、コンパイラ302は、日本語の文字列リテラルを参照するための適切なオペランドを一意に確定することができ、その適切なオペランドを含む命令を生成することができる。例えば、"勤続年数"という日本語の文字列リテラルのRO領域306内での開始アドレスを指定するための、"[BaseReg+34]"という適切なオペランドを、コンパイラ302は確定することができる。具体的には、コンパイラ302は、単にソースファイル301に出現する順にリテラルを解析し、リテラルのバイト長を順に合算してゆくだけで、上記オペランドに含まれる34という値を確定的に得ることができる。よって、コンパイラ302は、上記オペランドを含む命令309を生成することができる。
もちろん、ソースファイル301中に例示した他の各文字列リテラルに関しても、コンパイラ302は、適宜のオペランドを確定することができ、そのオペランドを含む命令を生成することができる。だからこそ、実行ファイル311の実行時には、各リテラルが正しく参照され、画面312に表示されるのである。
同様に、コンパイラ302は、英語向けソースファイル(図4に関して説明した、不図示のソースファイル)をコンパイルする際には、「実行時に参照されることになる文字列リテラルは、英語の文字列リテラルである」と確定することができる。そのため、コンパイラ302は、例えば、"Length of Service"という英語の文字列リテラルのRO領域321内での開始アドレスを指定するための、"[BaseReg+56]"という適切なオペランドを確定することができる。よって、コンパイラ302は、このオペランドを含む命令322を生成することができる。
同様に、コンパイラ302は、中国語向けソースファイコンパイルする際には、「実行時に参照されることになる文字列リテラルは、中国語の文字列リテラルである」と確定することができる。したがって、コンパイラ302は、例えば、命令332のオペランドを適切に確定することができ、命令332を生成することができる。
ところが、第3比較例では、どの言語の文字列リテラルが実行時に参照されるのかが、コンパイル時には不明である。この不確定性が、第3比較例において命令生成が失敗する原因である。仮に、コンパイラ402が図5のRO領域404のように日本語と英語と中国語の文字列リテラルを配置することができるとしても、コンパイラ402は、それらの文字列リテラルを参照するための適切な命令を生成することには失敗してしまう。
例えば、ソースファイル401に含まれる"勤続年数"という日本語の文字列リテラルに対応して、コンパイラ402は、RO領域404内に以下のように3種類の言語の文字列リテラルを配置することが可能である。
・104〜111バイト目:"勤続年数"という日本語の文字列リテラル
・112〜128バイト目:"Length of Service"という英語の文字列リテラル
・129〜132バイト目:
という中国語の文字列リテラル
しかし、上記3つの文字列リテラルのうちのいずれが実行時に参照されるのかは、コンパイラ402にとって不明である。したがって、コンパイラ402は、以下の3つの命令のうちのどれを生成すべきなのかを決められない。
・"勤続年数"という日本語の文字列リテラルの開始アドレスを、レジスタReg1に設定するための、"Mov Reg1, [BaseReg+104]"という命令
・"Length of Service"という英語の文字列リテラルの開始アドレスを、レジスタReg1に設定するための、"Mov Reg1, [BaseReg+112]"という命令
・
という中国語の文字列リテラルの開始アドレスを、レジスタReg1に設定するための、"Mov Reg1, [BaseReg+129]"という命令
以上の例から分かるように、第3比較例では、仮にコンパイラ402が図5のようにRO領域404内に日本語と英語と中国語の文字列リテラルを配置することができるとしても、コンパイラ402は命令のオペランドを決められない。その結果、第3比較例では、コンパイラ402は、文字列リテラルを参照するための命令の生成に失敗する。つまり、第3比較例のようなアプローチでは、文字列リテラルを参照するための有効な命令を含むオブジェクトコードの生成に失敗する。
したがって、第1・第2比較例の欠点を克服するには、第3比較例とは別のアプローチをとることが有益である。上記の第1実施形態および下記の各種実施形態では、第3比較例とは別のアプローチがとられているので、第3比較例のような失敗は避けられる。また、上記の第1実施形態および下記の各種実施形態によれば、第1・第2比較例の欠点が克服され、かつ、第2・第3比較例に関して説明した上述の時間短縮効果と同様の効果も得られる。第1実施形態を含む各種の実施形態の効果については、後に再び述べる。
続いて、図6〜13を参照して第2実施形態について説明する。
図6は、第2実施形態の概要を説明する図である。図6には、第2実施形態によるコンパイラ500と、コンパイラ500が入力として受け取るソースファイル501およびロケールリソースファイル502と、コンパイラ500が出力するオブジェクトファイル503が示されている。コンパイラ500の詳細は後述する。
ソースファイル501は、図3のソースファイル301および図5のソースファイル401と同じである。具体的には、ソースファイル501には、言語非依存の"20131226"および"G8-2"という文字列リテラルと、"富士通太郎"、"基本給"、"職責給"、"勤続年数"という日本語の文字列リテラルが含まれる。
ロケールリソースファイル502には、複数のロケールに対応する文字列リテラルの組(tuple)が、複数記憶されている。具体的には、図6のロケールリソースファイル502は、"en-us"と"zh-cn"と"ja"という3つのロケール名により識別される3種類のロケールに対応する。換言すれば、ロケールリソースファイル502では、3種類のロケールに対応する3種類の言語の文字列リテラルの組み合わせであるリテラル組が、定義されている。
なお、"en-us"というロケール名は、アメリカ合衆国の英語を表し、0x0409という16進数で表されるLCID(locale identifier)に対応する。また、"zh-cn"は中華人民共和国の中国語を表し、0x0804という16進数で表されるLCIDに対応する。そして、"ja"は日本語を表し、0x0411という16進数で表されるLCIDに対応する。
LCIDは、Windows(登録商標)OSでロケールを識別するために使われる識別子である。LCIDを取得するためのAPIも提供されている。
以下では説明の便宜上、LCIDによりロケールが識別されるものとするが、Windows(登録商標)以外のOSでも、ロケールを識別するための類似の識別子が使われる。よって、第2実施形態は、開発環境のOSや実行環境のOSによらず、適用可能である。
ロケールリソースファイル502のデータ形式は、実施形態に応じて適宜定められていてよい。図6では便宜上、ロケールリソースファイル502がテーブル形式で示されている。
ロケールリソースファイル502のヘッダには、ロケールリソースファイル502で文字列リテラルが定義される言語に対応するロケールの名前が記録されている。図6の例では、"en-us"と"zh-cn"と"ja"という3つのロケール名が、ヘッダに指定されている。ロケール名の代わりにLCIDがヘッダで指定されていてもよい。
ロケールリソースファイル502の個々のレコードは、文字列リテラルの組に対応する。各レコードには識別子(図6の例では識別番号)が割り当てられている。
例えば、1という識別番号が割り当てられたレコードは、"Fujitsu Taro"という英語の文字列リテラルと、"富士通太郎"という中国語の文字列リテラルと、"富士通太郎"という日本語の文字列リテラルを含む。これら3つの文字列リテラルは、互いに対応する意味を持つ。
また、2という識別番号が割り当てられたレコードは、"Base Salary"という英語の文字列リテラルと、
という中国語の文字列リテラルと、"基本給"という日本語の文字列リテラルを含む。これら3つの文字列リテラルは、互いに対応する意味を持つ。
そして、3という識別番号が割り当てられたレコードは、"Responsibility Salary"という英語の文字列リテラルと、
という中国語の文字列リテラルと、"職責給"という日本語の文字列リテラルを含む。これら3つの文字列リテラルは、互いに対応する意味を持つ。
また、4という識別番号が割り当てられたレコードは、"Length of Service"という英語の文字列リテラルと、
という中国語の文字列リテラルと、"勤続年数"という日本語の文字列リテラルを含む。これら3つの文字列リテラルは、互いに対応する意味を持つ。
なお、実施形態によっては、ロケールリソースファイル502が、物理的には複数のファイルの集まりであってもよい。例えば、ロケールリソースファイル502が、以下の3つのファイルの集まりであってもよい。
・"en-us"というロケール名に対応するファイル(具体的には識別番号と英語の文字列リテラルの組を含むファイル)。
・"zh-cn"というロケール名に対応するファイル(具体的には識別番号と中国語の文字列リテラルの組を含むファイル)。
・"ja"というロケール名に対応するファイル(具体的には識別番号と日本語の文字列リテラルの組を含むファイル)。
なお、複数のファイルの文字エンコーディング方式(character encoding scheme;CES)は互いに異なっていてもよい。例えば、"ja"というロケール名に対応するファイルでは、シフトJIS(Japanese industrial standard)が使われてもよく、他の2つのファイルではシフトJIS以外のCESが使われてもよい。
逆に、複数のファイルのCESが同じであってもよい。例えば、複数のファイルでUTF−8(UCS transformation format 8;UCSは、universal multiple-octet coded character setの略)が使われてもよい。
あるいは、1つのロケールリソースファイル502の中で、ロケールごとに別のCESが使われてもよい。CESに応じて、1文字に対応するバイト数は異なり得る(例えば、シフトJISでは2バイトで表される文字が、UTF−8では3バイトで表される場合がある)。
オブジェクトファイル503は、文字列リテラルが配置されるRO領域と、複数の命令を含む。RO領域は、言語非依存の文字列リテラル用の部分と、言語依存の文字列リテラル用の部分を含む。紙幅の都合上、図6には、RO領域と1つの命令だけが例示されている。オブジェクトファイル503に含まれる複数の命令の詳細は、図10〜11とともに後述する。図6に例示されている命令は、図11の命令837である。
オブジェクトファイル503のRO領域のうち、言語非依存の文字列リテラル用の領域には、ロケールによらず共通に使われる文字列リテラルが、ソースファイル501での出現順に、配置される。
具体的には、ソースファイル501には、まず"20131226"という言語非依存の文字列リテラルが出現し、その後、"G8-2"という言語非依存の文字列リテラルが出現する。よって、オブジェクトファイル503内の言語非依存の文字列リテラル用の領域において、0〜7バイト目には"20131226"という文字列リテラルが配置され、8〜11バイト目には"G8-2"という文字列リテラルが配置される。
以下では説明の便宜上、ソースファイル501に含まれる言語非依存の文字列リテラルのバイト長の合計を、「Xバイト」と表記する。よって、オブジェクトファイル503のRO領域のうち、言語非依存の文字列リテラルが配置される領域の長さは、Xバイトである。
また、第2実施形態では、ロケールリソースファイル502で定義される各リテラル組に属する3つの文字列リテラルのうちで最長の文字列リテラルのバイト長が、当該リテラル組に対応する「算出バイト長」(第1実施形態での説明を参照)として使われる。以下では説明の便宜上、ソースファイル501に出現する文字列リテラルに対応してロケールリソースファイル502で定義される全リテラル組の算出バイト長の合計を、「Yバイト」と表記する。
よって、RO領域のうち、言語依存の文字列リテラルが配置される領域の長さは、3Yバイトである。図1の表記法によれば、図6では、N=3であり、かつ、Y=B1+…+BMである。
以下では説明の便宜上、RO領域の開始アドレスが(1バイト目ではなく)「0バイト目」とカウントされるものとする。したがって、オブジェクトファイル503のRO領域のXバイト目から(X+3Y−1)バイト目までの範囲に、言語依存の文字列リテラルが配置される。
具体的には、以下のとおり、X〜(X+Y−1)バイト目までの範囲に、英語の文字列リテラルが配置される。なお、第2実施形態では、算出バイト長より短い文字列リテラルは、空白文字(space character)でパディングされて(詳しくは後述)、RO領域内に配置される。偶然にも図6の例では、英語の各文字列リテラルは、対応する算出バイト長と同じ長さなので、パディングされていない。
・(X+0)〜(X+11)バイト目:"Fujitsu Taro"
・(X+12)〜(X+22)バイト目:"Base Salary"
・(X+23)〜(X+43)バイト目:"Responsibility Salary"
・(X+44)〜(X+60)バイト目:"Length of Service"
そして、以下のとおり、(X+Y)〜(X+2Y−1)バイト目までの範囲に、中国語の文字列リテラルが配置される。なお、図示の便宜上、図6(および後述の図14)では、空白文字によりパディングされた各バイトを示すセルには、点線の斜線が引かれている。
・(X+Y+0)〜(X+Y+11)バイト目:"富士通太郎"
・(X+Y+12)〜(X+Y+22)バイト目:
・(X+Y+23)〜(X+Y+43)バイト目:
・(X+Y+44)〜(X+Y+60)バイト目:
さらに、以下のとおり、(X+2Y)〜(X+3Y−1)バイト目までの範囲に、日本語の文字列リテラルが配置される。
・(X+2Y+0)〜(X+2Y+11)バイト目:"富士通太郎"
・(X+2Y+12)〜(X+2Y+22)バイト目:"基本給"
・(X+2Y+23)〜(X+2Y+43)バイト目:"職責給"
・(X+2Y+44)〜(X+2Y+60)バイト目:"勤続年数"
例えば、(X+23)〜(X+43)バイト目と、(X+Y+23)〜(X+Y+43)バイト目と、(X+2Y+23)〜(X+2Y+43)バイト目は、ソースファイル501中に出現する"職責給"という日本語の文字列リテラルに対応する。(X+23)バイト目、(X+Y+23)バイト目、(X+2Y+23)バイト目という、3つの言語の文字列リテラルそれぞれの開始アドレスの共通点は、23というオフセットである。オフセットが共通な理由は、各リテラル組に属する3つの文字列リテラルには同じ算出バイト数が割り当てられるためである。
図6には、上記の共通のオフセットを含むオペランド(すなわち"[BaseReg+Reg2+23]"というオペランド)が指定された命令が例示されている。詳しくは後述するとおり、レジスタReg2には、実行時のロケールに応じた値が設定される。よって、"Mov Reg3, [BaseReg+Reg2+23]"という1つの共通の命令にしたがって、実行時のロケールに応じた適宜の言語(すなわち、英語、中国語または日本語)の文字列リテラルの開始アドレスが参照される。オペランドが不定な第3比較例とは異なり、第2実施形態のコンパイラ500は、コンパイル時に23という値を確定することができるので、以上のように適切な命令を生成することができる。
なお、図6では、省略符号により、「言語依存または言語非依存の他の1つ以上の文字列リテラルがソースファイル501にさらに含まれる」という可能性が示されている。しかし、もし仮に、ソースファイル501内に、図6には明示されていない他の文字列リテラルが含まれないならば、X=8+4=12であり、かつ、Y=12+11+21+17=61である。
図7は、第2実施形態のコンパイラのブロック構成図である。図7には、コンパイラ500だけでなく、コンパイラ500が入力として受け取るソースファイル501およびロケールリソースファイル502も示されている。さらに、図7には、コンパイラ500が出力するオブジェクトファイル503と、その他のオブジェクトファイル504および505と、リンカ506と、実行ファイル507も示されている。
ソースファイル501とロケールリソースファイル502の詳細は、例えば、図6に示すとおりであってもよい。また、オブジェクトファイル503の詳細は、例えば、図6および後述の図10〜11に示すとおりであってもよい。リンカ506は、オブジェクトファイル503〜505をリンクすることにより実行ファイル507を生成する。
コンパイラ500は、解析部600を有する。解析部600は、字句解析(lexical analysis)部601と、構文解析(syntactic analysis)部602と、意味解析(semantic analysis)部603を含む。意味解析部603は、手続き解析部604とリテラル登録部605を含む。コンパイラ500はさらに、割り付け(allocation)部606とオブジェクトコード生成部607を含む。オブジェクトコード生成部607はリテラル配置部608を含む。オブジェクトコード生成部607は、不図示のコード最適化部を含んでいてもよい。
また、図7には、コンパイラ500がコンパイル処理を実行している最中に作成および使用する、一時的なデータも例示されている。具体的には、コンパイラ500は、言語非依存リテラル一覧609を作成および使用する。また、図6に示すようにロケールリソースファイル502において英語と中国語と日本語の文字列リテラルが定義されている場合、コンパイラ500は、日本語リテラル一覧610と英語リテラル一覧611と中国語リテラル一覧612を作成および使用する。また、詳しくは後述するとおり、コンパイラ500は、オフセット一覧613も作成および使用する。なお、図7中に例示したこれらの一覧の具体例は、図9とともに後述する。
コンパイラ500の動作の詳細は、図12〜13とともに後述するが、概要は以下のとおりである。
字句解析部601は、ソースファイル501に書かれたソースコードをスキャンして解析する。つまり、字句解析部601は、ソースコードの文字列からトークン列を認識する。
構文解析部602はトークン列を解析(parse)し、それにより、構文木(parse tree)を生成する。
意味解析部603は、構文木をトラバースし、構文木の意味を解析(analyze)する。具体的には、意味解析部603は、ソースファイル501中に出現するシンボル(例えば、変数、定数、関数等の名称)の一覧(list)を作成したり、リテラルの一覧を作成したりする。また、意味解析部603は、型チェックなどの整合性チェックを行ってもよい。このように、意味解析部603が行う解析は複数種類の処理を含むので、意味解析部603は複数のモジュールを含んでいてよい。図6には、複数のモジュールのうちの2つ(すなわち手続き解析部604とリテラル登録部605)が示されている。
手続き解析部604は、ソースコード中のステートメントを順に解析してもよい。例えば、手続き解析部604は、構文木を適宜の順序(例えば後順(post-order))でトラバースしてもよい。それにより、手続き解析部604は、例えば、ステートメント間の入れ子構造や、関数の呼び出し元(caller)と呼び出される関数との関係を解析してもよい。
リテラル登録部605は、ソースコード中に現れるリテラルを、適宜のリテラル一覧に登録する。また、リテラル一覧への登録の際、リテラル登録部605は、オフセット一覧613にオフセットも登録する。
割り付け部606は、レジスタの割り付けを行う(つまり、どの命令でどのレジスタを使うかを決定する)。また、割り付け部606は、オブジェクトコード内の各領域(例えば、リテラルを記憶するためのRO領域や、命令列を記憶するための領域など)のバイト数も決定する。
そして、意味解析部603と割り付け部606による処理の結果に基づいて、オブジェクトコード生成部607が、オブジェクトコードを生成する。オブジェクトコード生成部607は、生成したオブジェクトコードをオブジェクトファイル503として出力する。なお、リテラル配置部608は、オブジェクトコードの生成する処理のうち、リテラルをオブジェクトコードのRO領域内に配置する処理を行う。
ところで、図6〜7のコンパイラ500は、具体的には、コンパイラ・プログラムを実行するコンピュータにより実現されるコンパイル装置であってもよい。具体的には、コンパイル装置は、コンパイル対象のソースファイル501と、リテラル組を定義するロケールリソースファイル502とに基づいて、オブジェクトファイル503を生成する生成部(例えばオブジェクトコード生成部607)を有する装置である。
コンパイラ500内の解析部600やオブジェクトコード生成部607等の各部は、具体的には、コンパイラ・プログラムに含まれるプログラム・モジュールをコンピュータが実行することにより実現されてもよい。コンパイラ・プログラムを実行するコンピュータは、具体的には、図8のコンピュータ700であってもよい。なお、コンパイラ・プログラムのことを単にコンパイラともいう。
図8は、コンピュータ700のハードウェア構成図である。コンピュータ700は、CPU(Central Processing Unit)701と、ROM(Read-Only Memory)702と、RAM(Random-Access Memory)703と、通信インタフェイス704を有する。コンピュータ700はさらに、入力装置705と、出力装置706と、記憶装置707と、可搬型記憶媒体710の駆動装置708を有する。コンピュータ700内の各コンポーネントは、バス709を介して互いに接続されている。
また、コンピュータ700はネットワーク711に接続されている。ネットワーク711は、例えば、LAN(Local Area Network)、WAN(Wide Area Network)、インターネット、またはその組み合わせである。ネットワーク711にはさらに、プログラム提供者712が接続されていてもよい。プログラム提供者712は、プログラムを提供するためのコンピュータである。
図7には1つのCPU701のみが図示されているが、コンピュータ700は複数のCPU701を有していてもよい。また、CPU701は、シングルコアCPUでもよいしマルチコアCPUでもよい。CPU701はプロセッサの一例である。
CPU701は、プログラムをRAM703にロードし、RAM703をワーキングエリアとしても使いながらプログラムを実行する。ROM702には、例えば、BIOS(Basic Input Output System)などのファームウェアが記憶されていてもよい。
通信インタフェイス704は、例えば、有線LANインタフェイス回路、無線LANインタフェイス回路、またはその組み合わせである。通信インタフェイス704は、具体的には、外付けのNIC(Network Interface Card)でもよいし、オンボード型のネットワークインタフェイスコントローラでもよい。例えば、通信インタフェイス704は、物理層の処理を行う「PHYチップ」と呼ばれる回路と、MAC(Media Access Control)副層の処理を行う「MACチップ」と呼ばれる回路を含んでいてもよい。
入力装置705は、例えば、キーボード、ポインティングデバイス、マイク、カメラ、またはそれらの2つ以上の組み合わせである。ポインティングデバイスは、例えば、マウスでもよいしタッチパッドでもよいしタッチスクリーンでもよい。
出力装置706は、ディスプレイ、スピーカ、またはその組み合わせである。ディスプレイはタッチスクリーンであってもよい。
記憶装置707は不揮発性である。具体的には、記憶装置707は、例えば、HDD(Hard Disk Drive)、SSD(Solid-State Drive)、またはその組み合わせである。
可搬型記憶媒体710の例は、CD(Compact Disc)やDVD(Digital Versatile Disk)などの光ディスク、光磁気ディスク、磁気ディスク、フラッシュメモリなどの半導体メモリカードなどである。駆動装置708は、具体的には、光ディスク駆動装置、光磁気ディスク駆動装置、または磁気ディスク駆動装置であってもよい。あるいは、駆動装置708は、メモリカード用のリーダおよびライタであってもよい。
コンピュータ700をコンパイラ500として動作させるためのコンパイラ・プログラムは、予め記憶装置707にインストールされていてもよい。あるいは、コンパイラ・プログラムは、可搬型記憶媒体710に格納されて提供され、可搬型記憶媒体710から駆動装置708により読み取られて記憶装置707にインストールされてもよい。または、コンパイラ・プログラムは、プログラム提供者712により提供され、ネットワーク711と通信インタフェイス704を介してコンピュータ700にダウンロードされ、記憶装置707にインストールされてもよい。
なお、ROM702、RAM703、記憶装置707、可搬型記憶媒体710は、いずれも、有形の(tangible)記憶媒体の例である。これらの有形の記憶媒体は、信号搬送波のような一時的な(transitory)媒体ではない。
コンパイラ・プログラムを実行することによってコンピュータ700がコンパイラ500として動作する場合、具体的には、解析部600、割り付け部606、およびオブジェクトコード生成部607は、CPU701により実現される。また、言語非依存リテラル一覧609、日本語リテラル一覧610、英語リテラル一覧611、中国語リテラル一覧612、およびオフセット一覧613は、RAM703に記憶されるのが好ましいが、記憶装置707に記憶されてもよい。
なお、ソースファイル501とロケールリソースファイル502は、例えば、記憶装置707に予め記憶されていてもよい。コンパイラ500は、オブジェクトファイル503を記憶装置707に出力してもよい。オブジェクトファイル504と505も、記憶装置707に記憶されていてよい。
リンカ506も、CPU701がプログラムを実行することで実現される。リンカ506は、実行ファイル507を記憶装置707に出力してもよい。実行ファイル507は、コンピュータ700上で実行されてもよいし、他のコンピュータ(例えばエンドユーザのコンピュータ)にコピーされて実行されてもよい。
さて、図9は、第2実施形態で使われるデータを例示する図である。図9には、図6に例示したソースファイル501とロケールリソースファイル502をコンパイラ500が入力として受け取った場合の、各種一覧が例示されている。
具体的には、言語非依存リテラル一覧609の各レコードは、「ID」(identifier)、「票長」(record length)、「項類」(category)、「長さ」、「オフセット」、「値」という6つのフィールドを持つ。「ID」はレコードに割り当てられた識別子である。「票長」はレコードの長さ(つまり6つのフィールドの長さの和)を示す。
「値」のフィールドには、言語に依存しないリテラルが記憶される。「項類」は、リテラルの種類を示す。図9の例では、数値(numerical)リテラルの項類は"1"と表され、言語に依存せず使われる共通の英数字(alphanumeric)リテラルの項類は"2"と表され、言語依存の文字列リテラルの項類は"3"と表されている。
「長さ」のフィールドには、「値」のフィールドに記憶されたリテラルのバイト長が記憶される。また、i番目のレコードの「オフセット」のフィールドには、1番目から(i−1)番目のレコードの、「長さ」のフィールドの値の和が記憶される(1<i)。1番目のレコードの「オフセット」は0である。
図9には、「ID」、「票長」、「項類」、「長さ」、および「オフセット」のフィールドのバイト長が、それぞれ、6、2、2、2、2バイトである例が示されている。
1番目のレコードの値は"20131226"という8バイトの数値リテラルなので、1番目のレコードの票長、項類、長さは、それぞれ22、1、8である。また、1番目のレコードには"A00001"というIDが割り当てられている。
2番目のレコードの値は"B8-2"という4バイトの英数字リテラルなので、2番目のレコードの票長、項類、長さは、それぞれ18、2、4である。また、2番目のレコードには"A00002"というIDが割り当てられている。2番目のレコードのオフセットは8である。
日本語リテラル一覧610には、ロケールリソースファイル502に記憶されている日本語の文字列リテラルが登録される。日本語リテラル一覧610の各レコードは、「ID」、「票長」、「項類」、「値」という4つのフィールドを持つ。
図9には、「ID」、「票長」、および「項類」のフィールドのバイト長が、それぞれ、6、2、2バイトである例が示されている。日本語リテラル一覧610のどのレコードにおいても、項類は"3"である。
図9の例では、日本語リテラル一覧610の1〜4番目のレコードには、"B00001"、"B00002"、"B00003"、"B00004"というIDが割り当てられている。また、1〜4番目のレコードの値のフィールドには、"富士通太郎"、"基本給"、"職責給"、"勤続年数"という日本語の文字列リテラルがそれぞれ記憶されている。これら4つの文字列リテラルのバイト長は、それぞれ、10、6、6、8バイトである。票長はレコードの長さ(つまり4つのフィールドの長さの和)を示すので、例えば、3番目のレコードの票長は、16(=6+2+2+6)である。
英語リテラル一覧611には、ロケールリソースファイル502に記憶されている英語の文字列リテラルが登録される。英語リテラル一覧611の形式は、日本語リテラル一覧610と同じである。英語リテラル一覧611においても、各レコードの項類は"3"である。
図9の例では、英語リテラル一覧611の1〜4番目のレコードには、"C00001"、"C00002"、"C00003"、"C00004"というIDが割り当てられている。また、1〜4番目のレコードの値のフィールドには、"Fujitsu Taro"、"Base Salary"、"Responsibility Salary"、"Length of Service"という英語の文字列リテラルがそれぞれ記憶されている。これら4つの文字列リテラルのバイト長は、それぞれ、12、11、21、17バイトである。
中国語リテラル一覧612には、ロケールリソースファイル502に記憶されている中国語の文字列リテラルが登録される。中国語リテラル一覧612の形式も、日本語リテラル一覧610と同じである。中国語リテラル一覧612においても、各レコードの項類は"3"である。
図9の例では、中国語リテラル一覧612の1〜4番目のレコードには、"D00001"、"D00002"、"D00003"、"D00004"というIDが割り当てられている。また、1〜4番目のレコードの値のフィールドには、"富士通太郎"、
、
、
という中国語の文字列リテラルがそれぞれ記憶されている。これら4つの文字列リテラルのバイト長は、それぞれ、10、8、8、4バイトである。
ところで、以上例示したとおり、第2実施形態では、各言語の文字列リテラル一覧で使われる各IDは、"B"、"C"、"D"などの言語に応じたプレフィックスと、"00002"などのサフィックスとの組み合わせである。そして、第2実施形態では、互いに対応する意味の複数の文字列リテラルのID同士のサフィックスは、互いに等しい。サフィックスは、ソースファイル501における出現順を示す。
例えば、"B00002"というIDで識別される日本語の文字列リテラルと、"C00002"というIDで識別される英語の文字列リテラルと、"D00002"というIDで識別される中国語の文字列リテラルは、互いに対応する意味を持つ。また、これら3つの文字列リテラルのID同士は、"00002"という共通のサフィックスを含む。"00002"というサフィックスは、ソースファイル501に出現する言語依存の文字列リテラルのうち、2番目の文字列リテラルに対応する。
上記のようなサフィックスが、オフセット一覧613の各レコードを識別するIDとして使われる。IDのほかに、オフセット一覧613の各レコードは、「最大長」と「オフセット」というフィールドも含む。
オフセット一覧613のID(例えば"00002")をサフィックスとして含むID(例えば"B00002"と"D00002"と"D00002")により識別される複数の文字列リテラルのバイト長のうちの最大値が、オフセット一覧613の「最大値」のフィールドに記憶される。「最大値」のフィールドに記憶された値は、図1に関して説明した「算出バイト長」として使われる。
また、オフセット一覧613のi番目のレコードの「オフセット」のフィールドには、1番目から(i−1)番目のレコードの「最大長」のフィールドの値の和が記憶される(1<i)。1番目のレコードのオフセットは0である。
例えば、1番目のレコードのIDは"00001"である。つまり、オフセット一覧613の1番目のレコードは、日本語リテラル一覧610と英語リテラル一覧611と中国語リテラル一覧612のそれぞれにおいて"00001"というサフィックスを含むIDで識別されるレコードと対応づけられている。
"B00001"と"C00001"と"D00001"というIDで識別される3つの言語の3つの文字列リテラルのバイト長は、上記のとおり、それぞれ、10、12、10である。よって、オフセット一覧613の1番目のレコードの「最大長」のフィールドには、12(すなわち、10、12、10という3つの値のうちの最大値)が記憶される。
また、2番目のレコードのIDは"00002"である。2番目のレコードの「最大長」のフィールドには、11(すなわち、6、11、8という3つの値のうちの最大値)が記憶される。2番目のレコードの「オフセット」のフィールドには、1番目のレコードの「最大長」と同じ、12という値が記憶される。
3番目のレコードのIDは"00003"である。3番目のレコードの「最大長」のフィールドには、21(すなわち、6、21、8という3つの値のうちの最大値)が記憶される。3番目のレコードの「オフセット」のフィールドには、1〜2番目のレコードの「最大長」のフィールドの値の和である23(=12+11)という値が記憶される。
4番目のレコードのIDは"00004"である。4番目のレコードの「最大長」のフィールドには、17(すなわち、8、17、4という3つの値のうちの最大値)が記憶される。4番目のレコードの「オフセット」のフィールドには、1〜3番目のレコードの「最大長」のフィールドの値の和である44(=12+11+21)という値が記憶される。
オフセット一覧613の最大長は、図1に関して説明した「算出バイト長」の例である。図1の表記法によれば、図9に示した4つの最大長は、B1=12、B2=11、B3=21、B4=17と表現される。
また、説明の便宜上、オフセット一覧613のi番目のレコードのオフセットをOiと表記することにする。オフセット一覧613は、O1=0、O2=B1=12、O3=B1+B2=23、O4=B1+B2+B3=44であることを示している。
続いて、オブジェクトファイル503に含まれる命令列について説明する。オブジェクトファイル503は、図6に示したように、文字列リテラルが配置されたRO領域を含む。RO領域の後に、命令列を記憶するための領域がある。図10〜11は、第2実施形態で生成される命令列を例示する図である。
なお、実際には、オブジェクトファイル503に含まれる個々の命令は、所定の命令セットに含まれるマシン語命令(machine language instruction)である。しかし、図10〜11では、理解の助けとするために、マシンコードに対応するアセンブリコードが示されている。後述の図15も同様である。
コンパイラ500(より具体的にはオブジェクトコード生成部607)は、まず図10〜11に示すようなアセンブリコードを生成してもよく、その後、生成したアセンブリコードをマシンコードに変換してもよい。実施形態によっては(例えばコンパイラ500に与えられるコマンドオプションによっては)、コンパイラ500は、マシン語で記述されたオブジェクトファイル503の代わりに、アセンブリコードのファイルを生成してもよい。
図10において、".TXT Section"というラベル800は、命令列用の領域の開始を示し、"Prologue"というラベル801は、プロローグの開始を示す。プロローグには、初期化のための命令列が含まれる。
プロローグにおいて、"LocaleJudgment"というラベル802から"EndLocaleJudgment"というラベル823までの部分が、実行時のロケールに応じた値をレジスタに記憶するための処理に対応する。詳細は以下のとおりである。
命令803は、第2オペランドにより指定されるアドレスを、レジスタReg0にロードするためのLEA(Load Effective Address)命令である。図10で便宜上"GetLocaleReturnAddr"と示されている第2オペランドは、具体的には、LCIDを取得するためのAPI関数の返り値が格納される領域を示すアドレスである。
命令804は、LCIDを取得するためのAPI関数を呼び出すサブルーチンコールを示す。API関数の実行後、命令805が実行される。
命令805は、レジスタReg0が保持するアドレス(つまり、図10では便宜上"GetLocaleReturnAddr"と示されているアドレス)に記憶されている値を、レジスタReg1にロードするための命令である。命令805の実行により、実行環境におけるLCIDの値が、レジスタReg1に記憶される。
ところで、図6のロケールリソースファイル502では、"en-us"と"zh-cn"と"ja"というロケール名で識別される3つのロケールで使われる文字列リテラルが定義されている。図10には、これら3つのロケールに対応する3つのラベル806、811、および816が示されている。
図10では、"English"というラベル806に続いて、「実行時のLCIDが0x0409と等しいか否かをチェックし、両者が等しければレジスタReg2に0を設定する」という処理のための命令807〜810が配置されている。0x0409は、"en-us"というロケール名に対応するLCIDである。
命令807は、レジスタReg1の値(つまり実行時のLCID)と0x0409という値を比較するための命令である。次の命令808は、命令807で比較された2つの値が等しくなければ"Chinese"というラベル811にジャンプするための、条件分岐命令(つまり条件付きジャンプ命令)である。
レジスタReg1の値と0x0409という値が等しければ、命令809が実行される。命令809は、レジスタReg2に0という値を設定するための命令である。命令809の次に配置される命令810は、"EndLocaleJudgment"というラベル823にジャンプするための無条件分岐命令(つまり無条件ジャンプ命令)である。
ラベル811から命令815までの部分は、ラベル806から命令810までの部分と類似である。具体的には、"Chinese"というラベル811に続いて、レジスタReg1の値(つまり実行時のLCID)と0x0804(つまり"zh-cn"というロケール名に対応するLCID)を比較するための命令812が配置される。次の命令813は、命令812で比較された2つの値が等しくなければ"Japanese"というラベル816にジャンプするための、条件分岐命令である。
レジスタReg1の値と0x0804という値が等しければ、命令814が実行される。命令814は、レジスタReg2に1という値を設定するための命令である。命令814の次に配置される命令815は、命令810と同じ無条件分岐命令である。
ラベル816から命令820までの部分も、ラベル806から命令810までの部分と類似である。具体的には、"Japanese"というラベル816に続いて、レジスタReg1の値(つまり実行時のLCID)と0x0411(つまり"ja"というロケール名に対応するLCID)を比較するための命令817が配置される。次の命令818は、命令817で比較された2つの値が等しくなければ"Others"というラベル821にジャンプするための、条件分岐命令である。
レジスタReg1の値と0x0411という値が等しければ、命令819が実行される。命令819は、レジスタReg2に2という値を設定するための命令である。命令819の次に配置される命令820は、命令810と同じ無条件分岐命令である。
命令820の次には、実行時のLCIDが0x0409、0x0804、0x0411のいずれとも等しくない場合のデフォルトの動作が指定されている。具体的には、"Others"というラベル821に続いて、レジスタReg2に0という値を設定するための命令822が配置されている。命令822は命令809と同じである。
つまり、命令822によれば、実行時のLCIDが0x0409、0x0804、0x0411のいずれとも等しくない場合、英語の文字列リテラルが使われることになる。以上のごとき命令822をオブジェクトコード生成部607が生成する理由は、英語に使われるラテン・アルファベットはどの環境でも使用可能だからである。つまり、第2実施形態のコンパイラ500は、デフォルト言語を英語にすることに決め、その決定に基づいてオブジェクトコード生成部607が命令を生成する。
命令822の後に"EndLocaleJudgment"というラベル823が配置される。以上の説明から分かるように、ロケールリソースファイル502のヘッダ行のj番目に示されているロケールと実行環境におけるロケールとが等しいとき、レジスタReg2には、(j−1)という値が設定される(1≦j)。また、実行環境におけるロケールが、ロケールリソースファイル502のヘッダ行に示されているどのロケールとも等しくないとき、レジスタReg2には、デフォルト値が設定される。第2実施形態でのデフォルト値は、英語を使うロケール用の値(つまり0)である。
プロローグの後に、手続きの開始を示す"StartProcedure"というラベル824が配置されている。図11には、図6のソースファイル501内の4つのDISPLAYステートメントに対応する命令825〜命令844が例示されている。
命令825は、レジスタReg2に記憶されている値と、Y(すなわち、オフセット一覧613の「最大長」フィールドの値の合計)とを乗算し、乗算の結果をレジスタReg2に記憶するための命令である。次の命令826は、レジスタReg2に記憶されている値と、X(すなわち、言語非依存リテラル一覧609の「長さ」フィールドの値の合計)とを加算し、加算の結果をレジスタReg2に記憶するための命令である。
また、命令827は、オブジェクトファイル503に記憶されているオブジェクトコードの、実行時におけるメモリ上の開始アドレスを、ベースレジスタに設定するためのロード命令である。上記開始アドレスは、図11では"StartAddr"と示されている。
次の命令828は、ベースレジスタに記憶されている値と、オブジェクトコードの先頭からRO領域の先頭までのオフセットとを加算し、加算の結果をベースレジスタに記憶するための命令である。命令825〜828でレジスタReg2とベースレジスタに設定された値は、命令829、833、837、841で使われる。
命令829〜832は、ソースファイル501に書かれた"富士通太郎"という1番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。
図9のオフセット一覧613によれば、1番目の言語依存文字列リテラルに対応するオフセットは0である。よって、オブジェクトコード生成部607は、オフセット一覧613の1番目のレコードの「オフセット」のフィールドから0という値を読み取り、読み取った値を使って、命令829を生成する。
命令829は、ベースレジスタに記憶されている値と、レジスタReg2に記憶されている値と、0との和を、レジスタReg3に設定するための命令である。
ここで、説明の便宜上、命令809、814、819、または822によりレジスタReg2に設定される値(つまり、実行時のロケールに応じた、0、1、または2という値)を「r」と表記する。また、図9に関して説明したとおり、言語依存の文字列リテラルのうち、ソースファイル501内でi番目に出現する文字列リテラルに対応するオフセットOiは、i=1のとき0であり、1<iのとき、(B1+…Bi−1)である。
なお、説明の簡単化のため、「言語依存の文字列リテラルのうち、ソースファイル501内でi番目に出現する文字列リテラル」を、単に「i番目の文字列リテラル」ということがある(後述の第3実施形態に関する説明でも同様)。また、ソースファイル501内でi番目に出現する文字列リテラルが属するリテラル組は、ロケールリソースファイル502で定義されており、当該リテラル組には、複数の言語で書かれた複数の文字列リテラルが属する。これらの複数の文字列リテラルのうち、実行時のロケールに応じた言語の文字列リテラルのことを、単に「実行時のロケールに応じた言語のi番目の文字列リテラル」ということがある(後述の第3実施形態に関する説明でも同様)。
したがって、図6、9、10、および11から分かるように、実行時のロケールに応じた言語のi番目の文字列リテラルの開始アドレスAiは、式(1)のように表現される。なお、「実行時のロケールに応じた言語」とは、実行環境におけるLCIDが0x0409であれば英語、0x0804であれば中国語、0x0411であれば日本語、その他の値であればデフォルト言語(すなわち英語)である。
Ai = StartAddr + Offset + X + r・Y + Oi (1)
命令829は、実行時のロケールに応じた言語の1番目の文字列リテラルの開始アドレスA1を算出し、開始アドレスA1をレジスタReg3に設定するための命令の例である。つまり、命令829の実行結果に基づいて、開始アドレスA1が参照される。
以下では説明の便宜上、画面に文字列リテラルを表示するためのサブルーチンが、具体的には次のようなサブルーチンであるものとする。
・表示対象の文字列リテラルの開始アドレスと長さを示す2つの引数をとる。
・第1の所定のレジスタ(以下「レジスタDispReg1」という)に設定された値を、第1引数(すなわち文字列リテラルの開始アドレスを示す引数)としてとる。
・第2の所定のレジスタ(以下「レジスタDispReg2」という)に設定された値を、第2引数(すなわち文字列リテラルの長さを示す引数)としてとる。
したがって、命令830は、具体的には、レジスタReg3に記憶されている値をレジスタDispReg1にコピーするための命令であり、命令831は、12というバイト長をレジスタDispReg2にコピーするための命令である。オブジェクトコード生成部607は、オフセット一覧613の1番目のレコードの「最大長」のフィールドから、12という値を読み取り、読み取った値を使って、命令831を生成する。命令832は、上記サブルーチンを呼び出すための命令である。
命令833〜836は、ソースファイル501に書かれた"基本給"という2番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。例えば、命令833は、実行時のロケールに応じた言語の2番目の文字列リテラルの開始アドレスA2をレジスタReg3に設定するための命令であり、命令833の実行結果に基づいて、開始アドレスA2が参照される。
命令833〜836は、命令829〜832と類似である。命令829〜832との違いは、命令833と835のオペランドのみである。
具体的には、オフセット一覧613の2番目のレコードの「オフセット」と「最大長」のフィールドの値がそれぞれ12と11なので、命令833のオペランドには12という値が含まれ、命令835のオペランドとして11という値が指定されている。つまり、オブジェクトコード生成部607は、オフセット一覧613の2番目のレコードに基づいて、命令833と835を生成する。
命令837〜840は、ソースファイル501に書かれた"職責給"という3番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。例えば、命令837は、実行時のロケールに応じた言語の3番目の文字列リテラルの開始アドレスA3をレジスタReg3に設定するための命令であり、命令837の実行結果に基づいて、開始アドレスA3が参照される。
命令837〜840も、命令829〜832と類似である。命令829〜832との違いは、命令837と839のオペランドのみである。
具体的には、オフセット一覧613の3番目のレコードの「オフセット」と「最大長」のフィールドの値がそれぞれ23と21なので、命令837のオペランドには23という値が含まれ、命令839のオペランドとして21という値が指定されている。つまり、オブジェクトコード生成部607は、オフセット一覧613の3番目のレコードに基づいて、命令837と839を生成する。
命令841〜844は、ソースファイル501に書かれた"勤続年数"という4番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。例えば、命令841は、実行時のロケールに応じた言語の4番目の文字列リテラルの開始アドレスA4をレジスタReg3に設定するための命令であり、命令841の実行結果に基づいて、開始アドレスA4が参照される。
命令841〜844も、命令829〜832と類似である。命令829〜832との違いは、命令841と843のオペランドのみである。
具体的には、オフセット一覧613の4番目のレコードの「オフセット」と「最大長」のフィールドの値がそれぞれ44と17なので、命令841のオペランドには44という値が含まれ、命令843のオペランドとして17という値が指定されている。つまり、オブジェクトコード生成部607は、オフセット一覧613の4番目のレコードに基づいて、命令841と843を生成する。
図10〜11から分かるように、第2実施形態によれば、コンパイル時にオブジェクトコード生成部607が、命令829、833、837、841のオペランド(つまり、実行時のロケールに依存する文字列リテラルの開始アドレス)を確定することが可能である。つまり、第3比較例のような「オペランドがコンパイル時には確定不能であるために、コンパイル処理が失敗する」という問題は、第2実施形態では起きない。
第2実施形態において問題が回避される理由について補足すると、以下のとおりである。第2実施形態では、1つのリテラル組に属する複数の文字列リテラルに、同じバイト長(すなわちオフセット一覧613の「最大長」フィールドの値)が割り当てられる。その結果、実行時のロケールに応じた文字列リテラルの開始アドレスを、実行時のロケールによらない共通の値(例えば命令833では12という値)をオフセットとして使って計算することが可能となる。この共通の値はコンパイル時に確定されるので、第2実施形態では、第3比較例のような問題は回避される。
さて、図12は、第2実施形態のコンパイラ500がリテラル一覧を作成する処理のフローチャートである。図12の処理は、字句解析部601による字句解析と構文解析部602による構文解析が終わった後で、意味解析部603により実行される。例えば、図6のようなソースファイル501とロケールリソースファイル502が入力として与えられると、意味解析部603は、図12の処理を実行することにより、図9の5つの一覧を生成する。
ステップS101で手続き解析部604は、最後のステートメントまで解析が済んだか否かを判断する。例えば、手続き解析部604は、構文木を後順(post-order)にトラバースしてもよい。構文木全体のトラバースが完了していれば、最後のステートメントまで解析が済んでいる。
最後のステートメントまで解析が済んでいれば、図12の処理も完了する。逆に、未解析のステートメントが残っていれば、図12の処理はステップS102に移行する。
そして、ステップS102で手続き解析部604は、次のステートメント(具体的には、例えば、次のステートメントに対応する部分木(subtree)のデータ)を読み込む。
なお、ソースコード内ではステートメントが入れ子になっている(nested)場合もあり得る。「次のステートメント」の「次」とは、手続き解析部604が構文木をトラバースする順序において「次」を意味する。
ステップS103で手続き解析部604は、ステップS102で読み込んだステートメントの中に文字列リテラルがあるか否かを判断する。ステップS102で読み込んだステートメントの中に文字列リテラルがなければ、図12の処理はステップS101に戻る。
逆に、ステップS102で読み込まれたテートメントの中に文字列リテラルがあれば、ステップS104〜S111の処理をリテラル登録部605が行う。以下では説明の便宜上、ステップS102で読み込まれたテートメントの中の文字列リテラルを「現在の文字列リテラル」という。
具体的には、ステップS104で、リテラル登録部605は、現在の文字列リテラルが言語依存の文字列リテラルか否かを判断する。ステップS104における判断の具体的手法は、実施形態によって異なっていてよい。
例えば、図6の例では、コンパイラ500はCOBOLのコンパイラである。そして、図6のソースファイル501に例示したとおり、COBOLでは、文字列リテラルの前に"N"というトークンを記述することで、その文字列リテラルが言語依存の文字列リテラル(つまり国別文字定数(national literal))であることを示せる。したがって、このようなプログラミング言語の仕様に基づいて(具体的には、"N"というトークンがあるか否かに応じて)、リテラル登録部605がステップS104の判断を行ってもよい。
あるいは、リテラル登録部605は、ロケールリソースファイル502を参照することでステップS104の判断を行ってもよい。
例えば、現在の文字列リテラルが図6のソースファイル501中の"G8-2"という文字列リテラルであるとする。この場合、リテラル登録部605は、ロケールリソースファイル502の日本語の列において、"G8-2"という文字列リテラルを検索する。検索の結果、"G8-2"という文字列リテラルは見つからないので、リテラル登録部605は、「"G8-2"という文字列リテラルは言語非依存の文字列リテラルである」と判断する。
別の例として、現在の文字列リテラルが図6のソースファイル501中の"基本給"という文字列リテラルであるとする。この場合、リテラル登録部605は、ロケールリソースファイル502の日本語の列において、"基本給"という文字列リテラルを検索する。検索の結果、"基本給"という文字列リテラルが見つかるので、リテラル登録部605は、「"基本給"という文字列リテラルは言語依存の文字列リテラルである」と判断する。
なお、リテラル登録部605は、ロケールリソースファイル502内のどの言語の列を検索するかを、実施形態に応じた適宜の方法により、適切に決めることができる。
例えば、コンパイラ500に対するコマンドオプションとして、ロケール名が指定されてもよい。この場合、リテラル登録部605は、ロケールリソースファイル502内の、指定されたロケール名に対応する列(例えば、"ja"が指定された場合は日本語の列)を検索する。
別の例として、コンパイラ500は、OSの提供するAPIを介して、ソースファイル501が開発された環境におけるロケールの名前を取得してもよい。この場合、リテラル登録部605は、ロケールリソースファイル502内の、取得されたロケール名に対応する列(例えば、"ja"が取得された場合は日本語の列)を検索する。
さらに別の例として、コンパイラ500(より具体的には例えば字句解析部601)は、ソースファイル501を解析することで、ソースファイル501で使われている文字符号化方式(character encoding scheme;CES)を判断してもよい。なお、ファイルの文字符号化方式を判断するための公知の解析手法が使われてもよい。また、コンパイラ500は、ロケール名と文字符号化方式との対応表を有していてもよい。この場合、コンパイラ500は、解析により認識した文字符号化方式に対応するロケール名を、対応表に基づいて認識することができる。
例えば、ソースファイル501に使われている文字符号化方式が、シフトJISであるとする。シフトJISは日本語用の文字符号化方式であるため、対応表では、シフトJISと"ja"というロケール名が対応づけられる。よって、この場合、コンパイラ500が対応表に基づいて認識した"ja"というロケール名にしたがって、リテラル登録部605は、ロケールリソースファイル502内の日本語の列を検索する。
以上のように、ステップS104の判断の具体的方法には様々なものがある。しかし、いずれにしろリテラル登録部605は、ステップS104で、現在の文字列リテラルが言語依存の文字列リテラルか否かを判断する。
現在の文字列リテラルが言語非依存の文字列リテラルである場合、次に、リテラル登録部605は、ステップS105において、言語非依存リテラル一覧609に現在の文字列リテラルを登録する。例えば、現在の文字列リテラルが"G8-2"という文字列リテラルである場合、図9の言語非依存リテラル一覧609の2番目のレコードが、リテラル登録部605によって新たに作成および追加される。ステップS105の後、図12の処理はステップS101に戻る。
逆に、現在の文字列リテラルが言語依存の文字列リテラルである場合、ステップS106〜S111が実行される。
ステップS106でリテラル登録部605は、オフセット一覧613に新たなレコードを追加する。リテラル登録部605は、追加したレコードに新たなIDを割り当て、追加したレコードの最大長のフィールドを0に初期化する。なお、オフセットのフィールドには、後述の図13の処理において適宜の値が設定される。例えば、現在の文字列リテラルが"富士通太郎"という文字列リテラルである場合、オフセット一覧613には、1番目のレコードが追加される。
次に、ステップS107でリテラル登録部605は、ロケールリソースファイル502に文字列リテラルが記憶されている言語のうち、現在の文字列リテラルに関して未選択の言語が残っているか否かを判断する。
例えば、図6の例では、「ロケールリソースファイル502に文字列リテラルが記憶されている言語」とは、具体的には、英語と中国語と日本語という3つの言語である。よって、リテラル登録部605は、英語と中国語と日本語のうち、現在の文字列リテラルに関して未選択の言語が残っているか否かを判断する。
未選択の言語が残っていなければ(つまり、すべての言語を選択済みであれば)、図12の処理はステップS101に戻る。逆に、未選択の言語が残っていれば、図12の処理はステップS108に移行する。
ステップS108でリテラル登録部605は、ロケールリソースファイル502に文字列リテラルが記憶されている言語のうち、未選択の言語を一つ選択する。そして、リテラル登録部605は、現在の文字列リテラルに対応する意味を有しており、かつ、選択した言語で書かれている文字列リテラルを、ロケールリソースファイル502から読み取る。
例えば、現在の文字列リテラルが、ソースファイル501中の"勤続年数"であるものとする。この場合、もしステップS108で英語が選択されると、リテラル登録部605は、"勤続年数"に対応する英語の文字列リテラルである"Length of Service"をロケールリソースファイル502から読み取る。つまり、リテラル登録部605は、現在の文字列リテラルと同じレコードの英語のフィールドから、"Length of Service"という文字列リテラルを読み取る。
別の例として、もしステップS108で日本語が選択されると、リテラル登録部605は、実際には、ロケールリソースファイル502の参照を省略してもよい。なぜなら、現在の文字列リテラルである"勤続年数"そのものが、選択された言語で書かれた文字列だからである。つまり、リテラル登録部605は、ステップS103で見つかった現在の文字列リテラルを、「ステップS108でロケールリソースファイル502から読み取った文字列リテラル」と見なしてもよい。
そして、ステップS109でリテラル登録部605は、ステップS108で読み取った文字列リテラルのバイト長が、ステップS106で追加したレコードの最大長のフィールドが示すバイト長より長いか否かを判断する。読み取った文字列リテラルのバイト長が、最大長のフィールドが示すバイト長より長ければ、図12の処理はステップS110に移行し、そうでなければ、図12の処理はステップS111に移行する。
ステップS110でリテラル登録部605は、ステップS108で読み取った文字列リテラルのバイト長を、ステップS106で追加したレコードの最大長のフィールドに書き込む。それにより、リテラル登録部605は最大長を適宜更新する。ステップS110での更新の後、図12の処理はステップS111へ移行する。
ステップS111でリテラル登録部605は、ステップS108で選択した言語のリテラル一覧に、ステップS108で読み取った文字列リテラルを登録する(詳細は後述する)。ステップS111での登録の後、図12の処理はステップS107に戻る。ステップS107〜S111のループにより、現在の文字列リテラルに対応する意味を持つ各言語の文字列リテラルが、各言語のリテラル一覧に登録される。
例えば、ステップS103で見つかった現在の文字列リテラルが、"勤続年数"であるものとする。この場合、ステップS106では、図9のオフセット一覧613の4番目のレコードが追加される。リテラル登録部605は、追加したレコードのために新たに"00004"というIDを発行し、発行した"00004"というIDを、追加したレコードに割り当て、「最大長」のフィールドを0に初期化する。
また、説明の便宜上、例えば、日本語、英語、中国語、という順でリテラル登録部605が言語を選択するものとする。リテラル登録部605が言語を選択する順序は任意である。
上記のような選択順の場合、"勤続年数"という現在の文字列リテラルに関するステップS108の1回目の実行において、日本語が選ばれる。よって、現在の文字列リテラルに関するS108の1回目の実行において、"勤続年数"という日本語の文字列リテラルが得られる。
"勤続年数"という日本語の文字列リテラルのバイト長は8であり、8は0より大きい。よって、ステップS110でオフセット一覧613の4番目のレコードの「最大長」のフィールドが、8に更新される。
そして、ステップS111では、日本語リテラル一覧610に、"勤続年数"という文字列リテラルが登録される。具体的には、図9の日本語リテラル一覧610の4番目のレコードが新たに追加される。なお、リテラル登録部605は、ステップS106で発行した"00004"というIDをサフィックスとして含む"B00004"というIDを新たなレコードに割り当て、"勤続年数"という文字列リテラルのバイト長に基づいて票長を計算する。その結果、図9のようなレコードが追加される。
続いて、現在の文字列リテラルに関するステップS108の2回目の実行において、英語が選ばれる。よって、現在の文字列リテラルに関するステップS108の2回目の実行において、"Length of Service"という英語の文字列リテラルが得られる。
"Length of Service"という英語の文字列リテラルのバイト長は17であり、17は8より大きい。よって、ステップS110でオフセット一覧613の4番目のレコードの「最大長」のフィールドが、17に更新される。
そして、ステップS111では、英語リテラル一覧611に、"Length of Service"という文字列リテラルが登録される。具体的には、図9の英語リテラル一覧611の4番目のレコードが新たに追加される。なお、リテラル登録部605は、ステップS106で発行した"00004"というIDをサフィックスとして含む"C00004"というIDを新たなレコードに割り当て、"Length of Service"という文字列リテラルのバイト長に基づいて票長を計算する。その結果、図9のようなレコードが追加される。
続いて、現在の文字列リテラルに関するステップS108の3回目の実行において、中国語が選ばれる。よって、現在の文字列リテラルに関するステップS108の3回目の実行において、
という中国語の文字列リテラルが得られる。
という中国語の文字列リテラルのバイト長は4であり、4は17より大きくない。よって、ステップS110はスキップされる。
そして、ステップS111では、中国語リテラル一覧612に、
という文字列リテラルが登録される。具体的には、図9の中国語リテラル一覧612の4番目のレコードが新たに追加される。なお、リテラル登録部605は、ステップS106で発行した"00004"というIDをサフィックスとして含む"D00004"というIDを新たなレコードに割り当て、
という文字列リテラルのバイト長に基づいて票長を計算する。その結果、図9のようなレコードが追加される。
そして、現在の文字列リテラルに関するステップS107の4回目の実行において、リテラル登録部605は、「未選択の言語はない」と判断する。その結果、図12の処理は、ステップS101に戻る。
なお、説明の簡単化のため、図12には、1つのステートメントに含まれる文字列リテラルの数が最大でも1つの場合のフローチャートを例示した。1つのステートメントに2つ以上の文字列リテラルが含まれる場合には、ステップS102で読み込まれたステートメントに含まれる各文字列リテラルについて、ステップS104の判断が行われる。そして、各文字列リテラルについて、ステップS104での判断結果に応じて、ステップS105が実行されるか、または、ステップS106〜S111が実行される。
さて、以上説明したような図12の処理が完了した後、割り付け部606がレジスタの割り付けや、個々の領域のバイト数の計算などの適宜の処理を行う。その後、オブジェクトコード生成部607がオブジェクトコードを生成する。
図13の処理は、オブジェクトコードを生成するためにオブジェクトコード生成部607が行う一連の処理のうちの一つである。具体的には、図13は、第2実施形態のコンパイラ500がRO領域を作成する処理のフローチャートである。より詳しくは、図13は、オブジェクトコード生成部607のうちのリテラル配置部608が、RO領域のうちで言語依存の文字列リテラルを記憶する領域を作成する処理のフローチャートである。
ステップS201でリテラル配置部608は、オフセット一覧613に記憶されている最大長を用いてオフセットを計算する。具体的には、リテラル配置部608は、オフセット一覧613の1番目のレコードの「オフセット」のフィールドを0に設定する。また、リテラル配置部608は、1<iなる各iについて、オフセット一覧613の(i−1)番目のレコードの「最大長」と「オフセット」のフィールドの値の和を計算し、計算した和を、i番目のレコードの「オフセット」のフィールドに設定する。その結果、図9のように、オフセット一覧613の各レコードの「オフセット」のフィールドには、値が設定される。
次に、ステップS202でリテラル配置部608は、ロケールリソースファイル502に文字列リテラルが記憶されている言語のうち、文字列リテラルの配置が済んでいない言語(つまり未選択の言語)が残っているか否かを判断する。なお、言語の選択順は固定されている。例えば、ロケールリソースファイル502での列同士の間の順にしたがって、リテラル配置部608は言語を選択する。
例えば、図6の例では、「ロケールリソースファイル502に文字列リテラルが記憶されている言語」とは、具体的には、英語と中国語と日本語という3つの言語である。よって、リテラル配置部608は、英語と中国語と日本語のうち、未選択の言語が残っているか否かを判断する。
未選択の言語が残っていなければ(つまり、すべての言語について文字列リテラルの配置が済んでいれば)、図13の処理は完了する。逆に、未選択の言語が残っていれば、図13の処理はステップS203に移行する。
ステップS203でリテラル配置部608は、ロケールリソースファイル502に文字列リテラルが記憶されている言語のうち、未選択の言語を一つ選択する。そして、リテラル配置部608は、選択した言語のリテラル一覧を参照する。例えば、リテラル配置部608は、日本語を選択する場合は、日本語リテラル一覧610を参照する。
次に、ステップS204でリテラル配置部608は、ステップS203で選択した言語のリテラル一覧(例えば日本語リテラル一覧610)に、未選択のレコードが残っているか否かを判断する。
未選択のレコードが残っている場合、リテラル配置部608は、ステップS205で次のレコード(つまり、未選択のレコードのうちで、IDにより示される順序が最も早いレコード)を読み込む。逆に、すべてのレコードが選択済みの場合、図13の処理はステップS202に戻る。
ステップS205の次に、ステップS206でリテラル配置部608は、以下の2つの値を比較する。
・ステップS205で読み込んだレコードの「値」のフィールドに記憶されている文字列リテラルの実長(つまり実際のバイト長)。
・ステップS205で読み込んだレコードのIDのサフィックスがIDとして割り当てられている、オフセット一覧613内のレコードの、「最大長」のフィールドの値。
例えば、ステップS205でリテラル配置部608が日本語リテラル一覧610の2番目のレコードを読み込んだとする。この場合、「値」のフィールドに記憶されている"基本給"という日本語の文字列リテラルの実長は6バイトである。また、日本語リテラル一覧610の2番目のレコードのIDは"B00002"であり、そのサフィックスは"00002"である。よって、リテラル配置部608はオフセット一覧613において"00002"というIDを有するレコードを参照し、このレコードの「最大長」のフィールドから、11バイトという最大長を読み取る。
そして、実長が最大長未満の場合、リテラル配置部608は、ステップS207で、ステップS205で読み込んだレコードの文字列リテラルを空白文字(space character)でパディングする。それにより、リテラル配置部608は、空白文字でパディングされた文字列リテラルのバイト長を、ステップS206で参照した最大長に一致させる。
例えば、ステップS205で日本語リテラル一覧610の2番目のレコードが読み込まれたとする。この場合、上記のとおり実長は6バイトであり、最大長は11バイトである。よって、リテラル配置部608は、"基本給"という日本語の文字列リテラルの後ろに5つの空白文字を追加(append)する。それにより、"基本給 "という、5つの空白文字でパディングされた11バイトの文字列リテラルが得られる。
逆に、ステップS206において実長が最大長未満ではなかった場合(つまり、実長と最大長が等しい場合)、ステップS207はスキップされる。例えば、ステップS203で英語が選択され、ステップS206で英語リテラル一覧611の2番目のレコードが読み込まれた場合、実長は11バイトであり、最大長も11バイトである。よって、この場合、ステップS207はスキップされる。
その後、ステップS208でリテラル配置部608は、文字列リテラルをオブジェクトコードのRO領域に出力する。具体的には、リテラル配置部608は、ステップS207を実行した場合は、ステップS207で得られた文字列リテラル(例えば、"基本給 "という、5つの空白文字でパディングされた文字列リテラル)を出力する。逆に、ステップS207をスキップした場合は、リテラル配置部608は、ステップS205で読み込んだレコードの「値」のフィールドに記憶されていた文字列リテラル自体(例えば、"Base Salary"という文字列リテラル)を出力する。
なお、リテラル配置部608は、図13の処理を実行する前に、言語非依存リテラル一覧609に基づいて、RO領域の0〜(X−1)バイト目に言語非依存の文字列リテラルを出力(つまり配置)する。そして、リテラル配置部608は、文字列リテラルを出力するアドレス(以下「出力アドレス」という)の初期値を、図13の処理を開始するときに設定する。出力アドレスの初期値は、具体的には、RO領域のうちの言語依存の文字列リテラル用の領域の開始アドレス(すなわちRO領域のXバイト目)である。
ステップS208でリテラル配置部608は、具体的には、出力アドレスに文字列リテラルを出力(つまり配置)する。そして、リテラル配置部608は、現在の出力アドレスに、ステップS206で参照した最大長を足し、加算結果を新たな出力アドレスとして設定する。
ステップS208の実行後、図13の処理はステップS204に戻る。その結果、図6に例示されているように、オブジェクトファイル503のRO領域においては、複数の言語で互いに対応する意味を持つ文字列リテラルに、同じバイト数が割り当てられることになる。例えば、ソースファイル501にi番目に出現する文字列リテラルに対応する3個の文字列リテラルのうち、j番目の言語の文字列リテラル(1≦j≦3)は、RO領域の(X+(j−1)・Y+Oi)バイト目から(X+(j−1)・Y+Oi+Bi−1)バイト目までの範囲内に配置される。
なお、リテラル配置部608が図13の処理を完了した後、オブジェクトコード生成部607は、図10〜11に例示したような命令列(より具体的には、図10〜11のアセンブリコードに対応するマシンコード)を生成し、生成した命令列をオブジェクトコードに含める。以上のようにして、オブジェクトコード生成部607は、文字列リテラルと命令列とを含むオブジェクトコードを生成し、生成したオブジェクトコードをオブジェクトファイル503として出力する。
続いて、図14〜15を参照して、第3実施形態について説明する。なお、第2実施形態との共通点についての説明は、適宜省略する。
第3実施形態では、オブジェクトコード内の言語依存の文字列リテラルの並び順が第2実施形態と異なる。また、言語依存の文字列リテラルの並び順の違いに応じて、第3実施形態では、第2実施形態とは異なる命令列が生成される。したがって、第3実施形態では、図7のコンパイラ500のうち、オブジェクトコード生成部607の動作が第2実施形態とは異なる。
図14は、第3実施形態で生成されるオブジェクトファイル900のRO領域中で、言語依存の文字列リテラルが配置される部分(以下、この部分を「領域901」という)を例示する図である。図14では、RO領域のうち、言語非依存の文字列リテラルを記憶するための領域(つまり、RO領域の0〜(X−1)バイト目)は、省略されている。言語非依存の文字列リテラルを記憶するための領域は、第2実施形態(図6を参照)と同様である。つまり、図14には、RO領域のXバイト目以降が例示されている。
説明の便宜上、第3実施形態でも、図6のソースファイル501とロケールリソースファイル502が使われるものとする。第3実施形態でも、ロケールリソースファイル502で互いに対応づけられている文字列リテラルには、同じバイト長が割り当てられる。
例えば、ロケールリソースファイル502の1番目のレコードにおいて互いに対応づけられている3つの文字列リテラルのいずれにも、12バイトが割り当てられる。なぜなら、これら3つの文字列リテラルのバイト長のうちの最大値が12バイトだからである。
同様に、ロケールリソースファイル502の2番目のレコードにおいて互いに対応づけられている3つの文字列リテラルのいずれにも、11バイトが割り当てられる。また、3番目のレコードにおいて互いに対応づけられている3つの文字列リテラルのいずれにも、21バイトが割り当てられ、4番目のレコードにおいて互いに対応づけられている3つの文字列リテラルのいずれにも、17バイトが割り当てられる。
具体的には、領域901内には、以下のように文字列リテラルが配置される。なお、領域901の開始アドレスは、上記のとおり、RO領域のXバイト目である。
・ 0〜 11バイト目:"Fujitsu Taro"(英語。パディングなし。)
・ 12〜 23バイト目:"富士通太郎"(中国語。22〜23バイト目はパディングされたバイトである。)
・ 24〜 35バイト目:"富士通太郎"(日本語。34〜35バイト目はパディングされたバイトである。)
・ 36〜 46バイト目:"Base Salary"(英語。パディングなし。)
・47〜 57バイト目:
(中国語。55〜57バイト目はパディングされたバイトである。)
・ 58〜 68バイト目:"基本給"(日本語。64〜68バイト目はパディングされたバイトである。)
・ 69〜 89バイト目:"Responsibility Salary"(英語。パディングなし。)
・90〜110バイト目:
(中国語。98〜110バイト目はパディングされたバイトである。)
・111〜131バイト目:"職責給"(日本語。117〜131バイト目はパディングされたバイトである。)
・132〜148バイト目:"Length of Service"(英語。パディングなし。)
・149〜165バイト目:
(中国語。153〜165バイト目はパディングされたバイトである。)
・166〜182バイト目:"勤続年数"(日本語。174〜182バイト目はパディングされたバイトである。)
第3実施形態のコンパイラ500は、図12の処理と図13のステップS201を第2実施形態と同様に実行する。しかし、以上の説明から明らかなように、図12の処理と図13のステップS201の実行後、第3実施形態のリテラル配置部608は、ステップS202〜S208とは異なる手順で、言語依存の文字列リテラルを領域901へ出力してゆく。
具体的には、リテラル配置部608は、オフセット一覧613のレコードをIDの順に選択する。この選択順は、ソースファイル501内での言語依存の文字列リテラルが出現する順序と同じである。そして、リテラル配置部608は、「オフセット一覧613から選択した現在のレコードに関して、未選択の言語が残っているか否か」を判断する。
未選択の言語があれば、リテラル配置部608は言語を選択する。言語の選択順は固定されている。例えば、ロケールリソースファイル502での列同士の間の順にしたがって、リテラル配置部608は、英語、中国語、日本語の順に、言語を選択する。
さらに、リテラル配置部608は、選択した言語のリテラル一覧を参照し、オフセット一覧613で選択したレコードのID(例えば"00001")をサフィックスとして含むID(例えば"B00003")が割り当てられているレコードの「値」のフィールドを読み込む。つまり、リテラル配置部608は、選択した言語の文字列リテラルを読み込む。
そして、リテラル配置部608は、ステップS206と同様に実長と最大長を比較する。実長が最大長未満ならば、リテラル配置部608は、ステップS207と同様に文字列リテラルを空白文字でパディングする。その後、リテラル配置部608は、文字列リテラルを出力アドレスに出力する。文字列リテラルの出力はステップS208と同様であり、出力アドレスの初期化および更新も、第2実施形態と同様である。
ただし、文字列リテラルの出力後、第3実施形態のリテラル配置部608は、次に、「オフセット一覧613から選択した現在のレコードに関して、未選択の言語が残っているか否か」を再び判断する。すべての言語が選択済みであれば、リテラル配置部608は、オフセット一覧613の次のレコードを選択する。
以上のような手順により、第3実施形態のリテラル配置部608は、言語依存の複数の文字列リテラルを、リテラル組ごとに、領域901に配置する。
さて、図15は、第3実施形態でオブジェクトコード生成部607により生成される命令列を例示する図である。オブジェクトファイル900のRO領域の後ろには、図15に例示するような命令列用の領域が配置される。
図15の"LocaleJudgment"というラベル902は、図10のラベル802と同様である。図15では省略されているが、ラベル902の前には、ラベル800や801と同様のラベルがある。また、図15では省略されているが、図10の命令803からラベル823までの部分と同様の命令列が、ラベル902の後に続く。したがって、命令903が実行される時点では、レジスタReg2には、実行環境のロケールに応じて0、1、または2という値が記憶されている。
命令903および904は、図11の命令827および828と同じである。なお、図11では、命令827の前に命令825と826があるが、第3実施形態では命令825と826は生成されない。
命令905〜910は、ソースファイル501に書かれた"富士通太郎"という1番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。
命令905は、レジスタReg2に記憶されている値をレジスタReg3に設定する(つまりコピーする)ための命令である。命令906は、レジスタReg3に記憶されている値と12を乗算し、乗算の結果をレジスタReg3に記憶するための命令である。オブジェクトコード生成部607は、オフセット一覧613の1番目のレコードの「最大長」のフィールドから12という値を読み出し、読み出した12という値を使って、命令906を生成する。
命令907は、ベースレジスタに記憶されている値と、レジスタReg3に記憶されている値と、Xと、0との和を、レジスタReg4に設定するための命令である。なお、Xは、第2実施形態と同様に、言語非依存文字列リテラル用の領域のバイト長である。
オブジェクトコード生成部607は、オフセット一覧613の1番目のレコードの「オフセット」のフィールドから0という値を読み出し、0と3(つまり、ロケールリソースファイル502で文字列リテラルが定義されている言語の数)とを乗じる。乗算の結果として、0という値が得られる。そして、オブジェクトコード生成部607は、以上のようにして得た0という値を使って、命令907を生成する。
ここで、式(1)に関して説明したとおり、命令809、814、819、または822によりレジスタReg2に設定される値(つまり、実行時のロケールに応じた、0、1、または2という値)をrと表記する。なお、上記のとおり、図15では省略されているが、第3実施形態でも、図10の命令803からラベル823までの部分と同様の命令列が、オブジェクトコード生成部607により生成されることに注意されたい。
また、言語依存の文字列リテラルのうち、ソースファイル501内でi番目に出現する文字列リテラルに対応してオフセット一覧613に記憶されているオフセットOiは、i=1のとき0であり、1<iのとき、(B1+…Bi−1)である。
したがって、図9、10、14、および15から分かるように、実行時のロケールに応じた言語のi番目の文字列リテラルの開始アドレスAiは、第3実施形態では、式(1)ではなく、式(2)のように表現される。
Ai = StartAddr + Offset + X + 3・Oi + r・Bi (2)
命令907は、実行時のロケールに応じた言語の1番目の文字列リテラルの開始アドレスA1を算出し、開始アドレスA1をレジスタReg4に設定するための命令の例である。つまり、命令907の実行結果に基づいて、開始アドレスA1が参照される。
なお、式(2)の右辺は、5つの値の加算を表している。このうち1〜2番目の値の和(StartAddr+Offset)は、命令903〜904の実行の結果として、ベースレジスタに設定される。また、5番目の値(r・Bi)は、命令905〜906の実行の結果として、レジスタReg3に設定される。そのため、開始アドレスA1は、命令907の第2オペランドのように表現される。
なお、第2実施形態の図11の例ではレジスタReg3に開始アドレスが設定されるのに対し、第3実施形態の図15の例では、上記のとおり、レジスタReg4に開始アドレスが設定される。そのため、命令908の第2オペランドとして、レジスタReg4が指定されている。しかし、それ以外の点では、命令908は図11の命令830と同じである。また、命令908に続く命令909および910は、図11の命令831および832と同じである。以上のとおり、オブジェクトコード生成部607は、オフセット一覧613の1番目のレコードに基づいて、命令906、907、909のオペランドを決め、命令906、907、909を生成する。
命令911〜916は、ソースファイル501に書かれた"基本給"という2番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。例えば、命令913は、実行時のロケールに応じた言語の2番目の文字列リテラルの開始アドレスA2をレジスタReg4に設定するための命令であり、命令913の実行結果に基づいて、開始アドレスA2が参照される。
命令911〜916は、命令905〜910と類似である。命令905〜910との違いは、命令912、913、および915のオペランドのみである。
具体的には、オフセット一覧613の2番目のレコードの「最大長」のフィールドの値が11なので、命令912と915それぞれの第2オペランドとして、11という値が指定されている。また、オフセット一覧613の2番目のレコードの「オフセット」フィールドの値が12であり、12と3の積は36なので、命令913のオペランドには、36という値が含まれる。つまり、オブジェクトコード生成部607は、オフセット一覧613の2番目のレコードに基づいて、命令912、913、および915を生成する。
命令917〜922は、ソースファイル501に書かれた"職責給"という3番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。例えば、命令919は、実行時のロケールに応じた言語の3番目の文字列リテラルの開始アドレスA3をレジスタReg4に設定するための命令であり、命令919の実行結果に基づいて、開始アドレスA3が参照される。
命令917〜922も、命令905〜910と類似である。命令905〜910との違いは、命令918、919、および921のオペランドのみである。
具体的には、オフセット一覧613の3番目のレコードの「最大長」のフィールドの値が21なので、命令918と921それぞれの第2オペランドとして、21という値が指定されている。また、オフセット一覧613の3番目のレコードの「オフセット」フィールドの値が23であり、23と3の積は69なので、命令919のオペランドには、69という値が含まれる。つまり、オブジェクトコード生成部607は、オフセット一覧613の3番目のレコードに基づいて、命令918、919、および921を生成する。
命令923〜928は、ソースファイル501に書かれた"勤続年数"という4番目の言語依存文字列リテラルに対応する、実行時のロケールに応じた文字列リテラルを、表示するための命令である。例えば、命令925は、実行時のロケールに応じた言語の4番目の文字列リテラルの開始アドレスA4をレジスタReg4に設定するための命令であり、命令925の実行結果に基づいて、開始アドレスA4が参照される。
命令923〜928も、命令905〜910と類似である。命令905〜910との違いは、命令924、925、および927のオペランドのみである。
具体的には、オフセット一覧613の4番目のレコードの「最大長」のフィールドの値が17なので、命令924と927それぞれの第2オペランドとして、17という値が指定されている。また、オフセット一覧613の4番目のレコードの「オフセット」フィールドの値が44であり、44と3の積は132なので、命令925のオペランドには、132という値が含まれる。つまり、オブジェクトコード生成部607は、オフセット一覧613の4番目のレコードに基づいて、命令924、925、および927を生成する。
図15から分かるように、第3実施形態によれば、コンパイル時にオブジェクトコード生成部607が、命令907、913、919、925のオペランドを確定することが可能である。なぜなら、第1に、例えば命令913における(X+36)というオフセットのように、実行時のロケールによらない共通のオフセットがコンパイル時に確定するからである。そして、第2に、この共通のオフセットを使って、実行時のロケールに応じた文字列リテラルの開始アドレスを表すことが可能だからである。つまり、第3比較例のような「オペランドがコンパイル時には確定不能であるために、コンパイル処理が失敗する」という問題は、第3実施形態でも起きない。
なお、図15では、命令913のオペランドの中に"+X+36"という部分が含まれる。この部分は、i=2の場合における、式(2)の中の"+X+3・Oi"という部分に対応する。しかし、命令913内の"+X+36"という部分は、実行時にXの加算と36の加算が行われることを意味するわけではない。
Xはコンパイル時に確定する値なので、オブジェクトコード生成部607は、実際には、Xと36の和を算出し、その算出した和(X+36)を、命令913のオペランドの中に指定する。命令907、919、925についても同様である。
続いて、図16を参照して、第4実施形態について説明する。なお、第2実施形態との共通点についての説明は、適宜省略する。
図16は、第4実施形態でオブジェクトファイルに埋め込まれるデータを例示する図である。図16のオブジェクトファイル1000は、言語非依存の文字列リテラル用の領域1001と、言語依存の文字列リテラル用の領域1002を含む。
領域1001と1002は、RO領域の一部を占める。領域1001と1002は、第2実施形態の図6のオブジェクトファイル503内のRO領域(言語非依存の文字列リテラル用の領域と言語依存の文字列リテラル用の領域を含む)と同様である。なお、第4実施形態では、領域1002におけるリテラルの並び順は、図6の第2実施形態での順序と同様である。しかし、領域1002におけるリテラルの並び順を、図14の第3実施形態での順序と同様の順序に変更した実施形態も可能である。
領域1002において、文字列リテラルは、第2・第3実施形態と同様に、所定の文字(例えば空白文字)でパディングされていてもよい。しかし、第4実施形態ではパディングが省略されてもよい。
領域1002においては、パディングが行われるか否かによらず、複数の言語の互いに対応する文字列リテラルには、同じバイト長が割り当てられる。例えば、"Base Salary"と
と"基本給"という文字列リテラルのいずれに対しても、領域1002内で11バイトが割り当てられる。なぜなら、これらの3つの文字列リテラルのうち最長の"Base Salary"の長さが11バイトだからである。パディングが省略される場合、"基本給"という6バイトの文字列リテラルに続く5バイトは、実行時に単に無視されるだけである。
第4実施形態では、オブジェクトファイル1000が、さらに、文字列リテラルの長さ用の領域1003も含む。領域1003もRO領域の一部である。図16には領域1003の詳細も例示されている。領域1003には、言語依存の各文字列リテラルの長さを示す数値が記憶される。図16では参照の便宜のため、これらの数値のほかに、文字列リテラルのIDと、アドレスも示してある。
例えば、図9に示すように、"C00001"と"D00001"と"B00001"というIDで識別される3つの文字列リテラル同士は互いに対応し、これらの文字列リテラルの長さは、それぞれ、12、10、10バイトである。図16には便宜上、文字列リテラルの長さが2バイトの数値で表現される場合のアドレス(すなわち、Qと、Q+2と、Q+4)が例示されている。つまり、領域1003には、12、10、および10という数値が格納されており、これらの数値が格納されているアドレスは、Q、Q+2、およびQ+4である。なお、Q=X+3Yである。
同様に、領域1003には、"C00002"と"D00002"と"B00002"というIDで識別される3つの文字列リテラルの長さをそれぞれ示す11、8、6という数値も格納されている。また、"C00003"と"D00003"と"B00003"というIDで識別される3つの文字列リテラルの長さをそれぞれ示す21、8、6という数値も格納されている。さらに、"C00004"と"D00004"と"B00004"というIDで識別される3つの文字列リテラルの長さをそれぞれ示す17、4、8という数値も格納されている。
第4実施形態のオブジェクトコード生成部607は、例えば、図13の処理を実行することで、言語依存の文字列リテラル用の領域1002に適宜文字列リテラルを配置してもよい。その後、オブジェクトコード生成部607は、各言語のリテラル一覧610〜612に基づいて、上記のように領域1003内に、文字列リテラルの長さを示す数値を記録してもよい。オブジェクトコード生成部607は、各言語のリテラル一覧610〜612を参照することで、各文字列リテラルの長さを認識することができる。
なお、オブジェクトコード生成部607は、領域1002での言語の順序にしたがって、領域1003内に数値を記録する。例えば、オブジェクトコード生成部607が、図6と同様の「英語が1番目で、中国語が2番目で、日本語が3番目」という順序にしたがって、領域1002に文字列リテラルを配置したとする。この場合、オブジェクトコード生成部607は、図16のとおり、各リテラル組について、以下の順序で3つの数値を配置する。すなわち、オブジェクトコード生成部607は、各リテラル組について、英語の文字列リテラルの長さを示す数値を1番目に配置し、中国語の文字列リテラルの長さを示す数値を2番目に配置し、日本語の文字列リテラルの長さを示す数値を3番目に配置する。
なお、オブジェクトファイル1000は、領域1001〜1003の後ろに、命令列用の領域1004も含む。領域1004には、図10〜11と類似の命令が含まれる。ただし、領域1004における命令列は、以下の点において図10〜11と異なる。
命令825の前に、レジスタReg2の値をレジスタReg5にコピーするための命令(例えば"Mov Reg5, Reg2")が挿入される。したがって、レジスタReg5には、実行時のLCIDに応じた0、1、2などの値が格納される。
次に、レジスタReg5の値を2倍するための命令(例えば"Mul Reg5, 2")が挿入される。この命令の第2オペランドが2である理由は、図16の例では文字列リテラルの長さを示す数値が2バイトで表されるためである。
その後に、図11と同様の命令825〜828が続く。第2実施形態では、1番目の文字列リテラルを表示するための命令829〜832が生成されるが、第4実施形態のオブジェクトコード生成部607は、命令831の代わりに、"Lea Reg6, [BaseReg+Reg5+Q]"と"Mov DispReg2, [Reg6]"のような命令を生成してもよい。
これらの2つの命令が実行されると、実行時のLCIDに応じた言語の文字列リテラルの長さを示す数値が読み出され、読み出された数値がレジスタDispReg2に設定される。
同様に、オブジェクトコード生成部607は、2番目の文字列リテラルの表示に関して、命令835の代わりに、"Lea Reg6, [BaseReg+Reg5+Q+6]"と"Mov DispReg2, [Reg6]"のような命令を生成してもよい。なお、文字列リテラルの長さが2バイトの数値で表され、3つの言語の文字列リテラルが領域1002に含まれ、2×3×(2−1)=6であるため、上記の命令には"+Q+6"という部分が含まれる。
同様に、オブジェクトコード生成部607は、3番目の文字列リテラルの表示に関して、命令839の代わりに、"Lea Reg6, [BaseReg+Reg5+Q+12]と"Mov DispReg2, [Reg6]"のような命令を生成してもよい(2×3×(3−1)=12であるため)。また、オブジェクトコード生成部607は、4番目の文字列リテラルの表示に関して、命令843の代わりに、"Lea Reg6, [BaseReg+Reg5+Q+18]"と"Mov DispReg2, [Reg6]"のような命令を生成してもよい(2×3×(4−1)=18であるため)。
以上説明したように、オブジェクトコード生成部607は、RO領域の中に各文字列リテラルの長さを示す数値を含めてもよく、その数値を参照するための命令を生成してもよい。互いに対応する文字列リテラル同士の長さは言語に応じて異なり得るが、第4実施形態によれば、実行時のロケールに応じた言語の文字列リテラルの長さを所定のレジスタに設定するための命令を、コンパイル時に確定することが可能である。
例えば、表示の都合などにより、言語に依存しない一律の長さに調整された(つまりパディングされた)文字列リテラルよりも、ロケールに応じた短い(つまりパディングされていない)文字列リテラルそのものを使う方が好ましいアプリケーションもあり得る。第4実施形態では、ロケールに応じた文字列リテラルの実際の長さが、実行時に領域1003から読み出されるので、第4実施形態は上記のようなアプリケーションにも好適である。
なお、上記のとおり、領域1002における文字列リテラルの並び順は、図14と同様の順序であってもよい。その場合、領域1004における具体的な命令列は、上述の例とは異なり、図15の命令列と似たものである。
ただし、上記と同様の"Mov Reg5, Reg2"および"Mul Reg5, 2"という命令が(例えば命令904の後に)挿入される。また、図15に含まれる命令のうち、命令909、915、921、927は、命令831、835、839、843が第4実施形態では上述のように別の命令に置き換えられるのと同様に、別の命令に置き換えられる。
なお、命令906、912、918、924の第2オペランドは、オフセット一覧613の最大長フィールドの値である。しかし、命令906、912、918、924は、第4実施形態においても変わらない。なぜなら、これらの命令の第2オペランドは、文字列リテラルの長さを指定するための値ではなく、文字列リテラルの開始アドレスを計算するために使われる値だからである。
また、第4実施形態における領域1003内での数値の並び順を変更した実施形態も可能である。具体的には、オブジェクトコード生成部607は、1つの言語の複数の文字列リテラルの長さを示す複数の数値を、連続した複数のアドレスに記録してもよい。その場合、オブジェクトコード生成部607は、領域1003内での数値の並び順に応じて適切にアドレスを指定するための適切なオペランドを含む命令を生成する。
ところで、本発明は第1〜第4実施形態に限られるものではない。上記の説明においてもいくつかの変形について説明したが、第1〜第4実施形態は、さらに例えば下記の観点から様々に変形することもできる。上記および下記の種々の実施形態は、相互に矛盾しない限り、任意に組み合わせることが可能である。
説明の便宜上、いくつかの図において具体的な命令をアセンブリコードの形式で例示したが、実際にオブジェクトコードに含まれる命令は、マシンコードである。そして、マシン語の個々の命令の形式は、オブジェクトファイルから得られる実行ファイルを実行するコンピュータの命令セットに応じて異なり得る。コンパイラは、実施形態に応じた命令セットにしたがって、適宜の命令を生成する。
コンパイラは、場合によっては(例えば、特定のコマンドオプションが指定された場合などには)、マシンコードで記述されるオブジェクトコードの代わりに、アセンブリコードを生成してもよい。そして、アセンブラが、アセンブリコードからオブジェクトコードを生成してもよい。
生成される命令は、命令セットに応じて異なり得るだけでなく、コンパイラの具体的実装に応じても異なり得る。もちろん、図10〜11、15等に例示されているレジスタの具体名は、説明の便宜上の例に過ぎない。
例えば、オブジェクトコード生成部607は、図11の命令825を省略してもよく、その代わりに、図10の命令814の第2オペランドとしてYを指定するとともに命令819の第2オペランドとして2Yを指定してもよい。なお、0とYの積は0なので、命令825が省略される場合も、命令809と822の第2オペランドは、図10と同様、0である。つまり、3つの言語に対応する0、Y、2Yという3つの数値のうち、実行時のロケールに対応する1つの数値を使って文字列リテラルの開始アドレスを算出するための1つ以上の命令が、生成されてもよい。
ところで、図13のステップS207では、パディングに空白文字が使われる。しかし、実施形態によっては(例えば、コンパイル対象のプログラミング言語によっては)、空白文字以外の文字(例えばNULL文字)がパディングに使われてもよい。
例えば、NULL終端の(null-terminated)文字列リテラルが使われてもよい。この場合、図12の処理によりオフセット一覧613に設定される最大長は、NULL文字を含むバイト長であってもよい。また、この場合、パディングにNULL文字が使われてもよい。
図11の命令831、835、839、843や、図15の命令909、915、921、927では、文字列リテラルの長さを示すオペランドとして、固定値が指定されている。しかし、実施形態によっては、固定値が指定された命令の代わりに、別の命令列が使われてもよい。
例えば、文字列リテラルの先頭から1バイトずつ読み取りながら文字列リテラルの末尾を探す処理のための命令列を、オブジェクトコード生成部607が生成してもよい。当該命令列は、例えば、文字列リテラルから読み取ったバイトを、文字列リテラルの末尾を示す特殊文字(例えばNULL文字)と比較する命令と、比較結果に応じた条件分岐命令とを含んでいてもよい。
ところで、複数の言語の互いに対応する文字列リテラルのうちの最大長は、例えば図9に例示されているように、様々な値をとり得る。一方で、ある種のアーキテクチャでは、メモリ管理の単位が1バイトより大きい場合があり得る。例えば、メモリ管理の単位が4バイトの場合があり得る。メモリ管理の単位が1バイトより大きい場合、「最大長そのもの」の代わりに、「最大長以上で、かつ、メモリ管理の単位で割り切れる長さのうちの最小値」が使われてもよい。
例えば、メモリ管理の単位が4バイトであるとする。また、図9のオフセット一覧613には、最大長として、12、11、21、17という値が記録されている。この場合、上記の各実施形態は、以下のように変形されてもよい。
・12は4で割り切れるので、12という最大長そのものが使われる。例えば、命令831、906、909で、12がオペランドとして指定される。
・11は4で割り切れない。11以上で、かつ、4で割り切れる最小の整数は、12である。よって、11の代わりに12が使われる。例えば、命令835、912、915で、11の代わりに12がオペランドとして指定される。
・21は4で割り切れない。21以上で、かつ、4で割り切れる最小の整数は、24である。よって、21の代わりに24が使われる。例えば、命令839、918、921で、21の代わりに24がオペランドとして指定される。
・17は4で割り切れない。17以上で、かつ、4で割り切れる最小の整数は、20である。よって、17の代わりに20が使われる。例えば、命令843、924、927で、17の代わりに20がオペランドとして指定される。
なお、11、21、17という実際の最大長の代わりに、上記のように12、24、20という値が使われる実施形態では、オフセット一覧613の「最大長」のフィールドには、これらの12、24、20という値が記録される。つまり、ステップS109・S110で参照・更新される「最大長」は、実際の最大長より大きい値のことがある。
また、ステップS201では、オフセット一覧613の「最大長」のフィールドに基づいてオフセットが算出される。こうして算出されるオフセットは、図9に例示された値とは異なり得る。例えば、オフセット一覧613の4番目のレコードのオフセットは、48(=12+12+24+20)と変更される。したがって、命令829、833、837、841、907、913、919、925のオペランドも、オフセット一覧613に記録されるオフセットの値に応じて、変更される。
以上のように、メモリ管理の単位に応じて実際の最大長よりも長いバイト長が使われる実施形態においても、コンパイラは、文字列リテラルの開始アドレスを算出するための命令のオペランドを、コンパイル時に確定することができる。
ところで、図6のロケールリソースファイル502において文字列リテラルが定義される言語の順序は、1番目が英語("en-us"に対応)、2番目が中国語("zh-cn"に対応)、3番目が日本語("ja"に対応)である。しかし、開発者は、任意の他の順序を採用してよい。例えば、1番目が日本語で2番目が英語で3番目が中国語であってもよい。
また、ロケールリソースファイル502では、3つの言語に対応する文字列リテラルが定義されている。しかし、ロケールリソースファイル502で文字列リテラルが定義される言語の数は、2以上の任意の数でよい。
ところで、実行環境のロケールで使われる言語が、ロケールリソースファイル502で文字列リテラルが定義されたどの言語とも等しくない場合があり得る。このような場合には、ロケールリソースファイル502で文字列リテラルが定義されている言語の中から、デフォルト言語が実行時に選ばれる。例えば、第2実施形態でのデフォルト言語は上記のとおり英語である。
英語の文字列リテラルがロケールリソースファイル502において定義されている場合、第2実施形態のオブジェクトコード生成部607は、自動的に、デフォルト言語を英語に決定する。図10の命令822は、この決定に基づいて生成される命令の例である。
しかし、ロケールリソースファイル502において、必ずしも英語の文字列リテラルが定義されているとは限らない。実施形態に応じて、コンパイラ500(特にオブジェクトコード生成部607)は、デフォルト言語を適宜の方法にしたがって決めてよい。以下に4つの方法を例示する。
第1の方法によれば、「英語の文字列リテラルが、ロケールリソースファイル502において定義されているか否か」を、オブジェクトコード生成部607がチェックする。英語の文字列リテラルがロケールリソースファイル502において定義されている場合、オブジェクトコード生成部607は、自動的に、デフォルト言語を英語に決定する。
逆に、英語の文字列リテラルがロケールリソースファイル502において定義されていない場合、オブジェクトコード生成部607が、コンパイル処理の途中で、インタラクティブに、ユーザにデフォルト言語を問い合わせてもよい。なお、ここでの「ユーザ」は、ソースファイル501のコンパイルをコンパイラ500に命じる開発者のことである。
英語を使う2つ以上のロケール(例えば、"en-us"と"en-gb"というロケール名で識別される2つのロケール)用の文字列リテラルが、ロケールリソースファイル502において別々に定義されている場合もあり得る。この場合、オブジェクトコード生成部607は、それら2つ以上のロケールのうちの1つで使われる英語を、デフォルト言語として自動的に選んでもよい。
第2の方法によれば、コンパイラ500のプログラムを呼び出すコマンドのオプションにより、デフォルト言語が明示的に指定される。例えば、図6のロケールリソースファイル502が入力としてコンパイラ500に与えられ、かつ、コマンドオプションで"zh-cn"というロケール名がユーザにより指定されてもよい。この場合、オブジェクトコード生成部607は、指定されたコマンドオプションにしたがって、図10の命令822の代わりに、"Mov Reg2, 1"という命令(つまり命令814と同じ命令)を生成する。なお、ここでの「ユーザ」も、ソースファイル501のコンパイルをコンパイラ500に命じる開発者のことである。
第3の方法によれば、ロケールリソースファイル502の形式により、デフォルト言語が指定される。ユーザは、どの言語をデフォルト言語として指定したいかに応じて、適切な形式でロケールリソースファイル502を作成する。ここでの「ユーザ」も、アプリケーションの開発者のことである。
例えば、ロケールリソースファイル502のヘッダ行で最初に指定される言語を、オブジェクトコード生成部607がデフォルト言語と見なしてもよい。例えば、図6のロケールリソースファイル502では、たまたま最初に"en-us"というロケール名が指定されている。よって、オブジェクトコード生成部607は、「指定されたデフォルト言語は英語である」と認識し、第2実施形態と同様に命令822を生成する。
逆に、ロケールリソースファイル502のヘッダ行で最後に指定される言語を、オブジェクトコード生成部607がデフォルト言語と見なしてもよい。この場合、オブジェクトコード生成部607は、図10の命令822の代わりに、"Mov Reg2, 2"という命令(つまり命令819と同じ命令)を生成してもよい。あるいは、この場合、オブジェクトコード生成部607は、単に、図10の命令817、命令818、命令820、ラベル821、命令822の生成を省略してもよい。
第4の方法は、デフォルト言語をコンパイル時に1つに決めない方法である。第4の方法では、オブジェクトコード生成部607は、命令822の代わりに、以下のような命令を含む命令列を生成してもよい。
・ロケールリソースファイル502のヘッダ行で指定されている複数の言語の中から1つをユーザに選ばせるためのGUI(Graphical User Interface)ウィジェット(例えばドロップダウンリスト)を表示するためのいくつかの命令。なお、ここでの「ユーザ」は、実行ファイル507を使うエンドユーザのことである。
・GUIウィジェットを介して入力される値に基づいて、レジスタReg2に適宜の値を設定するためのいくつかの命令。なお、これらの命令の中には、条件分岐命令が含まれる。
第4の方法によれば、実行環境のロケールで使われる言語が、ロケールリソースファイル502で文字列リテラルが定義されたどの言語とも等しくない場合には、実行時にデフォルト言語がユーザによりGUIウィジェットを介して指定される。なお、第4の方法においても、オブジェクトコード生成部607が生成する命令列自体は、コンパイル時に確定する。
以上、様々な実施形態について説明してきたが、いずれの実施形態によっても、以下のように様々な効果が得られる。
上記の各種実施形態によれば、図2の第1比較例のように実行時にリソースファイルを参照する必要がない。したがって、実行ファイルと複数のリソースファイルとをセットにしてエンドユーザに頒布する必要がない。
例えば図7の実行ファイル507のような単一の実行ファイルだけで、複数の文化圏(換言すれば複数のロケール)に適応することが可能である。つまり、単一の実行ファイルだけで、複数の言語に適応することが可能である。
実行時にリソースファイルを参照する必要がないと、リソース呼び出しDLL202を介した呼び出しのオーバヘッドをなくせる。その結果、アプリケーションの実行性能が向上する。また、実行時にリソースファイルを参照する必要がないと、エンドユーザが誤ってリソースファイルを削除・編集・移動することを防ぐための管理コストも、不要である。
さらに、上記の各種実施形態によれば、図3〜4の第2比較例のように、「複数のロケールに応じて複数のソースファイルを作り、各ソースファイルをコンパイルし、複数の実行ファイルをビルドする」という必要もない。上記の各種実施形態によれば、複数のロケールに適応可能な実行ファイル(例えば図7の実行ファイル507)を、1回のビルドで作成することが可能である。したがって、上記の各種実施形態は、開発・保守のコストが第2比較例よりも低い。
また、第3比較例では、コンパイル時にオペランドを確定することができないためにコンパイルが失敗してしまうが、上記の各種実施形態では、そのような失敗はない。なぜなら、同じリテラル組に属する複数の文字列リテラルに、同じ長さが割り当てられるからである。そのため、上記の各種実施形態では、同じリテラル組に属するどの文字列リテラルの開始アドレスも、実行時のロケールによらない共通のオフセットを使って計算することが可能であり、したがって、コンパイル時にオペランドを確定することができる。
例えば図6に示したように、同じリテラル組に属する複数の文字列リテラル自体の長さ同士は異なり得る。しかし、それらの複数の文字列リテラルに同じ長さが割り当てられている場合、各文字列リテラルの開始アドレスが、コンパイル時に確定される。つまり、コンパイル時にはオペランドが一意に定まる。したがって、第3比較例のような失敗は避けられる。
以上のように、上記の各種実施形態には、アプリケーションの多言語化を促進するうえで有利な種々の効果がある。したがって、上記の各種実施形態によれば、アプリケーションの多言語化が促進されると期待される。
最後に、上記の種々の実施形態に関して、さらに下記の付記を開示する。
(付記1)
コンピュータに、
コンパイル対象のソースコードと、複数の言語の間で互いに対応する意味を持つ複数の文字列リテラルの組み合わせであるリテラル組を定義する定義情報と、を読み込み、
各リテラル組について、当該リテラル組に属する複数の文字列リテラルのそれぞれに対して、当該リテラル組のうちで最長の文字列リテラルのバイト長以上である算出バイト長が割り当てられ、かつ、各文字列リテラルの開始アドレスが、実行時に指定されるロケールに応じて参照されるコードを生成する
ことを含むコンパイル処理を実行させるコンパイラ。
(付記2)
前記コードを生成する処理は、
前記ロケールを示すロケール識別情報を取得するための1つ以上の命令と、前記ロケール識別情報に応じた条件分岐のための1つ以上の命令と、前記複数の言語に対応する複数個の数値のうちの1つを用いて各文字列リテラルの前記開始アドレスを参照するための1つ以上の命令と、を含む複数の命令を生成し、
前記複数の命令を前記コードの中に含める
ことを含むことを特徴とする付記1に記載のコンパイラ。
(付記3)
生成される前記コードの中では、言語ごとに文字列リテラルが配置されており、かつ、各言語について、当該言語の複数の文字列リテラルは、リテラル組同士の間で定義される順序で配置されている
ことを特徴とする付記2に記載のコンパイラ。
(付記4)
前記コンパイル処理は、前記算出バイト長を累積加算することによって各リテラル組に対応するオフセットを算出することを含み、
各文字列リテラルの前記開始アドレスを参照するための前記1つ以上の命令は、前記オフセットを含むオペランドが指定された命令を含む
ことを特徴とする付記3に記載のコンパイラ。
(付記5)
前記コンパイル処理は、全リテラル組の前記算出バイト長の合計を算出することを含み、
各文字列リテラルの前記開始アドレスを参照するための前記1つ以上の命令は、前記複数の言語のうち前記ロケールに対応する1つの言語の複数の文字列リテラルが配置された範囲の開始アドレスを、前記合計に基づいて算出するための命令を含む
ことを特徴とする付記4に記載のコンパイラ。
(付記6)
前記ソースコードは、前記複数の言語のうちの1つの言語で書かれた複数の文字列リテラルのそれぞれについて、当該文字列リテラルか、または、当該文字列リテラルへの参照を含み、
前記リテラル組同士の間で定義される前記順序は、前記1つの言語で書かれた前記文字列リテラルまたは前記1つの言語で書かれた前記文字列リテラルへの前記参照が、前記ソースコード内に出現する順序に基づく
ことを特徴とする付記3から5のいずれか1項に記載のコンパイラ。
(付記7)
生成される前記コードの中では、リテラル組ごとに文字列リテラルが配置されており、かつ、各リテラル組について、当該リテラル組に属する複数の文字列リテラルは、前記複数の言語の間で定義される順序で配置されている
ことを特徴とする付記2に記載のコンパイラ。
(付記8)
前記コンパイル処理は、前記算出バイト長を累積加算することによって各リテラル組に対応する第1の値を算出することを含み、
各文字列リテラルの前記開始アドレスを参照するための前記1つ以上の命令は、前記複数の言語の数と前記第1の値とに応じて決まる第2の値を含むオペランドが指定された命令を含む
ことを特徴とする付記7に記載のコンパイラ。
(付記9)
第1のロケールと第2のロケールで特定の自然言語が使われ、
前記複数の言語のうちの2つは、前記第1のロケールで使われる前記特定の自然言語と、前記第2のロケールで使われる前記特定の自然言語であり、
前記ロケール識別情報が前記第1のロケールを示す場合には前記複数個の数値のうちの第1の数値を使って前記開始アドレスを算出し、前記ロケール識別情報が前記第2のロケールを示す場合には前記複数個の数値のうちの第2の数値を使って前記開始アドレスを算出するための命令が、前記複数の命令に含まれる
ことを特徴とする付記2から8のいずれか1項に記載のコンパイラ。
(付記10)
第1のロケールと第2のロケールで特定の自然言語が使われ、
前記複数の言語のうちの1つは、前記第1のロケールと前記第2のロケールに共通の前記特定の自然言語であり、
前記ロケール識別情報が前記第1のロケールを示す場合と、前記ロケール識別情報が前記第2のロケールを示す場合のいずれにおいても、前記複数個の数値のうちのある1つの数値を用いて前記開始アドレスを算出するための命令が、前記複数の命令に含まれる
ことを特徴とする付記2から8のいずれか1項に記載のコンパイラ。
(付記11)
前記コンパイル処理は、実行時に指定される前記ロケールで使われる言語が前記複数の言語のうちのいずれとも異なる場合に使われるデフォルト言語を、前記複数の言語のうちの1つに決定することを含み、
前記複数の言語のうちのいずれとも異なる言語を使うロケールを前記ロケール識別情報が示している場合に、前記複数個の数値のうちで前記デフォルト言語に対応する1つの数値を用いて前記開始アドレスを算出するための命令が、前記複数の命令に含まれる
ことを特徴とする付記2から10のいずれか1項に記載のコンパイラ。
(付記12)
各リテラル組について、当該リテラル組に属する複数の文字列リテラルのうち前記算出バイト長未満の長さの各文字列リテラルを所定の文字でパディングし、パディングした前記文字列リテラルを前記コード内に配置することを、前記コードを生成する処理が含む
ことを特徴とする付記1から11のいずれか1項に記載のコンパイラ。
(付記13)
前記コードを生成する処理は、
各リテラル組に属する複数の文字列リテラルそれぞれの長さを示す数値を前記コード内に埋め込み、
前記長さを示す前記数値が埋め込まれたアドレスを参照するための命令を生成する
ことを含むことを特徴とする付記1から11のいずれか1項に記載のコンパイラ。
(付記14)
前記ソースコードが、前記ロケールによらずに共通に使われる言語非依存の文字列リテラルを含むか、または、前記言語非依存の文字列リテラルへの参照を含むとき、前記コードを生成する処理は、前記言語非依存の文字列リテラルを前記コードに含めることを含む
ことを特徴とする付記1から13のいずれか1項に記載のコンパイラ。
(付記15)
各リテラル組に対応する前記算出バイト長は、当該リテラル組に属する複数の文字列リテラルのうちで最長の文字列リテラルのバイト長である
ことを特徴とする付記1から14のいずれか1項に記載のコンパイラ。
(付記16)
各リテラル組に対応する前記算出バイト長は、メモリ管理の単位である所定のバイト長の倍数であり、かつ、当該リテラル組に属する複数の文字列リテラルのうちで最長の文字列リテラルのバイト長以上である、という条件を満たす最小のバイト長である
ことを特徴とする付記1から14のいずれか1項に記載のコンパイラ。
(付記17)
コンピュータが、
コンパイル対象のソースコードと、複数の言語の間で互いに対応する意味を持つ複数の文字列リテラルの組み合わせであるリテラル組を定義する定義情報と、を読み込み、
各リテラル組について、当該リテラル組に属する複数の文字列リテラルのそれぞれに対して、当該リテラル組のうちで最長の文字列リテラルのバイト長以上である算出バイト長が割り当てられ、かつ、各文字列リテラルの開始アドレスが、実行時に指定されるロケールに応じて参照されるコードを生成する
ことを特徴とするコンパイル方法。
(付記18)
コンパイル対象のソースコードと、複数の言語の間で互いに対応する意味を持つ複数の文字列リテラルの組み合わせであるリテラル組を定義する定義情報とに基づいて、各リテラル組について、当該リテラル組に属する複数の文字列リテラルのそれぞれに対して当該リテラル組のうちで最長の文字列リテラルのバイト長以上である算出バイト長が割り当てられており、かつ、各文字列リテラルの開始アドレスが、実行時に指定されるロケールに応じて参照されるコードを、生成する生成部
を備えるコンパイル装置。