mtddc hokkaido : テンプレートタグでbrainf*ckを作ってみた

Post on 07-Dec-2014

3.490 Views

Category:

Self Improvement

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

MTDDC Hokkaido(2010/12/18)でライトニングトークした時のスライドです。

TRANSCRIPT

テンプレートタグでBrainf*ckを作ってみた

MTDDC Hokkaido2010/12/18

えんどうかつひろ

自己紹介● えんどうかつひろ

● @ka2hiro● フリーランスのプログラマ● MT歴

● 4年ほど(2006年頃から)● プラグイン書いたり、MTベースのWeb App書いた

り● 好きなテンプレートタグ

● mt:setVarTemplate と mt:date

今日お話すること● Brainf*ckを書いていて、はまったこと

きっかけ?● 単なる思いつき● テンプレートタグって、プログラミング言語だ

よね。● 変数あるし● 四則演算できるし● 条件分岐できるし● ループもできるし● 配列もハッシュもあるし

それに...● MT、テンプレートタグ、Brainfuckで、軽くぐ

ぐってみたけど、全然ヒットしない。● ってことは、これは...

ということでBrainf*ckのインタープリタを

書いてみた。

ところでBrainf*ckって何?

“Brainfuck(ブレインファック)は難解プログラミング言語のひとつ。

なお名称に卑語が含まれるため、Brainf*ckなどと表記されるこ

とがある。”wikipediaより

使える命令はこの↓8文字

> < + - . , [ ]だけ。

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

+++++++..+++.>-.------------.<+++++

+++.--------.+++.------.--------.>+.

これを実行すると

Hello World!

と表示するプログラミング言語。

で、書いてみたら、書けた。でも、けっこうはまった。

ここからが今日の本題。

はまったその1文字列中の任意の場所から1文字

だけ読み込む。

<mt:setvarblock name=”hoge”>The quick brown fox jumps over the lazy...</mt:setvarblock>

”Q”を表示するのに、<mt:var name=”hoge” substr=”4,1” setvar=”c”/>

と書けると思っていたら、substrモディファイア

なんてなかった。

仕方がないので、困った時の「正規表現」

にお願いしてみた。

正規表現/(?:.{<mt:var name="pos" />})(.)(?:.*)/

● posは、取得したい文字の位置(最初の文字は0番目)● 1つ目のかっこは読み飛ばす部分● 2つ目のかっこが取得したい文字● 3つ目のかっこは残りの文字(必要ないかも)● posが3の場合、/(?:.{3})(.)(?:.*)/ となる● $1で1文字取得できる

まとめるとこうなる。<mt:setvartemplate name="getchar"><mt:setvarblock name="pattern">/(?:.{<mt:var name="pos" />})(.)(?:.*)/</mt:setvarblock><mt:var name="code" regex_replace="$pattern","\1" setvar="c"/></mt:setvartemplate>

これで1文字ずつ読み込めるようになった。

はまったその2無限ループを作れない。

<mt:loop>は、配列の要素をたどることしかできないし、

<mt:for>はto=”N”で指定した回数しかループできないし、

どうしよう...

ちょっとかっこ悪いけど、<mt:for var=”i” from=”0” to=”1000”>

大きめの数値を終了条件にして、ごまかした。

はまったその3ループから脱出できない!

<mt:for var=”i” from=”0” to=”1000”> <mt:if name=”i” eq=”5”> <mt:setvar name=”i” value=”1000” /> ループ変数に終了条件を満たす値を 設定しても脱出できない! </mt:if></mt:for>

どうやらループ内では、ループ変数の参照はできるが、変更は反映されないようだ。

仕方がないので、<mt:for var=”i”� from=”0” to=”1000”> <mt:if name=”done” ne=”1”> 必要な処理を実施し、 終了条件を満たしたらdoneに1をセット    </mt:if></mt:for>

とした。でもこれだと...

10回目で終了条件を満たすと、残り990回は、

無駄に空回り。┐(´-`)┌

はまったその4完成したテンプレートを編集画面に貼付け、

プレビューしても真っ白け。

テンプレートのコンパイル結果をdumpして見ると、

<mt:elseif name=”c” eq=”>”>

どうもこのあたりから変。意図しない所でタグが閉じたり、

開いたり...

あっ、> と < は使えないのか。

ということで、8つの命令のうち、> を # に< を * に

に置換えた。

もっと早く気付けよ>自分

まとめ● いろいろあったけど、なんとかなったし、けっ

こう楽しめた。● みなさんもぜひ挑戦してみてください。● 今回書いたテンプレートは、githubにありま

す。● http://github.com/ka2hiro/brainfuck

● 次回はマンデルブロー集合の予定です(笑)

おまけ● 無限ループ/ループ脱出不可が悔しかったの

で、WhileTagというプラグインを書いてみた。● http://github.com/ka2hiro/WhileTag

● <mt:if>と同じ構文のブロックタグ● <mt:while name=”done” ne=”1”></mt:while>

● ループ内からループ変数を操作可能

ご清聴ありがとうございました。

top related