SICP 読み (385) 5.5 翻訳系

問題 5.51

なんかグズグズです。ヤッてて微妙感満点だし。とりあえず現時点では eq? も eqv? も equal? も同じと見て pair 方面に進めてみる。
以下の方向で

  • PairClass と NullClass を使う (ListClass はとりあえずスルー)
  • Scm_Cons が実装できないとマクロの試験もへったくれも無い
  • ScmPairRec 構造体の attributes って何だろ

多分、心理的に面倒クサイって思ってヤッてるから gdgd なんだろうな。(とほほ

とりあえず Scm_Cons から

ええと手順としては

  • new = SCM_NEW(ScmPair) して
  • SCM_SET_CAR(new, car) して
  • SCM_SET_CDR(new, cdr) して
  • new を戻せば OK??

てーコトは SCM_NEW とか SCM_SET_CAR とか SCM_SET_CDR の試験しねぇと駄目だな。一応 SCM_NEW は試験スルーとしても

void test-scheme-SET-CAR(void)
{
    ScmObj obj = SCM_OBJ(SCM_NEW(ScmPair));
    SCM_SET_CAR(obj, SCM_MAKE_INT(5));
    CU_ASSERT_EQUAL(5, SCM_INT_VALUE(SCM_PAIR(obj)->car));
    CU_ASSERT_EQUAL(5, SCM_INT_VALUE(SCM_CAR(obj)));
}

みたいな試験はしといた上で Scm_Cons の試験をした方が良いのか。Scm_Cons() ができたら SCM_LIST マクロなんかも試験できそげ。
ちょっと今、集中して何かをヤる態勢になれてないので微妙ッス。こんな下書き書くなら作業ヤレよ、って自分でも思うんですがなんとなく (以下略

で、作ってみた。試験が以下 (test-PAIR.c)

#include <CUnit/CUnit.h>

#include "gauche.h"

void test_gauche_SET_CAR(void)
{
    ScmObj obj = SCM_OBJ(SCM_NEW(ScmPair));
    SCM_SET_CAR(obj, SCM_MAKE_INT(5));
    CU_ASSERT_EQUAL(5, SCM_INT_VALUE(SCM_PAIR(obj)->car));
    CU_ASSERT_EQUAL(5, SCM_INT_VALUE(SCM_CAR(obj)));
}

void test_gauche_SET_CDR(void)
{
    ScmObj obj = SCM_OBJ(SCM_NEW(ScmPair));
    SCM_SET_CDR(obj, SCM_MAKE_INT(5));
    CU_ASSERT_EQUAL(5, SCM_INT_VALUE(SCM_PAIR(obj)->cdr));
    CU_ASSERT_EQUAL(5, SCM_INT_VALUE(SCM_CDR(obj)));
}

void test_scheme_Scm_Cons(void)
{
	ScmObj obj = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	CU_ASSERT_EQUAL(1, SCM_INT_VALUE(SCM_CAR(obj)));
	CU_ASSERT_EQUAL(2, SCM_INT_VALUE(SCM_CDR(obj)));
}

Scm_Cons() の定義が書いてある pair.c が以下なカンジ

#include "gauche.h"

SCM_DEFCLASS(Scm_PairClass, "Pair", NULL, NULL);

ScmObj Scm_Cons(ScmObj car, ScmObj cdr)
{
	ScmObj obj = SCM_OBJ(SCM_NEW(ScmPair));
	SCM_SET_CAR(obj, car);
	SCM_SET_CDR(obj, cdr);
	SCM_PAIR_ATTR(obj) = NULL;
	return obj;
}

cons が動いてるのが確認できたら色々やる事は沢山ありそげ。

  • SCM_PAIRP マクロの試験
  • SCM_CAAR, SCM_CADR, SCM_CDAR, SCM_CDDR マクロの試験
  • SCM_LISTP マクロ (これは一体何なのか、を未だ理解できてません
  • SCM_FOR_EACH マクロの試験
  • SCM_APPEND1 マクロの試験
  • SCM_APPEND マクロの試験
  • SCM_LIST の関係者な方々の試験
  • Scm_List() 関数の定義と試験
  • Scm_PairP() 関数の定義と試験
  • car/cdr 関連な関数の定義と試験
  • Scm_Length(), Scm_Append(), Scm_ListTail(), Scm_ListRef() 関数の定義と試験
  • memq/assq 関連
  • Scm_NullP(), Scm_ListP() 関連

帰宅後

Scm_Cons() の試験の修正含め、いくつか試験を書いてみた。

void test_scheme_Scm_Cons(void)
{
	ScmObj obj = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	CU_ASSERT_EQUAL(1, SCM_INT_VALUE(SCM_CAR(obj)));
	CU_ASSERT_EQUAL(2, SCM_INT_VALUE(SCM_CDR(obj)));
	CU_ASSERT_EQUAL(NULL, SCM_PAIR_ATTR(obj));
}

void test_gauche_SCM_PAIRP(void)
{
	ScmObj obj = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	CU_ASSERT_TRUE(SCM_PAIRP(obj));
}

void test_gauche_SCM_CAAR(void)
{
	ScmObj obj1 = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	ScmObj obj2 = Scm_Cons(SCM_MAKE_INT(3), SCM_MAKE_INT(4));
	ScmObj obj3 = Scm_Cons(obj1, obj2);
	CU_ASSERT_EQUAL(1, SCM_INT_VALUE(SCM_CAAR(obj3)));
}

void test_gauche_SCM_CDAR(void)
{
	ScmObj obj1 = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	ScmObj obj2 = Scm_Cons(SCM_MAKE_INT(3), SCM_MAKE_INT(4));
	ScmObj obj3 = Scm_Cons(obj1, obj2);
	CU_ASSERT_EQUAL(2, SCM_INT_VALUE(SCM_CDAR(obj3)));
}

void test_gauche_SCM_CADR(void)
{
	ScmObj obj1 = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	ScmObj obj2 = Scm_Cons(SCM_MAKE_INT(3), SCM_MAKE_INT(4));
	ScmObj obj3 = Scm_Cons(obj1, obj2);
	CU_ASSERT_EQUAL(3, SCM_INT_VALUE(SCM_CADR(obj3)));
}

void test_gauche_SCM_CDDR(void)
{
	ScmObj obj1 = Scm_Cons(SCM_MAKE_INT(1), SCM_MAKE_INT(2));
	ScmObj obj2 = Scm_Cons(SCM_MAKE_INT(3), SCM_MAKE_INT(4));
	ScmObj obj3 = Scm_Cons(obj1, obj2);
	CU_ASSERT_EQUAL(4, SCM_INT_VALUE(SCM_CDDR(obj3)));
}

void test_gauche_SCM_FOR_EACH(void)
{
	int i = 0;
	ScmObj tmp;
	ScmObj obj1 = Scm_Cons(SCM_MAKE_INT(2), SCM_NIL);
	ScmObj obj2 = Scm_Cons(SCM_MAKE_INT(1), obj1);
	ScmObj obj3 = Scm_Cons(SCM_MAKE_INT(0), obj2);
	SCM_FOR_EACH(tmp, obj3) {
		CU_ASSERT_EQUAL(i, SCM_INT_VALUE(SCM_CAR(tmp)));
		i++;
	}
}

あと、Scm_Cons() でクラス設定なソレを忘れてた。

ScmObj Scm_Cons(ScmObj car, ScmObj cdr)
{
	ScmObj obj = SCM_OBJ(SCM_NEW(ScmPair));
	SCM_SET_CLASS(obj, SCM_CLASS_PAIR);
	SCM_SET_CAR(obj, car);
	SCM_SET_CDR(obj, cdr);
	SCM_PAIR_ATTR(obj) = NULL;
	return obj;
}

やはり若干 Makefile が微妙らしいんですが、箇所が特定できとりません。