Exemplo n.º 1
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])
Exemplo n.º 2
0
    def test_left_right(self):
        # the 386_linux backend outputs different machine instructions
        # for LEFT and RIGHT depending on the size of the
        # argument. this tests the edge cases.

        ops = []

        # set up memory to 0,1,2,...,255,0,0,0,...
        for i in range(256):
            ops.append(ir.SET(i))
            ops.append(ir.RIGHT(1))

        # jump all the "edgy" distances left and right and output
        edges = [1, 2, 3, 4, 126, 127, 128, 129, 130, 131, 253, 254, 255]
        for i in edges:
            ops.append(ir.LEFT(i))
            ops.append(ir.OUTPUT())
            ops.append(ir.RIGHT(i))
            ops.append(ir.OUTPUT())

        # expected output is 0 alternated with all the edges
        expected = []
        for i in edges:
            expected.append(256 - i)
            expected.append(0)

        self.run_ir(ops, [], expected)
Exemplo n.º 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])
Exemplo n.º 4
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)
Exemplo n.º 5
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])
Exemplo n.º 6
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()])
Exemplo n.º 7
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)
Exemplo n.º 8
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)
Exemplo n.º 9
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)])
Exemplo n.º 10
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)])
Exemplo n.º 11
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)
Exemplo n.º 12
0
Arquivo: backend.py Projeto: nrh/awib
    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])
Exemplo n.º 13
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)
Exemplo n.º 14
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()])
Exemplo n.º 15
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()])
Exemplo n.º 16
0
        def ops(d):
            ops = []
            # first use only LEFT(1) and RIGHT(1) to set up memory
            ops += ([ir.RIGHT(1)] * (d) + [ir.SET(12)] + [ir.RIGHT(1)] * (d) +
                    [ir.SET(32)] + [ir.RIGHT(1)] * (d) + [ir.SET(17)] +
                    [ir.LEFT(1)] * (d * 2))

            # state:   0(d) *12 0(d - 1) 32 0(d - 1) 17 0

            # run a [.>>>>] construct to move up the pointer. this
            # should output 12, 32 and 17.
            ops += ([ir.OPEN(), ir.OUTPUT(), ir.RIGHT(d), ir.CLOSE()])

            # state:   0(d) 12 0(d - 1) 32 0(d - 1) 17 0(d - 1) *0

            # same thing in other direction. should output 17,32
            ops += [ir.LEFT(d)]
            ops += ([ir.OPEN(), ir.OUTPUT(), ir.LEFT(d), ir.CLOSE()])

            return ops
Exemplo n.º 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("[-][+++]", [])
Exemplo n.º 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)
Exemplo n.º 19
0
    def test_mul_overreaching(self):
        """Backend should handle MUL writing up to 127 cells outside of tape.

        There are perfectly valid programs for which the frontend will
        output multiplication operations that write to a position
        outside of the tape. One example would be '.[-<+>]' for which
        an OUTPUT() followed by LMUL(1,1) will be produced. There are
        other less obvious cases that the frontend cannot catch (and
        my gut says catching them all it's equivalent to the halting
        problem).

        One option is for the backends to always check that the
        current cell is non-zero before writing the product of a
        multiplication operation. Another option is to simply pad the
        tape with 127 cells on each end and to initialize the pointer
        at position 127 instead of 0 (and 127 is magic because it's
        the max offset the frontend emits for the multipication
        operations).
        """

        # offsets on the left
        self.run_ir([ir.LMUL(1, 1), ir.OUTPUT()], [], [0])
        self.run_ir([ir.LMUL(2, 1), ir.OUTPUT()], [], [0])
        self.run_ir([ir.LMUL(3, 1), ir.OUTPUT()], [], [0])
        self.run_ir([ir.LMUL(126, 1), ir.OUTPUT()], [], [0])
        self.run_ir([ir.LMUL(127, 1), ir.OUTPUT()], [], [0])

        # offsets on the right
        movetolastcell = [ir.RIGHT(127) for _ in range(516)] + [ir.RIGHT(2)]
        self.run_ir(movetolastcell + [ir.RMUL(1, 1), ir.OUTPUT()], [], [0],
                    steps=10000000)
        self.run_ir(movetolastcell + [ir.RMUL(2, 1), ir.OUTPUT()], [], [0],
                    steps=10000000)
        self.run_ir(movetolastcell + [ir.RMUL(3, 1), ir.OUTPUT()], [], [0],
                    steps=10000000)
        self.run_ir(movetolastcell + [ir.RMUL(126, 1), ir.OUTPUT()], [], [0],
                    steps=10000000)
        self.run_ir(movetolastcell + [ir.RMUL(127, 1), ir.OUTPUT()], [], [0],
                    steps=10000000)
Exemplo n.º 20
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])
Exemplo n.º 21
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)
Exemplo n.º 22
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()])
Exemplo n.º 23
0
Arquivo: backend.py Projeto: nrh/awib
 def test_eof_behaviour(self):
     # do no-change on EOF
     # ++++++++++,.
     self.run_ir([ir.ADD(10), ir.INPUT(), ir.OUTPUT()], [], [10])