BrainFuck Part.3 <[+-.,]>
そろそろ実用的なライブラリを
つくれうぜ
何番地と何番地を引数にして何番地に返すってか?
実行環境で一番おすすめのってどれ?
ぐぐったらたくさん見つかるのだけどどれもイマイチ
>>484 大して難しくないんだから自分で「イマイチ」じゃないように作ればいいじゃん。
尤も、他人に「イマイチ」である理由を説明できない位だと難しいかも試練が。
brainfuckでbrainfuckインタープリタを作ってみた
部室の入り口にbrainf*ckのコードが書いてあった
変形版Brainfuck
ジャンプ先のプログラムカウンタの値を記憶するためのスタックを用意しておく
> ポインタをインクリメント
< ポインタをデクリメント
+ ポインタが示すメモリ位置のデータをインクリメント
- ポインタが示すメモリ位置のデータをデクリメント
. ポインタが示すメモリ位置のデータを出力
, ポインタが示すメモリ位置のデータに入力
* 現在のプログラムカウンタの値をスタックに入れる
/ ポインタが示すメモリ位置のデータがヌルでなければ、スタックから取り出した値までジャンプ
ヌルならばスタックから値を抜き去り、次の命令にジャンプ
本家BFの場合は対応する括弧を調べる作業が必要だが変形版だとその必要はない
そのかわり後方へのジャンプはできないが、原理的には本家と同じくチューリング完全(…だと思う)
ぼくもはじめます
>>491 後方ジャンプがないとチューリング完全にならないと思う
代入式を導入してみたい
どこになにを代入すんだよ
=(>>)
二つ後の値を現在の場所に代入
とか
497 :
デフォルトの名無しさん:2013/05/05(日) 21:43:34.84
いっそのこと膨大な糖衣構文を作ったほうがいいかと
"Syntactic sugar causes cancer of the semicolon."
(>)|(>>)
1つ後の値と二つ後の値のビット論理和を現在の場所に代入
(>)||(>>)
ビット論理和じゃなくて普通の論理和
(>)|(>>))
((>)|(>>))|((<<)|(<))
1つ後の値と二つ後の値のビット論理和と
2つ前の値と一つ前の値のビット論理和の
ビット論理和を現在の場所に代入
([[[[[)<
Error: No right blanket
Use newspaper, instead.
([[[[[)< >(]]]]])
メモリフィールドが階層的になってて
特定の番地を全ての階層で同期とかできると楽しそう
507 :
デフォルトの名無しさん:2013/05/06(月) 08:26:09.23
オブジェクト指向のBrainFuckとか作れないかな?
コンパイラ大きくしたら意味無いじゃん(至言)
プリプロセッサを巨大化させよう(提案)
fork機能つけようぜ
brainfuck拡張するなら既存の言語でいいじゃん?
ぐぬぬ
ぐ ポインタをインクリメント
ぬ ポインタをデクリメント
入力された文字列の文字数の取得なんてできるんですかね
[;>+<].
わかんね
そもそもint[]の要素数とか無いだろ
文字入力は入力された一文字をポインタが指すメモリに代入するだけだろ
文字列を入力しているのは処理系がバッファを使ってるだけなんでは
>>515 最後は「>.」じゃないかな
あと、文字数が256以上の時と、マルチバイト文字を含む場合にも対応できるようにしたいね
ためしに 256回回る空ループを書いてみてくれ
それを見れば
>>514 も安心して成仏することだろう
519 :
デフォルトの名無しさん:2013/05/28(火) 21:10:00.01
+[+]
こんなんでいいの?
文字入力は呼び出し側の責任としても
ループ回数はコード内に書かれるべき…じゃないのか
BFのコンパイラ書いているのですが、最適化の議論ってどこかにありますか。
思いついて実装したのは、
@連続する+-や<>をまとめる(これは自明。>>>>> をadd r0, #5 にするとか)
Aメモリからレジスタに値をロード済みかを覚えておいてロード命令を減らす
です。
考えているだけのは、ループの頭でポインタの位置が不変かを判断し、ポインタの移動範囲を検出して、レジスタに割り当てるというものです。
例えば[>+<-]のようなループの場合、ポインタは当初の値(0)と次の値(+1)にしか移動しないので、これらの指すデータをレジスタに割り当て、
ループ脱出時にメモリに書き戻してやればいいかなと考えています。
動的コード生成をしているので軽い処理がいいのですがそうでないのも知りたいです。
対象CPUはARMで、使用マシンはなぜかHP50gっていうグラフ電卓です。
面白そうなお題だな。
空き時間に考えてみよう。
いっそC++へのトランスレータにして、後はC++コンパイラの最適化に任せるのはどうだろう。
>522 アイデアが出たらぜひ教えて下さい。
>523 それって既にあるのでは。BFでプログラムするのと同様でパズルみたいなものと思ってください。
[>+<-]をコンパイルした実行命令数(N=ループ回数)
@素朴版 12N+3
Aロード最適化 11N+3
B>+< を最適化 9N+3
Cレジスタ最適化 5N+6
D手動コンパイル 4N+6
詳細は、
http://pastebin.com/pk8fST8h レジスタ割当:
r0: 汎用
r1: ポインタ
r2: [r1, #1]
Aはr0と[r1]がエイリアスになっているかを覚えてロード命令を削減
Bは>+<のようなパターンでポインタのinc/decを省く。
CはAに加えてr2と[r1,#1]をエイリアスにする。
Dは自動化は考えずに手でガリガリ記述
525 :
524:2013/11/07(木) 15:18:20.89
脳内コンパイラがこんなコードを生成しました。
ローカルな最適化では定数部を除いてこれ以上は無理そうですね。
ldrb r0, [r1]
ldrb r2, [r1, #1]
cmp r0, r0, #1
b l1
l0:
add r2, #1
subs r0, #1
l1:
bne l0
strb r0, [r1]
strb r2, [r1, #1]
実行命令数 7 + 3N
本来なら、
ldrb r0, [r1]
ldrb r2, [r1, #1]
add r2, r0
strb r2, [r1, #1]
mov r0, #0
strb r0, [r1]
実行命令数 6
とか定数命令でできるのですが、、、
526 :
名無し募集中。。。:2014/06/08(日) 09:57:05.09 ID:TcDR/+bL
万能言語ならぬ全能言語
world* CreateWorld (darkness* Darkness) {
world* World = new World(Darkness);
World->Day = 1;
light* Light = CreateLight();
if (isGood(Light)) add(World, Light);
else throw BadCreation(Light);
Light->Name = "Day";
Darkness->Name = "Night";
++(World->Day); // World->Day = 2
/* 中略 */
bone* AdamsRib = (Adam->Rib[12])->Remove();
woman* Eve = CreateWoman(AdamsRib);
Eve->Name = "Eve";
add(World, Eve);
++(World->Day); // World->Day = 7
World->Sabbath->Interval = 7;
rest();
return World;
}
誤爆申し訳ない
世界はBrainFuckで記述されたのかもしれない
だれか BrainFuck の LLVM フロントエンド作らないかな
神はこれを見てよしとされた。はassert文
BFオワタ・・・
http://pc.watch.impress.co.jp/docs/news/yajiuma/20140620_654252.html IT'S SHOWTIME
HEY CHRISTMAS TREE isLessThan10
YOU SET US UP @NO PROBLEMO
HEY CHRISTMAS TREE n
YOU SET US UP 0
STICK AROUND isLessThan10
GET TO THE CHOPPER n
HERE IS MY INVITATION n
GET UP 1
ENOUGH TALK
TALK TO THE HAND n
GET TO THE CHOPPER isLessThan10
HERE IS MY INVITATION 10
LET OFF SOME STEAM BENNET n
ENOUGH TALK
CHILL
YOU HAVE BEEN TERMINATED
うつくしくない