# Copyright (c) 2009 Tim Freeman # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # (This is the standard MIT License, copied from # http://www.opensource.org/licenses/mit-license.php on 24 Apr 2007.) #desc Draw the state of a Turing machine as it executes, so they can #desc be debugged. import bits def draw_tape(tape_length, tape_bits, headpos): lineref = [""] def addmarker(where): if where == headpos: lineref[0] += ">" elif where == headpos - 1: lineref[0] += "<" else: lineref[0] += " " for i in range(tape_length, -1, -1): addmarker(i) if i == tape_length: bit = " " else: bit = str(bits.getbits(tape_bits, i, 1)) lineref[0] += bit addmarker(-1) return lineref[0] def show_octal(stateno): return "%03o" % (stateno,) # bpsn stands for "bits per state number". def draw_action(action, bpsn, state_to_name): action_str = ["w0", "w1", "tr", "dn"][bits.getbits(action, 0, 2)] motion = ["l", "r"][bits.getbits(action, 2, 1)] next = bits.getbits(action, 3, bpsn) return "%2s%1s %s" % (action_str, motion, state_to_name(next)) def draw_line(tape_length, tape_bits, headpos, sn, state, bpsn, short, state_to_name): tape = draw_tape(tape_length, tape_bits, headpos) bpa = bpsn + 3 def da(which): return draw_action(bits.getbits(state, which * bpa, bpa), bpsn, state_to_name) zero = bits.getbits(state, 0, bpa) one = bits.getbits(state, bpa, bpa) end = bits.getbits(state, 2*bpa, bpa) if not short: tape += " state %s 0>%s 1>%s end>%s" % (state_to_name(sn), da(0), da(1), da(2)) return tape def do_animation(tape_length, tape_bits, headpos, sn, state, bpsn, state_to_name, short): print draw_line(tape_length, tape_bits, headpos, sn, state, bpsn, state_to_name = state_to_name, short=short) def default_animation(tape_length, tape_bits, headpos, sn, state, bpsn, short): do_animation(tape_length, tape_bits, headpos, sn, state, bpsn, state_to_name=show_octal, short=short)