Io を組込め

私的には組込み言語として Io を使いたいと考えているので、そのへんで遊んでみます。

とりあえずとても簡単な例を。ドキュメントからパクっただけ。

// とってもシンプルな例。

#include "IoVM.h"

void MyPrint(void *state, char *s) { printf(s); }
void MyExit(void *state) { exit(0); }
void MyError(void *state, char *name, char *description) {
    printf("Error: %s - %s\n", name, description);
}

int main(int argc, char* argv[]) {
    IoObject* result;
    IoState* self;
    IoObject* context;

    self = IoState_new();

    IoState_printCallback_(self, MyPrint);
    IoState_errorCallback_(self, MyError);
    IoState_exitCallback_(self, MyExit);

    result = IoState_doCString_(self, "1+2");
    printf("result = <%s %d>\n",
           IoObject_name(result), IoNumber_asInt((IoNumber*)result));

    IoState_free(self);

    return 0;
}

1+2 = 3

次は C と Io の相互呼び出しを。とりあえず account.io と use_account.io を作る。

# account.io
Account = Object clone
Account init =  method(self balance = 0)
Account deposit = method(v, balance += v)
Account show = method(
  write("Account balance: $", balance, "\n")
)
# use_account.io
myAccount = Account clone
myAccount show
myAccount deposit(10)
myAccount show

この段階で動作確認。両方を順番に実行してみる。

> (echo 'doFile("account.io")'; echo 'doFile("use_account.io")') | io
IoVM version 20031028
Io>
==> Block_0x808c048
Io> Account balance: $0
Account balance: $10

==> Nil
Io>
==> Nil

OK。

では account.io を使って、C から Io を使う例。use_account.io 相当のことを C 内で行う。

// io を C から使う例

#include "IoVM.h"

void MyPrint(void *state, char *s) { printf(s); }
void MyExit(void *state) { exit(0); }
void MyError(void *state, char *name, char *description) {
    printf("Error: %s - %s\n", name, description);
}

int main(int argc, char* argv[]) {
    IoObject* Account;
    IoObject* myAccount;
    IoMessage* msgClone;
    IoMessage* msgShow;
    IoMessage* msgDeposit;
    IoState* self;
    IoObject* context;

    self = IoState_new();

    IoState_printCallback_(self, MyPrint);
    IoState_errorCallback_(self, MyError);
    IoState_exitCallback_(self, MyExit);

    IoState_doFile_(self, "account.io");

    context = (IoObject *)IoState_doCString_(self, "Lobby");

    Account = IoState_doCString_(self, "Account");

    msgClone = IoMessage_newWithName_(self, SIOSTRING("clone"));
    myAccount = IoObject_perform(Account, context, msgClone);

    msgShow = IoMessage_newWithName_(self, SIOSTRING("show"));
    IoObject_perform(myAccount, context, msgShow);

    msgDeposit = IoMessage_newWithName_(self, SIOSTRING("deposit"));
    IoMessage_addCachedArg_(msgDeposit, IoNumber_newWithDouble_(self, 10));
    IoObject_perform(myAccount, context, msgDeposit);

    IoObject_perform(myAccount, context, msgShow);

    IoMessage_free(msgClone);
    IoMessage_free(msgShow);
    IoMessage_free(msgDeposit);

    IoState_free(self);

    return 0;
}

Account 抜くのに IoState_doCString_ は使いたくないなあ…他の方法もあるんだろうけど見つけられてません。

次はその逆。account.io 相当を C で定義して、use_account.io を実行。

// C を io から使う例

#include "IoVM.h"

void MyPrint(void *state, char *s) { printf(s); }
void MyExit(void *state) { exit(0); }
void MyError(void *state, char *name, char *description) {
    printf("Error: %s - %s\n", name, description);
}

typedef struct {
    int balance;
} Account;

typedef IoObject IoAccount;

IoTag* IoAccount_tag(void* state);
IoAccount* IoAccount_proto(void *state);
IoAccount* IoAccount_rawClone(IoAccount* self);
IoAccount* IoAccount_new(void* state);
void IoAccount_free(IoAccount* self);
void IoAccount_mark(IoAccount* self);
int IoAccount_compare(IoAccount* self);
IoAccount* IoAccount_clone(IoAccount* self, IoObject* locals, IoMessage* m);
IoAccount* IoAccount_deposit(IoAccount* self, IoObject* locals, IoMessage* m);
IoAccount* IoAccount_show(IoAccount* self, IoObject* locals, IoMessage* m);

IoTag* IoAccount_tag(void* state) {
    IoTag *tag = IoTag_newWithName_("Account");
    tag->state = state;
    tag->freeFunc = (TagFreeFunc *)IoAccount_free;
    tag->cloneFunc = (TagCloneFunc *)IoAccount_rawClone;
    tag->markFunc = (TagMarkFunc *)IoAccount_mark;
    tag->compareFunc = (TagCompareFunc *)IoAccount_compare;
    return tag;
}

IoAccount* IoAccount_proto(void *state) {
    IoObject *self = IoObject_new(state);
    Account* account;
    self->tag = IoAccount_tag(state);

    account = (Account*)malloc(sizeof(Account));
    account->balance = 0;
    self->data = account;
    IoState_registerProtoWithFunc_(state, self, IoAccount_proto);

    IoObject_addMethod_(self, IOSTRING("clone"), IoAccount_clone);
    IoObject_addMethod_(self, IOSTRING("deposit"), IoAccount_deposit);
    IoObject_addMethod_(self, IOSTRING("show"), IoAccount_show);

    return self;
}

IoAccount* IoAccount_rawClone(IoAccount* self) {
    IoObject* child = IoObject_rawClonePrimitive(self);
    Account* account = (Account*)malloc(sizeof(Account));
    account->balance = 0;
    child->data = account;
    child->tag = self->tag;
    return child;
}

IoAccount* IoAccount_new(void* state) {
    IoObject* proto = IoState_protoWithInitFunction_(state, IoAccount_proto);
    return IoAccount_rawClone(proto);
}

void IoAccount_free(IoAccount* self) {
    free*1;
    account->balance = data)->balance);
    return self;
}

int main(int argc, char* argv[]) {
    IoState* self;
    IoObject* context;

    self = IoState_new();
    context = (IoObject *)IoState_doCString_(self, "Lobby");

    IoState_printCallback_(self, MyPrint);
    IoState_errorCallback_(self, MyError);
    IoState_exitCallback_(self, MyExit);

    IoObject_setSlot_to_(context, SIOSTRING("Account"), IoAccount_proto(self">*2;

    IoState_doFile_(self, "use_account.io");

    IoState_free(self);

    return 0;
}

ちょっとめんどいね。

さて、あっさり書いてきたわけですけど結構苦労してます。ていうか日本語のドキュメントが無いどころか英語でもほとんど無いよ… 1+2 の例だけ見せられても。

一応今回の参考文献。

http://groups.yahoo.com/group/iolanguage/message/1739
http://groups.yahoo.com/group/iolanguage/message/1808
http://groups.yahoo.com/group/iolanguage/message/2328

ML だけかよ。あとはソースを読むしか無い。

(少し前は Linux で seg ると記述していましたが、IoDesktop-2003-11-23 では解決されているようです)

*1:Account*)self->data); } void IoAccount_mark(IoAccount* self) {} int IoAccount_compare(IoAccount* self) { return 0; } IoObject* IoAccount_clone(IoAccount* self, IoObject* locals, IoMessage* m) { IoObject* child = IoObject_rawClonePrimitive(self); Account* account = (Account*)malloc(sizeof(Account

*2:Account*)self->data)->balance; child->data = account; child->tag = self->tag; return child; } IoObject* IoAccount_deposit(IoAccount* self, IoObject* locals, IoMessage* m) { IoObject* v = IoMessage_locals_valueArgAt_(m, locals, 0); ((Account*)self->data)->balance += IoNumber_asInt((IoNumber*)v); return self; } IoObject* IoAccount_show(IoAccount* self, IoObject* locals, IoMessage* m) { printf("Account balance: $%d\n", ((Account*)self->data)->balance); return self; } int main(int argc, char* argv[]) { IoState* self; IoObject* context; self = IoState_new(); context = (IoObject *)IoState_doCString_(self, "Lobby"); IoState_printCallback_(self, MyPrint); IoState_errorCallback_(self, MyError); IoState_exitCallback_(self, MyExit); IoObject_setSlot_to_(context, SIOSTRING("Account"), IoAccount_proto(self

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h