jLua特別な文法機能
概要
ここでは、jLuaインタプリタの特殊な機能について解説しています。
機能の概要
-
Luaのコアのバージョン
このカスタムされたLuaインタプリタは、Lua version 5.1.5 をコアとしています。
Lua 5.1.5 の標準文法については、原則利用可能です。
-
cp932(sjis)の文字コードに強い
レガシー環境やWindows日本語向けの環境にも適応しやすいように作られましたので、
cp932(sjis)の文字コードで記述されたLuaファイルが取り扱えるようになっています。
cp932の文字の勘定等をするための専用の関数なども取りそろっています。
-
5.2への対応
独自拡張を施しており、その中には、Lua 5.2向きに書かれたスクリプトを互換動作させるような修正も含まれます。
Lua5.2の深層機能を利用していない限り、Lua5.2のスクリプトも極めて高い確率で動作します。
但し、独自の機能としてcontinue文を追加した代わりに、Lua5.2には存在するgoto文がありませんので注意して下さい。
-
5.3への対応
Lua5.3にて導入されたビット演算等や、追加のLua関数も、そのほとんどが追加されています。
よって、Lua5.3向けに記述されたスクリプトすらも、それなりに高い確率で動作します。
-
UTF8のBOM付ファイルを読み込み実行可能
luaの5.1は本来UTF8のBOM付ファイルは読み込みができずエラーとなりますが、
jLuaでは、Lua5.2以降同様実行が可能となっています。
特別な追加機能
-
ModDebuggerへの出力機能
-
追加ライブラリ
-
lfs(LuaFileSystem)
準標準ライブラリともいえるlfsライブラリを追加しています。
-
bit32
Lua5.2の資産でも流用しやすいように、5.2と同一動作のbit32ライブラリを追加しています。
-
cp932(sjis)用の関数
stringライブラリやutf8ライブラリのcp932版として、
(cp932.len、cp932.upper、cp932.lower、cp932.reverse、cp932.sub、cp932.char、cp932.codepoint、cp932.codes、cp932.encode(文字列, "utf8"))
が追加されています。
-
math系関数
luaの5.3にて新たに加えられたmath関数を持っています。
(math.type、 math.ult、math.mininteger、math.maxinteger、math.tointeger、math.round(x [, precision ])))
-
string系関数
正規表現系のエンジン(string.match等)に関して、cp932(sjis)に適した対応がなされています。
luaの5.3にて新たに加えられたstring関数を持っています。
(string.pack、string.unpack)
-
文字列エンコードを推測する関数
string.getencoding(文字列)
が追加されています。
日本語系で、利用する可能性が高い「メジャーどころ」に絞った高速な判定です。
-
table系関数
nilもしくは空のテーブルであることを判定するtable.emptyが追加されています。
luaの5.2の機能に準ずる 2つの関数を搭載しています。
(table.unpack / table.pack)
luaの5.3にて新たに加えられたtable関数を持っています。
(table.move)
-
utf8系関数
luaの5.3にて加えられたutf8系ライブラリを全て持っています。
(utf8.encode(文字列, "cp932") )が特別に追加されています。
-
Lua5.2互換
-
Lua5.3互換
-
ビット演算子
Lua5.3 で実装された、ビット演算子(&,|,<<,>>,~)が実装されています。
また、対応するメタメソッド(__band, __bor, __bxor, __bnot, __shl, __shr)も実装されています。
-
整数除算
Lua5.3 で実装された、整数とみなしての除算 (例: 10 // 3 ) が実装されています。
また、対応するメタメソッド(__idiv)も実装されています。
-
独自文法拡張
-
continue 文
標準のluaには存在しない、continue文を持っています。
-
C風の「!=」比較演算子
luaでは「~=」と記述しますが、独特ですので、多くの言語で採用されている「!=」も利用可能としています。
-
C風の「+=」「-=」「*=」「/=」「%=」「^=」の6つの代入演算子
C風の「+=」「-=」「*=」「/=」「%=」「^=」の6つの代入演算子が使えます。
これは簡単な演算の際、ソースコードを結構短くできるはずです。
-
2進数表記
16進数の「0xF0」 などと同様に、「0b10101」の2進数表記を受け付けます。
-
テーブルの中に、「代入型ではなく定義型でメソッド」を記述できる
この場合、最初のパラメータは、暗黙で「self」となります。
通常、luaのメソッド定義スタイルは
tbl = {}
function tbl:my_method(x, y) end
もしくは
tbl = {
my_method = function(self, x, y) end
}
ですが、通常の関数と同じスタイルで、
tbl = {
function my_method(x, y) end
}
と、記述することが出来ます。
この場合、function内には、暗黙の第1引数として「self」が存在します。
-
__usedindex の追加
__newindexの逆の意味合いとなる__usedindexを持ちます。
これは、値を代入しようとする度に実行されますので、読み取り専用テーブルを作成するのに役立ちます。
function table.const(tbl)
-- テーブルの要素を
for k, v in pairs(tbl) do
-- 要素がテーブルなら再帰
if type(v) == "table" then
table.const(v)
end
end
return setmetatable(tbl, {
__usedindex = function(table, key, value)
dprint("警告!! このテーブルは読み取り専用です。\n")
dprint( string.format("\tキー:%s, 代入しようとした値:%s\n", tostring(key), tostring(value) ) )
end,
__newindex = function(table, key, value)
dprint("警告!! このテーブルは読み取り専用です。\n")
dprint( string.format("\tキー:%s, 代入しようとした値:%s\n", tostring(key), tostring(value) ) )
end,
});
end
local mytable = table.const{ 1,2, a=3, b={1,2} }
mytable[2] = 10 -- 直接の子要素も読み取り専用
mytable.b[1] = 30 -- ネストのテーブル要素も読み取り専用となる。
-
__iter の追加
テーブルにおいて、イテレータ関数を指定できます。
local mytbl = {1,2,3}
setmetatable(mytbl,{__iter=ipair})
-- すでにイテレータが指定されているので、ipair関数を使う必要がない。もちろんipairがpairを使っても良い。
for k, v in mytbl do
dprint(k, v)
end
-
classを完結に記述することが可能
class 'Person'
{
__init__ = function(self, name)
self.name = name
end;
say = function(self)
print('Hello, my name is ' .. self.name .. '.')
self:saySthElse()
end;
saySthElse = function(self)
end
}
class 'Worker'
{
function __init__(id)
self.id = id
end;
function showId()
print('My worker id is ' .. self.id .. '.')
end
}
class 'Employee: Person, Worker'
{
function __init__(name, salary, id)
Person.__init__(self, name)
Worker.__init__(self, id)
self.salary = salary
end;
function saySthElse()
print('My salary is ' .. self.salary .. '.')
end
}
p = cls.Person('Bob')
p:say()
p2 = cls.Person('David')
p2:say()
print '--------------------------------------------'
e = cls.Employee('Bob', 1000, 1)
e:say()
e:showId()
e2 = cls.Employee('Alice', 10000, 2)
e2:say()
e2:showId()
print '--------------------------------------------'
if is_instance_of(e, cls.Person) then
print 'e is an instance of Person'
else
print 'e is not an instance of Person'
end
if is_instance_of(e, cls.Worker) then
print 'e is an instance of Worker'
else
print 'e is not an instance of Worker'
end
w = cls.Worker(100)
if is_instance_of(w, cls.Person) then
print 'w is an instance of Person'
else
print 'w is not an instance of Person'
end
if is_instance_of(w, cls.Worker) then
print 'w is an instance of Worker'
else
print 'w is not an instance of Worker'
end
|