crowbar ver.0.1.01

マイナーバージョンアップ

次は配列を実装してからかなあ、と思っていたのですが、 for文とif文のえらくまぬけなバグを放置したままにしておくのはアレですので、 ひとまずver.0.1.01を上げておきます。

ver.0.1.01での修正点は以下の通りです。

今回追加したネイティブ関数については、前にもましてテストがぬるいので、 かえってバグが増えているかもしれませんが、 crowbarは所詮サンプルプログラムだということでひとつ(言い訳)。

GLOBALをかましたソースは こちらから参照可能です。

ダウンロードは、UNIX版がこちら、 Windows版がこちら

データ型の追加

上にも書いたように、ver.0.1.01では、 論理型とネイティブポインタ型を追加しています。

論理型は、Javaなどの他の言語でもよく見られる、 trueとfalseを表現する型です。 ver.0.1では整数型で代用していましたが、 論理型の導入に伴い、整数型を論理型として使うことはできなくなっています。 たとえばif文の条件式に整数型を使うことはもうできませんし、 &&, ||演算子のオペランドとしても論理型以外の型は使えません。

また、予約語としてtrue, falseを追加しました。

ネイティブポインタ型とは、 C#あたりでは「どうしてもメモリに直接アクセスしたい」 ケースで使用する型であるようですが、 crowbarのネイティブポインタ型は、そういう邪悪な型ではなく、 「ネイティブ関数からネイティブ関数へ、 Cレベルのポインタを持ち運ぶための型」です。

ネイティブポインタ型は、たとえばCのFILE*などを表現するために使います。 今回追加したネイティブ関数には、fopen()も含まれますが、

  fp = fopen("hoge.txt", "r");

と書くことができます。この時、fpがネイティブポインタ型です。

このfpは、fgets()やfclose()などに渡すことができます。 crowbarからは、 ネイティブポインタの指す先を読み書きするような操作はできません。

FILE*に限らず、GUIをサポートするネイティブ関数群を作る際に GUI部品へのポインタを入れるなど、利用範囲は広いと思います。 JavaのJNIにこれがなくて苦労した憶えが…

今回ふたつのデータ型が増えましたから、 CRB_Value型には以下の変更を加えました。

typedef enum {
    CRB_BOOLEAN_VALUE = 1,
    CRB_INT_VALUE,
    CRB_DOUBLE_VALUE,
    CRB_STRING_VALUE,
    CRB_NATIVE_POINTER_VALUE,
    CRB_NULL_VALUE
} CRB_ValueType;

typedef struct {
    CRB_ValueType       type;
    union {
        CRB_Boolean     boolean_value;
        int             int_value;
        double          double_value;
        CRB_String      *string_value;
        void            *native_pointer_value;
    } u;
} CRB_Value;

その他、予約語true, falseが増えたことでcrowbar.lとcrowbar.yに、 式の評価部分の変更でeval.cに変更が加わっています。

また、細かい修正では、nullが比較に使えるようになった、 という点があります。 今まではnullには文字列との加算以外の演算子が適用できませんでしたが、 ==と!=が使えるようになりました。 これがないとfgets()でファイルの終端が判定できなかったので―― いやその行き当たりばったりですみません。

ネイティブ関数の追加

ネイティブポインタ型によりFILE*が表現できるようになったので、 いくつかファイル操作の関数を追加してみました。 基本的にCのstdio.hからパクりましたが、 crowbarでは文字列型が使えることから、多少仕様が変わっています。

fopen(filename, mode) ファイルをオープンし、ファイルポインタを返します。 modeの仕様はCのfopen()と同じです(そのまま渡してるだけなので)。
fclose(fp) fpで渡されたファイルをクローズします。
fgets(fp) fpから1行分の文字列を取得して返します。
fputs(str, fp) fpに文字列を出力します。改行を追加するようなマネはしません。

これらのネイティブ関数を使ったサンプルプログラムとして、 ftest.crbを挙げておきます。

fp = fopen("ftest.crb", "r");
fp2 = fopen("ftest.result", "w");

while ((str = fgets(fp)) != null) {
    fputs(str, fp2);
}
fclose(fp);
fclose(fp2);

――しかし、今回はとりあえずCのstdio.hの仕様をパクったわけですが、 あらためて見てみるとつくづく酷いですな。 引数のfpが最初だったり最後だったり、 fputs()は改行を付けないのにputs()は付けたりします。 てなわけで、今回のネイティブ関数群は、出来た時から非推奨です。 いずれはストリーム的なオブジェクトのメソッドとして実現したいと思いますし。

既知の不具合(2005/4/20追加)

メモリ管理モジュールMEMに、以下の不具合があります。

ふたつめの問題は致命的です。早急に対処いたします(_o_)

2005/4/21追記:
ver.0.2にて修正しました。
ただ、この企画の性質上、 ver.0.1をベースにソースをこねくり回す人もいてもよく(0.2ではeval.c がごっそり変わっていますし)、 余裕のある時に0.1.01のソースは変更しておくつもりです(さらに追記:修正しました)。

今後のこと

次回はいよいよ配列を実装しようと思っています。

んで、配列リテラルを「{1, 2, 3}」というような形で書けるようにしてみたら、 for文あたりでconflict起こすわ、 配列の要素として配列を含むことができるようにしようとすると、 循環参照を許すことになるので参照カウンタ式のGCは破綻するわで、 実装は結構面倒です。

とはいえひと週末フルに使えばとりあえず目鼻は付く程度のことだと思うんですが、 最近仕事はアレな状態ですし、体調もすぐれなくて、なんとも。

すみませんが気長にお待ちくださいませ。


前のページ | 次のページ | ひとつ上のページに戻る | トップページに戻る