- 目次ページに戻る / 前 / 次
- 前回からの差分をまとめて見る
盤面の初期化ができたので続きをやります。
えーと続きというのは何かというと…… とりあえずループを回して盤面のセルを1個ずつスキャンする処理が必要なので、 それをやりましょう。
Ruby のコードでいうとこの部分。
(0...$h).each do |y| (0...$w).each do |x| # x, y を使った処理 end end
一度にあれこれやると大変そうなので、 前回のブリンカーの初期化を改造して、 まずは「メインの盤面のセルを全部 1(生存)にするだけ」 をやってみましょう。
1行だけでやってみる
いや、さらにステップを小さくしましょう。 まずは y を 0 に固定にして x だけ 0 から w-1 まで変化させるところからやってみます。 これなら単に一重の while ループ書くだけですね。
// 29_loop_x.vgt.json ["stmts" , ["func", "vram_set", ["w", "x", "y", "val"] , [ ["var", "yw"] , ["set", "yw", ["*", "y", "w"]] , ["var", "vi"] // vram index , ["set", "vi", ["+", "yw", "x"]] , ["set", "vram[vi]", "val"] ] ] , ["func", "main", [] , [ ["var", "w"] // 盤面の幅 , ["set", "w", 5] , ["var", "x"] , ["set", "x", 0] , ["while", ["neq", "x", "w"], [ ["call", "vram_set", "w", "x", 0, 1] , ["set", "x", ["+", "x", 1]] ]] ] ] ]
実行します。
$ ./run.sh 29_loop_x.vgt.json vgcg.rb:132:in `codegen_exp': Not yet implemented ("right") ("w") (RuntimeError) from vgcg.rb:78:in `codegen_while' from vgcg.rb:294:in `block in codegen_func_def' from vgcg.rb:274:in `each' from vgcg.rb:274:in `codegen_func_def' from vgcg.rb:315:in `block in codegen_stmts' from vgcg.rb:311:in `each' from vgcg.rb:311:in `codegen_stmts' from vgcg.rb:334:in `codegen' from vgcg.rb:346:in `<main>'
これは……あ、 codegen_exp
の右項の処理がローカル変数に未対応ですね。
対応させましょう。
--- a/vgcg.rb +++ b/vgcg.rb @@ -128,6 +128,8 @@ def codegen_exp(fn_arg_names, lvar_names, exp) case when fn_arg_names.include?(args[1]) to_fn_arg_addr(fn_arg_names, args[1]) + when lvar_names.include?(args[1]) + to_lvar_addr(lvar_names, args[1]) else raise not_yet_impl("right", args[1]) end
実行。
$ ./run.sh 29_loop_x.vgt.json vgcg.rb:168:in `codegen_exp': Not yet implemented ("operator") ("neq") (RuntimeError) from vgcg.rb:78:in `codegen_while' from vgcg.rb:296:in `block in codegen_func_def' from vgcg.rb:276:in `each' from vgcg.rb:276:in `codegen_func_def' from vgcg.rb:317:in `block in codegen_stmts' from vgcg.rb:313:in `each' from vgcg.rb:313:in `codegen_stmts' from vgcg.rb:336:in `codegen' from vgcg.rb:348:in `<main>'
なるほど、以前 eq
は作っていました
(※ 第23回)
が、 neq
は未実装でした。
実装しましょう。
eq
とだいたい同じ。
"neq" は "not equal" の略です。
--- a/vgcg.rb +++ b/vgcg.rb @@ -164,6 +164,24 @@ def codegen_exp(fn_arg_names, lvar_names, exp) alines << " set_reg_a 1" alines << "label end_eq_#{label_id}" + when "neq" + $label_id += 1 + label_id = $label_id + + alines << " set_reg_a #{left}" + alines << " set_reg_b #{right}" + alines << " compare" + alines << " jump_eq then_#{label_id}" + + # else + alines << " set_reg_a 1" + alines << " jump end_neq_#{label_id}" + + # then + alines << "label then_#{label_id}" + alines << " set_reg_a 0" + + alines << "label end_neq_#{label_id}" else raise not_yet_impl("operator", operator) end
eq
の部分をコピペして、
ラベルを修正して、
評価結果(set_reg_a
にセットする値)の真偽を逆にしただけ。
たぶんこれでいいはず……。
実行。
$ ./run.sh 29_loop_x.vgt.json vgcg.rb:339:in `block in codegen_stmts': Not yet implemented ("stmt_head") ("call") (RuntimeError) from vgcg.rb:331:in `each' from vgcg.rb:331:in `codegen_stmts' from vgcg.rb:91:in `codegen_while' from vgcg.rb:314:in `block in codegen_func_def' from vgcg.rb:294:in `each' from vgcg.rb:294:in `codegen_func_def' from vgcg.rb:335:in `block in codegen_stmts' from vgcg.rb:331:in `each' from vgcg.rb:331:in `codegen_stmts' from vgcg.rb:354:in `codegen' from vgcg.rb:366:in `<main>'
なるほど、 codegen_while()
→ codegen_stmts()
と呼び出しているのですが、
codegen_stmts()
が call文に対応していません。
--- a/vgcg.rb +++ b/vgcg.rb @@ -333,6 +333,8 @@ def codegen_stmts(fn_arg_names, lvar_names, rest) case stmt_head when "func" alines += codegen_func_def(stmt_rest) + when "call" + alines += codegen_call(lvar_names, stmt_rest) when "set" alines += codegen_set(fn_arg_names, lvar_names, stmt_rest) else
codegen_func_def()
からコピペ……。
前回ちょっと書いたように
codegen_stmts()
と codgen_func_def()
の内容が重複してます。
リファクタリングできそうですが、前回書いた通り放置して、
ベタに codegen_stmts()
を call文に対応させます。
ともかくこれで動くようになりました! VRAM のメイン領域の y=0 の行のセルが左から順に生存になっていき、 右端のセルまで全部生存になったところで while ループを抜けて プログラムが終了します。
---- memory (vram) ---- @@@@@ ..... ..... ..... ..... ..... ..... ..... ..... ..... exit
二重ループですべてのセルを生存にする
では二重ループですべてのセルを生存にしてみましょう! はたして二重ループはちゃんと動くでしょうか?
// 29_loop_xy.vgt.json ["stmts" , ["func", "vram_set", ["w", "x", "y", "val"] , [ ["var", "yw"] , ["set", "yw", ["*", "y", "w"]] , ["var", "vi"] // vram index , ["set", "vi", ["+", "yw", "x"]] , ["set", "vram[vi]", "val"] ] ] , ["func", "main", [] , [ ["var", "w"] // 盤面の幅 , ["set", "w", 5] , ["var", "h"] // 盤面の高さ , ["set", "h", 5] , ["var", "x"] , ["set", "x", 0] , ["var", "y"] , ["set", "y", 0] , ["while", ["neq", "y", "h"], [ ["set", "x", 0] , ["while", ["neq", "x", "w"], [ ["call", "vram_set", "w", "x", "y", 1] , ["set", "x", ["+", "x", 1]] ]] , ["set", "y", ["+", "y", 1]] ]] ] ] ]
実行。
$ ./run.sh 29_loop_xy.vgt.json vgcg.rb:341:in `block in codegen_stmts': Not yet implemented ("stmt_head") ("while") (RuntimeError) from vgcg.rb:331:in `each' from vgcg.rb:331:in `codegen_stmts' from vgcg.rb:91:in `codegen_while' from vgcg.rb:314:in `block in codegen_func_def' from vgcg.rb:294:in `each' from vgcg.rb:294:in `codegen_func_def' from vgcg.rb:335:in `block in codegen_stmts' from vgcg.rb:331:in `each' from vgcg.rb:331:in `codegen_stmts' from vgcg.rb:356:in `codegen' from vgcg.rb:368:in `<main>'
これも同じパターン。
codegen_while()
→ codegen_stmts()
と呼びだされて、
codegen_stmts()
が while文に対応してません。
同じように codegen_func_def()
からのコピペで修正します。
--- a/vgcg.rb +++ b/vgcg.rb @@ -337,6 +337,8 @@ def codegen_stmts(fn_arg_names, lvar_names, rest) alines += codegen_call(lvar_names, stmt_rest) when "set" alines += codegen_set(fn_arg_names, lvar_names, stmt_rest) + when "while" + alines += codegen_while(fn_arg_names, lvar_names, stmt_rest) else raise not_yet_impl("stmt_head", stmt_head) end
動くようになりました!! 下記のようにローカル変数 w, h, x, y が割り当てられていて、 x, y が指しているセルが生存に変わっていく様子が観察できます!
---- memory (stack) ---- 35 7 36 5 37 47 38 135 39 5 40 2 41 1 42 1 sp => 43 1 ... y 44 3 ... x 45 5 ... h 46 5 ... w bp => 47 49 48 2 49 0 ---- memory (vram) ---- @@@@@ ..... @@@.. ..... ..... ..... ..... ..... ..... .....
そのまま Enter キーを押しっぱなしにしていると、 下記のようにすべてのセルが生存になったところでプログラムが終了しました!
---- memory (stack) ---- 41 4 42 1 43 5 44 5 45 5 46 5 47 49 48 2 sp bp => 49 0 ---- memory (vram) ---- @@@@@ ..... @@@@@ ..... @@@@@ ..... @@@@@ ..... @@@@@ ..... exit
やぼうのじつげんに またいっぽ ちかづいたぞ!