SICP 読み (388) 5.5 翻訳系

そういえば下の手続きは繰り返しで書けるのか。

ScmObj Scm_VaList(va_list elts)
{
    ScmObj ret;
    ret = va_arg(elts, ScmObj);
    if (SCM_NULLP(ret)) {
        va_end(elts);
        return ret;
    }
    return Scm_Cons(ret, Scm_VaList(elts));
}

ええと、SCM_APPEND1 とか使えばなんとかなりそげ

#define VA_NEXT va_arg(elts, ScmObj)
ScmObj Scm_VaList(va_list elts)
{
    ScmObj tmp, ret = SCM_NIL, end;
    for(tmp = VA_NEXT; !SCM_NULLP(tmp); tmp = VA_NEXT) {
        SCM_APPEND1(ret, end, tmp);
    }
    va_end(elts);
}

で、試験してみたら SIGSEGV。よく見たら ret を戻してなひ (爆泣
正しくは以下。一応試験にもパスしてます。

#define VA_NEXT va_arg(elts, ScmObj)
ScmObj Scm_VaList(va_list elts)
{
    ScmObj tmp, ret = SCM_NIL, end;
    for(tmp = VA_NEXT; !SCM_NULLP(tmp); tmp = VA_NEXT) {
        SCM_APPEND1(ret, end, tmp);
    }
    va_end(elts);
	return ret;
}

VA_NEXT ってマクロも微妙感満点ですが ...

端末のセットアップ周辺の作業をしつつこちら方面も。
とりあえず gauche.h の

extern ScmObj Scm_PairP(ScmObj obj);
extern ScmObj Scm_Car(ScmObj obj);
extern ScmObj Scm_Cdr(ScmObj obj);
extern ScmObj Scm_Caar(ScmObj obj);
extern ScmObj Scm_Cadr(ScmObj obj);
extern ScmObj Scm_Cdar(ScmObj obj);
extern ScmObj Scm_Cddr(ScmObj obj);
(以下略

あたりの試験とか実装を機械的にヤッツケる方向で。

続々

で、以下の試験を書いて make したら試験が実行されない。コンパイル等は正常に処理されているように見える。.o 対象で grep してもその関数シンボルがありそげに見える。
色々試行錯誤を重ねて最終的に test suite を複数にしてみたら試験が実行された。どうも test suite 一つ当たり 42 を超えた試験がある場合、42 番目以降の試験は実行されないみたい。がしかし、test suite に登録する順番変えても動作は変わらんかったんだよなぁ。どーゆー事なんでしょうか。

void test_scheme_Scm_PairP(void)
{
	CU_ASSERT_EQUAL(SCM_TRUE, Scm_PairP(Scm_Cons(SCM_MAKE_INT(1), SCM_NIL)));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_OBJ(SCM_CLASS_TOP)));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_OBJ(SCM_CLASS_CLASS)));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_MAKE_CHAR('a')));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_MAKE_INT(1)));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_NIL));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_TRUE));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_FALSE));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_EOF));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_UNDEFINED));
	CU_ASSERT_EQUAL(SCM_FALSE, Scm_PairP(SCM_UNBOUND));
}

ちなみに実装が以下で、一つ目の assert は必ず失敗、だったのですが

ScmObj Scm_PairP(ScmObj obj)
{
	return SCM_FALSE;
}

なんか微妙なトコロでハマってるなぁ (駄目

やはり微妙だった Makefile

test ディレクトリの中の Makefile がやはり微妙だった模様。pair.c 修正しても試験に反映されていない。

TARGET  := test
OBJS    := main.o test-PRIMARY_TAG.o test-IMMEDIATES.o test-BOOLEAN.o \
	   test-FIXNUM.o test-CHARACTERS.o test-HEAP.o test-equivalence.o \
           test-PAIR.o test-APPEND.o test-LIST.o
CFLAGS  := -I.. -Wall -g
LDFLAGS := -lcunit -lgc
ARCHIVE := ../scheme.a

all: $(TARGET)
	@./$(TARGET)

$(TARGET): $(OBJS) ../gauche.h
	$(CC) -o $(TARGET) $(OBJS) $(LDFLAGS) $(ARCHIVE)

clean:
	-rm -rf $(TARGET) $(OBJS) *~

$(TARGET) が $(ARCHIVE) に依存していないコトになってるのでリコンパイルされていなかった、というのが原因。もっと早めに気づけよ、と。

続々の続き

そろそろ中見出しが微妙だな。Scm_PairP() 関数の実装は以下

ScmObj Scm_PairP(ScmObj obj)
{
	return SCM_MAKE_BOOL(SCM_PAIRP(obj));
}

gauche.h のマクロ達はなんかええ感じッス。一応上記な試験にもパス。次は car/cdr なんですが、これって全部マクロの組み合せで書いちゃって良いのかなぁ。

ScmObj Scm_Car(ScmObj obj)
{
    return SCM_CAR(obj);
}

つい、return って書くのを忘れてしまいがち (何