def test_empty_returning_main_block(self):
     block = InstructionBlock()
     self.assertEqual(0, block.get_start_address())
     self.assertIsNone(block.return_ip)
     ip = InstructionPointer(InstructionBlock(), 7)
     block.return_ip = ip # must have no effect
     self.__verify_block(block, [], [STOPInstruction()])
 def test_add_instruction_stop(self):
     block = InstructionBlock()
     expected_instructions = [STOPInstruction(), STOPInstruction()]
     block.add_instruction_stop()
     block.add_instruction_stop()
     expected_compiled_instructions = expected_instructions.copy()
     expected_compiled_instructions.append(STOPInstruction())
     self.__verify_block(block, expected_instructions, expected_compiled_instructions)
 def test_empty_relative_block(self):
     return_block = InstructionBlock()
     block = InstructionBlock(return_block)
     self.assertRaises(InstructionBlockNotYetPlacedException, block.get_start_address)
     self.assertRaises(MissingReturnAddressException, block.compile_sequence)
     ip = InstructionPointer(return_block, 7)
     block.return_ip = ip
     self.__verify_block(block, [], [GOTOInstruction(ip.block, ip.offset)])
 def test_create_embedded_block(self):
     parent_block = InstructionBlock()
     block = parent_block.create_embedded_block()
     self.assertRaises(InstructionBlockNotYetPlacedException, block.get_start_address)
     self.assertRaises(MissingReturnAddressException, block.compile_sequence)
     block.return_ip = InstructionPointer(parent_block, 0)
     self.__verify_block(block, [], [GOTOInstruction(parent_block, 0)])
     self.__verify_block(parent_block, [], [STOPInstruction(), GOTOInstruction(parent_block, 0)])
     self.assertEqual(1, block.get_start_address())
    def test_add_instruction_cjmp(self):
        block = InstructionBlock()
        expected_instructions = []
        expected_compiled_instructions = []
        
        targets = [(InstructionBlock(), 0), (InstructionBlock(), 1), (InstructionBlock(), 50)]
        triggers = [Trigger(), Trigger()]
        LOOKUP = [(0, 0), (1, 0), (1, 1), (0, 1), (2, 0), (1, 0), (0, 1), (0, 1), (0, 0), (1, 0), (2, 1), (2, 1)]
        for i in LOOKUP:
            block.add_instruction_cjmp(triggers[i[1]], targets[i[0]])
            expected_instructions.append(CJMPInstruction(triggers[i[1]], targets[i[0]], 0))

        expected_compiled_instructions = expected_instructions.copy()
        expected_compiled_instructions.append(STOPInstruction())
        self.__verify_block(block, expected_instructions, expected_compiled_instructions)
 def test_add_instruction_goto(self):
     block = InstructionBlock()
     expected_instructions = []
     
     targets = [(InstructionBlock(), 0), (InstructionBlock(), 1), (InstructionBlock(), 50)]
     LOOKUP = [0, 1, 1, 0, 2, 1, 0, 0, 0, 1, 2, 2]
     for id in LOOKUP:
         target = targets[id]
         instruction = GOTOInstruction(target[0], target[1])
         expected_instructions.append(instruction)
         block.add_instruction_goto(target[0], target[1])
         
     expected_compiled_instructions = expected_instructions.copy()
     expected_compiled_instructions.append(STOPInstruction())
     self.__verify_block(block, expected_instructions, expected_compiled_instructions)
 def test_add_instruction_exec(self):
     block = InstructionBlock()
     expected_instructions = []
     
     waveforms = [DummyWaveform(), DummyWaveform(), DummyWaveform()]
     LOOKUP = [0, 1, 1, 0, 2, 1, 0, 0, 0, 1, 2, 2]
     for id in LOOKUP:
         waveform = waveforms[id]
         instruction = EXECInstruction(waveform)
         expected_instructions.append(instruction)
         block.add_instruction_exec(waveform)
         
     expected_compiled_instructions = expected_instructions.copy()
     expected_compiled_instructions.append(STOPInstruction())
     self.__verify_block(block, expected_instructions, expected_compiled_instructions)
 def test_nested_block_construction(self):
     main_block = InstructionBlock()
     expected_instructions = [[], [], [], []]
     expected_compiled_instructions = [[], [], [], []]
     
     blocks = []
         
     waveforms = [DummyWaveform(), DummyWaveform(), DummyWaveform()]
     
     main_block.add_instruction_exec(waveforms[0])
     expected_instructions[0].append(EXECInstruction(waveforms[0]))
     
     block = main_block.create_embedded_block() 
     trigger = Trigger()
     main_block.add_instruction_cjmp(trigger, block)
     expected_instructions[0].append(CJMPInstruction(trigger, block, 0))
     block.return_ip = InstructionPointer(main_block, len(main_block))
     blocks.append(block)
     
     block = main_block.create_embedded_block()
     trigger = Trigger()
     main_block.add_instruction_cjmp(trigger, block)
     expected_instructions[0].append(CJMPInstruction(trigger, block, 0))
     block.return_ip = InstructionPointer(main_block, len(main_block))
     blocks.append(block)
     
     WAVEFORM_LOOKUP = [[2, 2, 1, 1],[0, 1, 1, 0, 2, 1]]
     for i in [0, 1]:
         block = blocks[i]
         lookup = WAVEFORM_LOOKUP[i]
         for id in lookup:
             waveform = waveforms[id]
             expected_instructions[i + 1].append(EXECInstruction(waveform))
             block.add_instruction_exec(waveform)
         
     block = blocks[0].create_embedded_block()
     blocks[0].add_instruction_cjmp(trigger, block)
     expected_instructions[1].append(CJMPInstruction(trigger, block, 0))
     block.return_ip = InstructionPointer(blocks[0], len(blocks[0]))
     blocks.append(block)
     
     for id in [1, 2, 0, 2]:
         waveform = waveforms[id]
         expected_instructions[3].append(EXECInstruction(waveform))
         block.add_instruction_exec(waveform)
     
     for i in [0, 1, 2, 3]:
         expected_compiled_instructions[i] = expected_instructions[i].copy()
     
     expected_compiled_instructions[0].append(STOPInstruction())
     for i in [0, 1, 2]:
         expected_compiled_instructions[i + 1].append(GOTOInstruction(blocks[i].return_ip.block, blocks[i].return_ip.offset))
     
     positions = [0, None, None, None]                
     positions[3] = len(expected_compiled_instructions[1])
     
     expected_compiled_instructions[1].extend(expected_compiled_instructions[3])
     for i in [1, 2]:
         positions[i] = len(expected_compiled_instructions[0])
         expected_compiled_instructions[0].extend(expected_compiled_instructions[i])
         
     positions[3] += positions[1]
     
     self.__verify_block(blocks[2], expected_instructions[3], expected_compiled_instructions[3])
     self.__verify_block(blocks[1], expected_instructions[2], expected_compiled_instructions[2])
     self.__verify_block(blocks[0], expected_instructions[1], expected_compiled_instructions[1])
     self.__verify_block(main_block, expected_instructions[0], expected_compiled_instructions[0])
     
     self.assertEqual(positions[3], blocks[2].get_start_address())
     self.assertEqual(positions[2], blocks[1].get_start_address())
     self.assertEqual(positions[1], blocks[0].get_start_address())
     self.assertEqual(positions[0], main_block.get_start_address())
     
     for instruction in main_block.instructions:
         if isinstance(instruction, GOTOInstruction) or isinstance(instruction, CJMPInstruction):
             self.assertIsInstance(instruction.target.get_absolute_address(), int)
 def test_empty_unreturning_main_block(self):
     block = InstructionBlock()
     self.__verify_block(block, [], [STOPInstruction()])
     self.assertEqual(0, block.get_start_address())
     self.assertIsNone(block.return_ip)
     self.__verify_block(block, [], [STOPInstruction()])
 def __verify_block(self, block: InstructionBlock, expected_instructions: InstructionSequence, expected_compiled_instructions: InstructionSequence) -> None:
     self.assertEqual(len(expected_instructions), len(block))
     self.assertEqual(expected_instructions, block.instructions)
     self.assertEqual(expected_compiled_instructions, block.compile_sequence())