テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

メッセージパッシングでビルドツールを作る案

今日は, 仕事に飽きたのでninja-rakeをちゃんと作るかと思ったが, Ninjaの仕様が私の知ってるより遥かに複雑になっていたのでもはやDSLでカバーすることが無理そうなのと, https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py というのが公式にあるということ(これはNinjaスクリプトの生成ツールだ. 基本的な思想はninja-rakeと同じ)なので, めんどくさくなってやめた. Ninjaのサブセットに対してならば, 良いDSLを書けると思うが, 今の自分にとってはただやるだけレベルなので, やめようと思った.

もう少し物思いに耽っていると, Erlangのメッセージパッシングを使って依存関係を自然に解決させるのはどうだろうか?と思い始めた. この案はたぶんその界隈では極めてふつうのアイデアだが, エクセサイズとしてはなかなかおもしろい. Elixirのメタプログラミングでメッセージパッシングをするエージェントを自動生成することはElixirのメタプログラミング練習としてなかなか質が良い. また, メッセージパッシングの練習にもなる.

macro-of-inlineが一段落したので, 今度はこちらにとりかかってみようと思う.


(追記)

別に関数を口にして中でreceiveしてもいいじゃんと思うかも知れないが, ダメだ. 例えば以下のような場合に死ぬ. 擬似コードだが,

B->[A]
A->[]
C->[A]

このようなタスクが並べられていた場合, 実装に依ると思うが, Cは永遠に実行されないということが起こりうる. また,

C -> [A]
C -> [B]

のような書き方を許すと, これも破綻する. これも実装に依存するが, これらが実行時にアトミックに認識されなければならない場合がある. 実行時に無理ということであれば, コンパイル時にということになる.

手順としては以下になるはず.

  1. T -> [T]の形を全部得る(エッジに相当する). それぞれが「メッセージが飛んできた時に依存タスクがなくなっていれば, 自分のタスクを実行して通知する」というreceive待ちを定義する. これは, [T]が空の場合も全部統一的に生成する (場合分けは美しくない). タスクがない, 単なるファイルなどもT -> の形を持つ(タスクは何もしない).
  2. 全タスクをstartする. これでみんな待ちに入る.
  3. T -> のものに対して, 適当なメッセージを与える. こいつはもともとタスクがないので, 自分のタスクを実行して終了し, 通知する. これでメッセージが自動で伝搬していく.

なので, 全部静的にやって, 実行が始まったらはじめにリーフへのメッセージ入力が行われるというコードを生成すればいい.

たぶん出来るはずと思ったが, 具体的なコードは出てこない. macro-of-inlineが一段落して, OCamlもあるので, 色々と自由ではない.