SICP 読み (391) 5.5 翻訳系
ざっくり以下なカンジの試験を作っていました。
static void test_priv_CopyList(ScmObj x, ScmObj y) { ScmObj tmp_x, tmp_y; for(tmp_x = x, tmp_y = y; SCM_PAIRP(tmp_x); ) { tmp_x = SCM_CDR(tmp_x); tmp_y = SCM_CDR(tmp_y); } } void test_scheme_Scm_CopyList(void) { ScmObj base, copy, tmp_b, tmp_c; base = ScmCons(Scm_MAKE_INT(1), Scm_Cons(SCM_MAKE_INT(2), Scm_Cons(SCM_MAKE_INT(3), SCM_NIL))); copy = Scm_CopyList(base); test_priv_CopyList(base, copy); }
とほほ。リハビリ必要だ。
前回のエントリでは
手順としては cdr をめくっていきながら (cdr が pair でなくなったら停止) car について
- 型が同じか (同じでないとダウト)
- immediate、fixnum、character ならポインタ値が同じでないとダウト
- pair だったらポインタ値が同じだとダウト
- pair の場合は中身 (car と cdr) の検証
- pair の場合は再帰にせざるを得ない??
みたいなコトを書いています。てーコトはこんな感じ??
static void test_priv_CopyList(ScmObj x, ScmObj y) { ScmObj tmp_x, tmp_y; for(tmp_x = x, tmp_y = y; SCM_PAIRP(tmp_x); ) { CU_ASSERT_EQUAL(SCM_TRUE, SCM_XTYPEP(SCM_CAR(tmp_x), SCM_CLASS_OF(SCM_CAR(tmp_y)))); if(SCM_IMMEDIATEP(SCM_CAR(tmp_x)) !! SCM_INTP(SCM_CAR(tmp_x)) !! SCM_CHARP(SCM_CAR(tmp_x))) CU_ASSERT_TRUE(SCM_EQ(SCM_CAR(tmp_x), SCM_CAR(tmp_y))); if(SCM_PAIRP(SCM_CAR(tmp_x))) { CU_ASSERT_FALSE(SCM_EQ(SCM_CAR(tmp_x), SCM_CAR(tmp_y))); test_priv_CopyList(SCM_CAR(tmp_x), SCM_CAR(tmp_y)); } tmp_x = SCM_CDR(tmp_x); tmp_y = SCM_CDR(tmp_y); } } void test_scheme_Scm_CopyList(void) { ScmObj base, copy, tmp_b, tmp_c; base = ScmCons(Scm_MAKE_INT(1), Scm_Cons(SCM_MAKE_INT(2), Scm_Cons(SCM_MAKE_INT(3), SCM_NIL))); copy = Scm_CopyList(base); test_priv_CopyList(base, copy); base = Scm_List(SCM_MAKE_CHAR('a'), SCM_FALSE, SCM_TRUE, Scm_List(SCM_MAKE_INT(1), SCM_MAKE_INT(2), SCM_MAKE_INT(3)), SCM_NIL); copy = Scm_CopyList(base); test_priv_CopyList(base); }
なんか微妙。面倒だからこのままどんどんやっちゃえ (何
ScmObj Scm_CopyList(ScmObj list) { return NULL; }
こんなのデッチ上げて make してみたらコンパイルエラーがばんばん出る。
- 関数の名前やら引数の数やら全然駄目
- 論理和な演算子が ! になってる
しかも make が通った、と思ったら試験にパスしてやがる。何故だ、と言いつつ試験な main に追加した試験を盛り込んでませんでした。ばたばたしてる中でリハビリ気味に進めるのは色んな意味で微妙。
続
最初こんな実装だったのですが
ScmObj Scm_CopyList(ScmObj list) { ScmObj tmp, ret = SCM_NIL, end; for(tmp = list; SCM_PAIRP(tmp); tmp = SCM_CDR(tmp)) { if(SCM_PAIRP(SCM_CAR(tmp))) tmp = Scm_CopyList(tmp); SCM_APPEND1(ret, end, tmp); } return ret; }
試験に通らんのは何故、と言ってたら car するのを忘れてます (@SCM_APPEND1)。次はリストの中にリストがあるケイス。再度試験を以下に。
static void test_priv_CopyList(ScmObj x, ScmObj y) { ScmObj tmp_x, tmp_y; for(tmp_x = x, tmp_y = y; SCM_PAIRP(tmp_x); ) { if(SCM_PTRP(SCM_CAR(x))) CU_ASSERT_TRUE(SCM_XTYPEP(SCM_CAR(tmp_x), SCM_CLASS_OF(SCM_CAR(tmp_y)))); if(SCM_IMMEDIATEP(SCM_CAR(tmp_x)) || SCM_INTP(SCM_CAR(tmp_x)) || SCM_CHARP(SCM_CAR(tmp_x))) CU_ASSERT_TRUE(SCM_EQ(SCM_CAR(tmp_x), SCM_CAR(tmp_y))); if(SCM_PAIRP(SCM_CAR(tmp_x))) { CU_ASSERT_FALSE(SCM_EQ(SCM_CAR(tmp_x), SCM_CAR(tmp_y))); test_priv_CopyList(SCM_CAR(tmp_x), SCM_CAR(tmp_y)); } tmp_x = SCM_CDR(tmp_x); tmp_y = SCM_CDR(tmp_y); } } void test_scheme_Scm_CopyList(void) { ScmObj base, copy; base = Scm_Cons(SCM_MAKE_INT(1), Scm_Cons(SCM_MAKE_INT(2), Scm_Cons(SCM_MAKE_INT(3), SCM_NIL))); copy = Scm_CopyList(base); test_priv_CopyList(base, copy); base = Scm_List(SCM_MAKE_CHAR('a'), SCM_FALSE, SCM_TRUE, Scm_List(SCM_MAKE_INT(1), SCM_MAKE_INT(2), SCM_MAKE_INT(3), SCM_NIL), SCM_NIL); copy = Scm_CopyList(base); test_priv_CopyList(base, copy); }
二つめの試験でループしている模様。よく見りゃ car がペアだった場合の処理が滅茶苦茶だし、ここでも car 取ってない。以下の修正して試験パス。
ScmObj Scm_CopyList(ScmObj list) { ScmObj tmp, ret = SCM_NIL, end, pair; for(tmp = list; SCM_PAIRP(tmp); tmp = SCM_CDR(tmp)) { if(SCM_PAIRP(SCM_CAR(tmp))) { pair = Scm_CopyList(SCM_CAR(tmp)); SCM_APPEND1(ret, end, pair); } else { SCM_APPEND1(ret, end, SCM_CAR(tmp)); } } return ret; }
それにしても SCM_APPEND1 ってマクロは便利。
ってか
そろそろ面倒臭くなりはじめています。gauche の実装カンニングしたひ。eq? とかのあたり特に。