Exemple #1
0
 def test_clear_loops(self):
     self._run_and_check_ir(
         "+[-]+[+]",
         [ir.ADD(1), ir.SET(1),
          ir.OPEN(), ir.ADD(1),
          ir.CLOSE()],
         maxdepth=2)
Exemple #2
0
    def test_cancellation_partial(self):
        # Cancellation can be partial, leaving part of the cancelling
        # instructions behind.

        # The basic brainfuck instructions
        self._run_and_check_ir("++++--", [ir.ADD(2)])
        self._run_and_check_ir("--++++", [ir.ADD(2)])
        self._run_and_check_ir("++----", [ir.SUB(2)])
        self._run_and_check_ir("----++", [ir.SUB(2)])
        self._run_and_check_ir(">>>><<", [ir.RIGHT(2)])
        self._run_and_check_ir("<<>>>>", [ir.RIGHT(2)])
        self._run_and_check_ir(">><<<<", [ir.LEFT(2)])
        self._run_and_check_ir("<<<<>>", [ir.LEFT(2)])

        # Cases with argument overflow, i.e. >255 of the same
        # instructions in a row, are also cancelled correctly.
        self._run_and_check_ir(['>'] * 258 + ['<', '<'],
                               [ir.RIGHT(255), ir.RIGHT(1)])
        self._run_and_check_ir(['>'] * 258 + ['<', '<', '<'], [ir.RIGHT(255)])
        self._run_and_check_ir(['>'] * 258 + ['<', '<', '<', '<'],
                               [ir.RIGHT(254)])

        self._run_and_check_ir(['<'] * 258 + ['>', '>'],
                               [ir.LEFT(255), ir.LEFT(1)])
        self._run_and_check_ir(['<'] * 258 + ['>', '>', '>'], [ir.LEFT(255)])
        self._run_and_check_ir(['<'] * 258 + ['>', '>', '>', '>'],
                               [ir.LEFT(254)])
Exemple #3
0
    def test_mul(self):
        self.run_ir([ir.ADD(4), ir.RMUL(2, 4), ir.RIGHT(2), ir.OUTPUT()],
                    [], [16])
        self.run_ir([ir.ADD(4), ir.RIGHT(2), ir.ADD(7), ir.LMUL(2, 254),
                     ir.LEFT(2), ir.OUTPUT()],
                    [], [246])

        self.run_ir([ir.RIGHT(127), ir.SUB(2), ir.LMUL(127, 1),
                     ir.LEFT(127), ir.OUTPUT()],
                     [], [254])
        self.run_ir([ir.RIGHT(127), ir.SUB(2), ir.LMUL(127, 12),
                     ir.LEFT(127), ir.OUTPUT()],
                    [], [232])
        self.run_ir([ir.RIGHT(127), ir.SUB(2), ir.LMUL(127, 255),
                     ir.LEFT(127), ir.OUTPUT()],
                    [], [2])

        self.run_ir([ir.SET(3), ir.RMUL(127, 1), ir.RIGHT(127), ir.OUTPUT()],
                    [], [3])
        self.run_ir([ir.SET(3), ir.RMUL(127, 12), ir.RIGHT(127), ir.OUTPUT()],
                    [], [36])
        self.run_ir([ir.SET(3), ir.RMUL(127, 255),
                     ir.RIGHT(127), ir.OUTPUT()],
                    [], [253])

        self.run_ir([ir.ADD(12), ir.RMUL(1, 12), ir.RIGHT(1), ir.OUTPUT()],
                    [], [144])
        self.run_ir([ir.RIGHT(1), ir.ADD(12), ir.LMUL(1, 12), ir.LEFT(1),
                     ir.OUTPUT()],
                    [], [144])
Exemple #4
0
 def test_contraction_overflow_arithmetic(self):
     # Arithmetic operations are removed on argument overflow
     self._run_and_check_ir(['+'] * 255, [ir.ADD(255)])
     self._run_and_check_ir(['+'] * 256, [])
     self._run_and_check_ir(['+'] * 257, [ir.ADD(1)])
     self._run_and_check_ir(['-'] * 255, [ir.SUB(255)])
     self._run_and_check_ir(['-'] * 256, [])
     self._run_and_check_ir(['-'] * 257, [ir.SUB(1)])
Exemple #5
0
 def test_deep_nested_loops(self):
     # +[{many}-(>+.<]){many}
     self.run_ir([ir.ADD(1)] +
                 ([ir.OPEN()] * self.MAX_NESTED_LOOPS) +
                 [ir.SUB(1)] +
                 ([ir.RIGHT(1), ir.ADD(1), ir.OUTPUT(),
                   ir.LEFT(1), ir.CLOSE()] * self.MAX_NESTED_LOOPS),
                 [], [i % 256 for i in range(1, self.MAX_NESTED_LOOPS + 1)],
                 steps=50000000)
Exemple #6
0
 def test_cells_wrap(self):
     # .-.++.+{254}.+.-.
     self.run_ir([ir.OUTPUT(),
                  ir.SUB(1), ir.OUTPUT(),
                  ir.ADD(2), ir.OUTPUT(),
                  ir.ADD(254), ir.OUTPUT(),
                  ir.ADD(1), ir.OUTPUT(),
                  ir.SUB(1), ir.OUTPUT()],
                 [], [0, 255, 1, 255, 0, 255])
Exemple #7
0
    def test_set(self):
        self.run_ir([ir.SET(0), ir.OUTPUT()], [], [0])
        self.run_ir([ir.SET(1), ir.OUTPUT()], [], [1])
        self.run_ir([ir.SET(2), ir.OUTPUT()], [], [2])
        self.run_ir([ir.SET(255), ir.OUTPUT()], [], [255])

        self.run_ir([ir.ADD(12), ir.SET(0), ir.OUTPUT()], [], [0])
        self.run_ir([ir.ADD(12), ir.SET(1), ir.OUTPUT()], [], [1])
        self.run_ir([ir.ADD(12), ir.SET(2), ir.OUTPUT()], [], [2])
        self.run_ir([ir.ADD(12), ir.SET(255), ir.OUTPUT()], [], [255])
Exemple #8
0
 def test_contraction(self):
     self._run_and_check_ir("+++", [ir.ADD(3)])
     self._run_and_check_ir(['+'] * 255, [ir.ADD(255)])
     self._run_and_check_ir(['+'] * 256, [])
     self._run_and_check_ir("---", [ir.SUB(3)])
     self._run_and_check_ir(['-'] * 255, [ir.SUB(255)])
     self._run_and_check_ir(['-'] * 256, [])
     self._run_and_check_ir("<<<", [ir.LEFT(3)])
     self._run_and_check_ir(['<'] * 128, [ir.LEFT(127), ir.LEFT(1)])
     self._run_and_check_ir(">>>", [ir.RIGHT(3)])
     self._run_and_check_ir(['>'] * 128, [ir.RIGHT(127), ir.RIGHT(1)])
Exemple #9
0
 def test_target_lang_c(self):
     self._run_and_check_target(17, _LANG_C, "@lang_c ")
     self._run_and_check_target(17, _LANG_C, "@lang_c\n")
     self._run_and_check_target(17, _LANG_C, "@lang_c+", ir=[ir.ADD(1)])
     self._run_and_check_target(17,
                                _LANG_C,
                                "@lang_c.+",
                                ir=[ir.OUTPUT(), ir.ADD(1)])
     self._run_and_check_target(17, _LANG_C, "@lang_c[.]")
     self._run_and_check_target(17,
                                _LANG_C,
                                "@lang_c..",
                                ir=[ir.OUTPUT(), ir.OUTPUT()])
Exemple #10
0
    def test_nested_loops(self):
        # ++[->++[->++[->++[->++[->++<]<]<]<]<]>>>>>.[-].
        self.run_ir([ir.ADD(2),
                     ir.OPEN(), ir.SUB(1), ir.RIGHT(1), ir.ADD(2),
                       ir.OPEN(), ir.SUB(1), ir.RIGHT(1), ir.ADD(2),
                         ir.OPEN(), ir.SUB(1), ir.RIGHT(1), ir.ADD(2),
                           ir.OPEN(), ir.SUB(1), ir.RIGHT(1), ir.ADD(2),
                             ir.OPEN(), ir.SUB(1), ir.RIGHT(1), ir.ADD(2),
                             ir.LEFT(1), ir.CLOSE(),
                           ir.LEFT(1), ir.CLOSE(),
                         ir.LEFT(1), ir.CLOSE(),
                       ir.LEFT(1), ir.CLOSE(),
                     ir.LEFT(1), ir.CLOSE(),
                     ir.RIGHT(5), ir.OUTPUT(), ir.SET(0), ir.OUTPUT()],
                    [], [64, 0])

        # ++>+[[[[->]<]>]<].<.
        self.run_ir([ir.ADD(2), ir.RIGHT(1), ir.ADD(1),
                     ir.OPEN(),
                       ir.OPEN(),
                         ir.OPEN(),
                           ir.OPEN(),
                             ir.SUB(1), ir.RIGHT(1),
                           ir.CLOSE(),
                           ir.LEFT(1),
                         ir.CLOSE(),
                         ir.RIGHT(1),
                       ir.CLOSE(),
                       ir.LEFT(1),
                     ir.CLOSE(),
                     ir.OUTPUT(), ir.LEFT(1), ir.OUTPUT()],
                    [], [0, 2])
Exemple #11
0
 def test_contraction_simple_cases(self):
     # Sequences of multiple brainfuck instructions can be
     # contracted into single bytecode operations
     self._run_and_check_ir("++", [ir.ADD(2)])
     self._run_and_check_ir("+++", [ir.ADD(3)])
     self._run_and_check_ir("+" * 128, [ir.ADD(128)])
     self._run_and_check_ir("--", [ir.SUB(2)])
     self._run_and_check_ir("---", [ir.SUB(3)])
     self._run_and_check_ir("-" * 128, [ir.SUB(128)])
     self._run_and_check_ir("<<", [ir.LEFT(2)])
     self._run_and_check_ir("<<<", [ir.LEFT(3)])
     self._run_and_check_ir("<" * 128, [ir.LEFT(128)])
     self._run_and_check_ir(">>", [ir.RIGHT(2)])
     self._run_and_check_ir(">>>", [ir.RIGHT(3)])
     self._run_and_check_ir(">" * 128, [ir.RIGHT(128)])
Exemple #12
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)
Exemple #13
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)])
Exemple #14
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)])
Exemple #15
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])
Exemple #16
0
    def test_target_incomplete(self):
        self._run_and_check_target(17, 17, "@lang_")
        self._run_and_check_target(17, 17, "@lang_ ")
        self._run_and_check_target(17, 17, "@lang_\n")
        self._run_and_check_target(17, 17, "@lang_+", ir=[ir.ADD(1)])

        self._run_and_check_target(17, 17, "@386_linu")
        self._run_and_check_target(17, 17, "@386_linu ")
        self._run_and_check_target(17, 17, "@386_linu\n")
        self._run_and_check_target(17, 17, "@386_linu_.", ir=[ir.OUTPUT()])
Exemple #17
0
 def test_loop_elimination(self):
     self._run_and_check_ir("[.]", [])
     self._run_and_check_ir(
         "[+++]+[][+++].[-][+++]",
         [ir.ADD(1),
          ir.OPEN(),
          ir.CLOSE(),
          ir.OUTPUT(),
          ir.SET(0)],
         maxdepth=2)
     self._run_and_check_ir("[-][+++]", [])
Exemple #18
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)
Exemple #19
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)
Exemple #20
0
 def test_nested_loops(self):
     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),
         ir.OPEN(),
         ir.ADD(1),
         ir.CLOSE()
     ],
                            maxdepth=4)
Exemple #21
0
    def test_contraction_and_cancellation(self):
        # basic cases
        self._run_and_check_ir("++++--", [ir.ADD(2)])
        self._run_and_check_ir("--++++", [ir.ADD(2)])
        self._run_and_check_ir("++----", [ir.SUB(2)])
        self._run_and_check_ir("----++", [ir.SUB(2)])
        self._run_and_check_ir(">>>><<", [ir.RIGHT(2)])
        self._run_and_check_ir("<<>>>>", [ir.RIGHT(2)])
        self._run_and_check_ir(">><<<<", [ir.LEFT(2)])
        self._run_and_check_ir("<<<<>>", [ir.LEFT(2)])

        # cases triggering argument overflow
        self._run_and_check_ir(['>'] * 130 + ['<', '<'],
                               [ir.RIGHT(127), ir.RIGHT(1)])
        self._run_and_check_ir(['>'] * 130 + ['<', '<', '<'], [ir.RIGHT(127)])
        self._run_and_check_ir(['>'] * 130 + ['<', '<', '<', '<'],
                               [ir.RIGHT(126)])

        self._run_and_check_ir(['<'] * 130 + ['>', '>'],
                               [ir.LEFT(127), ir.LEFT(1)])
        self._run_and_check_ir(['<'] * 130 + ['>', '>', '>'], [ir.LEFT(127)])
        self._run_and_check_ir(['<'] * 130 + ['>', '>', '>', '>'],
                               [ir.LEFT(126)])
Exemple #22
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)
Exemple #23
0
 def test_eof_behaviour(self):
     # do no-change on EOF
     # ++++++++++,.
     self.run_ir([ir.ADD(10), ir.INPUT(), ir.OUTPUT()], [], [10])
Exemple #24
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)