yuniのChicken-schemeサポート / AppVeyorでCI

- よく有るやつ
OSS側を触るのはなんか普通に半年ぶりになってしまった。。
今年はちょっと計画立てられるような状況でもないので、まぁノンビリと。。

Chicken-scheme上のsyntax-rulesの制限

諸般の事情でyuniから(yuni shorten)ライブラリを外すことにしたので、Chickenのような実装もサポートできるようになった。というのも、Chickenはマクロ内部で定義したマクロをexportできないという制約が有って( https://github.com/okuoku/yuni/issues/10 )、合成された、つまり、ソースコード上に無い名前を持つマクロをエクスポートするための良い手段が無い。
というわけでyuniは基本的にR5RS syntax-rulesの範囲で全てのライブラリを書くことにした。ただし、これでもChickenにしかない制約に当たることになった。

  • define-syntaxの直下はer-macro-transformer、ir-macro-transformer、syntax-rulesのいづれかしか書けない

これはマニュアルにも記述があって( http://wiki.call-cc.org/man/4/Macros )、

The transformer expression must the result of a call to er-macro-transformer or ir-macro-transformer, or it must be a syntax-rules form.

つまり、er-macro-transofmerマクロで展開して得た手続きか、syntax-rulesを直接書くしか方法が無い。仕方が無いので、define-syntaxとsyntax-rulesの両者に一度で展開されるマクロを用意した( https://github.com/okuoku/yuni/commit/5c90c89432b423f2af85688389390c41eb80f932#diff-a76e264688a36f78eb43c10a006ca861R8 )。

(define-syntax define-syntax-rules/keywords
  (syntax-rules ()
    ((_ nam (symlit ...) (keylit ...) clauses ...)
     (define-syntax nam ;; ← Chickenではdefine-syntax → syntax-rulesの順にしか書けない
       (syntax-rules (symlit ... keylit ...)
         clauses ...)))))

元々は、syntax-rulesに展開されるマクロだった。(ちなみに、let-syntaxの類にはこの制約は無い、はず。)

  • 非正規リストをsyntax-rulesのパタンに使用できない

yuniでは、lambdaの引数リストに見られるような、(a b c . d)といった引数を取れるマクロがいくつか有り、このようなマクロのテンプレート引数には(forms ... . last)のようなテンプレートが使用されている。

(define-syntax lambda*1
  (syntax-rules ()
    ((_ sym (spec0 ... . last) body ...)
     (lambda*1-itr sym () () (spec0 ...) last body ...))))

これはchibiやGaucheのような他のR7RSでは問題なく使用できるが、chickenでは

Error: during expansion of (syntax-rules ...) - Cannot combine dotted tail and ellipsis: (spec0 ... . last)

と言われてしまう。これが使えない処理系って他に有るんだろうか。。規格としてはこのようなテンプレート、つまり、

([pattern] ... [pattern] [ellipsis] . [pattern])

は定義に無いので却下しても構わないと言える。
... ということは、↑のようなマクロをポータブルに書くには最後の1要素までループして last を取り出すようなマクロを書く必要があることになる。
yuniのChickenサポートにはまだFFIが無いし、なにより、まだコンパイルしての使用ができない。対応する気は有るので、最初のサポートされるSchemeコンパイラになる見込。

AppVeyorでのCI

パブリックなCIが何処にも無いのは心象が悪いので、yuni側でAppVeyorを使って自動ビルドを始めた。といっても、まだyuniはリリースビルドができないので、単にライブラリのsanity checkだけが実行される。
yuniのbootstrapには動くnmoshが必要なので、AppVeyor側で毎回tarballを拾ってきてビルドしている。実はCMakeがtarballのダウンロードと展開をできるので、VisualStudioとCMakeさえ入っていればどこでもビルドできる。(実際にはAppVeyorにはCygwinなりMinGWなりPowerShellも入っては居るが。。)
というわけで、AppVeyorに食わせているビルドコマンドはCMake一発になっている:

build_script:
    - cmd: cmake %APPVEYOR_BUILD_FOLDER%/integration/buildhost-win

本来、yuniのビルド検証にはサポートしているScheme処理系をそれぞれビルドするなり持って来るなりしてテストする必要があるが、AppVeyorの持ち時間60分にはどうかんがえても収まらないのでnmoshだけ。。それでも14分掛かっている。
Windowsではそれなりに苦労して環境を構築しているが、LinuxだとDocker + (例えば)TravisCIで終わりなのでかなり楽になる。問題はそれ以外のOSをどうしたもんかというところ。。ハードウェア等も含めて現在調整中。