オブジェクト指向スクリプト言語 Clover マニュアル

目次

言語の特徴

UNIXシステム向けのスクリプト言語です。コンパイルはしますが速度を上げるためというよりは型チェックのためにコンパイラがあります。あとは基礎的なライブラリにもメソッドを追加したり改良したりでき自由度が高いので、楽しいプログラミングができるようになってます。
  1. 静的な型付けかつ動的な型付けにも対応
  2. C言語やJavaに似た文法
  3. ブロック付きメソッドがある
  4. 対話的な環境がある。readlineを使いメソッド名の補完にも対応
  5. 全てがオブジェクト
  6. 外部コマンドの実行をライブラリに組み込んでいて簡単に外部コマンドを呼び出せる
  7. 正規表現を使った文字列処理を行える
  8. ソースファイルをコンパイルして実行する。型チェックのためのテストは必要がない
  9. Javaに似たgenericsがある。

サンプルソース

iclover > echo("HELLO WORLD");
HELLO WORLD
=>

iclover > 1+1
=>2

iclover > 1.toString() * 3
=>"111"

iclover > Command.pwd()
=> /Users/ab25cq

iclover > Command.pwd().toString().scan(/./).join("+").toCommand().less()
=> /+U+s+e+r+s+/+a+b+2+5+c+q+/

ダウンロード

開発版の入手
git clone https://github.com/ab25cq/clover.git
安定版の入手
https://osdn.jp/projects/clover/

依存しているライブラリ

開発バージョンのパッケージが必要なので、Debian系では-dev、Fedora系では-develをインストールしてください。例えばlibmならlibm-devやlibm-develとなっているはずです。(未確認)

インストール

まず依存しているライブラリを入れてください。依存関係が解決しているかですか、./configureがエラーが無く実行できれば解決していると思ってください。
./configure --with-optimize
make
sudo make install
--with-optimizeで最適化を行います。プログラムの実行速度が上がります。
デフォルトではインストールされるディレクトリは/usr/localです。

--prefixでプログラムをインストールするディレクトリを決めます。例えば
./configure --prefix=$HOME --with-optimize
make 
make install
でユーザーディレクトリにインストールします。(root権限が要らない)

インストールされるファイルは
$PREFIXがインストールされるディレクトリをとすると、
$PREFIX/include → clover.hが置かれます。cloverを組み込む場合に必要になるかもしれません。今のところ、組み込める状態ではないです。
$PREFIX/lib/libclover.* → cloverコマンドのUNIX動的ライブラリが置かれます。実行に必要です。
$PREFIX/share/clover/doc → READMEやCHANGELOG, USAGEなどが置かれます。ドキュメントです。
$PREFIX/share/man/man1/clover.1 → UNIXのコマンドのマニュアルが置かれます。
$PREFIX/share/clover → Cloverのコンパイル済みの組み込みライブラリが置かれます。
$PREFIX/bin → Cloverの実行ファイルが置かれます。
~/.clover → Cloverが実行時に使うディレクトリです。一時ファイルを置いたりします。

プログラムは複数のコマンドから成り立ってます。

clover → プログラムを実行する仮想マシン。
cclover → コンパイラ。クラスを記述した.clc拡張子のソースや、スクリプト本体を書いた.cl拡張子のソースをコンパイルします。
pclover → Cloverプリプロセッサ。Cloverはシェルスクリプトなどを使ってソースを生成することができます。とりあえずC言語の定数をCloverに取り込むのに使っています。
psclover → Cloverのパーサ。今のところインタプリタ以外では意味がありませんが、将来的にはCloverのソースを解析するのに使いたいと思っています。
iclover → Cloverインタプリタです。

チュートリアル

Cloverを使うためには前提としてC言語、Javaのどちらかの知識が必要です。もし、どちらの言語の経験もない人は先にそちらを使ってください。

とりあえず、何か書いてみましょう。お決まりのHELLO WORLDでいきます。

$ vim a.cl
pritnln("HELLO WORLD");
$ cclover a.cl
$ clover a.cl
HELLO WORLD
好きなエディッタでa.clというファイルを編集してください。その後にそのファイルをccloverコマンドでコンパイルしてcloverコマンドで実行するとスクリプトは実行できます。

printlnは本来はClover.printlnと書かないといけないんですが、aliasされているので、Cloverは省略できます。コンパイルされるときに自動的にClover.printlnと入力したことと同じになります。

次はクラスを作ってみましょう。

$ vim student.clc
class Student 
{
    private String name;
    private int age;

    Student(String name, int age) {
        self.name = name;
        self.age = age;
    }
    void show() {
        printf("NAME: %ls AGE: %d\n", self.name, self.age);
    }
}
$ vim student.cl
Student ab25cq = new Student("ab25cq", 38);
ab25cq.show();
$ cclover student.clc
$ cclover studnet.cl
$ clover student.cl
NAME: ab25cq AGE: 38
クラスを書くためには拡張子がclcのソースファイルを書く必要があります。「cclover student.clc」というコマンドを実行するとStudent.cloというクラスファイルができるはずです。そのファイルが検索パスにあれば、そのクラスを使うときにincludeやimportする必要はありません。スクリプト本体であるstudent.clで何もせずに使うことができます。検索パスにはカレントディレクトリが含まれています。よく使うクラスは~/.clover/libに置いておくと、カレントディレクトリがどこでもクラスを使うことができます。

printfはprintlnと同じでClover.printfが本来の名前です。aliasされているので、printfと書くだけで使用できます。printfでself.nameを表示するために%lsを使ってる理由はCloverのStringはUTF16/UTF32なので、%sでは表示できないためです。
あと、フィールド名のselfは省略することができません。

次はintクラスにdownToメソッドを追加してみましょう。

$ vim my_int.clc
mixin class int version 3 
{
    int downTo(int value) with void block(int number) {
        for(int i=self; i>=value; i--) {
            block(i);
        }

        return self;
    }
}
$ vim my_int.cl
5.downTo(3) {|int n|
    n.toString().println();
}
$ cclover my_int.clc
$ cclover my_int.cl
$ clover my_int.cl
5
4
3
Cloverはopenクラスなので基礎的なクラスにもメソッドを追加することができます。その場合はmixinキーワードをclassの前に書いてversionを明記してください。intクラスはインストール時にversion2となっているので、この場合は3です。($PREFIX/share/clover/int#2.cloが存在している)

既存のクラスのメソッドを改良することもできます。

Arrayのoperator[]で存在しないindexを引数に取ると例外を出すようにしてみましょう。本来はnullを返します。

$ vim my_array.clc
mixin class Array <T implements IComparable> version 2
{
    T operator[](int index) throws Exception {
        T result = mixin(index);
        if(result == null) {
            throw new Exception("Invalid index");
        }
        return result;
    }
}
$ vim my_array.cl
{1,2,3,4,5,6 }[100];
$ cclover my_array.clc
$ cclover my_array.cl
$ clover my_array.cl
Exception: Invalid index
script file(my_array.cl) is abort
T result = mixin(index);は前に定義したT operator[](int index)を呼び出しています。
{1,2,3,4,5,6}[100]は範囲外なので例外が出ています。

次はインタラクティブに外部コマンドを使ってみましょう。

$ iclover
Welcome to Clover version 1.0.2
iclover > Command.pwd()
=> /Users/ab25cq

iclover > Command.pwd().toString().scan(/./).join("+").toCommand().less()
=> /+U+s+e+r+s+/+a+b+2+5+c+q+/
icloverコマンドでインタラクティブモードを実行します。icloverではTABキーで補完を行う事ができます。クラス名はCo[TAB]でCommandと補完されるはずです。また外部コマンドもCommand.pw[TAB]→Command.pwdと補完されます。scanやjoinなども同様です。その時、補完候補にはメソッドの引数の型も表示されます。

上記はまずCommand.pwd()で現在のカレントディレクトリを得ています。Command.pwdの戻り値はCommandクラスです。それをtoStringでStringクラスに変換して、scanやjoinなど文字列処理を行っています。StringクラスにはtoCommandメソッドがあるので、Commandクラスに変更でき、もう一度Commandクラスにしてlessを実行して端末制御して表示しています。ジョブコントールもあり、この時CTRL-Zキーでジョブを停止することもできます。ジョブの一覧はClover.jobsで見ることができます。Clover.jobs.forground(ジョブ番号)でジョブを復帰することもできます。

チュートリアルとしてこんなところです。CやJavaを知っている人には注意する点は少ないと思うので。ライブラリ解説を見ながら何か作ってみてください。注意点は言語仕様で書いています。

言語仕様

目次
  1. 数値クラス
  2. クラスの定義
  3. structとクラス
  4. コールバイリファレンス、コールバイバリュー
  5. 演算子メソッド
  6. ブロック付きメソッド
  7. anonymousクラスと動的型付け
  8. initializeクラスメソッドとpreinitializeクラスメソッド
  9. enum
  10. プリプロセッサー
  11. ユーザークラスとnativeクラス
  12. 暗黙の継承
  13. インターフェース
  14. モジュール
  15. open class
  16. クラスファイル
  17. クラスの検索パス
  18. アノテーション
  19. 浅いコピーと深いコピー
  20. コンストラクタの定義名
  1. 数値クラス
  2. 数値クラスはint, char, longなどC言語とよく似ています。unsignedやsingnedはありません。
    byte → 符号なし8bit
    short → 符号なし16bit
    int → 符号付き32bit
    uint → 符号なし32bit
    long → 符号なし64bit
    float → 浮動小数点型(32bit)
    double → 浮動小数点型(16bit)
    
    Cloverは数値もオブジェクトです。メッセージを送ることができます。
    1.toString() => "1"
    'a'.toInt() => 97
    
    数値も型には厳格で暗黙変換はありません。
    int a = 1.toByte();    => コンパイルエラー
    
    数値のオブジェクト表現としては以下です。

    数値y → byte
    数値s → short
    数値u → uint
    数値l → long
    数値 → int
    数値.数値 → double
    数値.数値f → float
    int a = 1; => aに1が入る。
    byte b = 1y; => bに1(byte)が入る
    short c = 1s; => cに1(short)が入る
    uint d = 1u; => dに1(uint)が入る。
    long e = 1l; -> eに1(long)が入る。
    double f = 1.1; -> fに1.1(double)が入る。
    float g = 1.1f; -> gに1.1(float)が入る。
    
    byte b = 1;  =>コンパイルエラー
    
    メソッドを使って相互に型を変換することができます。
    byte a = 1.toByte();
    int b = 1l.toInt();
    long c = 1y.toInt().toLong();
    int d = 1.1.toInt();
    
    Fundamental.clcを見ればわかりますが, intなどのクラスは全てstructとして宣言されています。structとclassの違いは代入時に値をコピーするかどうかです。
    int a = 1;
    object.method(1,2);
    
    上記の場合aには1という新しく生成されたオブジェクトのコピーがaに代入されます。またobject.method(1,2)の場合は1と2という新しく生成されたオブジェクトのコピーがメソッドに渡されます。メソッド呼び出しの時に値渡しをするのがstructでリファレンス渡しをするのがclassです。内部的にはcloneメソッドが呼ばれてコピーが生成されて代入されています。

    数値の演算子はC言語やJavaとよく似ているので説明は控えさせてもらいます。ただし、コンマ演算子だけはC言語と同じではありません。コンマ演算子はタプルを生成します。後は演算子の場合も数値の暗黙的な変換はありません。演算子の左右の型は揃えておく必要があります。
    byte a = 1 + 1.toByte();   => コンパイルエラー
    byte a = 1.toByte() + 1.toByte();   => aに2(byte)が入る。
    
  3. クラスの定義
  4. classの定義はJavaとほぼ同じです。単一継承でインターフェースがあり多重継承はできません。クラスの定義は拡張子clcで行う必要があります。スクリプト本体(拡張子cl)にはクラスの定義を含めることはできません。

    クラスの修飾キーワードには以下があります。
    native データがC言語で保持されています。フィールドを保持することができません。
    final 継承することができません。
    abstract 抽象クラスです。newすることができません。abstract methodを定義することができます。
    mixin 既存のクラスにフィールドやメソッドの定義を追加するときに必要です。
    dynamic_typing そのクラスに対する型チェックが動的になります。どのような変数にも代入でき、メソッドはどのようなメソッドも呼び出せます(エラーだと実行時にエラーがでます。)
    
    メソッドの中での自分自身へのインスタンスへの参照はthisではなくてselfを使います。またpythonと同じく、同じクラスのメソッドを呼び出す時も省略はできません。

    クラスにはstatic bool initialize()というクラスの読み込み時に呼び出されるメソッドがあります。処理中エラーがあればfalseを返せば実行を止めることができます。もう一つ同種のメソッドにstatic bool preinitialize()があります。こちらはinitialize()メソッドより先に呼び出されます。初期化コードの呼び出し順の問題が出たら、使ってください。

    メソッドの修飾子には以下があります。

    native C言語で記述されたメソッドを作る場合に必要です。
    nonsynchronized Cloverでは全てのメソッドはThreadを使っている時ロックされています。ロックしたくない場合はこの修飾子を使ってください。
    static クラスメソッドを定義したい場合はこれを使ってください。
    virtual コンパイル時にメソッドを決定するのではなく実行時にメソッドを決定するようになります。Javaと同じです。
    private 同一のクラスのメソッド定義時にしか呼び出せなくなります。
    protected privateとほぼ同じですが継承したクラスのメソッド定義時も呼び出せます。
    mixin メソッドを上書きする場合に使います。Cloverは同名で引数も同じメソッドを何度も定義することができ、メソッドを探すときには一番最後に定義されたメソッドが呼び出されます。
    abstract 抽象メソッドを定義するときに使います。abstract classでしか使うことができません。
    

  5. structとクラス
  6. classでキーワードでクラスを定義せずにstructキーワードでクラスを定義すると代入が起こるときにオブジェクトのコピーが渡されるようになります。
    具体的にはcloneメソッドが呼び出されます。

  7. コールバイリファレンス、コールバイバリュー
  8. メソッドの引数の渡し方にはリファレンス渡しと値渡しがありますが、classキーワードで宣言された引数がリファレンス渡し、structキーワードで宣言された引数が値渡しになります。反転させたい場合はメソッドの宣言で*をつけてください。

    $ vim test.clc
    class CallByValue {
        void method(int* value) {
            value.setValue(123);     // valueに入ったオブジェクト自体の値を123にする
                                     // value = 123だとvalueに123という新しく生成された
                                     // intオブジェクトが入ってしまう。
        }
    }
    $ vim test.cl
    CallByValue a = new CallByValue();
    int value = 0;
    a.method(value);
    value.toString().echo();
    $ cclover test.clc
    $ cclover test.cl
    $ clover test.cl
    123
    
  9. 演算子メソッド
  10. native struct char implements ICloneable, IComparableMore, IInspectable 
    {
        virtual bool operator==(char@Nullable value) {
            if(self.type() == Null || value.type() == Null) {
                return self.type() == Null && value.type() == Null;
            }
            return self.toInt() == value.toInt();
        }
    }
    
    のようにoperatorの後に演算子をつけて定義します。

  11. ブロック付きメソッド
  12. Rubyとほぼ同じです。

    クラスの定義時は
    class int 
    {
        void times() with void block(int n) {
            for(int i=0; i<self; i++) {
                block(i);
            }
        }
    }
    
    などと定義します。with後にブロックの戻り値を書き、ブロック名を書き、そのブロックの引数を書きます。

    呼び出すときは
    5.times() {|int n|
        n.toString().echo();
    }
    
    などとします。

    定義する場合ですが、ブロックの戻り値にはbreakされたかどうかの情報が追加されてTuple<bool,定義されたブロックの戻り値>となります。もし定義されたメソッドのユーザーがブロック内でbreakをした場合Tupleの第一要素にtrueが入ります。breakされなかったら、第一要素にはfalseが入ります。
    class ClassA {
        void method() with int block() {
            for(int i=0; i<5; i++) {
                Tuple block_result = block();
                if(block_result.get1() == true) {
                    break;
                }
            }
        }
    }
    
    上記の様にユーザーがブロック内でbreakした場合はblockの戻り値のTupleの第一要素にtrueが入るためループを脱出させなければいけません。(させたい場合は)
    この時の呼び出し方は
    new ClassA.method() int {
        return 123;
    }
    

    などです。ブロック前のintは省略できます。(省略できないこともあります)


    メソッドがクラスメソッドではない場合、使う側のブロックの定義時にはcallerという暗黙の引数があります。ブロックを呼んでいるオブジェクトを参照したい場合はcallerという変数を使ってください。

    { 1,2,3 }.each() {|int n|
        if(n == caller.length()-1) {  // caller == { 1,2,3 }
            n.toString().println();
        }
        else {
            (n.toString() + "+").print();
        }
    }
    
    上記の場合callerは{1,2,3}という配列のことになります。
  13. anonymousクラスと動的型付け
  14. annonymousクラスはdynamic_typingとして宣言されているので、どんな型の変数にも代入できます。また全てのメソッド呼び出しは実行時に解決されます。(どんなメソッド呼び出しをしようがエラーにならない。実行時にメソッドがない場合はエラーとなる)

    Cloverにはキャストがありませんが、ObjectクラスにtoAnonymousメソッドがあるので、コンパイル時に型チェックを行わない代入も行えます。

    Nullクラスも同様にdynamic_typingとして宣言されているのでインスタンスであるnullはどの型の変数にも代入できます。

  15. initializeクラスメソッドとpreinitializeクラスメソッド
  16. initializeクラスメソッドはクラスのロード時に呼ばれます。preinitializeクラスメソッドはクラスのロード時にinitializeクラスメソッドより前に呼ばれます。2種類ある理由ですが、たまにロードする順番が問題になることがあるためです。enumなど定数の初期化はpreinitializeメソッドで行うほうが良いでしょう。クラスのロードの順番を制御する方法はCloverにはありません。
  17. enum
  18. C言語のような列挙型があります。ただし初期化はenum宣言の中ではすることはできません。初期化する場合は以下のようにしてください
    enum EnumA
    {
        CONST_A, CONST_B, CONST_C
    }
    
    class EnumA
    {
        static bool preinitialize() {
            EnumA.CONST_A, EnumA.CONST_B, EnumA.CONST_C = 2, 5, 7;
            return true;
        }
    }
    
    enumもextendsすることができます。代入の時に重要になる場合があります。(intやlongなどをextendsすることができる)

    enumは何のクラスも継承しない場合はEnumクラスを継承します。

  19. プリプロセッサー
  20. 行頭に#preprocessorと書かれている行から#endpreprocessorまでのソースはシェルスクリプトによって出力がソースファイルに張り付けられます。以下が例です。

    $ vim preprocessor.cl.in
    String c =
    #preprocessor echo "\"abc\"" #endpreprocessor
    c.echo();
    $ pclover preprocessor.cl.in
    $ cclover preprocessor.cl
    $ clover preprocessor.cl
    abc
    
    プリプロセッサーが書かれたソースは拡張子はinとして、pcloverでコンパイルしないといけません。コンパイル後は拡張子inが取り除かれます。

    シェルスクリプトなのでPythonやRubyなどでソースを作成することができます。

    $ vim preprocessor.cl.in
    int e = 
    #preprocessor /usr/bin/python <<EOS
    print "123";
    EOS
    #endpreprocessor
    e.toString().prinln();
    $ pclover preprocessor.cl.in
    $ cclover preprocessor.cl
    $ clover preprocessor.cl
    123
    
    #defでプリプロセッサーの関数のようなものも作れます。
    #def DEFINE_CONSTRUCTOR_WITH_LONG
    
    if test -x /usr/bin/cat
    then
        CAT=/usr/bin/cat
    elif test -x /bin/cat
    then
        CAT=/bin/cat
    else
        CAT=cat
    fi
    
    if test -x /usr/bin/cc
    then
        CC=/usr/bin/cc
    elif test -x /bin/cc
    then
        CC=/bin/cc
    else
        CC=cc
    fi
    
    if test -x /usr/bin/rm
    then
        RM=/usr/bin/rm
    elif test -x /bin/rm
    then
        RM=/bin/rm
    else
        RM=rm
    fi
    
    $CAT < ~/.clover/tmpfiles/a.c
    #include 
    #include 
    #include 
    $PARAM0
    
    int main()
    {
        size_t size = sizeof($PARAM1);
    
        if(size == 1) {
            printf("$PARAM2(long value) { self.setValue(value.toByte()); }");
        }
        else if(size == 2) {
            printf("$PARAM2(long value) { self.setValue(value.toShort()); }");
        }
        else if(size == 4) {
            printf("$PARAM2(long value) { self.setValue(value.toUInt()); }");
        }
        else if(size == 8) {
            /// pass ///
        }
        else {
            exit(2);
        }
    
        exit(0);
    }
    EOS
    
    $CC -o ~/.clover/tmpfiles/a.out ~/.clover/tmpfiles/a.c
    ~/.clover/tmpfiles/a.out
    $RM -f ~/.clover/tmpfiles/a.c ~/.clover/tmpfiles/a.out
    #enddef
    
    引数は環境変数に保存されます。$PARAM0から$PARAM9までです。
    呼び出すときは以下のようにします。
    #call DEFINE_CONSTRUCTOR_WITH_LONG #include\ <fcntl.h> dev_t dev_t
    #endcall
    

    引数の区切りは空白でクォートすると空白はただのスペースとして扱われます。

    まあ、正直あまり使いみちは無いと思います。僕自身メタプログラミングは好きじゃなくて、RubyやPerl, Pythonで処理したテキストの結果はソースにそのまま張り付けておいた方がいいじゃないかと思わないでもないです。ただし、C言語の定数の値を貼り付けたい場合は環境によって値が変わるので、このプリプロセッサーが必要になります。C言語で言えば、autoconfみたいなものです。

  21. ユーザークラスとnativeクラス
  22. nativeクラスはC言語でデータが保持されているクラスです。intやArrayなどはC言語でデータが保持されています。ユーザークラスはCloverのヒープ上にデータが保持されています。
  23. 暗黙の継承
  24. 全てのクラスはObjectクラスの子クラスです。nativeクラスの場合はNativeClassクラス、enumの場合はEnumクラス、ユーザークラスの場合はUserClassが親クラスとなります。nativeクラスはICloneable, IDupeable, ISetValueインターフェースを実装する必要があります。UserClassクラスはComparableModuleがincludesされていてIComparableインターフェスを実装しています。(子クラスでも自動的に実装される)
  25. インターフェース
  26. ほとんどJavaと同じです。

  27. モジュール
  28. moduleはクラスからincludeするとその部分にソースを張り付けることができます。
    > vim test.clc
    module ModuleA
    {
        int field;
    
        void method(int value) {
            self.field = value;
        }
        void outputValue() {
            echo(self.field.toString());
        }
    }
    
    class TestA
    {
        include ModuleA;
    }
    
    > vim test.cl
    TestA a = new TestA();
    a.method(123);
    a.outputValue();
    
    > cclover test.clc
    > cclover test.cl
    > clover test.cl
    123
    
    自身のクラスと子クラスに自動的にmoduleをincludeさせたい場合は
    module ModuleA 
    {
        void helloWorld() {
            echo("Hello World");
        }
    }
    
    class TestA includes ModuleA
    {
    }
    
    class TestB extends TestA
    {
    }
    
    などと定義するとTestBにもhelloWorld()メソッドが実装されてます。(TestBの先頭にmoduleが張り付けられる)

    moduleではSelfを使って、そのクラス自身の名前を使うこともできます。

    module OperatorModule 
    {
        Self operator+(Self value) {
            return self \+ value;
        }
    }
    
    class MyInt 
    {
        include OperatorModule;
    }
    
  29. open class
  30. Cloverはopen classです。クラスの定義は何度も行うことができます。メソッドやフィールドがいくらでも追加することができます。
    > vim test.clc
    class TestA 
    {
        void method() {
            echo("TestA.method");
        }
    }
    
    > vim test2.clc 
    class TestA versioin 2 
    {
        void method2() {
            echo("TestA.method2");
        }
    }
    > vim test.cl
    TestA a = new TestA();
    a.method();
    a.method2();
    
    > cclover test.clc
    > cclover test2.clc
    > cclover test.cl
    > clover test.cl
    TestA.method();
    TestA.method2();
    
    となります。
    (追加するためにはversion番号が必要です。ただし同じファイルの中で複数回同じ名前のクラスを定義する場合、バージョン番号は必要ありません。)

    同じ名前のメソッドを定義することもできます。Cloverのメソッドコール時のメソッドサーチのアルゴリズムは定義順の後ろからなので、一番最後に定義されたメソッドが優先されます。この時、mixinというキーワードで前に定義された同名のメソッドを呼ぶことができます。
    > vim test.clc
    class TestA
    {
        void method() {
            echo("TestA.method()");
        }
    }
    
    class TestA
    {
        void method() {
            echo("caling TestA.method()");
            mixin();
            echo("called TestA.method()");
        }
    }
    
    > vim test.cl
    TestA a = new TestA();
    a.method();
    > cclover test.clc
    > cclover test.cl
    > clover test.cl
    caling TestA.method()
    TestA.method()
    called TestA.method()
    
  31. クラスファイル
  32. .clcをコンパイルするとコンパイルされたクラスの数だけ.cloファイルが作成されます。これがクラスファイルです。ファイル名は

    クラス名($ジェネリクスの引数の数).clo
    となります。例えばintクラスなら、int.clo, Array<T>ならArray$1.cloとなります。

    クラスファイルはクラスの検索パスに存在すると、どのディレクトリからでも検索されます。明示的にimportやinclude、loadする必要はありません。宣言したり必要になれば自動的に読み込まれます。

    .cl拡張子のスクリプト本体はコンパイルすると.o拡張子が付きます。例えばtest.clをコンパイルするとtest.cl.oというファイルが作成されます。

  33. クラスの検索パス
  34. 3つのディレクトリからクラスファイルは検索されます。
    1. $PREFIX/share/clover/
    2. ~/.clover/lib
    3. カレントディレクトリ

    $PREFIXはCloverがインストールされるディレクトリです。int.cloやshort.cloなど基礎的なクラスが入っています。テストコードはカレントディレクトリに置いて、よく使うクラスは~/.clover/libに入れれば良いでしょう。JavaのようなCLASSPATHの環境変数を使ったクラスの検索は行いません。この3つに固定されます。

  35. アノテーション

  36. ClassName@Anotationのようにクラス名の後に@をつけて英数字を書くと、その英数字はコメントとなります。nullを引数に取れるメソッドの場合などはNullableと書くなど自由に使ってください。
  37. 浅いコピーと深いコピー

  38. Objectで実装されているcloneはオブジェクトをコピーして新しいオブジェクトを返しますが、保持しているオブジェクトのリファレンスも新しいオブジェクトを作っています。これが深いコピーです。対してObjectで実装されているdupは同じくオブジェクトをコピーして新しいオブジェクトを返しますが、保持しているオブジェクトのリファレンスは新しくオブジェクトを作らずにそのままの値を保持しています。これが浅いコピーです。ユーザーが作るクラスでは特にcloneやdupは実装しなくてもいいですが、C言語でデータを保持しているnative classではユーザーが自身でcloneやdupを実装しないといけません。
  39. コンストラクタの定義名

  40. コンストラクタは_constructorという名前のメソッドとしてクラスに追加されます。Cloverはコンストラクタもinterfaceとして定義可能です。 

基礎的なライブラリ

目次

Object

全てのクラスの基本クラスです。intやcharなど数値型の親クラスでもあります。IHashKey, IInspectable, ICloneableを実装しています。abstractクラスでインスタンスは作成できません。
実装しているインターフェース
IHashKey → hashValue()が実装されています。
IInspectable → toString()が実装されています。
ICloneable → clone()が実装されています。
メソッド
native Type type() throws ConvertingStringCodeException
オブジェクトの型を返します。ConvertingStringCodeExceptionはほとんど返されることがないので無視してもいいでしょう。オブジェクトの型は実行時の型です。コンパイル時の型とは違うことがあるでしょう。

native int ID()
オブジェクトが固有に持っているオブジェクトIDを返します。全てのオブエジェクトで値が異なります。オブジェクトのリファレンスが同一かどうかを調べるのに使えます。
int a = 123;
int b = 123;

print("Object.ID() test...");
Clover.assert(a.ID() == b.ID() == false);
println("TRUE");

b = a;

print("Object.ID() test2...");
Clover.assert(a.ID() == b.ID() == false);   // structであるint型は代入時にcloneが起こる
println("TRUE");

String c = "ABC";
String d = "DEF";

print("Object.ID() test3...");
Clover.assert(c.ID() == d.ID() == false);
println("TRUE");

c = d;

print("Object.ID() test4...");
Clover.assert(c.ID() == d.ID());
println("TRUE");

int e = 123;
int* f = e;

print("Object.ID() test5...");
Clover.assert(e.ID() == f.ID());    // int*への代入はcloneが起こらない
println("TRUE");
native anonymous fields(int num) throws Exception, RangeException;

オブジェクトのフィールドの値を得ます。native classで作られたオブジェクトであった場合、Exceptionが起こります。フィールドのindexが範囲外の場合はRangeExceptionが起こります。

numはフィールドのインデックスです。クラスに宣言されている先頭から順番にインデックスが割り振られてます。クラスフィールドは含みません。
$ vim a.clc
class FieldsTestA {
    int field;
    static int fieldX;
}

class FieldsTestB extends FieldsTestA {
    static int fieldY;
    String field2;
}
$ vim a.cl
FieldsTestB a = new FieldsTestB();

a.field = 123;
a.field2 = "ABC";

print("Object.fields test...");
Clover.assert(a.fields(1) == "ABC");
println("TRUE");

Field field = FieldsTestB->toClass().getFieldFromName("field2");

print("Object fields test2...");
Clover.assert(field.index() == 1);
println("TRUE");
この場合num = 0がfieldでnum = 1がfields2です。
native int numFields()でオブジェクトが持つフィールドの数が得られるので0からその値より小さい値を指定すればいいです。
フィールド名からindexを得るにはClassクラスのgetFieldFromName(String name)を使ってください。

native anonymous setField(int num, anonymous obj) throws Exception, RangeException;
オブジェクトが持つフィールドに値を代入します。indexはanonymous fields(int num)と同じで親クラスから数えたindexとなります。クラスフィールドは含みません。同じようにフィールド名からアクセスしたいときはClassクラスのgetFieldFromName(String name)を使ってください。
$ vim a.clc
class FieldsTestA {
    int field;
    static int fieldX;
}

class FieldsTestB extends FieldsTestA {
    static int fieldY;
    String field2;
}
$ vim a.cl
FieldsTestB a = new FieldsTestB();

a.field = 123;
a.field2 = "ABC";

print("Object.fields test...");
Clover.assert(a.fields(0) == 123 && a.fields(1) == "ABC");
println("TRUE");

a.setField(0, 234);
a.setField(1, "DEF");

print("Object.fields test...");
Clover.assert(a.fields(0) == 234 && a.fields(1) == "DEF");
println("TRUE");
native int numFields();
オブジェクトが持つフィールドの数を返します。クラスフィールドは含みません。

$ vim a.clc
class FieldTest2A {
    int field;
    static int field2;
}

class FieldTest2B extends FieldTest2A {
    int field3;
    static int field4;
}
$ vim a.cl
FieldTest2B a = new FieldTest2B();

print("user object field test...");
Clover.assert(a.numFields() == 2);
println("TRUE");
bool instanceOf(Type@Nullable type_object)

オブジェクトが引数の型のインスタンスかどうか調べます

$ vim a.clc
class InstanceOfTestA<T, T2> {
    T field;
    T2 field2;
}
$ vim a.cl
String a = new String();

print("instanceOf test1...");
Clover.assert(a.instanceOf(String));
println("TRUE");

InstanceOfTestA<String, int> b = new InstanceOfTestA<String, int>();

print("instanceOf test2...");
Clover.assert(b.instanceOf(InstanceOfTestA<String, int>));
println("TRUE");

print("instanceOf test3...");
Clover.assert(b.instanceOf(InstanceOfTestA<String, String>> == false);
println("TRUE");
bool isChild(Type@Nullable type_object)

オブジェクトが持つ型オブジェクトのクラスが引数の型のクラスの子クラスかどうかを調べます。引数にgenericsの型情報は必要ありません。
$ vim a.clc
class ObjectChildTestA extends String {
}

class ObjectChildTestB<T, T2>
{
    T field;
    T2 field2;
}

class ObjectChildTestC<T> extends ObjectChildTestB<String, T>
{
}

$ vim a.cl
ObjectChildTestA a = new ObjectChildTestA();

print("Object.isChild test...");
Clover.assert(a.isChild(String));
println("TRUE");

ObjectChildTestC b = new ObjectChildTestC<int>();

print("Object.isChild test2....");
Clover.assert(b.isChild(ObjectChildTestC$1));
println("TRUE");

print("Object.isChild test3....");
Clover.assert(b.isChild(ObjectChildTestB$2));
println("TRUE");
型オブジェクトでクラス名を引数なしで表現したい場合は「クラス名$引数の数」と記述します。

Null toNull() throws TypeError
コンパイル時に型をNull型に変換します。実行時はオブジェクトがNullクラスのインスタンス出ない場合は例外を投げます。実行時ではnullであることを保証させる型チェックのようなものを行うだけで特に意味はありません。

anonymous toAnonymous()

コンパイル時に型をanonymous型に変換します。annonymous型となるので、コンパイル時に、どのような型にも代入できます。実行時には特に意味はありません。

virtual int hashValue()

オブジェクトのハッシュ値を計算します。ハッシュ値はオブジェクト固有ではありません。別のオブジェクトでも重複することがあります。ハッシュ値は連想配列を実装するときなどに使います。HashクラスがあるCloverでは意味はあまり無いかもしれませんが、一応入れています。

virtual String toString()

オブジェクトの文字列表現を返します。Object型ではクラス名を返すように実装されてます。ユーザーが任意で作ったクラスで独自の文字列表現を返したい場合はそのクラスでtoString()を実装してください。virtual宣言されているのでメソッド検索は実行時に行われ多態が起こります。

virtual void outputValueForInterpreter()

icloverで戻り値を表示するときに呼ばれます。Object型ではtoString()を呼んで画面に出力しているだけです。Objectクラスの子クラスで独自の実装を行いたい場合はオーバーライドしてください。

virtual anonymous clone() throws Exception

オブジェクトのコピーを行います。C言語でデータを保持しているnative classの場合は必ずオーバーライドしないといけません。(native classはNativeClassクラスの子クラスなので実装していない場合はinterfaceの不備によりコンパイルエラーとなる)
native classでない場合は特にオーバーライドする必要はなくObjectクラスで実装されているcloneをそのまま使えばいいでしょう。
コピーはdeep copyで保持しているフィールド全てでcloneが呼ばれます。つまり保持しているフィールドは全て同一のものではありません。

virtual anonymous dup() throws Exception

オブジェクトのコピーを行います。C言語でデータを保持しているnative classの場合は必ずオーバーライドしないといけません。
native class出ない場合は特にオーバーライドする必要はなくObjectクラスで実装されているdupeをそのまま使えばいいでしょう。
コピーは浅いコピーで保持しているフィールドはそのままコピーされます。つまり保持しているフィールドは全て同一です。

NativeClass

全てのnativeクラスの基本クラスです。Objectクラスが親クラスです。intやcharなどC言語でデータを保持しているクラスは全て、このクラスの子クラスになります。abstractクラスでインスタンスは作成できません。
実装しているインターフェース
ICloneable → anonymous clone()を実装する必要があります。
IDupeale → anonymous dup()を実装する必要があります。
ISetValue → void setValue(anonymous value)を実装する必要があります。
includeしているmodule
ConsturctorModule
メソッド
abstract void setValue(anonymous value)

値を変えるメソッドです。例えばintならvoid setValue(int value)と実装してください。setValue(5)でそのオブジェクトが保持する整数が5になるように実装してください。

abstract anonymous dup() throws Exception

オブジェクトのコピーを返すメソッドです。保持しているリファレンスはそのままコピーしてください。(浅いコピー)

abstract anonymous clone() throws Exception

オブジェクトのコピーを返すメソッドです。保持しているリファレンスは新しく生成したオブジェクトにしてください。(深いコピー)

UserClass

全てのnativeクラスでないクラスの基本クラスです。Objectクラスが親クラスです。ユーザーが作ったクラスは全て、このクラスの子クラスになります。abstractクラスでインスタンスは作成できません。
includeしているモジュール
ComparableModule → operator==とoperator!=が実装されています。
ConsturctorModule
実装しているインターフェース
IComparable → includesされているComparableModuleで子クラスでも自動的に実装されます。再実装したい場合は普通に宣言すると上書きされます(moduleは先頭でincludeされるので)
メソッド
virtual bool operator==(Self@Nullable right) throws TypeError
オブジェクトの比較を行うメソッドです。保持しているフィールド全てを==で比較しています。引数はNullableアノテーションなのでnullを引数に取ることもできます。比較は内容で行っており、同一リファレンスかどうかを比較するものではありません。同一リファレンスかどうかを調べたい場合はObject.IDメソッドを使ってください。

virtual bool operator !=(Self@Nullable right) throws TypeError
オブジェクトの比較を行うメソッドです。違うならtrueを返します。

void setValue(UserClass value) throws Exception

リファレンスはそのままで値を設定します。フィールドの値をvalueのフィールドから全てコピーします。

Class

クラスオブジェクトを保持するクラスです。genericsの型情報も保持しています。ほとんどTypeクラスと同じものだと考えてもらっていいです。ただ、こちらは実装しているフィールドやメソッドにアクセスする手段があります。
オブジェクト表現
ありません。Typeオブジェクトのオブジェクト表現にtoClassを使って生成してください。
int->toClass()
short->toClass()
この時->を使っている理由ですが、ドットだとクラスフィールドへのアクセスになるためです。Typeオブジェクトのメソッドを呼び出したいときは->を使ってください。
includeしているモジュール
ComparableModule → operator==とoperator!=が実装されています。
ConsturctorModule
実装しているインターフェース
ICloneable → cloneが実装されています。
IInspectable → toStringが実装されています。
IComparable → operator==, operator!=が実装されています。
メソッド
native virtual void setValue(Class class)
値を代入します。

virtual Class clone() throws Exception

自身のコピーを返します。

virtual Class dup()

自身のコピーを返します。

native Type toType()

Typeオブジェクトに変換します。

print("Class.toType() test...");
Clover.assert(int->toClass().toType() == int);
println("TRUE");

print("Class.toType() test2...");
Clover.assert(Array<int>->toClass().toType() == Array<int>);
println("TRUE");
genericsの情報も保持しているので、このような動作となります。

String name()

文字列表現で値を得ます。toString()を呼んでいるだけです。

native anonymous newInstance()

クラスの新しいインスタンスを作成します。新しく生成されたオブジェクトが返されます。
Class class = Array<String>->toClass();
Array<String> a = class.newInstance();

a.add("AAA");
a.add("BBB");
a.add("CCC");

print("Class.newInstance() test...");
Clover.assert(a.type() == Array<String> && a == {"AAA", "BBB", "CCC"});
println("TRUE");
native Array<Field> fields()

クラスオブジェクトが保持するフィールド全てFieldオブジェクトの配列として返します。クラスフィールドも含みます。

$ vim a.clc
class ClassClassFieldTest 
{
    int field1;
    static int field2;
}

class ClassClassFieldTest2 extends ClassClassFieldTest 
{
    int field3;
    static int field4;
}

$ vim a.cl
Array<Field> b = ClassClassFieldTest2->toClass().fields();

print("Class.fields() test...");
Clover.assert(b.length() == 2 && b[0].name() == "field3" && b[1].name() == "field4");
println("TRUE");
native Array<Method> methods()

クラスオブジェクトが保持するメソッドを全てMethodオブジェクトの配列として返します。クラスメソッドも含みます。

$ vim a.clc
class ClassClassMethodTest 
{
    void method1(int value) {
    }
    void method2(int value) {
    }
}

class ClassClassMethodTest2 extends ClassClassMethodTest 
{
    void method3(int value) {
    }
    void method4(int value) {
    }
}
$ vim a.cl
Array<Method> c = ClassClassMethodTest2->toClass().methods();

print("Class.methods() test...");
Clover.assert(c.length() == 4 && c[2].name() == "method3" && c[3].name() == "method4");
println("TRUE");
ClassClassMethodTest2には自動的にComparableModuleがincludeされているのでメソッド数は4つになってます。

Array<Method> constructors()

コンストラクタを返します。親クラスのコンストラクタも含みます。
$ vim a.cl
class ClassClassMethodTest 
{
    ClassClassMethodTest() {
    }
    ClassClassMethodTest(int value) {
    }

    void method1(int value) {
    }
    void method2(int value) {
    }
}

class ClassClassMethodTest2 extends ClassClassMethodTest 
{
    ClassClassMethodTest2() {
    }
    ClassClassMethodTest2(int value) {
    }
    void method3(int value) {
    }
    void method4(int value) {
    }
}

$ vim a.cl
Array<Method> d = ClassClassMethodTest2->toClass().constructors();

print("Class.constructors() test...");
Clover.assert(d.length() == 4);

Field@Nullable getFieldFromName(String name)

フィールドを名前で検索して返します。親クラスのフィールドも検索します。

$ vim a.clc
class ClassClassFieldTest3 
{
    int field1;
    static int field2;
}

class ClassClassFieldTest4 extends ClassClassFieldTest3 
{
    int field3;
    static int field4;
}
$ vim a.cl
Field field = ClassClassFieldTest4->toClass().getFieldFromName("field4");

print("Class.getFieldFromName test...");
Clover.assert(field.index() == 1 && field.name() == "field4" && field.fieldType() == int);
println("TRUE");
native bool isNativeClass()

native classならtrueを返します。

native bool isInterface()

interfaceならtrueを返します。

native bool isAbstractClass()

abstract classならtrueを返します。

native bool isFinalClass()

final classならtrueを返します。

native bool isStruct()

structならtrueを返します。

virtual bool operator==(Class@Nullable right)

同じクラスならtrueを返します。

virtual bool operator !=(Class@Nullable right)

違うクラスならtrueを返します。

native Array<Type> superClasses();

親クラスのリストを返します。

$ vim a.clc
class ClassClassFieldTest3 
{
    int field1;
    static int field2;
}

class ClassClassFieldTest4 extends ClassClassFieldTest3 
{
    int field3;
    static int field4;
}

$ vim a.cl
print("Class.superClasses test...");
Clover.assert(ClassClassFieldTest4->toClass().superClasses() == { Object, UserClass, ClassClassFieldTest3 });
println("TRUE");
native Array<Type> implementedInterfacesOnlyThisClass()

実装しているインターフェースのリストを返します。返すインターフェースはこのクラスでimplementsされているものだけです。

Array<Type> implementedInterfaces()

実装しているインターフェスのリストを返します。親クラスで実装されている物も含みます。
$ vim a.clc
class ClassClassFieldTest3 
{
    int field1;
    static int field2;
}

class ClassClassFieldTest4 extends ClassClassFieldTest3 
{
    int field3;
    static int field4;
}

$ vim a.cl
print("Class.implementedInterfaces test...");
Clover.assert(ClassClassFieldTest4->toClass().implementedInterfaces() == { IHashKey, IInspectable, ICloneable, IComparable});
println("TRUE");
native Array<Class> classDependences()

クラスが依存しているクラスのリストを返します。

native Array<GenericsParametor> genericsParametorTypes() throws NullPointerException

Classクラスオブジェクトのgenericsの型情報を返します。

$ vim a.clc
class ClassGenericsInfoTest <T extends int, T2 implements ICloneable&IInspectable>
{
}

$ vim a.cl
Array<GenericsParametor> parametors = ClassGenericsInfoTest$2->toClass().genericsParametorTypes();

print("ClassGenericsInfoTest test...");
Clover.assert(parametors[0].extendsType() == int && parametors[1].implementedInterfaces() == {ICloneable, IInspectable});
println("TRUE");

Field

Fieldのデータを保持したオブジェクトです。Classクラスのfields等によって得られます。フィールドのデータはC言語で保持しているのでnative classです。final宣言もされているので継承できません。
オブジェクト表現
ありません。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=を実装しています。
includeしているmoduel
ConsturctorModule
メソッド
native virtual void setValue(Field field) throws NullPointerException
オブジェクト保持するデータを代入します。リファレンス自体は変わりません。

native anonymous classFieldValue() throws NullPointerException, Exception;
クラスフィールドの値を得ます。anonymous型なのでコンパイル時の型チェックは行われません。

native void setClassFieldValue(anonymous value);
クラスフィールドの値を代入します。
$ vim a.clc
class FieldClassTest1 {
    int field;
    int field2;

    static int field3 = 111;
    static int field4;
}

$ vim a.cl
Field field3 = FieldClassTest1->toClass().getFieldFromName("field3");
Field field4 = FieldClassTest1->toClass().fields()[3];

field4.setClassFieldValue(123);

print("Field test...");
Clover.assert(FieldClassTest1.field4 == 123 && field3.classFieldValue() == 111);
println("TRUE");
native int index()
フィールドのindexを返します。クラスフィールドの場合は定義されたクラスでのフィールド番号です(0から始まりクラスで定義された上からの順番)。普通のフィールドの場合はObject.fieldsで使うindexを返します。

$ vim a.clc
class FieldClassTest1 
{
    int field;
    int field2;

    static int field3 = 111;
    static int field4;
}

class FieldClassTest2 extends FieldClassTest1
{
    int field5;
    static int field6;
}

$ vim a.cl
Field field5 = FieldClassTest2->toClass().getFieldFromName("field5");

FieldClassTest2 object = new FieldClassTest2();

object.setField(field5.index(), 123);

print("Field test2...");
Clover.assert(object.field5 == 123);
println("TRUE");
virtual Field clone() throws Exception
virtual Field dup()

Fieldオブジェクトのコピーを返します。

native bool isStaticField() throws NullPointerException

クラスフィールドなら真を返します。

native bool isPrivateField() throws NullPointerException

プライベートフィールドなら真を返します。

native bool isProtectedField() throws NullPointerException

Protectedフィールドなら真を返します。

bool isPublicField() throws NullPointerException

Publicフィールドなら真を返します。

native String name() throws NullPointerException, ConvertingStringCodeException

フィールド名を返します。

native Type fieldType()

フィールドの型を返します。

virtual String toString()

Fieldオブジェクトの文字列表現を返します。

virtual bool operator==(Field value)

Fieldオブジェクトの型と名前を比較して同じなら真を返します。所属しているクラスは同じでないといけません。

virtual bool operator!=(Field value)

Fieldオブジェクトの型と名前を比較して違うなら真を返します。

native Type class();

所属するクラスの型を返します。
$ vim a.clc
class FieldTest4ClassA {
    int field1;
    String field2;
}
$ vim a.cl
Field field = FieldTest4ClassA->toClass().getFieldFromName("field2");

print("Field test...");
Clover.assert(field.class() == FieldTest4ClassA && field.index() == 1);
println("TRUE");

Method

Methodのデータを保持したオブジェクトです。Classクラスのmethods等によって得られます。MethodのデータはC言語で保持しているのでnative classです。final宣言もされているので継承できません。
オブジェクト表現
ありません。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=を実装しています。
includeしているmoduel
ConsturctorModule
メソッド
native virtual void setValue(Method field);
Methodのデータを代入します。変数が指しているリファレンスは変わりません。内容が変わります。

virtual Method clone() throws Exception
virtual Method dup()
オブジェクトのコピーを返します。

native anonymous invokeMethod(Object object, Array<anonymous> param, ...) throws NullPointerException, MethodMissingException

メソッドを実行します。可変長引数を取ります。最初の引数のobjectはメソッドを呼び出すobjectです。

$ vim a.clc
class MethodClassTestA {
    int field1;
    int field2;

    MethodClassTestA(int value, int value2) {
        self.field1 = value;
        self.field2 = value2;
    }

    int method(int a, int b) {
        return b;
    }

    int method2() {
        return self.field1;
    }

    static int method3(int a, int b, int c ) {
        return c;
    }
}

$ vim a.cl
MethodClassTestA a = new MethodClassTestA(111, 222);

a.field1 = 333;

int c = a.type().toClass().methods()[3].invokeMethod(a, 111, 222); // int method(int a, int b)
int d = a.type().toClass().methods()[4].invokeMethod(a); // int method2()

print("Method Refrection Test1...");
if(c == 222 && d == 333) {
    println("TRUE");
}
else {
    println("FALSE");
    System.exit(2);
}
Classクラスのmethodsのメソッドのindexで注意してもらいたい点はユーザーオブジェクトは全てComparableModuleをincludesしているのでクラスの最初でoperator==()メソッドとoperator!=()メソッドが定義されている点です。そのため、int method(int a, int b)のindexは3となっています。indexでメソッドを得たくない場合はClassクラスのgetMethodFromNameAndParametorTypesを使ってください。

$ vim a.clc
class MethodClassTestA2 {
    int field1;
    int field2;

    MethodClassTestA2(int value, int value2) {
        self.field1 = value;
        self.field2 = value2;
    }

    int method(int a, int b) {
        return b;
    }

    int method2() {
        return self.field1;
    }

    static int method3(int a, int b, int c ) {
        return c;
    }
}

$ vim a.cl
MethodClassTestA2 a = new MethodClassTestA2(111, 222);

a.field1 = 333;

int c = MethodClassTestA2->toClass().getMethodFromNameAndParametorTypes("method", { int, int }).invokeMethod(a, 111, 222);
int d = a.type().toClass().methods()[4].invokeMethod(a); // int method2()

print("Method Refrection Test1...");
if(c == 222 && d == 333) {
    println("TRUE");
}
else {
    println("FALSE");
    System.exit(2);
}
native bool isNativeMethod() throws NullPointerException

nativeメソッドなら真を返します。

native bool isClassMethod() throws NullPointerException

classメソッドなら真を返します。

native bool isPrivateMethod() throws NullPointerException

privateメソッドなら真を返します。

native bool isConstructor() throws NullPointerException

コンストラクタなら真を返します。

native bool isSynchronizedMethod() throws NullPointerException

synchronizedメソッドなら真を返します。

native bool isVirtualMethod() throws NullPointerException

virtualメソッドなら真を返します。

native bool isAbstractMethod() throws NullPointerException

abstractメソッドなら真を返します。

native bool isProtectedMethod() throws NullPointerException
protectedメソッドなら真を返します。

bool isPublicMethod() throws NullPointerException

publicメソッドなら真を返します。

native bool isParamVariableArguments() throws NullPointerException;

可変長引数のメソッドなら真を返します。

native String name() throws NullPointerException

メソッド名を返します。

native String path() throws NullPointerException

メソッドのPath名を返します。クラス名も含みます。

native Type resultType() throws NullPointerException

メソッドの戻り値の型を返します。

native Array<Type> parametors() throws NullPointerException;

メソッドの引数の型の配列を返します。

native bool blockExists() throws NullPointerException;

メソッドにブロック引数がある場合真を返します。

native Type blockResultType() throws NullPointerException

メソッドのブロック引数の戻り値の型を返します。

native Array<Type> blockParametors() throws NullPointerException;

メソッドのブロック引数の引数の型の配列を返します。

native Array<Type> exceptions() throws NullPointerException

メソッドの例外の型の配列を返します。

virtual String toString()

メソッドの文字列表現を返します

virtual bool operator==(Method value)

同一クラスに属していてメソッドの内容が同じなら真を返します。

virtual bool operator!=(Method value)

メソッドの内容が同じでないなら真を返します。

native Type class()

所属しているクラスを返します。

$ vim a.clc
class MethodTest 
{
    int method(String a, String b) {
        return a.length() + b.length();
    }
}
$ vim a.cl
MethodTest a = new MethodTest();

Method method = MethodTest->toClass().getMethodFromNameAndParametorTypes("method", { String, String});

print("method test...");
Clover.assert(method.class() == MethodTest 
    && method.resultType() == int 
    && method.name() == "method" 
    && method.isPublicMethod() 
    && method.parametors() == { String, String } 
    && !method.blockExists());
println("TRUE");

Type

実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=を実装しています。
includeしているmoduel
ConsturctorModule
オブジェクト表現
クラス名がそのまま使えます。例えば、StringのTypeオブジェクトはStringと書きます。クラスに引数がある場合はHash<String,int>のように書きます。Hashに引数を持たせずにHashクラスそのものTypeオブエジェクト表現はHash$2のように書きます。$の後に型を書かずに引数の数を書けばいいです。

メソッド
native virtual void setValue(Type type)
オブジェクトの内容を代入します。

virtual native String toString()

文字列表現を返します。Stringクラスなら"String"を返します。

native static Type createFromString(String name) throws Exception

文字列表現から型オブジェクトを作ります。"String"という引数ならStringクラスの型を返します。Genericsの表現は"Array<int>"などとなります。Genericsの引数なしの場合は"Array$1"などとします。
print("Type test...");
Clover.assert(Type.createFromString("Type") == Type);
println("TRUE");

print("Type test2...");
Clover.assert(Type.createFromString("Array<int>") == Array<int>);
println("TRUE");

print("Type test3...");
Clover.assert(Type.createFromString("Array$1") == Array$1);
println("TRUE");
native bool equals(Type@Nullable value)
内容を比較して同じなら真を返します。

native Class toClass()
TypeオブジェクトをClassオブエジェクトに変換します。TypeオブジェクトとClassオブジェクトはほぼおなじもので、実装しているメソッドが違うだけです。Classオブジェクトはリフレクションに関係するメソッドが実装されています。

native Type class()

Genericsを持つクラスの型の場合クラス名だけを返します。
print("Type test4...");
Clover.assert(Array<int>->class() == Array$1);
println("TRUE");
native Type genericsParam(int index)

Genericsの引数の型オブジェクトを返します。
print("Type test5...");
Clover.assert(Array<int>->genericsParam(0) == int);
println("TRUE");
native int genericsParamNumber()

Genericsの引数の型の数を返します。
print("Type test6...");
Clover.assert(Hash<String, int>->genericsParamNumber() == 2);
println("TRUE");
native Type@CheckForNull parentClass()

型オブジェクトが保持するクラスの親クラスを型オブジェクトで返します。Objectクラスの親クラスは無いのでnullが返ります。

Array<Type> array = new Array<Type>();

Type it = int;
while(it != null) {
    array.add(it);
    it = it.parentClass();
}

print("Type test7...");
Clover.assert(array == { int, NativeClass, Object });
println("TRUE");
native int parentClassNumber()

親クラスの数を返します。
print("Type test8...");
Clover.assert(int->parentClassNumber() == 2);
println("TRUE");
native bool substitutionPosibility(Type object, bool dynamic_typing=true)
代入ができるかどうかをチェックします。メッセージを受け取るオブジェクトに引数の型オブジェクトが代入できるなら真を返します。bool dynamic_typingはnullやAnonymousクラスなどの型チェックを無視できる型の代入ができるかどうかを指定します。falseにしたら、nullなどは代入できません。

print("Type test9...");
Clover.assert(int->substitutionPosibility(NativeClass) == false);
println("TRUE");

print("Type test10...");
Clover.assert(NativeClass->substitutionPosibility(int));
println("TRUE");

print("Type test11...");
Clover.assert(String->substitutionPosibility(int) == false);
println("TRUE");
virtual bool operator==(Type@Nullable value)

内容が同じなら真を返します。

virtual bool operator !=(Type@Nullable value)

内容が違うなら真を返します。

virtual Type clone() throws Exception
virtual Type dup()

コピーしたオブジェクトを返します。

bool isInstance(Object object)

引数のオブジェクトがこの型のクラスのインスタスかどうかをチェックします。

print("Type test12...");
Clover.assert(int->isInstance(123));
println("TRUE");

int

数値を表すオブジェクトのクラスです。オブジェクトは32bit符号ありのデータを保持しています。Javaのようにプリミティブ型でもなくRubyのように即値オブジェクトでもなく、オブジェクトはあくまで生成された数値オブジェクトのリファレンスです。nativeクラス修飾子が付いているので、NativeClassの子クラスになります。またstructとしてクラスが宣言されているので、代入時にclone()が呼ばれます。(コピー時にそのオブジェクトのリファレンスではなくコピーが代入される)
オブジェクト表現
123,234など数値をそのまま書けばいいです。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModule ConsturctorModule
メソッド
native long toLong();
native short toShort();
native byte toByte();
native uint toUInt();
native float toFloat();
native double toDouble();

型を別の数値オブジェクトに変更します。値はそのままです。

native char toChar();

数値を文字UTF32(wchar_t)に変換します。

print("int test1...");
Clover.assert(65.toChar() == 'A');
println("TRUE");
virtual native String toString();

数値の文字列表現を返します。
print("int test2...");
Clover.assert(123.toString() == "123");
println("TRUE");
int times() with void block(int num)
int times() with void block()

ブロックをオブジェクトの回数分繰り返します。ブロックに引数をつけると、繰り返した回数を返します(0から始まる)

$ vim a.cl
3.times() {
    println("HELLO");
}
$ cclover a.cl
$ clover a.cl
HELLO
HELLO
HELLO
$ vim a.cl
3.times() {|int n|
    n.toString().println();
}
$ cclover a.cl
$ clover a.cl
0
1
2
int toInt()

その値を持ったintオブジェクトを返します。intクラスだけだと意味はありませんが、intの子クラスでint型のオブジェクトを返したい場合に使用してください。

bool toBool()

値が0以外ならtrueを返します。

native virtual void setValue(int value);

値を設定します。リファレンス自体は変わりません。内容が変わります。

virtual int clone() throws Exception
virtual int dup()

コピーしたオブジェクトを返します。

int(int value)

コンストラクタです。new int(123)などで呼ばれます。

byte

8bit符号なしの数値を表すクラスです。
オブジェクト表現
123y,234yなど数値の後にyをつけます。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModule ConsturctorModule
メソッド
native virtual void setValue(byte value);

オブジェクトの内容を設定します。

native int toInt();
native long toLong();

他の数値オブジェクトに変換します。

byte toByte()

byteを派生させたクラスで値はそのままでbyteオブジェクトを作りたい時に使用します。

virtual String toString()

文字列表現を返します。文字列表現は一度intに変換された後の値が文字列になります。

virtual int hashValue()

ハッシュ値を得ます。ハッシュ値は連想配列の実装などでC言語ではよく使われますが、Cloverではあまり意味が無いかもしれません。

virtual byte clone() throws Exception
virtual byte dup()

コピーしたオブジェクトを返します。

byte(byte value)
byte(int value)

コンストラクタです。newした時に呼ばれます。

short

16bit符号なしの数値を表すクラスです。
オブジェクト表現
123s,234sなど数値の後にsをつけます。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModule ConsturctorModule
メソッド
native virtual void setValue(short value)

オブジェクトの値を設定します。

native int toInt()
native long toLong()

他の数値オブジェクトに変換します。

short toShort()

short型のオブジェクトに変換します。shortを派生したクラスでshort型のオブジェクトが必要になった時に使います。

virtual String toString()

文字列表現を返します。int型に変換された後int型のtoStringが呼ばれます。

virtual int hashValue()

ハッシュ値を返します。

virtual short clone() throws Exception
virtual short dup()

コピーしたオブジェクトを返します。

short(short value)
short(int value)

コンストラクタです。intでもnewできます。

uint

32bit符号なしの数値を表すクラスです。
オブジェクト表現
123u,234uなど数値の後にuをつけます。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModule ConsturctorModule
メソッド
native virtual void setValue(uint value)

オブジェクトの値を設定します。リファレンスは変わりません。

native int toInt()
native long toLong()

他の数値オブジェクトに変換します。

virtual native String toString()

文字列表現を返します。
print("uint test...");
Clover.assert(123u.toString() == "123");
println("TRUE");
uint toUInt()

uintクラスのオブジェクトを作って返します。派生したクラスでuintオブジェクトが必要になったら使えます。

virtual int hashValue()

ハッシュ値を返します。

virtual uint clone() throws Exception
virtual uint dup()

コピーしたオブジェクトを返します。

uint(uint value)
uint(int value)

コンストラクタです。

long

64bit符号なしの数値を表すクラスです。
オブジェクト表現
123l,234lなど数値の後にlをつけます。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModule ConsturctorModule
メソッド
native virtual void setValue(long value)

オブジェクトの値を設定します。リファレンスは変わりません。

native byte toByte()
native short toShort()
native int toInt()
native uint toUInt()
native float toFloat()
native double toDouble()

他の数値オブジェクトに変換します。

native char toChar()

文字(UTF32/16、wchar_t)に変換します。

long toLong()

longオブジェクトに変換します。派生したクラスで意味があります。

virtual native String toString()

文字列表現を返します。
print("long test...");
Clover.assert(123l.toString() == "123");
println("TRUE");
virtual int hashValue()

ハッシュ値を返します。

virtual long clone() throws Exception
virtual long dup()

コピーしたオブジェクトを返します。

long(long value)
long(int value)

コンストラクタです。

char

文字を表すクラスです。内部的にはUTF32,C言語でのwchar_tとして保持されています。structとして宣言されているので代入時はcloneによってコピーされたオブジェクトが代入されます。
オブジェクト表現
'A', 'あ', '漢' など文字を'で囲ってください。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているmoduel
ConsturctorModule
メソッド
native virtual void setValue(char value)

内容を設定します。リファレンス自体は変わりません。

native int toInt()

int型の数値に変換してintオブジェクトを返します。

print("char test...");
Clover.assert('A'.toInt() == 65 && 'あ'.toInt() == 12354);
println("TRUE");
virtual native String toString()

変換して文字列を返します。

print("char test2...");
Clover.assert('あ'.toString() == "あ" && 'A'.toString() == "A");
println("TRUE");
virtual int hashValue()

ハッシュ値を返します。

char toChar()

char型に変換します。派生クラスで意味があります。

virtual char clone() throws Exception
virtual char dup()

コピーしたオブジェクトを返します。

char(char value)

コンストラクタです。

virtual bool operator==(char@Nullable value)
virtual bool operator!=(char@Nullable value)
virtual bool operator <(char value)
virtual bool operator <=(char value)
virtual bool operator >(char value)
virtual bool operator >=(char value)

文字の比較演算子です。int型に変換して比較しています。UTF16/32なのでASCIIのように'A' < 'B'は保証されます。詳しくはASCIIコード表を見てください。

print("char test...");
Clover.assert('A' == 'A' && 'A' < 'B');
println("TRUE");
char upcase()

英字の小文字を大文字に変換します。大文字や他の文字はそのままです。

print("char test4...");
Clover.assert('a'.upcase() == 'A' && 'あ'.upcase() == 'あ' && 'A'.upcase() == 'A');
println("TRUE");
char downcase()

英字の大文字を小文字に変換します。小文字や他の文字はそのままです。

print("char test5...");
Clover.assert('A'.downcase() == 'a' && 'あ'.downcase() == 'あ' && 'a'.downcase() == 'a');
println("TRUE");
bool isControlCharacter()

コントールキャラ(self >= 0x00.toChar() && self < ' ' || self == 0x7F.toChar())なら真を返します。コントロールキャラとはCTRL-CやCTRL-Aなどのキーが割り当てられた文字のことです。詳しくはASCIIキャラクターコード表を見てください。

bool isAsciiCharacter()

ASCIIキャラクター(self >= 0x00.toChar() && self <= 0xFF.toChar())なら真を返します。詳しくはASCIIキャラクターコード表を見てください。英字や記号などが割り当てられてます。

bool isDigitCharacter()

数字(self >= '0' && self <= '9')なら真を返します。

bool isAlphabetCharacter()

英字(self >= 'a' && self <= 'z' || self >= 'A' && self <= 'Z')なら真を返します。

bool isNonControlCharacter()

コントロールキャラじゃないなら真を返します。(self >= ' ' && self <= '~')

float

浮動小数点型を表すクラスです。doubleが32bitでfloatは16bitのデータ量を保持しています。
オブジェクト表現
1.1f, 1.2fなど少数にfをつけてください。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModuleForDouble ConsturctorModule
メソッド
native int toInt()

int型に変換してintオブジェクトを返します。

print("float test...");
Clover.assert(1.1f.toInt() == 1 && 2.2f.toInt() == 2);
println("TRUE");
native double toDouble()

double型に変換してdoubleオブジェクトを返します。

print("float test...");
Clover.assert(!(1.1f.toDouble() == 1.1 && 2.2f.toDouble() == 2.2));
println("TRUE");
少数の比較は誤差があるので正しい結果にはなりません。

以下のリンクを見てください
小数(浮動小数点型)の計算が思った結果にならない理由と解決方法

virtual native String toString()

文字列表現を返します。
print("float test...");
Clover.assert(1.1f.toString() == "1.100000");
println("TRUE");
float toFloat()

float型オブジェクトに変換して、その値を返します。

float(int value)
float(float value)

コンストラクタです。

native virtual void setValue(float value)

値を設定します。リファレンスは変わりません。

virtual float clone() throws Exception
virtual float dup()

コピーしたオブジェクトを返します。

double

浮動小数点型を表すクラスです。doubleが32bitでfloatは16bitのデータ量を保持しています。
オブジェクト表現
1.1, 1.2など少数をそのまま書けばいいです。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
includeしているモジュール
OperatorModuleForDouble ConsturctorModule
メソッド
native int toInt()

int型オブジェクトに変換します。

print("double test...");
Clover.assert(1.1.toInt() == 1 && 2.2.toInt() == 2);
println("TRUE");
native float toFloat()

float型オブジェクトに変換します。
print("double test2...");
Clover.assert(1.1.toFloat() == 1.1f && 2.2.toFloat() == 2.2f);
println("TRUE");
virtual native String toString()

文字列表現を返します。

print("double test3...");
Clover.assert(1.1.toString() == "1.100000");
println("TRUE");
native virtual void setValue(double value)

値を代入します。リファレンスは変わりません。

double(int value)
double(double value)

コンストラクタです。

double toDouble()

double型に変換して、そのオブジェクトを返します。派生クラスで意味があります。

virtual double clone() throws Exception
virtual double dup()

コピーしたオブジェクトを返します。

bool

真偽値を格納するクラスです。structとして宣言されているため代入時にcloneが呼ばれてコピーされたオブジェクトが代入されます。
オブジェクト表現
trueと書くと真の値を持つboolオブジェクトが生成されます。falseと書くと偽の値を持つboolオブジェクトが生成されます。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(bool value)

オブジェクトの値を設定します。リファレンスは変わりません。

bool(bool value)

コンストラクタです。

bool toBool()

boolの派生クラスでbool型のオブジェクトが必要になったら使ってください。

virtual bool clone() throws Exception
virtual bool dup()

コピーしたオブジェクトを返します。

virtual String toString()

値が真なら"true", 値が偽なら"false"が返されます。

print("bool test...");
Clover.assert(false.toString() == "false" && true.toString() == "true");
println("TRUE");
int toInt()

値が真なら1が、値が偽なら0が返されます。

print("bool test2...");
Clover.assert(false.toInt() == 0 && true.toInt() == 1);
println("TRUE");

pointer

C言語でのポインターを表現したクラスです。拡張ライブラリで必要になる場合があるでしょう。structとして宣言されているので代入時はcloneによって生成されたコピーが代入されます。
オブジェクト表現
ありません。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(pointer value)

値を設定します。リファレンスは変わりません。

native virtual String toString()

文字列表現を返します。


native bool equals(pointer right)

ポインタが保持するアドレスが等しいなら真を返します。

pointer(pointer value)

コンストラクタです。

virtual pointer clone()
virtual pointer dup()
コピーしたオブジェクトを返します。

native void forward(int size=1) throws NullPointerException, Exception

ポインタをsizeバイトだけ進めます。ポインタが範囲外になるとExceptionが起こります。

native void backward(int size=1) throws NullPointerException, Exception

ポインタをsizeバイトだけ戻します。

native byte getByte() throws NullPointerException

ポインタが指す値から1バイトだけのデータを取り出します。

native short getShort() throws NullPointerException

ポインタが指す値から2バイトだけのデータを取り出します。

native uint getUInt() throws NullPointerException

ポインタが指す値から4バイトだけのデータを取り出します。

native long getLong() throws NullPointerException

ポインタが指す値から8バイトだけのデータを取り出します。

virtual bool operator==(pointer@Nullable right)

ポインタの値を比較して同じなら真を返します。Nullableアノテーションが付いているのでnullとの比較も可能です。

virtual bool operator!=(pointer@Nullable right)

ポインタの値を比較して違うなら真を返します。Nullableアノテーションが付いているのでnullとの比較も可能です。

OnigurumaRegex

正規表現クラスです。abstract宣言されているRegex抽象クラスの実装です。Cloverの正規表現は鬼車という正規表現ライブラリを使っています。
オブジェクト表現
/.+/など/で正規表現の文字列を囲ってください。他にもr/.+/などr/と/で囲う表現も許されます。空の正規表現を表したい場合は//だとCloverの1行コメントとして解釈されてしまうので、r//としてください。
オプションとしてg,m,iがあります。正規表現のあとにg,m,iを付けるとそれぞれ

g → global。複数回の検索をします。
m → multiline。複数行にまたがる検索をします。
i → ignore case。大文字と小文字の違いを無視します。

という意味となります。
例としては/.+/g, /abc/giなどです。

正規表現については検索エンジンで検索を行ったりして調べてください。鬼車の正規表現のマニュアルは
鬼車 正規表現 Version 5.9.1にあります。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringメソッドが実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual String source()

正規表現を表す文字列を返します。データはC言語で保持されています。

native virtual bool ignoreCase()

大文字と小文字の比較を無視するかどうかの設定を返します。

native virtual bool multiLine()

複数行にまたがる検索を許すかどうかの設定を返します。

native virtual Encoding encode()

エンコーディングを返します。

エンコーディングは
enum Encoding
{
Binary, ASCII, Utf8, EucJP, SJIS
}

として宣言されています。

native virtual bool global()

何度も検索するかどうかの設定を返します。

native virtual void setIgnoreCase(bool ignore_case)

大文字と小文字を無視するかどうかの設定を行います。

native virtual void setMultiLine(bool mutiline)

複数行にまたがる検索をするかどうかの設定を行います。

native virtual void setGlobal(bool global)

複数回検索を行うかどうかの設定を行います。

native virtual void setEncode(Encoding encode)

エンコーディングの設定を行います。

native virtual void setValue(OnigurumaRegex regex)

値を代入します。リファレンスは変わりません。

native virtual void compile(String source, bool ignore_case, bool mutiline, bool global, Encoding encode) throws InvalidRegexException

正規表現をコンパイルします。コンパイル結果がオブジェクトに設定されます。コンパイルできない正規表現の文字列だった場合InvalidREgexExceptionが起こります。

OnigurumaRegex(String source, bool ignore_case=false, bool multiline=false, bool global=false, Encoding encode=Encoding.Utf8)

コンストラクタです。

virtual OnigurumaRegex clone() throws Exception
virtual OnigurumaRegex dup()

コピーしたオブジェクトを返します。

virtual String toString()

文字列表現を返します。

print("OnigurumaRegex test...");
Clover.assert(/ABC/.toString() == "ABC");
println("TRUE");

String

文字列クラスです。内部的にはwchar_tの配列として保持されています。UTF32/16文字列となります。
オブジェクト表現
"ABC", "123"などと文字を"で囲ってください。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator>=などを実装しています。IComparableMoreを実装しているのでSortableArrayで使うことができるクラスです。
IHashKey → hashValueが実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(String value)

保持しているデータに代入します。リファレンスは変わりません。

native int toInt()

数値に変換します。

print("string test...");
Clover.assert("123".toInt() == 123 && "-1".toInt() == -1 && "abc".toInt() == 0);
println("TRUE");
native double toDouble()

小数に変換します。

print("string test2...");
Clover.assert("1.1".toDouble() == 1.1 && "-1.2".toDouble() == -1.2);
println("TRUE");
Parser toParser()

Parserクラスに変換します。Parserクラスは高速に文字列をパースすることができます。詳しくはParserクラスの解説をみてください。

native int length()

文字列の文字数を返します。

print("string test3...");
Clover.assert("ABC".length() == 3 && "あいうえお".length() == 5);
println("TRUE");
native char@CheckForNull char(int index)
char@CheckForNull operator[] (int index)

index文字目の文字を返します。indexが範囲外であった場合nullが返ります。indexは0から始まります。indexは負の数だった場合-1が最後の文字です。

print("String test4...");
Clover.assert("あいうえお".char(0) == 'あ' && "あいうえお".char(-1) == 'お' && "あいうえお".char(1000) == null);
println("TRUE");
native char replace(int index, char character) throws RangeException
char operator[]= (int index, char character) throws RangeException

文字を置き換えます。その文字列に文字を追加することは文字列の長さが決まっているCloverにはできませんが置き換えることはできます。indexが範囲外の場合RnageExceptionが起こります。indexが負数だった場合最後から数えたindexになります。-1が最後の文字です。

String a = "あいうえお";
a.replace(0, 'か');
a.replace(-1, 'こ');

print("String test5...");
Clover.assert(a == "かいうえこ");
println("TRUE");
native Bytes toBytes() throws ConvertingStringCodeException

バイナリデータに変換します。wcstombsを使ってマルチバイト文字列に変換されます。

native int cmp(String right, bool ignore_case=false)

文字列を比較します。ignore_caseがtrueだと英字の大文字と小文字を区別しません。selfが大きい場合は1を、等しい時には0を、selfが小さい場合は-1を返します。

print("String test...");
Clover.assert("ABC".cmp("DEF") == -1 && "ABC".cmp("ABC") == 0 && "DEF".cmp("ABC") == 1 && "abc".cmp("ABC", true) == 0);
println("TRUE");
native void match(Regex regex, int@Nullable offset=0, int count=1) with void block(int begin, int end, Array<Range> group_strings)
native void matchReverse(Regex regex, int@Nullable offset=null, int count=1) with void block(int begin, int end, Array<Range> group_strings)

正規表現で文字列を比較します。ブロックを取ります。正規表現を使ったメソッドを作りたい時に使ってください。ユーザーレベルでは特に呼ぶ必要がないメソッドです。matchReverseは後方から検索します。

virtual void outputValueForInterpreter()

インタプリタで値を表示するために使われます。

virtual String toString()

String型の文字列に変換して返します。派生クラスで必要になることがあります。

bool operator =~ (Regex regex, Array<String>@Nullable group_strings=null) throws Exception

文字列を正規表現で比較します。マッチするとtrueが返されます。

print("String test...");
Clover.assert("あいうえお" =~ /い/);
println("TRUE");

Array<String> group_strings = new Array<String>();

print("String test2...");
"あいうえお" =~ (/(.)(.)(.)(.)(.)/, group_strings);
Clover.assert(group_strings == { "あ", "い", "う", "え", "お" });
println("TRUE");
virtual String clone() throws Exception
virtual String dup()

コピーしたオブジェクトを返します。

virtual int hashValue()

ハッシュ値を返します。

String(String value)

コンストラクタです。newすると呼ばれます。

void print()

文字列を出力します。改行はしません。

void println()

文字列を出力します。改行します。

String operator[] (Range range)

Rangeの範囲だけの部分文字列を返します。Rangeの最後のindexは含みません。負の数は-1が一番最後の文字で-2以下は後ろから数えた文字の範囲を表します。nullは終端を表します。Rangeが下降するなら逆順の文字列を返します。

print("String test...");
Clover.assert("あいうえお"[0..1] == "あ");
println("TRUE");

print("String test...");
Clover.assert("あいうえお"[0..-1] == "あいうえ");
println("TRUE");

print("String test...");
Clover.assert("あいうえお"[2..null] == "うえお");
println("TRUE");

print("String test...");
Clover.assert("あいうえお"[4..2] == "えう");
println("TRUE");

print("String test...");
Clover.assert("あいうえお"[null..2] == "おえう");
println("TRUE");
String operator +(String value)

左辺と右辺の文字列を連結させた文字列を返します。

String operator+= (String string)

追記します。リファレンスは変わりません。内容が変わります。

virtual bool operator==(String@Nullable right)
virtual bool operator!=(String@Nullable right)
virtual bool operator>(String right)
virtual bool operator<(String right)
virtual bool operator>=(String right)
virtual bool operator<=(String right)

文字列を比較します。

String operator *(int num)

num個分の文字列を返します。

print("String test...");
Clover.assert("あいう" * 2 == "あいうあいう");
println("TRUE");
bool asciiOnly()

ASCII文字列でできた文字列の場合真を返します

String capitalize()

英数字の場合、先頭文字が小文字の場合大文字にします。

String each() with void block(char c)

一文字ずつブロックを呼び出し、ブロックの引数にその文字を入れます。

$ vim a.cl
"あいうえお".each() {|char c|
    c.toString().println();
}
$ cclover a.cl
$ clover a.cl
あ
い
う
え
お
String chomp(String separator=null)

最後の文字が改行なら改行を取り除きます。改行とは\n, \r\n, \rの3種類です。

print("String test...");
Clover.assert("abc\n".chomp() == "abc" && "abc\r".chomp() == "abc" && "abc\r\n".chomp() == "abc");
println("TRUE");
String chop()

文字列の最後の文字を取り除いた新しい文字列を生成して返します。 ただし、文字列の終端が "\r\n" であればその 2 文字を取り除きます。

print("String test...");
Clover.assert("あいうえお".chop() == "あいうえ" && "あいうえお\r\n".chop() == "あいうえお");
println("TRUE");
int count(char character)

指定した文字がいくつあるか数えます。

print("String test...");
Clover.assert("あああああ".count('あ') == 5);
println("TRUE");
int count(Regex regex)

正規表現にマッチする文字がいくつあるか数えます。

print("String test...");
Clover.assert("あいうえお".count(/[あう]/) == 2);
println("TRUE");
String delete(char character)

selfからcharacterの文字を取り除いた文字列を作って返します。

print("String test...");
Clover.assert("あいうえお".delete('あ') == "いうえお");
println("TRUE");
String delete(Regex regex)

正規表現にマッチする文字を削除した文字列を返します
print("String test...");
Clover.assert("あいうえお".delete(/[うえ]/g) == "あいお");
println("TRUE");
String downcase()

文字列に含まれる全ての英字の大文字を小文字に変換します。

Array<String> lines(String separator="\n")

文字列が複数行でできている場合改行区切りで文字列を分けて、各行を配列に入れて返します。

String sub(Regex regex, String replacement)

正規表現にマッチする文字列を置き換えます。

print("String test...");
Clover.assert("あいうえお".sub(/[うえ]/g, "け") == "あいけけお");
println("TRUE");
String sub(Regex regex) with String block(Array<String> group_strings, String prematch, String match, String postmatch)

正規表現にマッチする文字列をブロックが返す文字列に置き換えます。

print("String test...");
Clover.assert("あいうえお".sub(/[うえ]/g) {
    |Array<String> group_strings, String prematch, String match, String postmatch| 
    return match.length().toString(); } == "あい11お");
println("TRUE");
ブロックの引数のgroup_stringsには正規表現のグループ化にマッチした文字列が、prematchはマッチした文字列の前の部分の文字列が、matchにはマッチした文字列が、postmatchにはマッチした部分から後ろの文字列が入っています。

String sub(Regex regex, Hash replacement)

マッチした文字列がハッシュのキーに対応したものなら、対応するハッシュの値に文字列を置き換えます。ハッシュのキーに対応したものが無いならマッチした文字列はそのまま残します。

print("String test...");
Clover.assert("あいうえお".sub(/[うえ]/g, { "う"=>"く", "え"=>"け" }) == "あいくけお");
println("TRUE");

print("String test...");
Clover.assert("あいうえお".sub(/[うえ]/g, { "あ"=>"か", "う"=>"く"}) == "あいくえお");
println("TRUE");

print("String test...");
Clover.assert("ABCDEFG".sub(/./g, {"A"=>"a"}) == "aBCDEFG");
println("TRUE");
bool include(String@Nullable other_str)

引数の文字列を含むなら真を返します。

print("String test....");
Clover.assert("あいうえお".include("うえ") && !"あいうえお".include("かき"));
println("TRUE");
int index(String substr, int@Nullable offset=0, int count=1)

引数の部分文字列を含むindex返します。indexは0から始まります。
オプションとしてoffsetとcountがあります。offsetは検索を開始するindexです。nullが末尾になります。countは例えば2を指定すると2回目に含んでいたindexを返します。

見つからない場合は-1を返します。

print("String test...");
Clover.assert("あいうえお".index("い") == 1 
    && "あいうえお".index("か") == -1 
    && "あいうえおあいうえお".index("あいう", 0, 2) == 5 
    && "あいうえおあいうえお".index("お", 5) == 9);
println("TRUE");
int index(Regex regex, int@Nullable offset=0, int count=1)

正規表現にマッチするindexを返します。
他はindex(String,int,int)とほぼ同じです。

int rindex(String substr, int@Nullable offset=null, int count=1)

後ろから引数の部分文字列を検索します。
offsetのnullは末尾を表します。
他はindex(String,int,int)と同じです。

int rindex(Regex regex, int@Nullable offset=null, int count=1)

後ろから引数の正規表現にマッチするindexを返します。
offsetのnullは末尾を表します。
他はindex(String,int,int)と同じです。

String lstrip()

前の部分の空白を取り除きます。

print("String lstrip test...");
Clover.assert("   あいう   ".lstrip() == "あいう   " 
    && "あいう   ".lstrip() == "あいう   " 
    && "   あいう".lstrip() == "あいう" 
    && "     ".lstrip() == "");
println("TRUE");
String strip()

最初の空白と最後の空白を削除します。

print("String strip test...");
Clover.assert("   あいう   ".strip() == "あいう" 
        && "あいう   ".strip() == "あいう" 
        && "   あいう".strip() == "あいう" 
        && "    ".strip() == "");
println("TRUE");
String rstrip()

最後の空白を削除します。

print("String rstrip test...");
Clover.assert("   あいう   ".rstrip() == "   あいう" 
    && "あいう   ".rstrip() == "あいう" 
    && "   あいう".rstrip() == "   あいう" 
    && "     ".rstrip() == "");
println("TRUE");
String reverse()

文字列を逆順にします。self[null..0]を返します。

print("String test...");
Clover.assert("あいうえお".reverse() == "おえういあ");
println("TRUE");
Array<anonymous> scan(Regex regex)

文字列から正規表現マッチする文字列を取ります。何度も検索を繰り返しマッチした文字列の配列を返します。戻り値の型はArray<String>かArray<Array<String>>です。

print("String test...");
Clover.assert("あいうえお".scan(/./) == { "あ", "い", "う", "え", "お" } 
        && "あいうえお123かきくけこ456".scan(/[0-9]+/) == { "123", "456" });
println("TRUE");
Array<String> split(Regex regex=null, int limit=0)

文字列を正規表現にマッチする部分で分割します。regexがnullの時は空白を区切りとします。

print("String test...");
Clover.assert("あいう かきく さしす".split() == { "あいう", "かきく", "さしす" }
    && "あいう123かきく456さしす789".split(/[0-9]+/) == { "あいう", "かきく", "さしす" });
println("TRUE");
String squeeze()

同じ文字が続く場合、一つにします。

print("String test...");
Clover.assert("あああいいいううう".squeeze() == "あいう");
println("TRUE");
String swapcase()

英字の大文字なら小文字に、英字の小文字なら大文字に変換します。

print("String test...");
Clover.assert("AbcDEf".swapcase() == "aBCdeF");
println("TRUE");
String tr(String from_str, String to_str)

文字列を一括変換します。

print("String test...");
Clover.assert("abc".tr("a-z", "A-Z") == "ABC" 
                && "ABCABC".tr("A", "X") == "XBCXBC");
println("TRUE");
int hex()

文字列が16進数を表している場合、int型に変換します。

print("String test...");
Clover.assert("0xFF".hex() == 255 && "10".hex() == 16);
println("TRUE");
int oct()

文字列が8進数を表している場合、int型に変換します。

print("String test...");
Clover.assert("010".oct() == 8 && "20".oct() == 16);
println("TRUE");

Array

大きさが可変な配列クラスです。genericsの引数を一つ取ります。Array<int>などです。genericsの引数はIComparableを実装している必要があります。ユーザーのクラスでは自動的にComparableModuleがincludeされICmparableが実装されているので、特に気をつける必要はありません。native宣言されているのでデータはC言語で保持されています。
オブジェクト表現
{ 1,2,3}, {"ABC", "DEF", "GHI"}などです。要素の型は全て同じじゃないといけません。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(Array<T> value)

値を設定します。リファレンスは変わりません。

native Array<T> add(T@Nullable item)

配列の要素を追加します。大きさは自動的に大きくなるので、メモリが許すだけ要素を追加できます。selfを返します。

Array<String> array = new Array<String>();

array.add("ABC");
array.add("DEF");
array.add("GHI");

print("Array add test...");
Clover.assert(array == {"ABC", "DEF", "GHI"});
println("TRUE");

print("Array add test...");
Clover.assert({1,2,3}.add(4).add(5) == { 1,2,3,4,5 });
println("TRUE");
native T@CheckForNull items(int index)
T@CheckForNull operator[] (int index)

配列の要素を一つ取り出します。indexは0が先頭です。負数だと後ろからアクセスします。範囲外のindexの時はnullを返します。

print("Array test...");
Clover.assert({"あ", "い", "う"}[0] == "あ"
            && {"あ", "い", "う"}[1] == "い"
            && {"あ", "い", "う"}[-1] == "う"
            && {"あ", "い", "う"}[-2] == "い"
            && {"あ", "い", "う"}[100] == null);
println("TRUE");
native int length()

要素の数を返します。

print("Array test...");
Clover.assert({"あ", "い", "う"}.length() == 3
        && {1,2,3,4,5}.length() == 5);
println("TRUE");
native Array<T> setItem(int index, T@Nullable item)
Array<T> operator[]= (int index, T item)
要素を置き換えます。indexが配列の大きさより大きい場合は空いているindexの要素はnullが入ります。selfを返します。
Array<String> array2 = { "あ", "い", "う" };
array2[1] = "き";

print("Array setItem test...");
Clover.assert(array2 == { "あ", "き", "う" });
println("TRUE");

array2[5] = "X";

print("Array setItem test...");
Clover.assert(array2 == { "あ", "き", "う",null,null,"X" });
println("TRUE");

print("Array setItem test...");
Clover.assert({1,2,3}.setItem(1, 9) == { 1,9,3});
println("TRUE");
Array<T> toArray()

Array型の配列を返します。派生クラスでArray型に変換したい場合はこれを使ってください。

virtual Array<T> clone() throws Exception

コピーしたオブジェクトを返します。要素でもcloneが呼び出されます。

Array<String> array3 = { "あいうえお", "かきくけこ", "さしすせそ" };

Array<String> array4 = array3.clone();

print("Array test...");
Clover.assert(array3 == array4);
println("TRUE");

print("Array test...");
Clover.assert(array3.ID() != array4.ID());
for(int i=0; i<3; i++) {
    Clover.assert(array3[i].ID() != array4[i].ID());
}
println("TRUE");
virtual Array<T> dup() throws Exception

コピーしたオブジェクトを返します。要素が保持するリファレンスは元の配列の要素と同じものです。

Array<String> array3 = { "あいうえお", "かきくけこ", "さしすせそ" };

Array<String> array4 = array3.dup();

print("Array test...");
Clover.assert(array3 == array4);
println("TRUE");

print("Array test...");
Clover.assert(array3.ID() != array4.ID());
for(int i=0; i<3; i++) {
    Clover.assert(array3[i].ID() == array4[i].ID());
}
println("TRUE");
Array<T> operator*(int num)

要素を引数の数だけ繰り返して作った配列を返します。

print("Array test...");
Clover.assert({ "あ", "い" } * 3 == { "あ", "い", "あ", "い", "あ", "い" });
println("TRUE");
Array<T> operator + (Array<T> right)

引数の要素を加えた配列を返します。
print("Array test...");
Clover.assert({ "あ", "い", "う" } + { "え", "お" } == { "あ", "い", "う", "え", "お"});
println("TRUE");
virtual bool operator==(Array<anonymous>@Nullable array2)
virtual bool operator!=(Array<anonymous>@Nullable array2)

配列同士の比較をします。要素の比較にはoperator==が使われます。

print("Array test...");
Clover.assert({ "あああ", "いいい", "ううう" } == { "あああ", "いいい", "ううう" } && {1, 2, 3 } != { 3, 4, 5 });
println("TRUE");
Array<T> deleteAt(int number)

配列の要素をindexで削除します。selfを返します。

print("Array test....");
Clover.assert({"あああ", "いいい", "ううう"}.deleteAt(1) == { "あああ", "ううう" });
println("TRUE");
T@CheckForNull pop()

配列の一番最後の要素を取り出します。最後の要素は削除されます。

Array<String> array6 = { "あああ", "いいい", "ううう" };

String str = array6.pop();

print("Array test...");
Clover.assert(str == "ううう" && array6 == {"あああ", "いいい"});
println("TRUE");
Array(Array<T> array)

コンストラクタです。new した時に呼ばれます。

bool include(T item)

引数の要素を含んでいれば真を返します。比較はoperator==によって行われます。

print("Array test...");
Clover.assert({1,2,3,4,5}.include(5) && !{ 1,2,3 }.include(6));
println("TRUE");
int count(T item)

配列に含まれる引数の要素の数を数えて、その数を返します。

print("Array test....");
Clover.assert({1,2,2,3,3,3,4,4,4,4,5,5,5,5,5}.count(4) == 4);
println("TRUE");
Array<T> delete(T@Nullable item)

配列に含まれる引数の要素を全て削除します。selfを返します。

print("Array test...");
Clover.assert({ 1,2,2,3,3,3,4,4,4,4 }.delete(2) == { 1,3,3,3,4,4,4,4 });
println("TRUE");
int index(T@Nullable item, int count=1)

要素のindexを返します。indexは0から始まります。countは何個目の要素のindexを返すかを決めます。見つからない場合は-1を返します。

print("Array test...");
Clover.assert({1,2,1,2}.index(2) == 1 && {1,2,1,2}.index(2, 2) == 3 && {1,2,1,2}.index(3) == -1);
println("TRUE");
int index(int count=1) with bool block(T item)

ブロックが真になる要素を返します。countが>1ならcount個目の要素を返します。見つからない場合は-1を返します。

print("Array test...");
Clover.assert({1,2,3,1,2,3,1,2,3}.index() { |int n| return n == 3} == 2);
println("TRUE");

print("Array index with block test...");
Clover.assert({"AAA", "123", "BBB"}.index() { |String value| return value.toInt() != 0;} == 1);
print("TRUE");

print("Array index with block test...");
Clover.assert({"あああ", "いいい", "ううう"}.index() { |String value| return value.toInt() != 0;} == -1);
print("TRUE");
virtual String toString()

文字列表現を返します。

String join(String separator="")

要素の文字列表現をsperatorを間に入れて文字列を作り、それを返します。

print("Array test...");
Clover.assert({ "あ", "い", "う" }.join(" ") == "あ い う" && { 1,2,3 }.join("+") == "1+2+3");
println("TRUE");
int rindex(T@Nullable item, int count=1)

引数の要素のindexを返します。後ろから数えます。countが例えば2なら2つめに見つかったindexを返します。見つからない場合は-1を返します。

print("Array rindex test...");
Clover.assert({1,2,3,1,2,3,1,2,3}.rindex(2) == 7 && {1,2,3,1,2,3,1,2,3}.rindex(2, 2) == 4);
println("TRUE");

print("Array rindex test...");
Clover.assert({1,2,3,4,5,6,7,8}.rindex(9) == -1);
println("TRUE");
int rindex(int count=1) with bool block(T item)

ブロックが真になる要素を返します。後ろから数えます。見つからない場合は-1を返します。

print("Array rindex test...");
Clover.assert({1,2,3,1,2,3,1,2,3}.rindex() { |int n| return n == 1 } == 6);
println("TRUE");

print("Array rindex test...");
Clover.assert({"あああ", "いいい", "ううう"}.rindex() { |String str| return str.toInt() != 0; } == -1);
println("TRUE");
Array<T> each() with void block(T item)

要素の数だけブロックを繰り返します。ブロックの引数には要素が入っています。selfを返します。breakでループを中断できます。

$ vim a.cl
Array<String> array8 = { "あ", "い", "う" };

array8.each() { |String element|
    element.println();
}
$ cclover a.cl
$ clover a.cl
あ
い
う
Array<T> each() with void block(T item, int index)

each()とほぼ同じですが、ブロックの引数にindexを持ちます。indexは0から始まります。selfを返します。breakでループを中断できます。

$ vim a.cl
Array<String> array8 = { "あ", "い", "う" };

array8.each() { |String element, int index|
    printf("%d: %ls\n", index, element);
}
$ cclover a.cl
$ clover a.cl
0: あ
1: い
2: う
Array<T> clear()

要素を全て削除します。selfを返します。

Array<anonymous> collect() with anonymous block(T item)

要素の数だけブロックを繰り返し、ブロックの戻り値を新しい配列に入れて返します。返される配列の要素はanonymous型なので型チェックは実行時に行われます。新しく作った配列を返します。selfを返すわけじゃありません。

print("Array collect test...");
Clover.assert({ 1, 2, 3 }.collect() {|int n| return n * 2 } == { 2, 4, 6 });
println("TRUE");

print("Array collect test...");
Clover.assert({ 1, 2, 3 }.collect() {|int n| return (n * 2).toString() } == { "2", "4", "6" });
println("TRUE");
Array<T> concat(Array<T> array)

配列の末尾に配列を追加します。selfを返します。

print("Array test...");
Clover.assert({1,2,3}.concat({4,5}) == { 1,2,3,4,5 });
println("TRUE");
Array<T> deleteIf() with bool block(T item)

要素の数だけブロックを繰り返して、ブロックの戻り値がtrueの要素を全て削除します。selfを返します。

print("Array test...");
Clover.assert({111,222,333,222}.deleteIf() {|int n| return n == 222 } == { 111,333 });
println("TRUE");
Array<T> fill(T@Nullable item)

要素を全て引数の値に変えます。引数はcloneされるので値が同じなだけで全て違うオブジェクトです。selfを返します。

print("Array fill test...");
Clover.assert({"あああ", "いいい", "ううう"}.fill("あいう") == { "あいう", "あいう", "あいう" });
println("TRUE");
Array<T> fill(T@Nullable item, Range range)

配列を要素を全て引数の値に変えます。変えるのはrangeの範囲だけです。

print("Array fill test...");
Clover.assert({ 1,2,3,4,5,6,7,8,9 }.fill(0, 1..3) == { 1,0,0,4,5,6,7,8,9 });
println("TRUE");
Array<T> insert(int index, T@Nullable item)

indexの位置に要素を入れます。index以降の要素は全て後ろ側に1つずつずれていきます。indexが配列の大きさより大きい時はnullで間を埋めます。selfを返します。

print("Array insert test...");
Clover.assert({ 1,2,3,4,5 }.insert(3, 0) == { 1,2,3,0,4,5 });
println("TRUE");

print("Array insert test...");
Clover.assert({ 1,2,3,4,5 }.insert(7, 0) == { 1,2,3,4,5,null,null,0 });
println("TRUE");
Array<T> insert(int index, Array<T> array)

indexの位置にarrayの要素を入れます。indexが配列の大きさより大きい時はnullで埋めます。selfを返します。

print("Array insert test...");
Clover.assert({ 1,2,3,4,5 }.insert(2, { 0, 0, 0}) == { 1,2,0,0,0,3,4,5 });
println("TRUE");

print("Array insert test...");
Clover.assert({ 1,2,3,4,5 }.insert(7, { 0, 0, 0 }) == { 1,2,3,4,5,null,null, 0,0,0});
println("TRUE");
Array<T> push(T@Nullable item)

addと同じで末尾に要素を追加します。selfを返します。

Array<T> reverse()

要素を逆順にした配列にします。selfを返します。

print("Array reverse test...");
Clover.assert({1,2,3}.reverse() == { 3, 2, 1 });
println("TRUE");
T sample()

配列の要素の中からランダムに一つだけ要素を返します。

$ vim a.cl
{ 1,2,3 }.sample().toString().println();
$ cclover a.cl
$ clover a.cl
3
$ clover a.cl
1
Array<T> sample(int num)

num個だけの要素をランダムに取り出します。戻り値はその要素が入った配列です。

Array<T> select() with bool block(T item)

ブロックが真となる要素だけを入れた配列にします。selfを返します。

print("Array select...");
Clover.assert({1,2,3,4,5,6,7,8,9}.select() {|int num| return num > 5; } == { 6,7,8,9 });
println("TRUE");
Array<T> shuffle()

要素をランダムに並び替えます。

$ vim a.cl
{1,2,3,4,5}.shuffle().toString().println();
$ cclover a.cl
$ clover a.cl
{3,1,4,5,2}
Array<T> slice(Range range)
Array<T> operator[](Range range)

配列の要素を引数の範囲だけ取り出し配列に入れて返します。範囲は0から始まり1..3などと指定しますが、この場合3自身は含みません。負数は-1が最後の要素を表します。末尾はnullで表します。

print("Array slice test...");
Clover.assert({1,2,3,4,5}[2..4] == {3,4});
println("TRUE");

print("Array slice test2...");
Clover.assert({1,2,3,4,5}[2..-1] == {3,4});
println("TRUE");

print("Array slice test3...");
Clover.assert({1,2,3,4,5}[2..null] == {3,4,5});
println("TRUE");
Array<T> uniq()

要素で重複するものがあれば削除します。selfを返します。

print("Array uniq test...");
Clover.assert({1,3,5,3,2,1,2,3,4,5,1,2,3}.uniq() == {1,3,5,2,4});
println("TRUE");
Array<T> valueAt(Array<anonymous> params, ...) throws TypeError

配列から引数で指定した位置の要素を全て含めたは新しい配列を返します。引数はindex, rangeなど、複数取ることができます。

print("Array valueAt test....");
Clover.assert({0,1,2,3,4,5,6,7,8,9}.valueAt(1,3,5, 3..6, 9) == {1,3,5,3,4,5,9});
println("TRUE");

SortableArray

ソートが可能な配列クラスです。Genericsの引数を一つとります。Genericsの引数はIcomparableMoreを実装しているひつようがあります。operator>()やoperator<()を実装している必要があります。(ソートするためには大きさを比較できないといけない)。Arrayクラスを継承しています。Arrayクラスのメソッドは全て使えます。
オブジェクト表現
ありません。SortableArray<int> sortable_array = new SortableArray<int>({1,2,3});などと宣言してください。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>,operator>=,operator<,operator<=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
SortableArray<T> sort()

要素を並び替えます。selfを返します。

print("SortableArray sort test...");
Clover.assert(new SortableArray<int>({ 5,8,4,6,3,2,1 }).sort() == { 1,2,3,4,5,6,8 });
println("TRUE");
SortableArray<T> sort() with int block(T item, T item2)

要素を並び替えます。selfを返します。ブロックの戻り値は左右の引数(item, item2)を比較してitemが小さい場合は-1を返して、同じ場合は0を返し、item2が小さい場合は1を返してください。そうすると昇順に並び替わります。
print("SortableArray sort test...");
Clover.assert(new SortableArray<int>({ 5,9,3,6,4}).sort() {|int left, int right|
    if(left < right) {
        return -1;
    }
    else if(left > right) {
        return 1;
    }

    return 0;
} == {3,4,5,6,9});
println("TRUE");

print("SortableArray sort test...");
Clover.assert(new SortableArray<int>({ 5,9,3,6,4}).sort() {|int left, int right|
    if(left > right) {
        return -1;
    }
    else if(left < right) {
        return 1;
    }

    return 0;
} == {9,6,5,4,3});
println("TRUE");

Hash

連想配列です。Genericsの引数を2つとります。Hash<String, int>などです。Genericsの引数はIComparableを実装しているひつようがあります。
オブジェクト表現
{ "Apple" => 1, "Banana" => 2, "Orange" => 3 }
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(Hash value) throws MethodMissingException
値を設定します。hashValue()メソッドがないとMethodMissingExceptionが起きますが、ObjectクラスにhashValue()メソッドは実装されているので、無視してもらって大丈夫です。

native Hash erase(K key) throws MethodMissingException, Exception;

引数のキーを持つ要素を削除します。戻り値はselfです。キーが存在しない場合Exceptionが起こります。

print("Hash erase test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.erase("A") == { "B"=>2, "C"=>3 });
println("TRUE");

native Tuple@CheckForNull assoc(K key) throws MethodMissingException;

引数のキーを持つ要素をキーと値両方をTupleにして返します。

print("Hash assoc test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.assoc("A") == ("A", 1));
println("TRUE");
native Hash put(K key, V item) throws MethodMissingException;
Hash operator[]=(K key, V item) throws MethodMissingException

要素を追加します。selfを返します。

print("Hash put test...");
Clover.assert({"A"=>1, "B"=>2}.put("C", 3) == { "A"=>1, "B"=>2, "C"=>3 });
println("TRUE");
native int length()

要素の数を返します。

print("Hash length test...");
Clover.assert({"A"=>1, "B"=>2}.length() == 2);
println("TRUE");
native Hash each() with void block(K key, V value)

要素の数だけブロックを繰り返します。ブロックの引数にはキーと値が渡されます。

int n = 0;
print("Hash each test...");
{"あ"=>1, "い"=>2, "う"=>3}.each() { |String key, int value|
    n += value;
}
Clover.assert(n == 6);
println("TRUE");
Hash toHash()

子クラスでHashオブジェクトを得たい場合に使います。

V@CheckForNull get(K key) throws MethodMissingException
V@CheckForNull operator[](K key) throws MethodMissingException

キーから値を得ます。キーが存在しない場合nullを返します。

print("Hash get test...");
Clover.assert({"あ"=>1, "い"=>2, "う"=>3, "え"=>4, "お"=>5}.get("あ") == 1 && {"A"=>1, "B"=>2}.get("C") == null);
println("TRUE");
V fetch(K key) throws KeyNotFoundException

キーから値を得ます。getと違いキーが存在しない場合は例外を投げます。

print("Hash fetch test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.fetch("C") == 3);
try {
    {"A"=>1, "B"=>2, "C"=>3}.fetch("D");
}
catch(KeyNotFoundException e) {
    println("TRUE");
}
Array<K> keys()

全てのキーを配列に入れて返します。

print("Hash keys test...");
{"A"=>1, "B"=>2, "C"=>3}.keys().each() {|String key|
    Clover.assert(caller.length() == 3);
    Clover.assert({ "A", "B", "C" }.include(key));
}
println("TRUE");
Array<V> values()

全ての値を配列に入れて返します。

print("Hash values test...");
{"A"=>1, "B"=>2, "C"=>3}.values().each() {|int value|
    Clover.assert(caller.length() == 3);
    Clover.assert({ 1,2,3 }.include(value));
}
println("TRUE");
Array<Tuple<K,V>> toArray()

全ての要素を返します。キーと値のTupleの配列となります。

print("Hash toArray test...");
{ "A"=>1, "B"=>2, "C"=>3}.toArray().each() {|Tuple element|
    Clover.assert(element == ("A", 1) || element == ("B", 2) || element == ("C", 3));
}
println("TRUE");
virtual bool operator==(Hash@Nullable hash) throws MethodMissingException
virtual bool operator!=(Hash@Nullable hash) throws MethodMissingException

Hash同士の比較です。要素のキーと値が全て一致するなら真を返します。格納されている順番は関係ありません。

print("Hash operator== test...");
Clover.assert({ "A"=>1, "B"=>2, "C"=>3 } == { "B"=>2, "A"=>1, "C"=>3 });
println("TRUE");
Hash clear() throws MethodMissingException

要素を全て削除します。

print("Hash clear test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.clear().length() == 0);
println("TRUE");
virtual Hash clone() throws MethodMissingException

要素を全てコピーした新しいHashを返します。要素は全てclone()されて同一オブジェクトではありません。

virtual Hash dup() throws MethodMissingException
要素を全てコピーした新しいHashを返します。要素はコピー元のオブジェクトと同一でID()メソッドが一致します。

print("Hash dup test...");
Hash<String, int> hash = {"A"=>1, "B"=>2, "C"=>3};
Hash<String ,int> hash2 = hash.dup();

Clover.assert(hash.ID() != hash2.ID());

Clover.assert(hash["A"].ID() == hash2["A"].ID());

println("TRUE");
virtual String toString()

文字列表現を返します。

virtual int hashValue()

ハッシュ値を返します。

Hash deleteIf() with bool block2(K key, V value)

ブロックの戻り値が真なら、その要素を削除します。selfを返します。

print("Hash deleteIf test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.deleteIf() {|String key, int value| return value == 2; } == { "A"=>1, "C"=>3});
println("TRUE");
K@CheckForNull key(V value)

引数の値を持つキーを返します。

print("Hash key test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.key(3) == "C");
println("TRUE");
Hash invert() throws KeyOverlappingException, MethodMissingException

キーと値を入れ替えた新しいHashを返します。キーが重複した場合はKeyOverlappingExceptionが起こります。

print("Hash invert...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.invert() == {1=>"A", 2=>"B", 3=>"C"});
println("TRUE");
Hash select() with bool block(K key, V value)

ブロックが真を返す要素だけを選んで、そのHashを返します。self自体の要素が変化してselfを返します。

print("Hash select test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3, "D"=>4, "E"=>5, "F"=>6}.select() { |String key, int value| return (value % 2) == 0;} == { "B"=>2, "D"=>4, "F"=>6 });
println("TRUE");
Hash merge(Hash other) throws MethodMissingException

同じ型を持つ他のHashと合わせた配列を返します。selfの内容が変わり、selfを返します。

print("Hash merge test...");
Clover.assert({"A"=>1, "B"=>2}.merge({"C"=>3, "D"=>4}) == {"A"=>1, "B"=>2, "C"=>3, "D"=>4 });
println("TRUE");
Tuple@CheckForNull rassoc(V value) throws MethodMissingException

値から要素を検索してキーと値のペアのTupleを返します。

print("Hash rassoc test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3}.rassoc(3) == ("C",3));
println("TRUE");
Array<V> valuesAt(Array<anonymous> param, ...)

複数のキーから複数の値を得て配列に入れて返します。

print("Hash valuesAt test...");
Clover.assert({"A"=>1, "B"=>2, "C"=>3, "D"=>4, "E"=>5}.valuesAt("B", "D") == { 2, 4 });
println("TRUE");

StringBuffer

大きさが可変な文字列です。文字列を追記する場合はStringではなくて、こちらを使ってください。Stringのoperator+=()メソッドはとても重い処理です。こちらのStringBufferのoperator+=()は重くはありません。
オブジェクト表現
ありません。new StringBuffer()でオブジェクトを作ってください。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(StringBuffer value)

値を設定します。リファレンスは変わりません。

native virtual String toString()

文字列に変換します。

StringBuffer buf = new StringBuffer();
buf += 'あ'
buf += "いうえお";

print("StringBuffer test...");
Clover.assert(buf.toString() == "あいうえお");
println("TRUE");
native int length()

文字列の文字数を返します。

native virtual void setValue(String value)

Stringクラスで値を設定します。

StringBuffer(String value)

コンストラクタです。文字列で初期値を指定できます。

StringBuffer buf2 = new StringBuffer("あいう");
buf2 += "えお";

print("String buffer test...");
Clover.assert(buf2.toString() == "あいうえお");
println("TRUE");
virtual StringBuffer clone()
virtual StringBuffer dup()

コピーを作成します。

native StringBuffer append(String value)
StringBuffer operator+=(String value)
native StringBuffer append(char c)
StringBuffer operator+=(char value)

文字列や文字を追記します。

StringBuffer buf3 = new StringBuffer("1");
buf3 += '2';
buf3 += "345";

print("Clover string buffer test...");
Clover.assert(buf3.toString() == "12345");
println("TRUE");
StringBuffer clear()

内容を削除します。selfを返します。

StringBuffer buf4 = new StringBuffer("あいうえお");

buf4 += "かきくけこ";

Clover.print("String buffer clear test...");
Clover.assert(buf4.toString() == "あいうえおかきくけこ");
Clover.assert(buf4.clear().toString() == "");
println("TRUE");
virtual bool operator==(StringBuffer@Nullable right)
virtual bool operator!=(StringBuffer@Nullable right)

内容を比較します。

Parser

文字列を最初から最後までパースするときに使うクラスです。文字列がstrとしたらfor(int i=0; i<str.length(); i++) { if(str[i] == ,,,,} などと書いても文字列はパースできますが、速度が出ません。こちらを使うと無駄なオブジェクトが作られないため、とても高速に文字列をパースできます。
オブジェクト表現
ありません。new Parser(String)もしくはStringクラスのtoParser()メソッドでオブジェクトを作ってください。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(Parser value)

値を設定します。

native virtual String toString() throws Exception;

パースしている文字列を返します。

native long point() throws Exception;

パースしている位置を返します。

Parser parser = "あいうえお".toParser();

parser.forward(1);
print("Parser test1...");
Clover.assert(parser.getChar() == 'い' && parser.point() == 1l);
println("TRUE");
native void setString(String value)

パースする文字列を設定します。

native void setPoint(long point)

パースする位置を設定します。
Parser parser2 = "あいうえお".toParser();

parser.setPoint(2l);
print("Parser test1...");
Clover.assert(parser.getChar() == 'う' && parser.point() == 2l);
println("TRUE");
native bool end() throws Exception;

パースしている位置が終端まで来たら真を返します。

$ vim a.cl
Parser parser3 = "あいうえお".toParser();

while(!parser3.end()) {
    char c = parser3.getChar();
    c.toString().println();
    parser3.forward(1);
}
$ cclover a.cl
$ clover a.cl
あ
い
う
え
お
native char getChar()

パーサーの現在位置の文字を返します。

$ vim a.cl
Parser parser3 = "あいうえお".toParser();

while(!parser3.end()) {
    char c = parser3.getChar();
    c.toString().println();
    parser3.forward(1);
}
$ cclover a.cl
$ clover a.cl
あ
い
う
え
お
native String getString(int num) throws Exception

パーサーの現在位置から文字列をnum文字分返します。

$ vim a.cl
Parser parser4 = "あいうえおかきくけこ".toParser();

while(!parser4.end()) {
    parser4.getString(2).println();
    parser4.forward(2);
}
$ cclover a.cl
$ clover a.cl
あい
うえ
おか
きく
けこ
native Parser forward(int num=1)

パーサーの現在位置をnum文字分だけ進めます。終端以上になると終端に補正されます。

$ vim a.cl
Parser parser5 = "あいうえお".toParser();

while(!parser5.end()) {
    parser5.getString(3).println();
    forward(3);
}
$ cclover a.cl
$ clover a.cl
あいう
えお
native Parser backward(int num=1)

パーサーの現在位置をnum文字分戻ります。

Parser parser6 = "あいうえお".toParser();

print("Parser backward test...");
parser6.forward(3);
Clover.assert(parser6.getChar() == 'え');
parser6.backward(2);
Clover.assert(parser6.getChar() == 'い');
println("TRUE");
Parser(String value)

コンストラクタです。引数の文字列をパースの対象とします。

virtual Parser clone()
virtual Parser dup()

コピーしたパーサーを返します。

virtual bool operator==(Parser@Nullable right)
virtual bool operator!=(Parser@Nullable right)
内容を比較して同じなら真を返します。

Bytes

バイト列を格納するクラスです。Fileクラスでreadを行った時の戻り値もBytesクラスになります。可変長でappendを使うとデータを追記していくことができます。
オブジェクト表現
B"ABC", B"DEF"などBのあとに文字列がきます。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=とoperator>, operator<, operator>=, operator<=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(Bytes value)

値を設定します。

virtual Bytes clone() throws Exception
virtual Bytes dup()
コピーしたオブジェクトを返します。

Bytes toBytes()
Byteオブジェクトに変換します。子クラスで意味があります。

native int length()
バイト列のバイト数を返します。

print("Bytes length test...");
Clover.assert(B"ABC".length() == 3 && B"あいう".length() == 9);
println("TRUE");
native byte@CheckForNull char(int index)
byte@CheckForNull operator[] (int index)
indexの位置のバイトを返します。範囲外の位置だとnullを返します。

print("Bytes operator[] test...");
Clover.assert(B"ABC"[1] == 'B'.toInt().toByte() && B"ABC"[-2] == 'B'.toInt().toByte() && B"ABC"[4] == null);
println("TRUE");
native byte replace(int index, byte c) throws RangeException
byte operator[]= (int index, byte c) throws RangeException

indexの位置のバイトを置き換えます。indexが範囲外だとRangeExceptionを返します。

Bytes bytes1 = B"ABCDEFG";
bytes1[1] = 'D'.toInt().toByte();

print("Bytes replace test...");
Clover.assert(bytes1 == B"ADCDEFG");
println("TRUE");
virtual native String toString() throws ConvertingStringCodeException

文字列に変換します。変換に失敗するとConvertingStringCodeExceptionが返されます。

print("Bytes toString() test..");
Clover.assert(B"ABC".toString() == "ABC" && B"あいうえお".toString() == "あいうえお");
println("TRUE");
native int cmp(Bytes right)

バイト列とバイト列を比較します。strcmp(3)が使われています。selfがrightより大きければ正の値をselfがrightより小さければ負数を等しければ0を返します。

print("Bytes cmp test....");
Clover.assert(B"ABC".cmp(B"ABC") == 0 && B"ABC".cmp(B"DEF") < 0 && B"DEF".cmp(B"ABC") > 0);
println("TRUE");
native void append(Bytes string)
Bytes operator+= (Bytes string)

データを追記します。

print("Bytes append test...");
Clover.assert(B"ABC".append(B"DE") == B"ABCDE");
println("TRUE");
virtual bool operator==(Bytes@Nullable right)
virtual bool operator!=(Bytes@Nullable right)
virtual bool operator>(Bytes right)
virtual bool operator<(Bytes right)
virtual bool operator>=(Bytes right)
virtual bool operator<=(Bytes right)

内容で比較します。

Bytes operator +(Bytes value)

左右のBytesオブジェクトを足して新しいBytesオブジェクトを返します。

native void forward(int size=1) throws Exception

Bytesオブジェクトは内部でポインタを保持しています。そのポインタをsize分だけ進めます。

Bytes data = B"ABCDE";

print("Bytes forward test...");
Clover.assert(data.getByte().toInt().toChar() == 'A');
println("TRUE");

data.forward(1);

print("Bytes forward test2...");
Clover.assert(data.getByte().toInt().toChar() == 'B');
println("TRUE");
native void backward(int size=1) throws Exception

ポインタをsize分だけ戻します。

Bytes data2 = B"ABCDE";

print("Bytes forward test...");
Clover.assert(data2.getByte().toInt().toChar() == 'A');
println("TRUE");

data2.forward(1);

print("Bytes forward test2...");
Clover.assert(data2.getByte().toInt().toChar() == 'B');
println("TRUE");

data2.backward(1);

print("Bytes backward test3...");
Clover.assert(data2.getByte().toInt().toChar() == 'A');
println("TRUE");
native void setPoint(long point) throws Exception

ポインタの位置を設定します。

Bytes data5 = B"12345";

data5.setPoint(2l);

print("Clover setPoint test...");
Clover.assert(data5.getByte().toInt().toChar() == '3');
println("TRUE");
native long point()

オブジェクトが保持するポインタの位置を返します。

Bytes data6 = B"ABCDE";

data6.forward(2);
print("Bytes test....");
Clover.assert(data6.point() == 2l);
println("TRUE");
native byte getByte()

ポインタの位置のデータを1バイト返します。

native short getShort()

ポインタの位置のデータを2バイト返します。

native uint getUInt()

ポインタの位置のデータを4バイト返します。

native long getLong()

ポインタの位置のデータを8バイト返します。

Range

範囲を表すクラスです。配列のindexとして使ったりします。int(32bit符号あり)の先頭位置と後方位置を保持しています。Rangeクラスを使っているメソッドの実装方法によりますが、負数は後方から数えた位置を表します。-1が一番最後のデータ、nullが末尾を表します。
オブジェクト表現
1..2, 5..-1
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparableMore → operator==とoperator!=,operetor>,operator>=,operator<,operator<=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native void setHead(int head)

オブジェクトが保持する範囲の先頭を設定します。

Range range = 1..5;

range.setHead(3);

print("Range test...");
Clover.assert(range.head() == 3);
println("TRUE");
native void setTail(int tail)

Range range2 = 3..-1;

range2.setTail(500);

print("Range test...");
Clover.assert(range2.tail() == 500);
println("TRUE");
native virtual void setValue(Range range)

引数の値と同じ値に設定します。

native int head()

範囲の先頭の値を返します。
print("Range test...");
Clover.assert((1..5).head() == 1);
println("TRUE");
native int tail()

範囲の末尾の値を返します。
print("Range test...");
Clover.assert((1..6).tail() == 6);
println("TRUE");
Range toRange()

Rangeオブジェクトに変換します。子クラスで意味があります。

virtual Range clone() throws Exception
virtual Range dup()

コピーしたオブジェクトを返します。

virtual bool operator==(Range@Nullable range)
virtual bool operator!=(Range@Nullable range)
virtual bool operator>(Range@Nullable range)
virtual bool operator<(Range@Nullable range)
virtual bool operator>=(Range range)
virtual bool operator<=(Range range)

値を比較して真偽値を返します。

bool include(int number)

引数が範囲内なら真を返します。

print("Range test....");
Clover.assert((1..5).include(3) && !(1..5).include(6));
println("TRUE");
virtual String toString()

文字列表現を返します。

Tuple

Tupleは違う型を持つオブジェクトの集合を保持するコンテナクラスです(オブジェクトの入れ物のクラス)。言語の仕様上8個までオブジェクトしか保持できません。保持するオブジェクトの分だけgenericsの引数を取ります。例えばintとStringを保持するTupleクラスはTuple<int,String>です。Tupleはgenericsの引数の数によって別のクラスなのですが、メソッド一覧では2つの引数を取るときを例として書いています。
オブジェクト表現
(1,2,3)や("AAA", 1, 1..5)などコンマで区切ります。コンマ演算子は優先順位が低いので、括弧で一応括っておいたほうがいいかもしれません。
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
IHashKey → hashValueを実装しています。
includeしているモジュール
ConsturctorModule
メソッド
Tuple(T1 value, T2 value2)

コンストラクタです。

Tuple<T1, T2> toTuple()

タプルに変換します。子クラスで意味があります。

void set1(T1 value)
void set2(T2 value)

値を設定します。

Tuple<int, String> tuple1 = (1, "ABC");
tuple1.set1(5);
print("Tuple test...");
Clover.assert(tuple1.get1() == 5 && tuple1.get2() == "ABC");
println("TRUE");
T1 get1()
T2 get2()

値を得ます。

Tuple<int, String> tuple2 = (1, "ABC");
tuple2.set1(100);
tuple2.set2("DEF");
print("Tuple test...");
Clover.assert(tuple2.get1() == 100 && tuple2.get2() == "DEF");
println("TRUE");
virtual bool operator==(Tuple@Nullable right)
virtual bool operator!=(Tuple@Nullable right)

値を比較します。

virtual Tuple clone() throws Exception
virtual Tuple dup() throws Exception

コピーした新しいオブジェクトを返します。
cloneは保持しているオブジェクトもcloneします。dupは保持しているオブジェクトはselfと同一のオブジェクトを返します。

virtual String toString()

文字列表現を返します。

virtual int hashValue()

ハッシュ値を返します。

Block

メソッドの引数になるブロックのクラスです。単体で実行することはできません。abstractクラスなのでnewできません。
オブジェクト表現
ありません。
実装しているインターフェース
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
native Array<Type> parametors()

ブロックのパラメータの型を返します。

native Type resultType()

ブロックの戻り値の型を返します。

virtual String toString()

文字列表現を返します。

Null

何もないことを表すnullオブジェクトのクラスです。nullはNullクラスのインスタンスとなります。dynamic_typingされているので、どの型の変数にも代入できます。voidクラスからextendsされています。
オブジェクト表現
null
実装しているインターフェース
ICloneable → cloneを実装しています。
IInspectable → toStringを実装しています。
IComparable → operator==とoperator!=が実装されています。
includeしているモジュール
ConsturctorModule
メソッド
virtual Null dup()
virtual Null clone()

new Nullを返します。

int toInt()

0を返します。

virtual String toString()

"null"を返します。

bool toBool()

falseを返します。

virtual bool operator==(anonymous@Nullable value)
virtual bool operator!=(anonymous@Nullable value)

Null型同士なら真を返します。

void

戻り値が無いことを表すためにあるクラスです。ただし、メソッドは必ず戻り値を返さないといけないので、内部的にはnullオブジェクトが返ってます。abstractクラスでnewはできません
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド

Thread

並列的にブロックを実行します。
オブジェクト表現
ありません。
実装しているインターフェース
ICloneable → cloneを実装しています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(Thread value)

値を設定します。

native nosynchronized Thread() with void block() throws Exception

スレッドを作ります。ブロックが並列実行されます。並列実行したブロックはjoinしないといけません。

print("Thread test...");
Thread thread = new Thread() {
    1+1+1;
}
thread.join();
println("TRUE");
native nosynchronized void join()

実行したスレッドを削除します。(実行を合流させます)

virtual Thread clone() throws Exception
virtual Thread dup()

コピーしたオブジェクトを返します。

Mutex

オブジェクト表現
Mutexです。threadで排他処理が必要になったら使ってください。
実装しているインターフェース
ICloneable → cloneを実装しています。
includeしているモジュール
ConsturctorModule
メソッド
native virtual void setValue(Mutex value)

内容を設定します。
native void run() with void block()

排他処理を施してブロックを実行します。

virtual Mutex clone() throws Exception
virtual Mutex dup()

コピーしたオブジェクトを返します。

Clover

言語に関するメソッドを集めたクラスです。ほとんどのメソッドはstaticメソッドです。
オブジェクト表現
ありません。
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
native static Array<String>@Nullable getCloverArgv()

コマンドライン引数を返します。

$ vim a.cl
Clover.getCloverArgv().toString().println();
$ cclover a.cl
$ clover a.cl 
{clover,a.cl}
native static void print(String string) throws NullPointerException, ConvertingStringCodeException

文字列を出力します。aliasされています。

static void println(String string)
static void echo(String string)

文字列を出力します。最後に改行をします。aliasされています。

native static void showClasses()

ロードされているクラスを全て出力します。

native static String outputToString() with void block() throws ConvertingStringCodeException

ブロック内の出力を文字列に変換します。

print("outputToString test...");
Clover.assert(Clover.outputToString() {
    print("A");
    print("B");
    print("C");
} == "ABC");
println("TRUE");
native static void gc()

GCを動かします。Cloverは必要なときにGCを行うので特に必要はありません。

static bool initialize()

Cloverクラスがロードされるときに自動的に呼ばれます。

static void assert(bool expression, int err_num=2)

expressionが偽なら実行を停止します。err_numは実行を止める時のSystem.exitのエラーコードです。

System

オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
ソースを見てください。大体はC言語とUNIXシステムコールの薄いラッパーです。

標準ライブラリ

目次

mode_t

statクラスのフィールドであるst_modeのクラスです。System.statによってstatクラスの情報が得られます。st_modeはその一部の情報になります。ファイルのアクセス権やファイルの種類、ファイルのパーミッションなどの情報が入っています。permissionクラス、FileKindクラス、FileAccessクラスの親クラスです。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
permission to_permission()

permissionクラスに変換します。
$ vim a.cl
Command.touch("ABC");

p"ABC".to_stat().to_permission().toString().println();

Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
---rw-rw-r--

permission

ファイルのパーミッション情報を保持しているクラスです。System.openなどのメソッドの引数に使われます。statクラスのフィールドのst_modeの情報の一部です。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
virtual String toString()
パーミッション情報をls -lと同じ形式で文字列にします。
$ vim a.cl
Command.touch("ABC");

p"ABC".to_stat().to_permission().toString().println();

Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
---rw-rw-r--

uid_t

System.statによって得られるstatクラスのフィールドst_uidのクラスです。statクラスの情報の一部になります。ファイルのユーザーIDを保持しています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
virtual String toString()

ユーザー名を文字列で返します。

$ vim a.cl
Command.touch("ABC");
p"ABC".to_stat().to_uid_t().toString().println();
Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
ab25cq:1001

gid_t

System.statによって得られるstatクラスのフィールドであるst_gidのクラスです。statクラスの情報の一部になります。ファイルのグループIDの情報を保持しています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
virtual String toString()

グループ名を文字列で返します。

$ vim a.cl
Command.touch("ABC");
p"ABC".to_stat().to_gid_t().toString().println();
Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
ab25cq:1001

off_t

System.statで得られるstatクラスのフィールドの一部であるst_sizeのクラスです。ファイルの大きさが入っています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
サンプルコード
$ vim a.cl
Command.touch("ABC");
p"ABC".to_stat().size().type().toString().println();
Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
off_t

time_t

System.statで得られるstatクラスのフィールドの一部であるst_atime,st_mtime,st_ctimeなどの型です。時間を保持しています。単一の数値型です。他にも時間を保持する場合はtime_t型が使われます。ちなみにst_atimeはアクセス時間をst_mtimeはファイルを改変した時間をst_ctimeはファイルが作られた時間を保持しています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
tm to_tm()

時間の表現のよりわかりやすい形式である。tmクラスに変換します。

$ vim a.cl
Command.touch("ABC");
p"ABC".to_stat().st_ctime.to_tm().toString().println();
Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
2016-01-14 22:25

pid_t

プロセスのIDを保持します。様々なシステムコールでプロセスを識別するのに使われます。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド

tm

時間を表すクラスです。time_tと比べて、よりわかりやすい形式となっています。time_tと相互に変換できます。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
tm(int year, int month, int day_of_month, int hour=0, int minuts=0, int sec=0, int day_of_week=0, int day_of_year=0, bool isdst=false)
コンストラクタです。isdstは夏時間を表します。

int second()

秒を返します。

void setSecond(int value)

秒を設定します。

int minuts()

分を返します。

void setMinuts(int value)

分を設定します。

int hour()

時間を返します。

void setHour(int value)

時間を設定します。

int dayOfMonth()

日付を返します。

void setDayOfMonth(int value)

日付を設定します。

int month()

月を返します。

void setMonth(int value)

月を設定します。

int year()

年を返します。

void setYear(int value)

年を設定します。

int dayOfWeek()

曜日を返します。(0が日曜日、1が月曜日,,,,)

void setDayOfWeek(int value)

曜日を設定します。(0が日曜日、1が月曜日,,,,)

int dayOfYear()

1/1からの日数を返します。

void setDayOfYear(int value)

1/1からの日数を設定します。

bool isDaylightSavingTime()

夏時間かどうかの真偽値を返します。

void setDaylightSavingTime(bool value)

夏時間かどうかの真偽値を設定します。

virtual String toString()

文字列表現にして返します。

$ vim a.cl
tm time = new tm(System.time());
time.toString().println();
$ cclover a.cl
$ clover a.cl
2016-01-15 10:54
time_t to_time_t() throws SystemException

System.mktimeを使ってtime_t型に変換します。

stat

System.statで得られるファイルの情報です。所有者やグループ、パーミッション情報などを保持しています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
stat(Path path, bool lstat=false) throws SystemException

コンストラクタです。pathが表すファイルの情報を得ます。

bool S_ISDIR()

ディレクトリなら真を返します。

Command.mkdir("ABCDEFG");
print("S_ISDIR test...");
Clover.assert(p"ABCDEFG".to_stat().S_ISDIR());
println("TRUE");
Command.rmdir("ABCDEFG");
bool S_ISCHR()

キャラクターデバイスなら真を返します。

bool S_ISBLK()

ブロックデバイスなら真を返します。

S_ISREG()

レギュラーファイルなら真を返します。

Command.touch("ABC");
print("S_ISREG test...");
Clover.assert(p"ABC".to_stat().S_ISREG());
println("TRUE");
bool S_ISFIFO()

FIFOなら真を返します。

bool S_ISLNK()

シンボリックリンクなら真を返します。

bool S_ISSOCK()

ソケットなら真を返します。

uid_t to_uid_t()

uid_tに変換します。所有者情報がわかります。

$ vim a.cl
Command.touch("ABC");
p"ABC".to_stat().to_uid_t().toString().println();
Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
ab25cq:1001
gid_t to_gid_t()

gid_tに変換します。所有グループが得られます。

permission to_permission()

permission型に変換します。パーミッション情報が得られます。

$ vim a.cl
Command.touch("ABC");
p"ABC".to_stat().to_permission().toString().println();
Command.rm("ABC");
$ cclover a.cl
$ clover a.cl
---rw-rw-r--
bool S_IXUGO()

実行権限があれば、真を返します。

tm atime()

ファイルにアクセスした時間を返します。

tm ctime()

ファイルを作成した時間を返します。

tm mtime()

ファイルを修正した時間を返します。

off_t size()

ファイルのサイズを返します。

Path

ファイルが存在する場所を示すクラスです。
オブジェクト表現
p"/etc/passwd", p"ABC"などpの後に"パス名"を書いてください。
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
Path(String value)
コンストラクタです。

virtual String toString()

文字列型に変換します。

void toFile(String mode="r", int permission=0666) with void block(File file) throws Exception, SystemException

File型に変換してファイルをオープンしてブロックを呼びます。ブロックが終わるとファイルは閉じられます。

print("Path toFile test...");
Command.echo("12345").write(p"ABC");
p"ABC".toFile() {|File file|
    Bytes data = new Bytes();
    file.read(data, 5);
    Clover.assert(data == B"12345");
}
Command.rm("ABC");
println("TRUE");
void write(Bytes data, int permission=0666) throws SystemException, Exception

パスが表すファイルにデータを書き込みます。

Clover.print("Path write test...");
p"ABC".write(B"12345");
Clover.assert(p"ABC".readOut() == B"12345");
println("TRUE");
Command.rm("ABC");
Bytes readOut(int permission=0666) throws SystemException, Exception

ファイルを全て読み込みます。

Command.echo("12345").write(p"ABC");
print("Path.readOut test...");
Clover.assert(p"ABC".readOut() == B"12345\n");
println("TRUE");

Command.rm("ABC");
stat to_stat()

statクラスに変換します。

stat to_lstat()

lstat(2)を使ってstatクラスに変換します。

Path basename(String suffix=null)

basename(3)を使ってパス名を変換します。パスからディレクトリ部分が取り除かれます。suffixを指定すると拡張子を削除します。

print("Path.basename test...");
Clover.assert(p"/etc/aaa.txt".basename() == p"aaa.txt");
println("TRUE");

print("Path basename test2...");
Clover.assert(p"/etc/aaa.txt".basename(".txt") == p"aaa");
println("TRUE");

print("Path basename test3...");
Clover.assert(p"/etc/aaa.txt".basename(".*") == p"aaa");
println("TRUE");
Path dirname()

パスのディレクトリ部分を取り出します。

print("Path.dirname test....");
Clover.assert(p"/etc/aaa.txt".dirname() == p"/etc");
println("TRUE");
Path extname()

パスの拡張子部分を取り出します。

print("Path.extname test...");
Clover.assert(p"/etc/aaa.txt".extname() == ".txt");
println("TRUE");
void chmod(mode_t mode) throws SystemException

chmod(2)を実行します。パーミッションを変更します。

void lchmod(mode_t mode) throws SystemException

lchmod(2)を実行します。パーミッションを変更します。

void chown(uid_t owner=-1l.to_uid_t(), gid_t group=-1l.to_gid_t()) throws SystemException

chown(2)を実行します。ファイルのオーナーを変更します。

void lchown(uid_t owner=-1l.to_uid_t(), gid_t group=-1l.to_gid_t()) throws SystemException

lchown(2)を実行します。ファイルのオーナーを変更します。

void unlink() throws SystemException

パスの位置のファイルを削除します。

int access(AccessMode mode=AccessMode.F_OK)

access(2)を実行します。ファイルが存在するかどうかを調べます。

void utime(time_t actime, time_t modtime)

utime(2)を実行します。ファイルのアクセス時間と修正時間を変更します。

bool fnmatch(String pattern, FnmatchFlags flags=0.toFnmatchFlags())

fnmatch(2)を実行します。

print("fnmatch test...");
Clover.assert(p"ABC.txt".fnmatch("*.txt") && !p"ABC.txt".fnmatch("*.c"));
println("TRUE");
bool isIdentical(Path path2)

パス同士が同じものか絶対パスに変換して比較します。

print("Path.isIdentical test...");
Clover.assert(p"/etc/../bin".isIdentical(p"/./bin"));
println("TRUE");
Path realpath()

絶対パスを返します。ファイルが存在していないとエラーを返します。

Path absolutePath()

絶対パスを返します。ファイルが存在していなくてもエラーを返しません。

print("Path.realpath test...");
Clover.assert(p"/./././usr/bin/..".realpath() == p"/usr");
println("TRUE");
void link(Path newpath) throws SystemException

link(2)を使ってハードリンクを作ります。

void symlink(Path newpath) throws SystemException

symlink(2)を使ってシンボリックリンクを作ります。

Path readlink() throws SystemException

readlink(2)を使ってシンボリックリンクを読み込みます。

void rename(Path path) throws SystemException

rename(2)を使ってファイル名を変更します。

void truncate(off_t length) throws SystemException

truncate(2)を使ってファイルの大きさをlengthサイズにします。

Array<Path> entries() throws SystemException

パスがディレクトリーなら所属するファイルを全て得ます。

$ vim a.cl
p"/".entries().each() {|Path path|
    path.toString().println();
}
$ cclover a.cl
$ clover a.cl
boot
dev
home
proc
run
sys
etc
root
var
usr
bin
sbin
lib
lib64
media
mnt
opt
srv
tmp
.rnd
Array<Path> glob(String pattern, FnmatchFlags flags=0.toFnmatchFlags()) throws SystemException

fnmatchを使ってパターンにマッチするファイルのパスを配列にして返します。

$ vim a.cl
p"/etc/".glob("*.conf").each() {|Path path|
    path.toString().println();
}
$ cclover a.cl
$ clover a.cl
resolv.conf
krb5.conf
fprintd.conf
sestatus.conf
host.conf
sysctl.conf
ld.so.conf
nsswitch.conf
libaudit.conf
xattr.conf
request-key.conf
e2fsck.conf
mke2fs.conf
slp.conf
logrotate.conf
dracut.conf
libuser.conf
idmapd.conf
oddjobd.conf
dnsmasq.conf
tcsd.conf
autofs.conf
autofs_ldap_auth.conf
ntp.conf
nfsmount.conf
kdump.conf
lftp.conf
updatedb.conf
man_db.conf
chrony.conf
rsyslog.conf
sensors3.conf
passwdqc.conf
sos.conf
jwhois.conf
vconsole.conf
locale.conf
yum.conf
asound.conf
void chdir() throws SystemException
chdir(2)を使ってカレントディレクトリを変更します。

void rmdir() throws SystemException

rmdir(2)を使ってディレクトリを削除します。

void mkdir(mode_t mode=0777l.to_mode_t())

mkdir(2)を使ってディレクトリを作成します。

File

オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
File(Path path, String mode="r", int permission=0666) throws Exception, SystemException

コンストラクタです。modeは"r","r+","w","w+","a"があります。

static File open(Path path, String mode="r", int permission=0666)

コンストラクタを呼び出します。

static void open(Path path, String mode="r", int permission=0666) with void block(File file) throws Exception, SystemException

ブロック内でファイルの操作を行った後ファイルを閉じます。

virtual int write(Bytes data) throws SystemException, Exception

ファイルにバイト列を書き込みます。

File file = new File(p"aaa.txt", "w", 0644);
file.write(B"ABC");
file.close();
Command.rm("aaa.txt");
virtual int read(Bytes data, int size) throws SystemException, Exception

ファイルからバイト列を読み込みます。

Command.echo("12345").write(p"ABC");
Bytes data3 = new Bytes();

File file2 = new File(p"ABC", "r");
file2.read(data3, 5);
file2.close();

print("File read test...");
Clover.assert(data3 == B"12345");
println("TRUE");

Command.rm("ABC");
int close() throws SystemException, Exception

ファイルを閉じます。ファイルはopenした後閉じないといけません。

static mode_t umask()
現在のumask(2)の値を返します。umaskとはファイルのパーミッションのマスクのことです。

static void umask(mode_t mask)
umask(2)を実行します。ファイルのパーミッションのマスクを設定します。

void flock(FileLockOperation operation) throws SystemException,Exception

flock(2)を使ってファイルをロックします。

Path toPath() throws Exception

ファイルがオープンされていた場合、オープンしたファイルのパスを返します。

stat to_stat() throws Exception

ファイルがオープンされていた場合、オープンしたファイルのパスのstatクラスを返します。

Bytes readOut() throws SystemException, Exception

ファイルからバイト列を全て読み込みます。

Directory

オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
Directory(Path path) throws SystemException

コンストラクタです。パスを引数にとりディレクトリをopenします。

Path@Nullable readdir() throws SystemException, Exception

ディレクトリを読み込みます。ディレクトリに所属するファイルのパスを返します。nullが返ると、それ以上は読み込めません。

void close() throws Exception

ディレクトリを閉じます。

static Array<Path> entries(Path path) throws SystemException

ディレクトリに所属する全てのファイルのパスを配列で返します。

static Array<Path> glob(Path path, String pattern, FnmatchFlags flags=0.toFnmatchFlags()) throws SystemException

globにマッチするファイルを全て返します。

static Array<Path> glob(String pattern, FnmatchFlags flags=0.toFnmatchFlags()) throws SystemException
カレントディレクトリでglobにマッチするファイルをすべて返します。

Jobs

プロセスのジョブを管理するクラスです。Clover.jobsにジョブが含まれています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
void forground(int job_num)
ジョブをフォアグランドにします。

virtual String toString()
ジョブの一覧を文字列にします。

Command

Command.ls("-al")などとすれば外部プログラムのlsに引数-alを付けて呼ぶことができます。この仕組はmethodMissingメソッドによって実現されています。
オブジェクト表現
実装しているインターフェース
includeしているモジュール
ConsturctorModule
メソッド
int resultCode()
外部プログラムが返したリターンコードを返します。

Command write(Path path, int permission=0666) throws SystemException, Exception

コマンドの出力をファイルに書き込みます。

Command.echo("12345").write(p"ABC");
print("Command test...");
Clover.assert(p"ABC".readOut() == B"12345\n");
println("TRUE");
Command.rm("ABC");

vimの設定

~/.vimrc
filetype plugin indent on

~/.vim/filetype.vim
augroup filetypedetect
    au BufRead,BufNewFile *.cl setfiletype Clover
    au BufRead,BufNewFile *.clc setfiletype Clover
augroup END

~/.vim/ftplugin/Clover.vim
:set cindent
:set shiftwidth=4
:set expandtab
:set tabstop=4
などとしておくと快適かもしれません。

readlineの設定

~/.inputrc
set blink-matching-paren on
としておくとicloverで便利かもしれません。

あとがき

とりあえず、完成しました。version1.0とします。マニュアルはかなり適当に書いているので分かってもらえるか心配です。

もともと僕は15年前からUNIXのプログラミングを行っていて、mfiler2というRubyを組み込んだコンソールファイラを作っていました。fd cloneみたいなやつです。mfiler2にはversion 1.40d以前で脆弱性が出たりしてIPAから警告を受けたりしました。2chでは少し話題になったり。まつもとゆきひろさんのブログで紹介されたり。

コンソールファイラを作っていると、そのうちに組み込みシェルが欲しくなって、xyzshというRubyのコマンドを組み込んだような変なシェルを開発したりしました。そのうちmfilerシリーズも4となり、無事シェルを組み込んだファイラが完成したのですが、さらに機能拡張していると、これは別にシェルやファイラの形に拘らなくてもいいのではないかという思いが出てきてました。それでCloverを作った次第です。そういう経緯ですので、スクリプティングというよりは対話的(iclover)に使ってもらえると嬉しいです。

それでは。enjoy Programing!

作者の情報

湊 大典(Daisuke Minato)
福島県立会津大学出身。京都府亀岡市在住。介護福祉士。1978年2月21日生まれ。

github → https://github.com/ab25cq