片方のファイルにしか含まれない行の抽出
30分プログラム、その443。AとBというファイルを与えたときに、Aにだけ含まれる行を抽出するプログラム。
TODO一覧と、完了したタスク一覧を渡して、未完了のタスク一覧を出力したかった。要するに集合的な意味での差なんだから、ファイルのdiffといったらこっちを指すべきじゃね、とちょっと思ったりしてる。
使い方
$ cat a foo bar baz $ cat b bar $ ya-diff a b foo baz
ソースコード
import System.Environment import Data.List main = do [x,y] <- getArgs >>= mapM readFile putStr $ unlines $ (lines x) \\ (lines y)
ABCのSlotがさっぱりなので、コードを読もう
ABCのSlotがさっぱりなので、Tamarinのコードを読もう。
目的
(define foo (new Foo))
というコードのfooにslotを割り当てたら、
TypeError: Error #1034: Type Coercion failed: cannot convert Foo@11177c9 to class Foo. at global$init()
と怒られた。でも、どこが悪いのかさっぱりなので、コードを読もう。
対象
- http://hg.mozilla.org/tamarin-central/file/2cee46be9ce0(2cee46be9ce0)
あと、上記の例外を投げているのはToplevel::coerceなので、そこを中心に。
ドキュメント生成
まずはDoxygenを使って、メソッド一覧とかを作ってやる。
http://howdyworld.org/junk/tamarin/namespaceavmplus.html
ホントは、EAを使ってクラス図を生成するつもりだったけど、うまくいかなかった。foo()->bar()のパースに失敗するような気がする。
XCodeでデバッグ
ブレイクポイントとかが使えると便利なので、XCodeのプロジェクトを開いてやる。
プロジェクトのファイルはplatform/mac/shell/shell.xcodeprojに置いてある。
実行するABCをコマンドラインで指定するにはXcodeでコマンドライン引数を指定する: シン石丸の電脳芸事ニッキを参考にする。
Toplevel.cpp
エラーになるのは、Toplevel.cppの761行目付近。
if (actual->containsInterface(expected)) { return atom; } else { // failed #ifdef AVMPLUS_VERBOSE //core->console << "checktype failed " << expected << " <- " << atom << "\n"; #endif throwTypeError(kCheckTypeFailedError, core->atomToErrorString(atom), core->toErrorString(expected)); return atom;//unreachable }
Traits::containsInterfaceは次のようになっている。
inline bool containsInterface(Traitsp t) { return this == t || this->getTraitsBindings()->containsInterface(t); }
で、本体のTratsBinding::containsInterfaceはこんな感じ。
bool TraitsBindings::containsInterface(Traitsp t) const { for (TraitsBindingsp self = this; self; self = self->base) { if (self->owner == t || self->findInterfaceAddr(t)->t != NULL) return true; } return false; }