gmnlisp とは、自分が Go言語で開発している ISLisp 規格準拠の Lisp インタープリタです。自作の Go言語アプリケーションを Lisp にてカスタマイズするために作成しました。
そして、ついにやりましたよ。
Release v0.7.19 · hymkor/gmnlisp
Verified using the ISLisp Verification System. TP Result : PASS = 15760, FAIL = 651 (Pass rate: 96.03%)
ISLisp 検証システムとは islisp.org で公開されている、処理系が ISLISP 規格にどの程度準拠できているかを検証してくれる Lisp スクリプトです。
そのスコアが96%に達した今、完全準拠とまでは言わないにしても、"サブセット実装" と呼ぶ段階はもう過ぎたと言えると思います。
検証の仕方ですが、ISLisp.org のダウンロードページ より、ISLisp検証システム
のリンクをたどると、Verify.zip というアーカイブがダウンロードできます。
これを次のように展開し、gmnlisp で実行します
> curl -O http://islisp.org/program/Verify.zip % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 76761 100 76761 0 0 131k 0 --:--:-- --:--:-- --:--:-- 131k > unzip Verify.zip Archive: Verify.zip inflating: readme.txt inflating: tp-ipa.zip > unzip tp-ipa.zip Archive: tp-ipa.zip creating: tp-ipa/ creating: tp-ipa/data/ inflating: tp-ipa/data/array.lsp creating: __MACOSX/ : > cd tp-ipa > mkdir \tmp > gmnlisp -strict gmnlisp v0.7.19-11-g68f6fb4-windows-amd64 by go1.20.14 gmnlisp> (load "tp.lsp") TP-ALL gmnlisp> (tp-all)
-strict
は厳密な ISLisp 準拠を指定するオプションで、これを使うと一部の便利機能が抑制されます。たとえば、Common Lisp などで使える初期値指定なしの変数宣言(let (x y z) ...)
などがありますが、これらを使えるようにすると、スコアがそこそこ落ちてしまうのです。ただ、これ-strict
モードをデフォルトにして、拡張モードの方をオプションにした方が正しかったかもしれません(検討中)- Windows の場合は、カレントドライブに
/tmp
というディレクトリが必要になります。
以上のように実行すると、検証システムは標準エラー出力にテスト結果が 1MB ほど出力します。
> TP File : data/formeval.lsp
> TP File : data/pred.lsp
> TP File : data/control.lsp
> TP File : data/object.lsp
> NG: (DEFCLASS C-1 (B-1 A-1) NIL) -> C-1 [#<Error> <ERROR>]
> NG: (READ-FOO-A) -> #<Correct number of arguments] [#<Wrong number of arguments>]
> NG: (READ-FOO-A NIL NIL) -> #<Correct number of arguments] [#<Wrong number of arguments>]
> :
(中略)
> :
> NG: (CDR (CATCH 'C-ARITHMETIC-ERROR (WITH-HANDLER (FUNCTION ARITHMETIC-ERROR-HANDLER) (* 0.000000 0.000000)))) -> #<Error> <DOMAIN-ERROR> [(0.000000 0.000000)]
> NG: (EQ (CDR DATA) (CLASS <LIST>)) -> NIL [T]
> NG: (EQ (CDR DATA) (CLASS <SERIOUS-CONDITION>)) -> NIL [T]
> TP File : data/misc.lsp
> TP Result: OK = 15784, NG = 627
この出力は次のように見ます。
- 規格を満たせた項目(OK項目)はデフォルトではで出力されない(
(tp-all 'verbose)
と呼び出すと出力される ) - 規格を満たせなかった項目(NG 項目)は
NG: 評価した式 -> 処理系が評価した結果 [規格が期待する評価結果]
という形式で出力される - 最後に、規格を満たせた数・満たせなかった数のサマリーが出力される
ご覧の結果は gmnlisp のスナップショットなので、リリース版(0.7.19)より若干よいスコアになっていますが、パーセントをとると
> gmnlisp
gmnlisp v0.7.19-11-g68f6fb4-windows-amd64 by go1.20.14
gmnlisp> (- 1 (quotient 627.0 15784))
0.960276
gmnlisp>
と、ほぼ 96% を達成していることがわかります。
処理系の主な未達点は認識している範囲では次のとおりです。
- 包括関数
- 包括関数でのパラメーターの型の照合が最初にヒットするものしかしていない
(call-next-method)
,(next-method-p)
が未実装
- ILOS
- ILOS 関係の検証項目は 0.7.19 時点で未着手 (テストが致命的エラーで止まらないだけ)
今後の課題
公開Go言語関数の整備
gmnlisp はそもそもは Go言語アプリケーションに組み込んで機能をカスタマイズするために作成した言語処理系です。gmnlisp を組み込んだビルドツール smake の開発を通じて、仕様を調整していました。
が、それでもまだまだ不十分である点は否めません。
- gmnlisp の中身を知っている自分でないと分からない仕様が多過ぎる
- 開発期間が長くなって、内部で使用しているツール関数の使用方法の一貫性がなくなっている
- 公開すべき型・関数が非公開のままになっていて、外部からつっこんだ使い方がまだまだしづらい
これらの解消が必要だと強く感じています。 (これまでは検証システムのスコアの改善を最優先にし、あとまわしにしていました)
ドキュメントの充実
API についての情報が少ないです。README に幾らか書いていますが、Go言語で ISLisp 上の変数や関数を定義する方法と参照する方法しか書いていません。これはちょっと辛いです。Lua系のドキュメントをお手本に、Example や go doc を充実させていく必要があると思います。
ISLisp そのものの仕様については「仕様書読んで」で済むかと思ってましたが、実際、読むとなると意外とネットには日本語情報が少なく、JISの規格書もなかなか難しい内容です。ゆえに優先順位的には低いものの、なにかしら書いた方がよいだろうなと考えています。
検証スコア 100% への道
100%準拠したといい切れない、この歯切れの悪さ。
実質問題ないと言い切りたいところですが、包括関数、ILOS がきちんと実装しきれていないところがなかなか辛いです。
しばらくは、これまで同様、地道に NG を解消してゆくだけですね。 ( そして、100% になった頃に同じようなエントリを書くわけだ )