クリスマスを前にしてBFを先に作られてしまった話2012年11月11日 23:11

思うに、多少の欠点があっても目をつぶることって、ときにすごく大事なんだなって思います。 なんだそりゃって話なのですが、作ったBFの紹介で先を越されてしまって、大変くやしい思いをしてます。 この記事を読む大部分であろう異性愛者の男性の方々におかれましては、そんなにホイホイとBFをつくってしまっていいのか、あるいは果てしない苦労の先に手にいれるのがBFでいいのか、ちょっと落ち着いて考えるべきだと思います。

……ええと、おわかりだと思いますが、BFはもちろんbrainf*ckのことです。彼氏などいない!

キーボードマクロでbrainf*ckデバッガつくったよ

Vimで brainf*ck を作る試みは過去に thincaさんのものや mattnさんのものなど、いくつかあるようです。

しかし未だにVimScriptのよくわからない私がもっとも衝撃を受けたのは、つい先日 匿名の方がマクロで作った恐ろしいものです。

うわーん、今年の Vim Advent Calendar に使おうと思ってたネタだったのに!

……というのはさておき、 発表者は私ではないかと想像された方が何人かいらっしゃったようですが、残念ながら違います。 私はあんなに頭おかしくありませんし、マクロ漁船に乗船できる自信あんまりありません(ぉ

というわけで、もはや保存しておく意義が特にない「キーボードマクロで実装するbrainf*ckに対する私なりの解」をさっさと紹介してしまうことにします。

いろいろ欠点あるのですが「これはデバッガだ!」と言い張ればそれっぽく見えないこともない気がしているのでそのように主張しつつ紹介することにします。

マクロ漁船の匿名の方の発表と重なってしまう部分もあるかと思いますがご容赦ください。

特徴

  • @b でステップ実行できます。10@b など、ステップ数を指定して実行することもできます。
  • PCとポインタとメモリ空間をすべて可視化します。編集も可能です。
  • 名前付きのレジスタを2つだけ使います。(@b@x)

実行準備

まずは、お手元のVimを起動して、[CTRL-W]n を 2回ほど実行しましょう。あと、おまじないで、ステータスラインを2〜4行ほど上に持ちあげておきます(やらないとうまく動かないことがあります)。

ここまでできたら、一番上のウィンドウにこれを書いてください。

  • yl^Wk"xY^Wj@=(@0=='>'?'^V^Wk+^V^Wj':@0=='<'?'^V^Wk-^V^Wj':@0=='+'?'^V^Wk^V^A^V^Wj':@0=='-'?'^V^Wk^V^X^V^Wj':@0=='.'?'^V^Wj"=nr2char(@x)^V^Mp^V^Wk':@0=='['?@x?'':'%':@0==']'?@x?'%':'':'').' '

なお、ここに限り「^V」のように書いてあるのは[CTRL-V]と同じ意味です。

書けましたら、"bdd します。あと 30000O0[Esc] です。

最後に、真ん中のウィンドウにbrainf*ckソースコードを貼り付けます。

…と、ここまでの操作をきちんとこなすのは結構骨なので、お手軽実行ファイルを用意しておきました。

bfdebug.vi をダウンロードして、vim -s bfdebug.vi hello.bf のようにしてVimを起動するか、起動後のVimで:so! bfdebug.viしましょう。

これで準備完了です。

実行

プログラムの実行開始したい部分、つまり先頭行1カラム目にカーソルをもってきて、1000@b などとしてみましょう。 私の手元の環境で実行してみた様子を、以下に貼っておきます。

hello.bf

無事Hello, world!が出力されましたね。

たった218バイトでbrainf*ckデバッガができちゃうなんて、Vimはほんとにすごい!

え、デバッグしてない、ですか?すいませんbrainf*ck書いたことないんです……

備考

制限がいろいろあるので、gdgdと書き並べてみます。

  • ステップ実行しかできません。一度に走らせるには9999ステップ実行とかで代用してください。
  • コメントに使える文字が限られているかもしれません。変な文字(特に括弧やバックスラッシュ)は使わないでください。試してないだけなので、意外と大丈夫かもしれませんが……
  • メモリがバイト列でないため、オーバーフロー時および負になったときの挙動に依存したbrainf*ckプログラムは正しく動作しません。
  • メモリ空間は、ひとまず30000です。増やすことはできますが、マクロ実行前に決めておく必要があります。
  • 負のアドレスにアクセスできません。
  • 出力命令「.」は標準出力ではなく、バッファへ書き出します。マルチバイト文字はおそらく正しく出力できません。
  • 入力命令「,」は未実装です。単に無視されます。
  • ブレークポイント(独自拡張)を実装するつもりだったのですが、たかだか十数バイトを書き加える気力が捻出できないため、ありません。
  • Vimでしか動きません。nvi非対応です。

ともあれ、キーボードマクロの認知度が上がって世の中に受け入れられつつあるようで、この傾向が今後も維持されることを願ってやみません。

あと、Vim Advent Calendar 2011電子書籍、無事公開されましたようで、おめでとうございます。 前回は変なこと書いてすみませんでした。

コメント

_ 匿(完全匿名主義) ― 2012年11月12日 10:47

nvi 非対応としながら拡張子が .vi なのは明らかな誤りだと考えます。nvi では必要なアプローチが細部に関して根本的に異なります。Vim は Vim であり、vi の機能が豊富なバージョンではなく、Lisp と Scheme のような関係だと捉えるべきでしょう。やれることもキーアサインも違うんです。

尼崎の発表では、入力 , の実装を完了させたものを発表しました。制御コードを多用しながら、かつそのデバッグを容易にできるよう、tmux からキーの受付を行いましたが、正直に言って Vim の -s オプションを知らなかったので、そこは自分の調査の拙さが伺えますね。普段は Vim でバッファを切り替えたりせずに、tmux のウィンドウの切り替えで済ませることに頭の中を最適化している、というところから発想を広げたプレゼン内容なので、-s オプションを調べなかったのは当然の流れではあるのですが。

しかし tmux を経由でキーを送り込むと、特定の処理(つまりレジスタ)だけを書き直すことや、必要な部分だけをレジスタに入れず実際に動かしてみる、ということが容易だったのは事実ではあると思います。Vim のことをほぼ何も知らないまま 2 週間ちょっとで書き上げたので、この手法による生産性の高さは必須でした。

しかし、pla さんのコードは短いですね……。そこは自分のものより圧倒的に美しいと思います。自分は開発効率重視で、各レジスタ(nvi ではバッファ)の内容がある程度は疎結合になっており、極めて実行効率の悪い動きをします。詳しくは新しいスライドを御覧ください。スライドは、細かい修正が終わったら GitHub の ujihisa アカウントに委託している公開場所を更新しする予定なので、そちらをご覧ください。@ujm からアナウンスがあるでしょう。

_ pla ― 2012年11月12日 22:20

匿さん(でいいでしょうか?)

「,」の実装されたのですね!これは完敗です。
私の解にいろいろある制限の大部分は「手抜き」および「やる気のなさ」に起因している一方で、
「,」が未実装なのは方法を思いつかなかったためです。参りました。
改訂版のスライド、楽しみにしています。

そのマクロ漁船のスライド(11月4日版)ですが、なんといっても分岐の方法に唖然としました。なんという力技……
これは、大変マゾいということ以外ほぼなにも私には分かっていないnvi実装の都合でしょうか?
実際、expression registerなんて便利なものの代わりになるものは、さすがにないでしょうし……

ところで拡張子が「.vi」なのは、意図したものです。
というのも、anarchy golf でVimのキーシーケンスをファイルアップロードする場合、拡張子がそれなのです。
公式にはviということになっていた気もしますが、vi縛りでの投稿って見ない気がしますし、実装依存なんでもアリの世界ですので、むしろ実質Vim限定といってもよいかもしれません。
そういうわけで、キーシーケンスをファイルに保存するときの標準的な命名をほかに特に知らなかったこともあり、今回はこれを採用しました。
どの実装に対応しているかにかかわらず、キーシーケンスは「.vi」で配布する、みたいなのがデファクトになるといいんじゃないかなあ、みたいなことを考えています。

ほかに「.vim」も有り得そうなのですが、これは通常 VimScript に使われる拡張子のはずなので、読者層を考えると選択肢から外れます。
コントロールコードがあんまり入ってなかったら「.txt」でもいいかなと思うところなのですが……
それにしても、そこで出てくる喩えがLispとSchemeというのが素敵ですね。(でも、どっちがどっちなのでしょう?)
いったいどういう方なのか、ますます気になってきました。

最後に、私のコードが短いのは、短くてもできることしかやらなかった、と捉えるべきものかと思います。
疎結合の件、私も、命令ごとにレジスタを用意することも考えていました。
特に、実行キャプチャを撮るとき、ステータスラインの下に表示されるマクロがやたらと長くなってしまうのをどうにかしたかったからです。
とはいうものの、「実行準備」のところをあまり長く書きたくなかったこともあって、結局今の形のまま公開となりました。
とにかく単純な構造をと思っていたので、結果デバッグにそれほど苦労しなかったというのもあるかもしれません。

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※投稿には管理者が設定した質問に答える必要があります。

名前:
メールアドレス:
URL:
次の質問に答えてください:
Vimで「i」や「:」や「Esc」は「○○○」の切り替え。
「○○○」をカタカナ三文字で答えよ。

コメント:

トラックバック

このエントリのトラックバックURL: http://pla.asablo.jp/blog/2012/11/11/6631528/tb