Пример #1
0
    def test_loop_elimination(self):
        # Obviously dead loops are skipped entirely

        # Loop open as first op => dead
        self._run_and_check_ir("[+,-.]", [])
        self._run_and_check_ir("[+[[[,]-]-]-.]", [])
        self._run_and_check_ir("[+[[[,]-]-]-.][-]", [])
        self._run_and_check_ir("[+[[[,]-]-]-.][+]", [])
        self._run_and_check_ir("[+[[[,]-]-]-.][>>>]", [])
        self._run_and_check_ir("[+[[[,]-]-]-.][>>>][.]", [])

        # Loop open after loop close => dead
        self._run_and_check_ir(
            "+[>][.]",
            [ir.ADD(1), ir.OPEN(),
             ir.RIGHT(1), ir.CLOSE()],
            maxdepth=2)

        # Loop open after SET(0) => dead
        self._run_and_check_ir(",[-][>>]", [ir.INPUT(), ir.SET(0)])
        self._run_and_check_ir(",[-][>>][..]", [ir.INPUT(), ir.SET(0)])
        self._run_and_check_ir(
            ",[-][>>].",
            [ir.INPUT(), ir.SET(0), ir.OUTPUT()])

        # But open after SET(x) where x > 0 => alive
        self._run_and_check_ir(
            ",[-]+[>>]",
            [ir.INPUT(),
             ir.SET(1),
             ir.OPEN(),
             ir.RIGHT(2),
             ir.CLOSE()],
            maxdepth=2)
Пример #2
0
    def test_copy_loop_multiple_separate_offsets(self):
        # 2 offsets
        self._run_and_check_ir(
            ',[->+>+<<]',
            [ir.INPUT(), ir.RMUL(1, 1),
             ir.RMUL(2, 1),
             ir.SET(0)])
        self._run_and_check_ir(
            ',[->->-<<]',
            [ir.INPUT(),
             ir.RMUL(1, 255),
             ir.RMUL(2, 255),
             ir.SET(0)])
        self._run_and_check_ir(
            ',[<+>>-<-]',
            [ir.INPUT(), ir.LMUL(1, 1),
             ir.RMUL(1, 255),
             ir.SET(0)])

        # many but less than 127 offsets
        self._run_and_check_ir(',[-' + '<+' * 126 + '>' * 126 + ']',
                               [ir.INPUT()] +
                               [ir.LMUL(i, 1)
                                for i in range(1, 127)] + [ir.SET(0)])
        self._run_and_check_ir(',[<<<+>>>>>-<<<<<<<+>>>>>-<+>]', [
            ir.INPUT(),
            ir.LMUL(3, 1),
            ir.RMUL(2, 255),
            ir.LMUL(5, 1),
            ir.LMUL(1, 1),
            ir.SET(0)
        ])
Пример #3
0
 def test_target_386_linux(self):
     self._run_and_check_target(17, _386_LINUX, "@386_linux ")
     self._run_and_check_target(17,
                                _386_LINUX,
                                "@386_linux,,",
                                ir=[ir.INPUT(), ir.INPUT()])
     self._run_and_check_target(17,
                                _386_LINUX,
                                "@386_linux->",
                                ir=[ir.SUB(1), ir.RIGHT(1)])
     self._run_and_check_target(17, _386_LINUX, "@386_linux[foobar]")
     self._run_and_check_target(17, _386_LINUX, "@386_linux foobar")
Пример #4
0
 def test_contraction_set_arithmetic(self):
     # Arithmetic ops after a SET() are collapsed into the SET()
     self._run_and_check_ir(',[-]--', [ir.INPUT(), ir.SET(254)])
     self._run_and_check_ir(',[-]-', [ir.INPUT(), ir.SET(255)])
     self._run_and_check_ir(',[-]', [ir.INPUT(), ir.SET(0)])
     self._run_and_check_ir(',[-]+', [ir.INPUT(), ir.SET(1)])
     self._run_and_check_ir(',[-]++', [ir.INPUT(), ir.SET(2)])
     self._run_and_check_ir(',[+]--', [ir.INPUT(), ir.SET(254)])
     self._run_and_check_ir(',[+]-', [ir.INPUT(), ir.SET(255)])
     self._run_and_check_ir(',[+]', [ir.INPUT(), ir.SET(0)])
     self._run_and_check_ir(',[+]+', [ir.INPUT(), ir.SET(1)])
     self._run_and_check_ir(',[+]++', [ir.INPUT(), ir.SET(2)])
Пример #5
0
 def test_nested_loops(self):
     # Loops can be nested
     # Loop depth is calculated
     self._run_and_check_ir("+[-[+<].]>[[[]+]+]+", [
         ir.ADD(1),
         ir.OPEN(),
         ir.SUB(1),
         ir.OPEN(),
         ir.ADD(1),
         ir.LEFT(1),
         ir.CLOSE(),
         ir.OUTPUT(),
         ir.CLOSE(),
         ir.RIGHT(1),
         ir.OPEN(),
         ir.OPEN(),
         ir.OPEN(),
         ir.CLOSE(),
         ir.ADD(1),
         ir.CLOSE(),
         ir.ADD(1),
         ir.CLOSE(),
         ir.ADD(1)
     ],
                            maxdepth=4)
     self._run_and_check_ir("+[[[[[[[[.]]]]],[[[]]]]]]",
                            [ir.ADD(1)] + [ir.OPEN()] * 8 + [ir.OUTPUT()] +
                            [ir.CLOSE()] * 5 + [ir.INPUT()] +
                            [ir.OPEN()] * 3 + [ir.CLOSE()] * 6,
                            maxdepth=9)
Пример #6
0
 def test_clear_loops(self):
     # The [-] and [+] constructs become SET(0)
     # These are not included when calculating loop depth
     self._run_and_check_ir(
         ",[-].[+]",
         [ir.INPUT(), ir.SET(0),
          ir.OUTPUT(), ir.SET(0)],
         maxdepth=1)
Пример #7
0
 def test_single_instruction(self):
     # Single brainfuck instructions can be valid programs
     self._run_and_check_ir(">", [ir.RIGHT(1)])
     self._run_and_check_ir("<", [ir.LEFT(1)])
     self._run_and_check_ir(",", [ir.INPUT()])
     self._run_and_check_ir(".", [ir.OUTPUT()])
     self._run_and_check_ir("+", [ir.ADD(1)])
     self._run_and_check_ir("-", [ir.SUB(1)])
Пример #8
0
 def test_single_instruction_with_comment(self):
     # Single instructions with comments can be valid programs
     self._run_and_check_ir("a>", [ir.RIGHT(1)])
     self._run_and_check_ir("<a", [ir.LEFT(1)])
     self._run_and_check_ir("a.a", [ir.OUTPUT()])
     self._run_and_check_ir("aa,", [ir.INPUT()])
     self._run_and_check_ir("+aa", [ir.ADD(1)])
     self._run_and_check_ir("aa-aa", [ir.SUB(1)])
Пример #9
0
 def test_basic_operations(self):
     # ,[->>++++++++<<]>>.[-].[-]+
     self.run_ir([ir.INPUT(),
                  ir.OPEN(),
                    ir.SUB(1), ir.RIGHT(2), ir.ADD(8), ir.LEFT(2),
                  ir.CLOSE(),
                  ir.RIGHT(2), ir.OUTPUT(), ir.SET(0), ir.OUTPUT()],
                 [8],
                 [64, 0])
Пример #10
0
    def test_cancellation_of_basic_instructions(self):
        # Two pairs of the basic brainfuck instructions are mutually
        # cancelling

        # Pairs of cancelling instructions are reduced
        self._run_and_check_ir("+-", [])
        self._run_and_check_ir("+-", [])
        self._run_and_check_ir("><", [])
        self._run_and_check_ir("<>", [])

        # Longer sequences of cancelling instructions are reduced
        self._run_and_check_ir("-+<>+-><", [])
        self._run_and_check_ir(".<<<<>>>>++++----.",
                               [ir.OUTPUT(), ir.OUTPUT()])

        # The cancelling instructions do not have to be immediately adjacent
        self._run_and_check_ir("+++-->><-+<-,  <>-++-+-<><>.",
                               [ir.INPUT(), ir.OUTPUT()])
        self._run_and_check_ir(",>>+++>+--+<----+<<++>><<--", [ir.INPUT()])
Пример #11
0
 def test_copy_loop_multiple_repeated_offsets(self):
     # repeated offsets result in multiple LMUL/RMUL
     self._run_and_check_ir(',[->+>++<+++>----<<]', [
         ir.INPUT(),
         ir.RMUL(1, 1),
         ir.RMUL(2, 2),
         ir.RMUL(1, 3),
         ir.RMUL(2, 252),
         ir.SET(0)
     ])
Пример #12
0
 def test_basic_operations(self):
     self._run_and_check_ir(">+.<-[,]", [
         ir.RIGHT(1),
         ir.ADD(1),
         ir.OUTPUT(),
         ir.LEFT(1),
         ir.SUB(1),
         ir.OPEN(),
         ir.INPUT(),
         ir.CLOSE()
     ],
                            maxdepth=2)
Пример #13
0
 def test_all_instructions(self):
     # All instructions can live in the same program
     self._run_and_check_ir(">+.<-[,]", [
         ir.RIGHT(1),
         ir.ADD(1),
         ir.OUTPUT(),
         ir.LEFT(1),
         ir.SUB(1),
         ir.OPEN(),
         ir.INPUT(),
         ir.CLOSE()
     ],
                            maxdepth=2)
     self._run_and_check_ir("+,[->.]<", [
         ir.ADD(1),
         ir.INPUT(),
         ir.OPEN(),
         ir.SUB(1),
         ir.RIGHT(1),
         ir.OUTPUT(),
         ir.CLOSE(),
         ir.LEFT(1)
     ],
                            maxdepth=2)
Пример #14
0
 def test_copy_loop_wrap_around(self):
     self._run_and_check_ir(
         ',[->' + '+' * 255 + '<]',
         [ir.INPUT(), ir.RMUL(1, 255),
          ir.SET(0)])
     self._run_and_check_ir(',[->' + '+' * 256 + '<]',
                            [ir.INPUT(), ir.SET(0)])
     self._run_and_check_ir(
         ',[->' + '+' * 257 + '<]',
         [ir.INPUT(), ir.RMUL(1, 1), ir.SET(0)])
     self._run_and_check_ir(
         ',[-<<' + '-' * 255 + '>>]',
         [ir.INPUT(), ir.LMUL(2, 1), ir.SET(0)])
     self._run_and_check_ir(',[-<<' + '-' * 256 + '>>]',
                            [ir.INPUT(), ir.SET(0)])
     self._run_and_check_ir(
         ',[-<<' + '-' * 257 + '>>]',
         [ir.INPUT(), ir.LMUL(2, 255),
          ir.SET(0)])
Пример #15
0
 def test_copy_loop_simple(self):
     # single cell copy loops
     self._run_and_check_ir(
         ',[->+<]',
         [ir.INPUT(), ir.RMUL(1, 1), ir.SET(0)])
     self._run_and_check_ir(
         ',[->-<]', [ir.INPUT(), ir.RMUL(1, 255),
                     ir.SET(0)])
     self._run_and_check_ir(
         ',[-<+>]',
         [ir.INPUT(), ir.LMUL(1, 1), ir.SET(0)])
     self._run_and_check_ir(
         ',[-<->]', [ir.INPUT(), ir.LMUL(1, 255),
                     ir.SET(0)])
     self._run_and_check_ir(
         ',[<->-]', [ir.INPUT(), ir.LMUL(1, 255),
                     ir.SET(0)])
     self._run_and_check_ir(
         ',[>+<-]',
         [ir.INPUT(), ir.RMUL(1, 1), ir.SET(0)])
Пример #16
0
    def test_copy_loop_not_optimizeable(self):
        # loop must end where it started
        self._run_and_check_ir(',[->+]', [
            ir.INPUT(),
            ir.OPEN(),
            ir.SUB(1),
            ir.RIGHT(1),
            ir.ADD(1),
            ir.CLOSE()
        ],
                               maxdepth=2)
        self._run_and_check_ir(',[->+<<]', [
            ir.INPUT(),
            ir.OPEN(),
            ir.SUB(1),
            ir.RIGHT(1),
            ir.ADD(1),
            ir.LEFT(2),
            ir.CLOSE()
        ],
                               maxdepth=2)

        # must subtract 1 from cell 0 exactly once
        self._run_and_check_ir(',[->+<-]', [
            ir.INPUT(),
            ir.OPEN(),
            ir.SUB(1),
            ir.RIGHT(1),
            ir.ADD(1),
            ir.LEFT(1),
            ir.SUB(1),
            ir.CLOSE()
        ],
                               maxdepth=2)
        self._run_and_check_ir(',[+>+<--]', [
            ir.INPUT(),
            ir.OPEN(),
            ir.ADD(1),
            ir.RIGHT(1),
            ir.ADD(1),
            ir.LEFT(1),
            ir.SUB(2),
            ir.CLOSE()
        ],
                               maxdepth=2)
        self._run_and_check_ir(',[->+<+<->-]', [
            ir.INPUT(),
            ir.OPEN(),
            ir.SUB(1),
            ir.RIGHT(1),
            ir.ADD(1),
            ir.LEFT(1),
            ir.ADD(1),
            ir.LEFT(1),
            ir.SUB(1),
            ir.RIGHT(1),
            ir.SUB(1),
            ir.CLOSE()
        ],
                               maxdepth=2)

        # must be fewer than 127 < and 127 >
        self._run_and_check_ir(',[-' + '>' * 127 + '+' + '<' * 127 + ']', [
            ir.INPUT(),
            ir.OPEN(),
            ir.SUB(1),
            ir.RIGHT(127),
            ir.ADD(1),
            ir.LEFT(127),
            ir.CLOSE()
        ],
                               maxdepth=2)
        self._run_and_check_ir(',[-' + '<' * 127 + '+' + '>' * 127 + ']', [
            ir.INPUT(),
            ir.OPEN(),
            ir.SUB(1),
            ir.LEFT(127),
            ir.ADD(1),
            ir.RIGHT(127),
            ir.CLOSE()
        ],
                               maxdepth=2)
Пример #17
0
    def test_set(self):
        # simple cases
        self._run_and_check_ir(',[-]-', [ir.INPUT(), ir.SET(255)])
        self._run_and_check_ir(',[-]', [ir.INPUT(), ir.SET(0)])
        self._run_and_check_ir(',[-]+', [ir.INPUT(), ir.SET(1)])
        self._run_and_check_ir(',[-]++', [ir.INPUT(), ir.SET(2)])
        self._run_and_check_ir(',[-]+++', [ir.INPUT(), ir.SET(3)])
        self._run_and_check_ir(',[-]-', [ir.INPUT(), ir.SET(255)])
        self._run_and_check_ir(',[-]--', [ir.INPUT(), ir.SET(254)])
        self._run_and_check_ir(',[-]---', [ir.INPUT(), ir.SET(253)])

        # overflow
        self._run_and_check_ir(',[-]' + '+' * 255, [ir.INPUT(), ir.SET(255)])
        self._run_and_check_ir(',[-]' + '+' * 256, [ir.INPUT(), ir.SET(0)])
        self._run_and_check_ir(',[-]' + '+' * 257, [ir.INPUT(), ir.SET(1)])

        self._run_and_check_ir(',[-]' + '-' * 255, [ir.INPUT(), ir.SET(1)])
        self._run_and_check_ir(',[-]' + '-' * 256, [ir.INPUT(), ir.SET(0)])
        self._run_and_check_ir(',[-]' + '-' * 257, [ir.INPUT(), ir.SET(255)])
Пример #18
0
 def test_eof_behaviour(self):
     # do no-change on EOF
     # ++++++++++,.
     self.run_ir([ir.ADD(10), ir.INPUT(), ir.OUTPUT()], [], [10])
Пример #19
0
 def test_cancellation(self):
     self._run_and_check_ir("+++-->><-+<-,  <>-++-+-<><>.",
                            [ir.INPUT(), ir.OUTPUT()])
     self._run_and_check_ir("-+<>+-><", [])
     self._run_and_check_ir(".<<<<>>>>++++----.",
                            [ir.OUTPUT(), ir.OUTPUT()])