CT Brainf*ck

ふと思い立ったので書いてみた.D言語のCTFEは優秀なのですっきり書けたのは書けたけど,何かちょっと嵌まった.以下嵌まった所.

  • 配列のlength
arr ~= 0;        // OK
arr.length = 10; // Error : cannot be evaluated at compile time

時間があったらrt以下を読んでみる

  • mixin後の関数呼び出し
mixin("int func() { return 0; }");
func();               // Error : no identifer func
pragma(msg, func());  // OK

これ何でなんだろ?

enum map = ['a':""];
if ('a' in map) // Error : Cannot interpret 'a' in (['a':""]) at compile time

mapは置換されてるはずなんだけど,どうしてだろうか.このせいでswitchを使うはめに…

上の点ふまえてソースは以下.さすがにコンパイルタイムにIO処理は出来ないので,入力スルーで出力は戻り値のバッファに貯めている.

/**
 * Translates Brainf*ck to D.
 */
pure nothrow string translate(in string src)
{
    string code = q"EOS
string run()
{
string  result;
ubyte[] tape = [0];
size_t  i;
EOS";

    foreach (c; src) {
        switch (c) {
        case '+':
            code ~= "tape[i]++;";
            break;
        case '-':
            code ~= "tape[i]--;";
            break;
        case '.':
            code ~= "result ~= tape[i];";
            break;
        case '<':
            code ~= "i--;";
            break;
        case '>':
            code ~= "i++; if (tape.length <= i) tape ~= 0;";
            break;
        case '[':
            code ~= "while (tape[i]) {";
            break;
        case ']':
            code ~= "}";
            break;
        default:
        }
    }

    return code ~ "return result; }";
}

// test
mixin(translate(import("hello.bf")));
pragma(msg, run());