公開技術情報

[English] [Japanese]

03. Lua バージョン間のクロスコンパイル

今回は少し予定を変更して、LuneScript のクロスコンパイルについて説明します。

クロスコンパイル

ここでいう「クロスコンパイル」とは、 Lua のバージョン間の「クロスコンパイル」という意味です。

LuneScript は、Lua へのトランスコンパイルを行なう際、 LuneScript を実行している Lua のバージョンに合せたトランスコンパイルを行ないます。

例えば、次のような制御を行ないます。

  • Lua5.2 で実行している場合、ビット演算は bit32 ライブラリを利用する。
  • Lua5.3 で実行している場合、ビット演算は Lua の組込み演算子を利用する。

クロスコンパイルは、出力する Lua のコードを、 LuneScript を実行している Lua のバージョンではなく、 指定の Lua バージョンにトランスコンパイルします。

これにより、次のようなことが可能になります。

「LuneScript は Lua5.3 で実行し、トランスコンパイル先は Lua5.1 にする」

使用方法

使用方法は、次のように -ol オプションでバージョンを指定するだけです。

$ lnsc src.lns lua -ol 51

上記の例は src.lns を lua5.1 用にトランスコンパイルし、 結果を stdout に出力します。

-ol オプションに指定する値は、次の通りです。

オプション バージョン
51 Lua5.1
52 Lua5.2
53 Lua5.3

-ol オプションは、 save, lua で指定可能です。

LuneScript の Lua5.1 対応

これまで LuneScript は、実行に Lua5.2, Lua5.3 が必要でしたが、 上記クロスコンパイル対応によって、 Lua5.1 でも実行できるようになりました。

LuneScript は、それ自体を LuneScript で開発するセルフホスティングであるため、 LuneScript 自体をクロスコンパイルすることで Lua5.1 対応しました。

LuneScript で開発することにより、「生産性を上げる」ということ以外にも、 「Lua のバージョン違いを ある程度 吸収できる」というメリットがあります。

ただし、吸収できるのはあくまでも ある程度 です。

Lua5.1 は、次節で説明する制限があります。

Lua5.1 の制限

LuneScript のコードを Lua5.1 にトランスコンパイルする場合、次の制限があります。

LuneScript の制限というよりは、 Lua5.1 の制限とも言えますが。。

  • クラスのデストラクタが使用できない。
  • ビット演算が使用できない。
  • find() などの文字クラスに %g が利用できない。
  • string.format() の書式に %s, %q を指定した場合、 文字列以外を指定できない。

上記において、デストラクタ、ビット演算に関しては、 コンパイル時にエラー出力しますが、 %g, %s, %q に関しては、コンパイル時にエラーを出力しませんので注意が必要です。

ただし、 %s, %q に関しては、次のパターンではトランスコンパイル時に、 tostring() を付加することでエラーしないように回避しています。

// @lnsFront: ok
print( string.format( "%d,%s,%s,%s",  1, 1.0, {}, [] ) );

上記のように、リテラルな文字列を使った format 書式は、 %s とそれに対応するデータの型を見て、 str でなければ次のように tostring() を付加します。

print( string.format( "%d,%s,%s,%s", 1, tostring( 1.0), tostring( {}), tostring( {}) ) )

この変換が可能なのは、リテラル文字列を利用している時だけです。

例えば、次の場合は変換できません。

// @lnsFront: ok
let formatTxt = "%d,%s,%s,%s";
print( string.format( formatTxt,  1, 1.0, {}, [] ) );

まとめ

LuneScript は、 Lua のバージョン間のクロスコンパイルをサポートします。

これにより Lua5.1, Lua5.2, Lua5.3 での、実行をサポートします。

ただし、 Lua5.1 には制限があります。

次回はクラスについて説明します。