root/lang/ruby/brainfuck/trunk/lib/brainfuck/writer.rb @ 3244

Revision 3244, 19.4 kB (checked in by naoya_t, 5 years ago)

r3308@localhost: naochan | 2007-12-18 02:04:53 +0900
supporting / and %; sample program to calculate prime numbers

Line 
1module Brainfuck
2
3  def self.writer
4    BrainfuckWriter.new
5  end
6
7  class BrainfuckWriter
8    def initialize
9      @_st = Array.new
10      @_ix = 0
11
12      @wrap_around = false
13      @debug_mode = false
14      @debug_indent = "\t: "
15    end
16    attr_accessor :wrap_around, :debug_mode
17
18    private
19    def debug_indent_incr
20      @debug_indent += "  "
21    end
22    def debug_indent_decr
23      @debug_indent.sub!(/  \Z/,"")
24    end
25    def debug_print(s)
26      printf("%s%s\n", @debug_indent, s)
27    end
28
29    I_NODE     = 0
30    I_NODE_TMP = 1
31    I_TMP_SPACE = 2
32    I_TMP_PUT   = 3 # +2 ; 文字列を表示するだけのプログラムに有利なように
33    I_TMP_COPY = 5
34    I_TMP_ZNZ  = 6
35    I_TMP_EQ   = 7
36    I_TMP_ADD  = I_TMP_SUB = 8
37
38    I_TMP_MUL  = 9
39    I_TMP_MUL1 = 10 ; I_TMP_MUL2 = 11
40    I_TMP_DIV  = 12 ; I_TMP_DIV1 = 13
41    I_TMP_MOD  = 14 ; I_TMP_MOD1 = 15
42
43    I_FLAG     = 16
44    I_FLAG_AND = I_FLAG_OR = I_FLAG_NOT  = 17
45    I_FLAG_BUP = 18
46    I_FLAG_BORROW = 19 # 減算で0を下回るときに立つフラグ
47
48    I_TMP_YN   = 20 # +3
49
50    K_         = 23 # +2
51    K100       = 25 ; K10 = 26 ; K1 = 27
52
53#   TMP        = 19
54    VAR_BASE   = 28
55
56    private
57    def label(pos)
58      case pos
59      when 0 ; "I_NODE"
60      when 1 ; "I_NODE_TMP"
61      when 2 ; "I_TMP_SPACE"
62      when 3 ; "I_TMP_PUT"
63      when 4 ; "I_TMP_PUT + 1"
64      when 5 ; "I_TMP_COPY"
65      when 6 ; "I_TMP_ZNZ"
66      when 7 ; "I_TMP_EQ"
67      when 8 ; "I_TMP_ADD"
68      when 9 ; "I_TMP_MUL"
69      when 10 ; "I_TMP_MUL1D"
70      when 11 ; "I_TMP_MUL2"
71      when 12 ; "I_TMP_DIV"
72      when 13 ; "I_TMP_DIV+1"
73      when 14 ; "I_TMP_MOD"
74      when 15 ; "I_TMP_MOD+1"
75      when 16 ; "I_FLAG"
76      when 17 ; "I_FLAG_AND"
77      when 18 ; "I_FLAG_BUP"
78      when 19 ; "I_FLAG_BORROW"
79      when 20 ; "I_TMP_YN"
80      when 21 ; "I_TMP_YN+1"
81      when 22 ; "I_TMP_YN+2"
82      when 23 ; "K_"
83      when 24 ; "K_+1"
84      when 25 ; "K100"
85      when 26 ; "K10"
86      when 27 ; "K1"
87      when 28 ; "VAR_BASE"
88      else "VAR_BASE+#{pos-28}"
89      end
90    end
91
92    private
93    # st[ix] の値を得る
94    def _curr
95      @_st[@_ix] ||= 0
96    end
97    # set[ix] = value
98    def _set(value)
99      if @wrap_around
100        @_st[@_ix] = value % 256
101      else
102        @_st[@_ix] = value
103      end
104    end
105
106    def var_ofs(ch)
107      VAR_BASE + (ch - 0x61)*2
108    end
109
110    # 基本8命令
111    public
112    def bf_fwd  ; ">" ; end  # ix++
113    def bf_back ; "<" ; end  # ix--
114    def bf_incr ; _set(_curr + 1) ; "+" ; end  # st[ix]++  - @_st[@_ix]も++
115    def bf_decr ; _set(_curr - 1) ; "-" ; end  # st[ix]--  - @_st[@_ix]も--
116    private  # while_wend は loop{...} または loop_at(k){...} を使う
117    def bf_while ; "[" ; end # while (st[ix]) {
118    def bf_wend  ; "]" ; end # }
119    public
120    def bf_write ; "." ; end # putchar(st[ix])
121    def bf_read  ; "," ; end # st[ix] = getchar()
122
123    # ちょっと拡張命令
124    # 相対移動: ix += d
125    def move(d)
126      # ix += d
127      @_ix += d
128      if d > 0
129        ">"*d
130      elsif d < 0
131        "<"*(-d)
132      else
133        ""
134      end
135    end
136    # 絶対移動: ix = pos
137    def move_to(pos)
138      if @debug_mode
139        debug_print "move_to #{label(pos)}"
140        return
141      end
142
143      return "" if pos == @_ix
144      move(pos - @_ix)
145    end
146
147    # レジスタ値を増減
148    private
149    def pm(d)
150      # st[ix] += d
151      # 一般には add_uint8(d) または sub_uint8(d) を利用するように
152      if d > 0
153        "+"*d
154      elsif d < 0
155        "-"*(-d)
156      else
157        ""
158      end
159    end
160
161    public
162    # while (st[ix]) { ...content... }
163    def bf_loop(&b)
164      if @debug_mode
165        debug_print "loop {"
166        debug_indent_incr
167
168        b.call
169
170        debug_indent_decr
171        debuf_print "}"
172        return
173      end
174
175      "[" + b.call + "]"
176    end
177    def loop_at(k,&b)
178      if @debug_mode
179        debug_print "loop_at #{label(k)} {"
180        debug_indent_incr
181
182        # move_to(k) + "["
183        b.call
184        # move_to(k) + "]"
185        move_to(k)
186
187        debug_indent_decr
188        debug_print "}"
189        return
190      end
191
192      move_to(k) + "[" + b.call + move_to(k) + "]"
193    end
194    def do_once_if(flag_pos,&b)
195      if @debug_mode
196        debug_print "do_once_if #{label(flag_pos)} {"
197        debug_indent_incr
198
199        # move_to(flag_pos) + "["
200        b.call
201        # + clr_at(flag_pos) + "]"
202
203        debug_indent_decr
204        debug_print "}"
205        return
206      end
207
208      move_to(flag_pos) + "[" + b.call + clr_at(flag_pos) + "]"
209    end
210
211    # st[ix] = 0
212    def clr
213      if @debug_mode
214        debug_print "clr"
215        return
216      end
217
218      _set 0
219      "[-]"
220    end
221
222    def save_ix(&b)
223      if @debug_mode
224        ix_keep = @_ix
225        b.call
226        move_to(ix_keep)
227        return
228      end
229
230      ix_keep = @_ix
231      b.call + move_to(ix_keep)
232    end
233
234    #
235    # バイト演算 ← st[ ] の各メモリ領域をここでは「バイト」と呼んでいる
236    #
237    # st[src_pos] の内容を st[dest_pos] にコピー。
238    # st[src_pos] の内容は保持される。
239    def copy_byte(dest_pos, src_pos)
240      if @debug_mode
241        debug_print "copy_byte #{label(dest_pos)}, #{label(src_pos)}"
242        return
243      end
244
245      return "" if dest_pos == src_pos
246
247      save_ix {
248        clr_at(dest_pos) + clr_at(I_TMP_COPY) +
249        repeat(src_pos) { incr_at(dest_pos) + incr_at(I_TMP_COPY) } +
250        repeat(I_TMP_COPY) { incr_at(src_pos) }
251      }
252    end
253
254    # st[ix] += st[k]
255    def add_byte(k)
256      if @debug_mode
257        debug_print "add_byte #{label(k)}"
258        return
259      end
260
261      ix_keep = @_ix
262      save_ix {
263        copy_byte(I_TMP_ADD, k) +
264        repeat(I_TMP_ADD) { incr_at(ix_keep) }
265      }
266    end
267
268    # st[ix] -= st[k], set borrow_flag if result < 0
269    def sub_byte(k)
270      if @debug_mode
271        debug_print "sub_byte #{label(k)}"
272        return
273      end
274
275#      save_ix {
276#        copy_byte(I_TMP_SUB, k) +
277#        repeat(I_TMP_SUB) { decr_at(ix_keep) }
278#      }
279      ix_keep = @_ix
280      save_ix {
281        reset_flag_at(I_FLAG_BORROW) +
282        copy_byte(I_TMP_SUB, k) +
283        repeat(I_TMP_SUB) {
284          if_zero_at(ix_keep) { set_flag_at(I_FLAG_BORROW) } +
285          decr_at(ix_keep)
286        }
287      }
288    end
289
290    #
291    # uint8 - 符号なし8ビット整数演算
292    #
293
294    # st[ix] = val
295    def set_uint8(val)
296      if @debug_mode
297        debug_print "set_uint8 #{val}"
298        return
299      end
300
301      clr + add_uint8(val)
302    end
303
304    # st[ix] += val
305    def add_uint8(val)
306      if @debug_mode
307        debug_print "add_uint8 #{val}"
308        return
309      end
310
311      if val == 0
312        return ""
313      elsif val < 0
314        sign = -1
315        val = -val
316      else
317        sign = 1
318      end
319
320      a = Math::sqrt(val).to_i
321      c = val % a
322      b = (val - c) / a
323      if c > (a/2).to_i
324        b += 1
325        c -= a
326      end
327      if a + b + c + 7 < val
328        # >+++[<+++>-]<+
329        bf = bf_fwd + "+"*a + bf_loop{ bf_back + pm(sign * b) + bf_fwd + "-" } + bf_back + pm(sign * c)
330      else
331        bf = pm(sign * val)
332      end
333      _set(_curr + sign * val)
334      bf
335    end
336
337    # st[ix] -= val
338    def sub_uint8(val)
339      if @debug_mode
340        debug_print "sub_uint8 #{val}"
341        return
342      end
343
344      add_uint8(-val)
345    end
346
347    # st[ix] *= val
348    def mul_uint8(val)
349      if @debug_mode
350        debug_print "mul_uint8 #{val}"
351        return
352      end
353
354      save_ix {
355        copy_byte(I_TMP_MUL1,@_ix) +
356        clr_at(I_TMP_MUL) + # result
357        set_uint8_at(I_TMP_MUL2,val) +
358        repeat(I_TMP_MUL2) {
359          move_to(I_TMP_MUL) +
360          add_byte(I_TMP_MUL1)
361        }
362      } +
363      copy_byte(@_ix, I_TMP_MUL)
364    end
365
366    # st[ix] / st[k] = I_TMP_DIV ... I_TMP_MOD
367    def div_byte(k)
368      if @debug_mode
369        debug_print "div_byte #{label(k)}"
370        return
371      end
372
373      ix_keep = @_ix
374      save_ix {
375        copy_byte(I_TMP_MOD,ix_keep) +
376        clr_at(I_TMP_DIV) +
377        copy_byte(I_TMP_DIV1,k) +
378        set_flag_at(I_TMP_MOD1) + # use this addr for flag
379        loop_at(I_TMP_MOD1) {
380          move_to(I_TMP_MOD) +
381          sub_byte(I_TMP_DIV1) +
382          incr_at(I_TMP_DIV) +
383          if_nonzero_at(I_FLAG_BORROW) {
384            move_to(I_TMP_MOD) +
385            add_byte(I_TMP_DIV1) +
386            decr_at(I_TMP_DIV) +
387            reset_flag_at(I_TMP_MOD1)
388          }
389        }# +
390#        copy_byte(ix_keep,I_TMP_MOD)
391      }
392    end
393
394    # st[ix] / val = st[ix] ... I_MOD
395    def div_uint8(val)
396      if @debug_mode
397        debug_print "div_uint8 #{val}"
398        return
399      end
400
401      ix_keep = @_ix
402      save_ix {
403        copy_byte(I_TMP_DIV, ix_keep) +
404        set_uint8_at(I_TMP_DIV1,val) +
405        move_to(I_TMP_DIV) +
406        div_byte(I_TMP_DIV1) +
407        copy_byte(ix_keep, I_TMP_DIV)
408      }
409    end
410    # st[ix] %= val
411    def mod_uint8(val)
412      if @debug_mode
413        debug_print "mod_uint8 #{val}"
414        return
415      end
416
417      ix_keep = @_ix
418      save_ix {
419        copy_byte(I_TMP_DIV, ix_keep) +
420        set_uint8_at(I_TMP_DIV1,val) +
421        move_to(I_TMP_DIV) +
422        div_byte(I_TMP_DIV1) +
423        copy_byte(ix_keep, I_TMP_MOD)
424      }
425    end
426
427    # boolean
428    # st[ix] &= st[k]
429    def and_bool(k)
430      if @debug_mode
431        debug_print "and_bool #{label(k)}"
432        return
433      end
434
435      save_ix {
436        if_zero_at(k) { clr_at(@_ix) }
437      }
438    end
439
440    # st[ix] |= st[k]
441    def or_bool(k)
442      if @debug_mode
443        debug_print "or_bool #{label(k)}"
444        return
445      end
446
447      save_ix {
448        if_nonzero_at(k) { copy_byte(@_ix,k) }
449      }
450    end
451
452    # st[ix] = not st[k]
453    def bool_not(k)
454      if @debug_mode
455        debug_print "bool_not #{label(k)}"
456        return
457      end
458
459      save_ix {
460        copy_byte(I_FLAG_NOT, I_FLAG) +
461        set_uint8_at(I_FLAG,1) + sub_byte(I_FLAG_NOT)
462      }
463    end
464
465    # ***_at(pos) - ※ixはposに留める
466    def incr_at(pos)
467      if @debug_mode
468        debug_print "incr_at #{label(pos)}"
469        return
470      end
471      move_to(pos) + bf_incr
472    end
473    def decr_at(pos)
474      if @debug_mode
475        debug_print "decr_at #{label(pos)}"
476        return
477      end
478      move_to(pos) + bf_decr
479    end
480    def read_at(pos)
481      if @debug_mode
482        debug_print "read_at #{label(pos)}"
483        return
484      end
485      move_to(pos) + bf_read
486    end
487    def clr_at(pos)
488      if @debug_mode
489        debug_print "clr_at #{label(pos)}"
490        return
491      end
492      move_to(pos) + clr
493    end
494    def set_uint8_at(pos,val)
495      if @debug_mode
496        debug_print "set_uint8_at #{label(pos)},#{val}"
497        return
498      end
499      move_to(pos) + set_uint8(val)
500    end
501    def add_uint8_at(pos,val)
502      if @debug_mode
503        debug_print "add_uint8_at #{label(pos)},#{val}"
504        return
505      end
506      move_to(pos) + add_uint8(val)
507    end
508    def sub_uint8_at(pos,val)
509      if @debug_mode
510        debug_print "sub_uint8_at #{label(pos)},#{val}"
511        return
512      end
513      move_to(pos) + sub_uint8(val)
514    end
515    def set_flag_at(pos)
516      if @debug_mode
517        debug_print "set_flag_at #{label(pos)}"
518        return
519      end
520      set_uint8_at(pos,1)
521    end
522    def reset_flag_at(pos)
523      if @debug_mode
524        debug_print "reset_flag_at #{label(pos)}"
525        return
526      end
527      clr_at(pos)
528    end
529
530    # ブロック
531    def if_nonzero_at(pos, &b)
532      if @debug_mode
533        debug_print "if_nonzero_at #{label(pos)} {"
534        debug_indent_incr
535
536        b.call
537
538        debug_indent_decr
539        debug_print "}"
540        return
541      end
542      # st[pos]が 0 でない場合のみブロックの内容を実行。
543      # st[pos]の値は保持される。
544      # bool値とわかっている場合は次のrepeatを使うとよい。
545
546#      loop_at(pos) { b.call + clr_at(pos) }
547      save_ix {
548        move_to(pos) + check_if_nonzero + do_once_if(I_FLAG,&b)
549      }
550    end
551    def repeat(count_pos, &b)
552      if @debug_mode
553        debug_print "repeat #{label(count_pos)}"
554        debug_indent_incr
555
556        b.call
557
558        debug_indent_decr
559        debug_print "}"
560        return
561      end
562      # st[count_pos]に指定された回数だけブロックの内容を実行
563      loop_at(count_pos) { b.call + decr_at(count_pos) }
564    end
565
566    # test系。ここではtestで始まる名前を付けない
567    def check_if_zero
568      if @debug_mode
569        debug_print "check_if_zero"
570        return
571      end
572
573      # st[ix] の内容が 0 かどうかを I_FLAG にセットする
574      copy_byte(I_TMP_ZNZ, @_ix) +
575        set_flag_at(I_FLAG) +
576        do_once_if(I_TMP_ZNZ) { decr_at(I_FLAG) } +
577#       if_nonzero_at(I_TMP_ZNZ) { decr_at(I_FLAG) } +
578        move_to(I_FLAG)
579      # ix = I_FLAGで戻る
580    end
581
582    def check_if_nonzero
583      if @debug_mode
584        debug_print "check_if_nonzero"
585        return
586      end
587
588      # st[ix] の内容が 0 でないかどうかを I_FLAG にセットする
589      copy_byte(I_TMP_ZNZ, @_ix) +
590        reset_flag_at(I_FLAG) +
591        do_once_if(I_TMP_ZNZ) { incr_at(I_FLAG) } +
592#       if_nonzero_at(I_TMP_ZNZ) { incr_at(I_FLAG) } +
593        move_to(I_FLAG)
594      # ix = I_FLAGで戻る
595    end
596
597    def check_if_n(n)
598      if @debug_mode
599        debug_print "check_if_n #{n}"
600        return
601      end
602
603      # st[ix] の内容が n に等しいかどうかを I_FLAG にセットする
604      sub_uint8(n) + check_if_zero + add_uint8(n)
605    end
606
607    # i/o
608    def write_char(c)
609      if @debug_mode
610        debug_print "write_char #{c}"
611        return
612      end
613
614      # 1文字表示する。引数cはコード。
615      save_ix {
616        set_uint8_at(I_TMP_PUT,c) + bf_write
617      }
618    end
619    def write_string(s)
620      if @debug_mode
621        debug_print "write_string \"#{s.gsub(/\n/,"\\n")}\""
622        return
623      end
624
625      return "" unless s and s.length > 0
626
627      has_space = (s =~ / /)
628
629      save_ix {
630        bf = move_to(I_TMP_PUT) + "<[-]>[-]"  # st[I_TMP_PUT-1] = st[I_TMP_PUT] = 0
631        last_putchar_code = 0
632
633        if has_space
634          bf += ">++++++++[<++++<++++>>-]<" # st[I_TMP_PUT] = st[I_TMP_PUT-1] = 0x20
635          # bf_next()
636          @_ix = I_TMP_PUT #+1
637          last_putchar_code = 32
638        end
639        s.length.times do |i|
640          c = s[i]
641          if c == 0x20
642            bf += bf_back if @_ix == I_TMP_PUT
643            bf += bf_write
644            @_ix = I_TMP_SPACE
645          else
646            bf += bf_fwd if has_space and @_ix == I_TMP_SPACE
647            bf += add_uint8(c - last_putchar_code) + bf_write
648            last_putchar_code = c
649            @_ix = I_TMP_PUT
650          end
651        end
652        bf
653      }
654    end
655    def write_uint8(i)
656      if @debug_mode
657        debug_print "write_uint8 #{i}"
658        return
659      end
660
661#      set_uint8_at(I_TMP_PUT,i) + write_byte_as_uint8(I_TMP_PUT)
662      save_ix {
663        set_uint8_at(I_TMP_PUT,i) + write_curr_as_uint8
664      }
665    end
666
667    def write_byte_as_uint8(k)
668      if @debug_mode
669        debug_print "write_byte_as_uint8"
670        return
671      end
672
673      save_ix {
674        move_to(k) + write_curr_as_uint8
675      }
676    end
677    def write_curr_as_uint8
678      if @debug_mode
679        debug_print "write_curr_as_uint8"
680        return
681      end
682#      save_ix {
683        # st[K_] = k
684        # st[K100] = st[K10] = st[K] = 10
685      copy_byte(K_, @_ix) +
686        set_uint8_at(K1, 10) + set_uint8_at(K10, 10) + set_uint8_at(K100, 10) +
687        loop_at(K_) { #  if k
688          decr_at(K_) +  # K_ -= 1
689          decr_at(K1) +  # K1 -= 1
690          if_zero_at(K1) {  # if K1 == 0
691            add_uint8_at(K1,10) + decr_at(K10) +  # K1 += 10, K10 -= 1
692            if_zero_at(K10) {  # if K10 == 0
693              add_uint8_at(K10,10) + decr_at(K100)   # K10 += 10, K100 -= 1
694            }
695          }
696        } +
697        # ここまでで、st[K1],st[K10],st[K100]には
698        # kの1の位、10の位、100の位の値を10から引いた数がそれぞれ入る
699        # eg. k=123なら st[K1]=7, st[K10]=8, st[K100]=9
700        reset_flag_at(I_FLAG_BUP) +
701
702        # print (at most 3) digit(s)
703        set_uint8_at(K_,10) + sub_byte(K100) +  # K_ = 10 - K100
704        if_nonzero_at(K_) {
705          add_uint8_at(K_,0x30) + bf_write() +
706          set_flag_at(I_FLAG_BUP)
707        } +
708
709        set_uint8_at(K_,10) + sub_byte(K10) +  # K_ = 10 - K10
710        if_nonzero_at(I_FLAG_BUP) {
711          if_zero_at(K_) {
712            write_char(0x30)
713          }
714        } +
715        if_nonzero_at(K_) {
716          add_uint8_at(K_,0x30) + bf_write
717        } +
718
719        set_uint8_at(K_,10) + sub_byte(K1) +  # K_ = 10 - K1
720        add_uint8_at(K_,0x30) + bf_write
721    end
722
723    def if_zero_at(pos,&b)
724      if @debug_mode
725        debug_print "if_zero_at #{label(pos)} {"
726        debug_indent_incr
727
728#        move_to(pos) + check_if_zero + do_once_if(I_FLAG,&b) #if_nonzero_at(I_FLAG,&b)
729        b.call
730
731        debug_indent_decr
732        debug_print "}"
733        return
734      end
735
736      # st[pos]=0ならブロックの内容実行
737      save_ix {
738        move_to(pos) + check_if_zero + do_once_if(I_FLAG,&b) #if_nonzero_at(I_FLAG,&b)
739      }
740    end
741
742    def yn_inkey
743      if @debug_mode
744        debug_print "yn_inkey\t\t# I_TMP_YN <-- 'y' ? 1 : 0"
745        return
746      end
747      # y か n が入力されるまで入力ループ。
748      # I_TMP_YN に結果が入る。(yなら1,nなら0)
749      # この結果は I_FLAG にもコピーされる。
750      y_or_n    = I_TMP_YN   # 1:y 0:n  ==> copied to I_FLAG
751      loop_flag = I_TMP_YN+1 # 1:[^yn] 0:[yn]
752      inkey     = I_TMP_YN+2 # inkey
753
754      save_ix {
755        reset_flag_at(y_or_n) + set_flag_at(loop_flag) +
756        loop_at(loop_flag) {
757             read_at(inkey) + sub_uint8(0x6e) +  # 0x6e = 'n'
758             if_zero_at(inkey) { reset_flag_at(loop_flag) } + # + clr_at(y_or_n) } +
759             move_to(inkey) + sub_uint8(11) +  # 11 = 'y' - 'n'
760             if_zero_at(inkey) { reset_flag_at(loop_flag) + set_flag_at(y_or_n) } # +
761        } +
762        copy_byte(I_FLAG, y_or_n)
763      }
764    end
765
766    def say(s, next_node=0)
767      if @debug_mode
768        printf("//   say(\"%s\", %d)\n", s, next_node)
769
770        write_string(s + "\n")
771        set_uint8_at(I_NODE, next_node)
772        return
773      end
774      # 文字列 s を表示し改行する。
775      write_string(s + "\n") + set_uint8_at(I_NODE, next_node)
776    end
777
778    def ask(s, n_node, y_node)
779      if @debug_mode
780        printf("//   ask(\"%s\", %d, %d)\n", s, n_node, y_node)
781
782        write_string(s + " [y/n]\n> ")
783        yn_inkey
784        if_nonzero_at(I_TMP_YN) { set_uint8_at(I_NODE, y_node) }
785        if_zero_at(I_TMP_YN) { set_uint8_at(I_NODE, n_node) }
786        return
787      end
788      # 文字列(質問文)s を表示し、y/n の入力を促し、I_NODEを適切なノード番号にセットする
789      # n_node が先なのはZuの仕様に合わせているため
790      write_string(s + " [y/n]\n> ") +
791        yn_inkey +
792        if_nonzero_at(I_TMP_YN) { set_uint8_at(I_NODE, y_node) } +
793        if_zero_at(I_TMP_YN) { set_uint8_at(I_NODE, n_node) }
794    end
795
796    def node_switch(table)
797      if @debug_mode
798        print "// switch (node) {\n"
799
800        set_flag_at(I_NODE)
801        debug_print "loop {"
802        debug_indent_incr
803        copy_byte(I_NODE_TMP, I_NODE)
804
805        (1..table.size-1).each {|i|
806          decr_at(I_NODE_TMP)
807          if table[i]
808            print "// case #{i}:\n"
809            if_zero_at(I_NODE_TMP) { eval(table[i]) }
810          end
811        }
812        move_to(I_NODE)
813        debug_indent_decr
814        debug_print "}"
815
816        print "// }\n"
817        return
818      end
819
820      bf = set_flag_at(I_NODE) + "[" + copy_byte(I_NODE_TMP, I_NODE)
821      (1..table.size-1).each {|i|
822        bf += decr_at(I_NODE_TMP)
823        if table[i]
824          bf += if_zero_at(I_NODE_TMP) { eval(table[i]) }
825        end
826      }
827      bf + move_to(I_NODE) + "]"
828    end
829
830  end
831end
Note: See TracBrowser for help on using the browser.