Upload
katsuhiro-endo
View
3.490
Download
5
Embed Size (px)
DESCRIPTION
MTDDC Hokkaido(2010/12/18)でライトニングトークした時のスライドです。
Citation preview
テンプレートタグで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>
● ループ内からループ変数を操作可能
ご清聴ありがとうございました。