構文拡張

このプラグインは、標準の Lua には無い簡易な記法をいくつか追加しています。キーボードで打ちやすく、 入力量と読み替えの手間を減らすための糖衣構文です。スクリプトは実行前に等価な標準 Lua へ変換されるため、 すべての実行エンジン(LuaJIT・MoonSharp・CPU カーネル)で同じように動きます。

変換は字句単位で行い、文字列とコメントの内側は変換しません。 また Lua に存在しない記号(? ! & | => `in < の並び)だけを入口にしているため、 通常の Lua スクリプトはそのまま動作します。

比較演算子

isis not は、値どうしを比べる位置に書いたときだけ演算子として扱います。変数名としての is は変換しません。

書き方意味
a is ba == b
a is not ba ~= b
a != ba ~= b
if frame is not 0 then
    obj.x = 100
end

論理演算子

他言語でなじみのある記号を、Lua の and / or / not の別名として使えます。

書き方意味
!anot a
a && ba and b
a || ba or b
if !hidden && frame != 0 then
    obj.alpha = 255
end

複合代入

左辺の値を使って計算し、同じ場所へ書き戻す記法です。右辺は括弧で包んで展開するため、演算子の優先順位はそのまま保たれます。

書き方展開後
x += 1x = x + (1)
x -= 1x = x - (1)
x *= 2x = x * (2)
x /= 2x = x / (2)
x %= 2x = x % (2)
x ^= 2x = x ^ (2)
s ..= "b"s = s .. ("b")(文字列の連結)
local total = 0
total += obj.track0
total *= 2

インクリメント

++ は行単位の文として使い、1 を加えて書き戻します。

count++

上の count++count = count + 1 に展開します。

nil 合体演算子

a ?? b は、anil のときだけ b を返します。 a and b or c と違い、afalse のときは false をそのまま返します。既定値を安全に書けます。

obj.x = obj.track0 ?? 100
a ?? b は左辺を 1 度だけ評価する無名関数に展開します。b は左辺が nil のときだけ評価されます。

代入をともなう演算子

変数が未設定・偽のときにまとめて代入する記法です。

書き方意味
x ??= bxnil のときだけ b を代入
x ||= bx = x or (b)
x &&= bx = x and (b)
speed ??= 90
obj.rz = time * speed

範囲 for

数値 for を、範囲を視覚的に表す <開始..終了> で書けます。.. は終端を含み、 ..< は終端を含みません。, のあとに増分を指定できます。

書き方意味
for i in <0..10> dofor i = 0, 10 do(10 を含む)
for i in <0..<10> dofor i = 0, (10) - 1 do(10 を含まない)
for i in <0..10, 2> dofor i = 0, 10, 2 do(増分 2)
local sum = 0
for i in <1..10> do
    sum = sum + i
end
in < の並びは通常の Lua には現れないため、ipairspairs を使う汎用 for には影響しません。

三項演算子

条件 ? A : B は、条件が真のとき A を、偽のとき B を返します。 a and A or B と違い、Afalsenil のときも、その値をそのまま返します。

書き方意味
c ? 1 : 2c が真なら 1、偽なら 2
obj.alpha = obj.frame == 0 ? 0 : 255
? : は条件を 1 度だけ評価する無名関数に展開します。: のあとにもう一度 ? : を書けば、else 側で分岐を続けられます。

nil 条件演算子

t?.name は、tnil のときは nil を返し、そうでなければ t.name を返します。 nil の値へ添字アクセスして落ちるのを防ぎます。t?[k] と書けば添字でも同じことができます。

書き方意味
t?.xtnil なら nil、そうでなければ t.x
t?[k]tnil なら nil、そうでなければ t[k]
local title = data?.title ?? "無題"
?. は対象を 1 度だけ評価する無名関数に展開します。a?.b?.c のように連ねれば、途中が nil でも安全にたどれます。

ラムダ式

(引数) => 式 は、その式を返す無名関数に展開します。引数が 1 つのときは括弧を省いて x => 式、 引数が無いときは () => 式 と書けます。本体には 1 つの式を書きます。

書き方展開後
(a, b) => a + b(function(a, b) return a + b end)
x => x * 2(function(x) return x * 2 end)
() => 1(function() return 1 end)
local t = { 3, 1, 2 }
table.sort(t, (a, b) => a < b)
=> だけを入口にしているため、比較演算子の >=<= には影響しません。

パイプ

x |> ff(x) の形に展開し、左辺を関数の第 1 引数として渡します。 x |> f(a, b) のように引数を書いたときは、左辺が第 1 引数に入り、残りの引数は後ろへ続きます。

書き方展開後
x |> ff((x))
x |> clamp(0, 255)clamp((x), 0, 255)
local v = obj.track0 |> math.floor |> tostring
|> は左から右へ連ねられます。a |> f |> gg(f(a)) と同じ順序で評価します。

補間文字列

バッククォート ` で囲んだ文字列の中に {式} を書くと、その値を tostring で文字列にして差し込みます。 { } の中では拡張構文もそのまま使えます。

書き方展開後
`x={a}`("x=" .. tostring(a))
`hello`"hello"
obj.text = `フレーム {obj.frame} / {obj.totalframe}`
バッククォートを入口にしているため、通常の文字列やコメントの中の ` は変換しません。

範囲判定

x in <開始..終了> は、x がその範囲に入っているかどうかを判定します。 .. は終端を含み、..< は終端を含みません。

書き方意味
x in <1..5>1 <= x and x <= 5
x in <1..<5>1 <= x and x < 5(5 を含まない)
if obj.frame in <0..9> then
    obj.alpha = 255
end
左辺は 1 度だけ評価する無名関数に展開します。範囲 for の for i in <0..10> とは書く位置が異なるため、for のヘッダーには影響しません。

[fast] 高速化マーカー

obj.fill obj.convolve obj.resize は、処理量がしきい値以上で GPU の結果が CPU と一致すると確認できたとき、自動で GPU へ委譲します。[fast] を付けると、このしきい値を無視して強制的に GPU へ委譲します。YMM4 独自拡張です。

書き方意味
[fast] の次の行に obj.convolve(k, 5)しきい値を無視して GPU へ委譲を強制する
obj.convolve(k, 5)処理量に応じて自動で GPU / CPU を判定する

マーカーは単独の行に置いても、同じ行に続けて書いても構いません。GPU が使えない環境や GPU の結果が CPU と一致しない環境では、[fast] を付けても自動で CPU 実行に戻ります。

--track@size:Size,1,15,3,2
local n = math.floor(obj.track0)
if n % 2 == 0 then n = n + 1 end
local k = {}
for i = 1, n * n do k[i] = 1 end
[fast]
obj.convolve(k, n)
文の先頭でのみマーカーとして働くため、t[fast] のような添字アクセスは変換しません。[fast] を付けた対象が上記 3 関数以外のときはエラーを表示します。GPU 側の検証(ハードウェア対応と CPU との一致確認)は変わらず行われるため、結果が変わることはありません。従来エンジンと高速ランタイムの両方で動作します。処理量が小さいときは、GPU への委譲自体の往復コストが CPU 実行を上回ることがあり、[fast] を付けるとかえって遅くなる場合があります。
← 標準ライブラリ グローバル変数 →