秀丸マクロで Brainf*ck #2

とりあえず現時点のマクロを晒しときますか。

// Brainf_ck.mac 1.09
// Copyright (C) 2003-2008 Satoshi Ogata
// satosystems@gmail.com
// 
// [usage]
// Brainf*ck のスクリプトを開いた秀丸でこのマクロを実行するか
// 実行したいスクリプト箇所を選択してこのマクロを実行します。
// スクリプト中では Brainf*ck に使用する 8 種類のキャラクタ以外は
// 無視されます。
// また、# から行末までは完全に無視されますが、debug フラグが
// true の場合は、# を読み取ったタイミングでデバッグ用ダイアログが
// 表示されます。
// 最初の行に # debug=on があれば、デバッグフラグが ON になります。
// 最後の結果出力で「はい」を選択すると、結果をクリップボードにコピーします。
// 
// [history]
// 1.09 結果をクリップボードにコピーするかどうかを問い合わせるように機能追加。
// 1.08 スクリプト上でデバッグの ON/OFF を選択できるように機能追加。
// 1.07 選択範囲外まで計算してしまう不具合を修正。
// 1.06 エディタ上をカーソルが移動するように実装変更。
// 1.05 デバッグ処理の実装。
// 1.04 バッファ内の数値の扱い方の不具合修正。
// 1.03 選択領域による部分的な実行。
// 1.02 入力の不具合修正。
// 1.01 ループの不具合修正。
// 1.00 完成。
// 
// [specification]
// > ポインタを1進める
// < ポインタを1戻す
// + ポインタの指す要素の値を1増やす
// - ポインタの指す要素の値を1減らす
// . ポインタの指す要素の値を外に出力
// , 外から値を入力して、 ポインタの指す場所へ入れる
// [ ポインタの指す要素の値が 0 だったら対応する次の ] までジャンプ
// ] 対応する前の [ までジャンプ

#debug = false;

if (selecting) {
    #selecting = true;
    #selendx = selendx;
    #selendy = selendy;
    escape;
    moveto seltopx, seltopy;
} else {
    gofiletop;
}

while (true) {
    if (code == '>') {
        #ptr = #ptr + 1;
        if (#debug) { if (#ptr > #max) #max = #ptr; }
    } else if (code == '<') {
        #ptr = #ptr - 1;
    } else if (code == '+') {
        #c[#ptr] = #c[#ptr] + 1;
        if (#c[#ptr] > 127) {
            #c[#ptr] = -128;
        }
    } else if (code == '-') {
        #c[#ptr] = #c[#ptr] - 1;
        if (#c[#ptr] < -128) {
            #c[#ptr] = 127;
        }
    } else if (code == '.') {
        $out = $out + char(#c[#ptr]);
    } else if (code == ',') {
        if ($in == "") {
            $in = input("Input ascii charactor");
            $s = $in;
        }
        if ($s == "") {
            break;
        }
        #c[#ptr] = ascii($s);
        $s = rightstr($s, strlen($s) - 1);
    } else if (code == '[') {
        if (#c[#ptr] == 0) {
            #n = 0;
            while (true) {
                right;
                if (code == '[') {
                    #n = #n + 1;
                } else if (code == ']') {
                    if (#n == 0) {
                        break;
                    }
                    #n = #n - 1;
                }
            }
        }
    } else if (code == ']') {
        #n = 0;
        while (true) {
            left;
            if (code == '[') {
                if (#n == 0) {
                    left;
                    break;
                }
                #n = #n + 1;
            } else if (code == ']') {
                #n = #n - 1;
            }
        }
    } else if (code == eof) {
        break;
    } else if (code == '#') {
        if (!#checked) {
            #checked = true;
            $s = gettext(x, y, linelen2, y);
            if (strstr($s, "debug=on") != -1) {
                #debug = true;
                debuginfo 1;
            }
        }
        if (#debug) {
            #j = 0;
            $msg = "#ptr:" + str(#ptr) + " #c[" + str(#ptr) + "]=" + str(#c[#ptr]);
            while (#j <= #max) {
                if (#j % 8 == 0) {
                    $msg = $msg + "\n";
                } else {
                    $msg = $msg + " ";
                }
                $msg = $msg + "[0x" + hex(#c[#j]) + ":" + str(#c[#j]) + "]";
                #j = #j + 1;
            }
            golineend;
            beginsel;
            golinetop2;
            endsel;
            debuginfo $msg;
        }
        golineend2;
    } else {
        // それ以外は無視する
    }
    if (#selecting && (y > #selendy || y >= #selendy && x >= #selendx)) {
        break;
    }
    right;
}

question $out;
if (result) {
    setclipboard $out;
}

このマクロは処理速度を追求してなくて、Brainf*ck のコードをマクロが一生懸命処理している様を見て楽しむ、というのが正しい用法ですからねっ。

動かしてみよう


最初はもちろん「hello, world!」でしょう(Wikipedia より)。

 +++++++++[>++++++++>+++++++++++>
+++++<<<-]>.>++.+++++++..+++.>-.
 ------------.<++++++++.--------
.+++.------.--------.>+.

ピラミッドを作るコードです(どう書く?org より)。
入力ダイアログに一桁の数字を入れてね。

>++[-<+++++>]>++++++[-<+++++++>]>++++++++[-<++++>],>++++++++
[-<------>]<[->+>+<<]>>->>+<<<[->[->+<<<<.>>>]>[-<+>]<->>-
[->+<<<<<<<..>>>>>>]<<<<<<.>>>>>>>[-<+>]<++<<<<<<<.>>>>]

最後に紹介するのは、僕が動かした中でもっとも時間のかかる Brainf*ck コードです。
大文字を小文字に変換します(k.inaba さんの Brainf*ck より)。

あらかじめ伝えておくと、このコードで HOGEhoge に変換するのに、僕のマクロだと 5 分ぐらいかかるからね。しかも CPU 100% 使うよ。欲張って長い文字列を入力すると夜が明けてしまうからね

でも、Esc でいつでもやめられるから安心してね。

>>++++++++[->++++++++<]>>>>+++++++++[->++++++++++<]>[<<,[->+<<+<<+>>>]<<<[
->>>+<<<]>>>>>[->+>>+<<<]>[<<[->+>>+<<<]>>>[-<<<+>>>]<<[[-]<->]>-]>>[-<<<+
>>>]<<<<<<<[-<+<<+>>>]<[>>[-<+<<+>>>]<<<[->>>+<<<]>>[[-]>-<]<-]<<[->>>+<<<
]>>>>><[[-]>++++++++++++++++++++++++++++++++>[[-]<------------------------
-------->]<<]>>[-]<.>>]

YouTube に動画を上げてみたよ。