"""
File: bf_compiler.py
Author: AN
Date: May 2005
Description:

Using the function bf2py, you can convert valid a string containing valid BF
source into a string containing the equivalent Python source.

See the end of this file for example usage.

 Cmd  Effect                                 Equivalent in C
 ---  ------                                 ---------------
 +    Increases element under pointer        array[p]++;
 -    Decrases element under pointer         array[p]--;
 >    Increases pointer                      p++;
 <    Decreases pointer                      p--;
 [    Starts loop, counter under pointer     while(array[p]) {
 ]    Indicates end of loop                  }
 .    Outputs ASCII code under pointer       putchar(array[p]);
 ,    Reads char and stores ASCII under ptr  array[p]=getchar();


TODO:
- Gather together multiple +, -, < and >.
"""

def bf2py(bf_src, mem_size=100):
    """Return bf source string as a python source string"""

    src = [
        'import sys',
        'write = sys.stdout.write',
        'mem = [0] * %d' % mem_size,
        'ptr = 0',]
    src_append = src.append
    # ptr
    indent = 0
    add_line = lambda line: src_append(('  ' * indent) + line)

    for char in bf_src:

        if char == '+':
            add_line('mem[ptr] += %d')
        elif char == '-':
            add_line('mem[ptr] -= %d')
        elif char == '>':
            add_line('ptr += %d')
        elif char == '<':
            add_line('ptr -= %d')
        elif char == '[':
            add_line('while mem[ptr]:')
            indent += 1
        elif char == ']':
            indent -= 1
        elif char == '.':
            add_line('write(chr(mem[ptr]))')
        elif char == ',':
            add_line('mem[ptr] = int(raw_input())')

    # Turn consecutive additions/subtractions into single statements.
    compact_src = []
    compact_src_add = compact_src.append
    src_pop = src.pop

    # while there's lines to be had:
    while src:
        line = src_pop(0)

        if '%d' in line:
            counter = 1
            # try to get as many of the same lines from the source
            while src and src[0] == line:
                src_pop(0)
                counter += 1
            # populate the line with the number we got.
            line %= counter

        #  add the line to the stack
        compact_src_add(line)


    return '\n'.join(compact_src)

if __name__ == '__main__':
    exec bf2py('''
            *
            >
           +++
         ++++[<+
          +++++
         +++++>-
       ]<.>++++[<+
        +++++>-]<
       .++++++++++
     +++..+++++++.[-
      ]>++++[<+++++
     +++>-]<.>+++++[
   <+++++++>-]<.>+++++
    +[<++++++>-]<+.++
   ++++++++.---------.
 ++++++++++.+.-------.--
  ----------.>+++[<++++
++>-]<.[-]>++++[<++++++++
          >-]<+
         .[-]+++
         +++++++.''')



