ど〜なっつは、時を司るプログラミング言語です。…はて。

普通のプログラミング言語では、実行の流れはただひとつ、過去から未来に流れていき、戻ることはありません。覆水盆に返らずってやつです。

でも、それでは困ることもあります。過去の時点に戻りたい、やり直したい、そういう時もあるでしょう。プログラミング言語「ど~なっつ」では、ソフトウェアの中でだけですが、そういった事を実現することができます。

ど~なっつは…

  • 処理系の状態を過去に遡らせ、未来に還せるプログラミング言語です。
  • 任意の時点でのセーブデータを書き出し、後で実行を再開できます。
  • C++ネイティブのアプリケーションから組み込まれる事を意識しています。
  • 「反副作用」というアプローチによって、組み込み先の外部環境も過去に戻せます
  • C++11の可変長引数テンプレートを使って、簡単にネイティブとの接続ができます。
  • JavaScript: The Good Partsを元にした、JavaScriptを意識しつつ残念な点を取り除いたシンプルなプロトタイプ型オブジェクト指向言語です。
  • 同じポリシーに基づいた「時を司るGUIツールキット:ちさ」も開発中です。

# サンプル

いくつかサンプルを示します。

Hello world

System.println("Hello world");

再帰を使った階乗の計算

f = func(idx, acc){
    if( idx <= 0 ){
        acc; //最後に評価された値が戻り値になる
    }else{
        return f(idx-1, acc+idx); //戻り値を明示することもできます。
    };
};
System.println(f(10, 0)); // prints 55

ブロックの一番最後に評価された式がそのブロックの値になります。return式を使ってそのことを明示することもできます。

なお、ど~なっつにはCなどにある「文」はありません。ifも式です。

##スクリプト内から時を操作する

「時を司るプログラミング言語」の二つ名の通り、「ど~なっつ」ではスクリプト言語の中の時間を自由に操作することができます。

//普通の変数は、時間操作の影響を受けますが…
tabeta=0;

//Homuraは時間操作前の事を覚えていて、時間操作の影響を受けません。
Homura.counter=0;

//このあとの命令を使って、この時点まで時を戻せるようになります。
save_time=Homura.tick();

if(Homura.counter < 10){
  // ドーナッツを食べましょう。
  // この足し算の結果は、時間操作で戻ってしまいます。
  tabeta++;

  // ドーナッツを食べた回数を表示しましょう
  System.println(tabeta, "番目のドーナッツを食べた!");

  // Homuraに入った値は時間操作の影響を受けないので、
  // 時間操作を行なってもこの足し算の結果は戻りません。
  Homura.counter+=1;

  // 上で記録した時間まで、スクリプトエンジン全体を戻します。
  Homura.seek(save_time);
} else {
  //ど~なっつでは、else節を省略することはできません。
};

これを実行すると…

% donut time_op.donut
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!
 1番目のドーナッツを食べた!

このように何度ループをめぐっても1番めのドーナッツを食べ続けることができますが、Homuraは時間操作の影響を受けないので、無限ループには陥らずに済みます。

# ホストアプリケーションとのデータのやり取り ど~なっつは、C++に組み込むことを前提に作られたスクリプト言語です。以下のようにして比較的簡単にネイティブアプリに組み込むことができます。

#include <donut/Donut.h> //includeが必要なのはひとつだけです。
using namespace donut;

int main(char argc, char** argv){
    Handler<Donut> donut(new Donut()); //ど〜なっつ本体の作成を行います

    //セーブデータの読み込みではなく、新規の環境を作ります。
    donut->bootstrap();

    //実際に実行を行う仮想マシンを取得します
    Handler<Machine> machine = donut->queryMachine();

    //ソースをコンパイルします。
    Handler<Source> src = donut->parse( "1+1;" );

    //コンパイルしたソースを実行し、結果が帰ってきます。
    Handler<Object> obj = machine->start( src );

    //ど〜なっつのオブジェクトをC++の数値に変換します。
    int num = obj->toInt(donut->heap());

    //その結果を表示します
    std::cout << num << std::endl;

    return 0;
}

その他のサンプルはサンプルフォルダにあるかもしれません。

ライセンス

ど~なっつのライセンスはGPLv3となっています。

ど~なっつの誕生経緯

ど~なっつはIPAの未踏IT人材発掘・育成事業に採択された「CPUの理解を容易にするシステムと解説サイトの構築」の一部分として開発され、支援を受けています。