toge's diary

コンピュータ関連の趣味をつらつらと。

C++でxtalのiteratorを返す関数を作る

さらにしつこくC++からxtalをいじってみてます。
次はC++で書いたxtaliteratorを、生成して返すC++の関数を作ってみます。(わけわからん)
ちょっとソース読んでごにょごにょしてたら、動いたのでよしとします。

#include "xtal/xtal.h"

class IterTest {
  int value_;

public:
  IterTest(int value)
    : value_(value)
  {}

  void iter_next(const xtal::VMachine& vm) {
    if (value_ > 10) {
      vm.return_result(xtal::Null());
      return;
    }
    vm.return_result(xtal::UserData<IterTest>::from_this(this), xtal::Any(value_));
    value_++;
  }
};

//これがiteratorを返す関数
xtal::Any gen_itertest(int value) {
  return xtal::new_userdata<IterTest, int>(value);
}

int
main()
{
  // Xtalの初期化
  xtal::initialize();

  try
  {
    xtal::TClass<IterTest> itertest("IterTest"); // IterTest クラスを構築

    itertest.inherit(xtal::Iterator());
    itertest.def("new", xtal::New<IterTest, int>().param(xtal::Named("value", 0)));
    itertest.method("iter_first", &IterTest::iter_next);
    itertest.method("iter_next", &IterTest::iter_next);

    // これを書いておかないとループに入ってメモリを馬鹿食いする
    xtal::lib().def("IterTest", itertest);

    xtal::Class iter("iter");
    iter.fun("gen", &gen_itertest);
    xtal::lib().def("iter", iter);

    xtal::Any ret = xtal::lib().member("iterator");
  }
  catch(xtal::Any ex) {
    std::cout << ex << std::endl;
  }

  return 0;
}

コメントに書きましたが、別にlibに登録したくないIterTestを登録しないと、うまく動かなくなっちゃいます。動かすと(おそらくコンパイルで)無限ループに陥り、メモリを馬鹿食いし始めます。

string.cppのStringSPlitImplとか見る限りでは、IterTestは登録しなくてもいいように見えるんだけどなぁ。

test : lib::IterTest(5); 
test.join("-").p;

lib::iter::gen(5).join(",").p;