確かめて配る
ゲート、方言が断る書き方、バンドル、そしてまだできないこと。
ウィンドウなしの実行とゲート
PIXIE_SCRIPT が人の操作の代わりになります。
エンジンが木を組み、そこに書かれた手順のとおりに動かして、dump を出力します。
click:<label> 表示されている文字でボタンを押す
input:<text> 欄に打つ submit その欄で改行する
slide / select つまみを動かす、選択肢を選ぶ
click@1:<label> 同じ文字のボタンの二つ目(n はツリー順に 0 から数える)
input@n:、submit@n、slide@n:、select@n: も同じ
key:<chord> shortcut に結ばれた打鍵
keydown:<key> / keyup:<key> キーを押したままにする、離す
menu:<item> メニュー項目を選ぶ file:<path> ダイアログの答え
drop:<path> ウィンドウにファイルを落とす
hover:<i> チャートの i 番目の点にポインタを載せる(n 番目のチャートなら hover@n:<i>)
hover: ポインタを外す
advance:<ms> 時計を進める theme:dark|light
dump ツリーを出力 a11y 読み上げが読むものを出力
rakugan gate は、一つのスクリプトでアプリを二回走らせます。
片方は perl が XS モジュール越しに動かすもので、もう片方は翻訳した .pix から作ったバイナリです。
最後に、二つの記録を一バイトずつ比べます。
$ rakugan gate demo/counter.pl --script "click:+1,dump,input:Momo"
GATE OK — 3 dump lines identical in both runs
ゲートが、Rakugan の約束そのものです。 このページのほかの部分では、そのゲートを通るものをどう書くかを説明しています。
Rakugan が断る書き方
rakugan check はアプリを読み、受け取れない書き方があれば、その行番号と書き換え方を示します。
先に読むのは perl です。
構文の可否は perl が決めるので、perl が撥ねた書き方が翻訳器に届くことはありません。
そのあとで翻訳器が、方言から外れた最初のものを指します。
ビルドの前にもゲートの前にも毎回走り、言うことがなければ何も出力しません。
$ rakugan check demo/broken.pl
demo/broken.pl:9:26: Rakugan cannot take this — a hash may not have that
key, so say what to answer when it does not: `$prices{$k} // 0`
$picked = $prices{"apple"};
^
断るものと、代わりの書き方は次のとおりです。
- 初期値のないフィールドと、アプリ自身のクラスのフィールドに付けた
:param。 型は初期値から来ます。 - 何を入れるか言わずに空で始まるリストやハッシュ。
empty(Str)と書きます。 - 二つの型が混ざったリスト。
- 引数があるのに
:Sigのないメソッド。 Boolではない条件。!= 0やne ""のように比べます。- 片側が文字列の
+。 文字列を数として読むのは0 + $sです。 - 文字列への
++。 perl はそこで文字を数え上げますが("az"++は"ba")、コンパイルした実行はそれをしません。 //のないハッシュの読みと、sortのないkeys。- フィールドの初期値としての
undef(型はmaybe(Int)が言います)、definedや//の外で読む「なにもないかもしれない値」、ifの条件の全部としてではないdefined、そして自分のdefinedの分岐の中でのその値への書き込み。 - メソッドを持つクラスの中の
$self、リストやハッシュのフィールド、ADJUST、フィールドやset_<field>と同じ名前のメソッド、そして二つの値で二度宣言された定数。 - リストの中に収まっていることをビューが示せない添字。
- ビューを組み立てている最中に呼ばれる、フィールドを書き換えるメソッド。
- 一致を作った
ifの外の$1、実行時に組み立てたパターン、置換の/e。 print、printf、say。 コンパイルしたアプリが書くのは画面で、標準出力ではありません。 標準エラーに出すwarnは受け取ります。- 文字列の
eval、goto、local、wantarray、each、tie、bless、ref、AUTOLOAD。 finally、そしてループや失敗しうるメソッドを囲むtry。- 書き下していない数を指数にした整数の冪(
2 ** $n)。 perl は負の指数に小数を答え、コンパイルした実行はどちらになるかを知っていなければなりません。2.0 ** $nと書けば小数です。 - ラベルつきのループ、
state、値としてのsub、自分のモジュール、eval { … }(tryとcatchを書きます)、whileで一致を一つずつ歩く形(先に全部取ります:my @found = ($s =~ /(\d)/g))、捕まえたものを自分のmyで名づける一致。 どれも代わりの書き方を添えて断り、翻訳器が知らない Perl の関数は Perl 自身のものだと言い、代わりがあればそれも言います。 - 同じブロックで
dieの後ろに続く行(perl はそこに届きません)と、同じハンドラでtaskの後ろに続く行(perl はすぐに届き、コンパイルした実行は処理が終わってから届きます)。 - サブルーチンでないハンドラと、呼ばれ方に引数の数が合わないハンドラ。
- 要素の知らないキーワードと、型の合わないキーワード。 文面は、その要素が取るものを並べます。
どれも、出力される文面ごと test/refuse/ に置いてあります。
だから、断りの文面が黙って変わることはありません。
リリース
$ rakugan build demo/todo.pl --release --app
built: ~/.cache/pixie/target/release/main (11.9 MB)
bundle: demo/dist/todo.app (11.9 MB)
--release は symbol table を落とします。
--app はバイナリを macOS のアプリケーションバンドルに包み、ad-hoc 署名をつけます。
アプリと同じ場所に <stem>.png か <stem>.icns を置いておくと、それがアイコンになります。
バイナリはエンジンと翻訳したアプリを含んでいて、システム自身のライブラリ以外は何もリンクしません。
だから、このバンドルだけでプログラムが完結します。
perl 5.40 もツールチェインも入っていないマシンで、そのまま開きます。
まだできないこと
- 方言は部分集合で、Rakugan が断る書き方がその外側です。 どれも、翻訳器がまだコンパイルした実行まで運べない書き方であって、Perl についての評価ではありません。
- 実行中に 64 bit を超える整数。
perl はそれを小数のある数に育て、コンパイルした実行はそこでハンドラを止めます。
書き下した数がそこに達すれば断りますが、実行中に足し上げて達するものは
checkには見えず、捕まえるのはゲートです。 - 末尾を越えたリストの読み。
perl は
undefを答えて先へ進み、コンパイルした実行はハンドラを止めます。$xs[$i] // $dと書けば代わりに答えるものを言えますが、checkはまだそれを求めません。 末尾を越えたスライスは、perl がundefで埋めるところで端に揃えます。 - 空のリストの
sum、max、min、maxstr、minstrは、perl がundefを答えるところで0や""を答えます。sum0はどちらでも同じです。 - 64 bit を超える
**、hex、octは、perl が小数のある数に育てるところでハンドラを止めます。 和の縁と同じ縁です。 また、整数どうしの**を perl は、底が 2 の冪であるか答えが 64 bit を超えるときには小数のある数として計算し、1e15 以上では表示が変わります(2 ** 50は perl では1.12589990684262e+15)。 ここでは整数のままです。 fc、/cつきのtr///、sprintfの%*d、そしてfor my ($i, $x) (indexed @xs)。 最後のものは翻訳器が読むのに使うパーサがまだ知りません(for my $i (0 .. $#xs)が同じことを読みます)。- リファレンスは、次のものだけです。
要素に渡すリストとハッシュ、それに自分で書いたクラスです。
ハンドラ以外のコードリファレンス、リファレンスへのリファレンス、
refはありません。 - 自分で書くモジュールはありません。
アプリは 1 ファイルで、翻訳器が知っているモジュールの関数は
List::UtilとPOSIXのものだけです。 ほかのモジュールのuseは読んで無視され、その中の関数を呼べば名前を挙げて断られます。 sprintfは%s %d %i %f %F %e %E %g %G %x %X %o %b %%までです。 幅と精度、-、+、空白、0、#の指定は付けられます。checkが見つけるのは上に挙げたものです。 翻訳器が取りこぼすものをすべて見ているわけではないので、残りを見つけるのは今もゲートです。- macOS と Linux です。
--appは macOS の形なので、そこ以外では名前を挙げて止まります。buildが書くネイティブバイナリはどちらでも動きます。 バイナリが描画に使うエンジンを含むので、小さなアプリでも 12 MB ほどになります。