[Anthy-dev 2503] r5rs: portの抽象化

Back to archive index

YamaKen yamak****@bp*****
2005年 10月 8日 (土) 01:55:36 JST


ヤマケンです。

SigSchemeにstring portが追加されましたが、インタプリタ側がこれを
認知して個別対応する必要があるのでメンテナンス性や今後の拡張に難
があると感じています。また、Schemeで書かれたportへの対応が不十分
です。

そこで以下のような抽象化によりタイプ依存コードを隠蔽する事を提案
します。どうでしょうか。

enum ScmPortDirection {
    SCM_PORTDIR_NONE   = 0,
    SCM_PORTDIR_OUTPUT = 1 << 0,
    SCM_PORTDIR_INPUT  = 1 << 1
};

struct ScmPortCell {
    enum ScmPortDirection direction;
    ScmCPort *cport;
} port;

struct ScmCPortVTbl {
    ScmObj (*type)(ScmCPort cport);  /* returns a symbol */
    int (*finalize)(ScmCPort cport);
    int (*close_input)(ScmCPort cport);
    int (*close_output)(ScmCPort cport);
    /* input */
    int (*getc)(ScmCPort cport);
    int (*peek_char)(ScmCPort cport);
    int (*char_readyp)(ScmCPort cport);
    /* output */
    int (*vprintf)(ScmCPort cport, const char *str, va_list args);
    int (*display)(ScmCPort cport, const char *str);
    size_t (*ndisplay)(ScmCPort cport, size_t size, const char *str);
    int (*putc)(ScmCPort cport, int ch);
    int (*flush)(ScmCPort cport);
};

struct ScmCPort {
    const ScmCPortVTbl *vptr;
};

struct ScmFilePort {
    const ScmCPortVTbl *vptr;

    FILE *file;
};

/* in/out */
struct ScmStrPort {
    const ScmCPortVTbl *vptr;

    char *str;
    char *cur_pos;
    size_t buf_size;
};

/* input only */
struct ScmStrInputPort {
    const ScmCPortVTbl *vptr;

    const char *str;
    const char *cur_pos;
};

#define SCM_CPORT_GETC(cport)     ((*cport->vptr->getc)(port))
#define SCM_CPORT_PUTC(cport, ch) ((*cport->vptr->putc)(port, ch))

- ScmPortTypeは廃止。SigSchemeが予め知っているタイプのportにしか
  対応できないため

- ScmPort自体は単一のオブジェクトで入出力の両方に対応可能とする

- ScmPortDirectionはSchemeレベルで入力/出力を制限するためのもの。
  ScmCell側に持たせる事により、単一のScmCPortを共有したin/out2つ
  のportを作成可能にする

- printf()は現在の実装のようにインタプリタ側の前処理で文字列とし
  て直接展開するより、各port実装に委譲してしまった方が効率的。
  portがprintfに責任を持つモデルも不自然ではない。ただしSchemeで
  書かれたportに対しては展開して渡してやる必要がある(固定サイズ
  バッファを使うよりはasprintfをreplace functionとして導入する方
  が良いと思います)


Schemeで書かれたportについては以下のような対応を行う必要がありま
す。

- デフォルトportの取得は内部関数といえども必ず
  current-(input|output)-portの呼び出しにより行う必要がある。
  procedureが再定義される場合があるため

- portを操作する内部関数(SigScm_WriteToPort(),
  print_ScmObj_internal()等)はSchemeで書かれたportにも対応する必
  要がある。portの実体が単なるlistやvectorだったりするするので、
  その場合はwrite, display等のprocedure呼び出しにより実行する必
  要がある

-------------------------------
ヤマケン yamak****@bp*****



Anthy-dev メーリングリストの案内
Back to archive index