28. shebang とコマンドライン引数
LuneScript は shebang に対応しています。
shebang 対応
shebang とは、シェルスクリプト等で良く見られるスクリプトファイルの最初の行に、 使用するインタプリタをコメントに指定することで、 そのスクリプトファイルを実行すると指定しているインタプリタが実行される機能です。 例えば bash では次のように指定します。
#! /bin/bash
LuneScript では、次のように指定します。
#! /usr/bin/lnsc -shebang
ここで、 /usr/bin/lnsc
は環境に合せた指定が必要です。
これによって、 #!
が記載された LuneScript ファイルをそのまま実行できます。
例えば次のようなファイル hello.lns があった場合、
#! /usr/bin/lnsc -shebang
print( "hello world" );
この hello.lns を直接実行できます。
$ hello.lns
hello world
この時、次の制限があります。
go 版 lnsc では、 import している .lns ファイルに対応する .lua を事前に生成しておく必要がある。
コマンドライン引数
shebang で起動された場合や、 go へトランスコンパイルした場合など、 コマンドライン引数を処理したいケースがあります。
このコマンドライン引数を処理するためには、 次の __main 関数を定義し、 この関数の引数に渡されるコマンドライン引数を処理します。
// @lnsFront: skip
pub fn __main( argList:&List<str> ):int
__main 関数の型は、 引数名 argList 以外、必ず上記の型での宣言が必要です。
__main の実行順
この __main 関数の実行順序は、トップスコープの処理終了後に行なわれます。 つまり、次のスクリプトの場合、
#! /usr/bin/lnsc -shebang
// @lnsFront: skip
print( "hello world" );
pub fn __main( argList:&List<str> ):int {
print( "hoge" );
return 0;
}
出力結果は以下になります。
$ ./mini.lns
hello world
hoge
__main の引数
__main
の引数は &List<str>
です。
このリストには、先頭にスクリプトのパス、以降にコマンドライン引数が格納されます。
#! /usr/bin/lnsc -shebang
// @lnsFront: skip
pub fn __main( argList:&List<str> ):int {
foreach arg in argList {
print( arg );
}
return 0;
}
lua へトランスコンパイルした時の __main() 関数の動作
次の LuneScript のコードはコマンドラインオプションを出力します。
// @lnsFront: skip
pub fn __main( argList:&List<str> ) : int {
foreach arg, index in argList {
print( index, arg );
}
return 0;
}
以下は実行結果のサンプルです。
$ lnsc -shebang mini.lns a b c
1 mini.lns
2 a
3 b
4 c
このコードをトランスコンパイラするには、次のコマンドを実行します。
lnsc mini.lns save
これによって、 mini.lua が出力されます。
この mini.lua を実行すると、以下のようになります。
$ lua5.3 mini.lua a b c
これが何を意味するかというと、「 __main() 関数が呼ばれていない 」ということです。
lnsc に -shebang オプションを指定して実行した場合、 .lns ファイルに定義されている __main() 関数を実行します。 一方で、トランスコンパイルした lua コードには __main() を実行するコードが 出力されないため、このような動作になります。
トランスコンパイルした lua コードの __main() を実行するには、次のいずれかが必要です。
- __main() を実行するコードを別途自前で作成する
- トランスコンパイルする際に
--main
オプションを指定する
--main
オプション
トランスコンパイルする際に --main
オプションを指定することで、
指定のモジュールに __main()
関数を実行する処理を出力します。
以下は、 --main
オプションのサンプルです。
$ lnsc mini.lns save --main mini
ここで、 --main mini
の mini は、実行する __main() を含むモジュール名です。
これにより、 mini.lua には __main() を実行するコードが出力されます。
以下は、 --main mini
を指定して生成した mini.lua の実行結果です。
$ lua5.3 mini.lua a b c
1 mini.lua
2 a
3 b
4 c
ここで注意が必要なのは、 lnsc の shebang で実行した場合の argList の第一引数には .lns のパスが入るのに対し、 lua へトランスコンパイルした後の argList の第一引数には .lua のパスが入る違いがあります。