コード例 #1
0
 def test_str(self) -> None:
     block = DummyInstructionBlock()
     trigger = Trigger()
     instr = CJMPInstruction(trigger, InstructionPointer(block, 3))
     self.assertEqual(
         "cjmp to {} on {}".format(InstructionPointer(block, 3), trigger),
         str(instr))
コード例 #2
0
ファイル: conditions_tests.py プロジェクト: peendebak/qupulse
    def test_build_sequence_loop(self) -> None:
        sequencer = DummySequencer()
        block = DummyInstructionBlock()
        block.add_instruction(DummyInstruction())

        delegator = DummySequencingElement()
        body = DummySequencingElement()

        trigger = Trigger()
        condition = HardwareCondition(trigger)
        condition.build_sequence_loop(delegator, body, sequencer, {}, {}, {},
                                      {}, block)

        self.assertEqual(1, len(block.embedded_blocks))
        body_block = block.embedded_blocks[0]

        self.assertEqual(
            [
                DummyInstruction(),
                CJMPInstruction(trigger, InstructionPointer(body_block))
            ], block.instructions,
            "The expected conditional jump was not generated by HardwareConditon."
        )
        self.assertEqual(
            InstructionPointer(block, 1), body_block.return_ip,
            "The return address of the loop body block was set wrongly by HardwareCondition."
        )
        self.assertEqual(
            {body_block: [(body, {}, {}, {}, {})]},
            sequencer.sequencing_stacks,
            "HardwareCondition did not correctly push the body element to the stack"
        )
        self.assertFalse(condition.requires_stop())
コード例 #3
0
 def test_create_embedded_block(self) -> None:
     parent_block = InstructionBlock()
     block = InstructionBlock()
     block.return_ip = InstructionPointer(parent_block, 18)
     self.__verify_block(
         block, [], [GOTOInstruction(InstructionPointer(parent_block, 18))],
         InstructionPointer(parent_block, 18))
     self.__verify_block(parent_block, [], [STOPInstruction()], None)
コード例 #4
0
 def test_iterable_empty_return(self) -> None:
     parent_block = InstructionBlock()
     block = AbstractInstructionBlockStub([],
                                          InstructionPointer(
                                              parent_block, 13))
     count = 0
     for instruction in block:
         self.assertEqual(0, count)
         self.assertIsInstance(instruction, GOTOInstruction)
         self.assertEqual(InstructionPointer(parent_block, 13),
                          instruction.target)
         count += 1
コード例 #5
0
 def test_item_access_empty_return(self) -> None:
     parent_block = InstructionBlock()
     block = AbstractInstructionBlockStub([],
                                          InstructionPointer(
                                              parent_block, 84))
     self.assertEqual(GOTOInstruction(InstructionPointer(parent_block, 84)),
                      block[0])
     with self.assertRaises(IndexError):
         block[1]
     self.assertEqual(GOTOInstruction(InstructionPointer(parent_block, 84)),
                      block[-1])
     with self.assertRaises(IndexError):
         block[-2]
コード例 #6
0
 def test_iterable_return(self) -> None:
     parent_block = InstructionBlock()
     wf = DummyWaveform()
     block = AbstractInstructionBlockStub([EXECInstruction(wf)],
                                          InstructionPointer(
                                              parent_block, 11))
     count = 0
     for expected_instruction, instruction in zip([
             EXECInstruction(wf),
             GOTOInstruction(InstructionPointer(parent_block, 11))
     ], block):
         self.assertEqual(expected_instruction, instruction)
         count += 1
     self.assertEqual(2, count)
コード例 #7
0
 def test_item_access_return(self) -> None:
     wf = DummyWaveform()
     parent_block = InstructionBlock()
     block = AbstractInstructionBlockStub([EXECInstruction(wf)],
                                          InstructionPointer(
                                              parent_block, 29))
     self.assertEqual(EXECInstruction(wf), block[0])
     self.assertEqual(GOTOInstruction(InstructionPointer(parent_block, 29)),
                      block[1])
     with self.assertRaises(IndexError):
         block[2]
     self.assertEqual(GOTOInstruction(InstructionPointer(parent_block, 29)),
                      block[-1])
     self.assertEqual(EXECInstruction(wf), block[-2])
     with self.assertRaises(IndexError):
         block[-3]
コード例 #8
0
 def build_sequence_branch(self,
                           delegator: SequencingElement,
                           if_branch: SequencingElement,
                           else_branch: SequencingElement,
                           sequencer: Sequencer,
                           parameters: Dict[str, Parameter],
                           conditions: Dict[str, Condition],
                           measurement_mapping: Dict[str, str],
                           channel_mapping: Dict[ChannelID, ChannelID],
                           instruction_block: InstructionBlock) -> None:
     if_block = InstructionBlock()
     else_block = InstructionBlock()
     
     instruction_block.add_instruction_cjmp(self.__trigger, if_block)
     sequencer.push(if_branch, parameters, conditions, window_mapping=measurement_mapping,
                    channel_mapping=channel_mapping,
                    target_block=if_block)
     
     instruction_block.add_instruction_goto(else_block)
     sequencer.push(else_branch, parameters, conditions, window_mapping=measurement_mapping,
                    channel_mapping=channel_mapping,
                    target_block=else_block)
     
     if_block.return_ip = InstructionPointer(instruction_block,
                                             len(instruction_block.instructions))
     else_block.return_ip = if_block.return_ip
コード例 #9
0
ファイル: plotting.py プロジェクト: peendebak/qupulse
def iter_waveforms(
    instruction_block: AbstractInstructionBlock,
    expected_return: Optional[InstructionPointer] = None
) -> Generator[Waveform, None, None]:
    # todo [2018-08-30]: seems to be unused.. remove?
    for i, instruction in enumerate(instruction_block):
        if isinstance(instruction, EXECInstruction):
            yield instruction.waveform
        elif isinstance(instruction, REPJInstruction):
            expected_repj_return = InstructionPointer(instruction_block, i + 1)
            repj_instructions = instruction.target.block.instructions[
                instruction.target.offset:]
            for _ in range(instruction.count):
                yield from iter_waveforms(repj_instructions,
                                          expected_repj_return)
        elif isinstance(instruction, MEASInstruction):
            continue
        elif isinstance(instruction, GOTOInstruction):
            if instruction.target != expected_return:
                raise NotImplementedError(
                    "Instruction block contains an unexpected GOTO instruction."
                )
            return
        elif isinstance(instruction, STOPInstruction):
            return
        else:
            raise NotImplementedError(
                'Rendering cannot handle instructions of type {}.'.format(
                    type(instruction)))
コード例 #10
0
    def __verify_block(
        self, block: AbstractInstructionBlock,
        immutable_block: ImmutableInstructionBlock,
        context: Dict[AbstractInstructionBlock, ImmutableInstructionBlock]
    ) -> None:
        self.assertIsInstance(immutable_block, ImmutableInstructionBlock)
        self.assertEqual(len(block.instructions),
                         len(immutable_block.instructions))
        self.assertEqual(len(block), len(immutable_block))
        if block.return_ip is None:
            self.assertIsNone(immutable_block.return_ip)
        else:
            self.assertEqual(
                InstructionPointer(context[block.return_ip.block],
                                   block.return_ip.offset),
                immutable_block.return_ip)

        for instruction, immutable_instruction in zip(
                block.instructions, immutable_block.instructions):
            self.assertEqual(type(instruction), type(immutable_instruction))
            if isinstance(instruction,
                          (GOTOInstruction, CJMPInstruction, REPJInstruction)):
                target_block = instruction.target.block
                immutable_target_block = immutable_instruction.target.block
                self.assertEqual(instruction.target.offset,
                                 immutable_instruction.target.offset)
                self.assertIsInstance(immutable_target_block,
                                      ImmutableInstructionBlock)
                self.assertEqual(context[target_block], immutable_target_block)
                self.assertEqual(immutable_block,
                                 immutable_target_block.return_ip.block)
                self.__verify_block(target_block, immutable_target_block,
                                    context)
コード例 #11
0
    def build_sequence(self,
                       sequencer: Sequencer,
                       parameters: Dict[str, Parameter],
                       conditions: Dict[str, Condition],
                       measurement_mapping: Dict[str, Optional[str]],
                       channel_mapping: Dict[ChannelID, Optional[ChannelID]],
                       instruction_block: InstructionBlock) -> None:
        self.validate_parameter_constraints(parameters=parameters)
        try:
            real_parameters = {v: parameters[v].get_value() for v in self._repetition_count.variables}
        except KeyError:
            raise ParameterNotProvidedException(next(v for v in self.repetition_count.variables if v not in parameters))

        self.insert_measurement_instruction(instruction_block,
                                            parameters=parameters,
                                            measurement_mapping=measurement_mapping)

        repetition_count = self.get_repetition_count_value(real_parameters)
        if repetition_count > 0:
            body_block = InstructionBlock()
            body_block.return_ip = InstructionPointer(instruction_block, len(instruction_block))

            instruction_block.add_instruction_repj(repetition_count, body_block)
            sequencer.push(self.body, parameters=parameters, conditions=conditions,
                           window_mapping=measurement_mapping, channel_mapping=channel_mapping, target_block=body_block)
コード例 #12
0
 def test_nested_goto(self) -> None:
     parent_block = InstructionBlock()
     block = InstructionBlock()
     block.return_ip = InstructionPointer(parent_block, 1)
     parent_block.add_instruction_goto(block)
     context = dict()
     immutable_block = ImmutableInstructionBlock(parent_block, context)
     self.__verify_block(parent_block, immutable_block, context)
コード例 #13
0
 def test_initialization(self) -> None:
     block = InstructionBlock()
     trigger = Trigger()
     for offset in [0, 1, 23]:
         instr = CJMPInstruction(trigger, InstructionPointer(block, offset))
         self.assertEqual(trigger, instr.trigger)
         self.assertEqual(block, instr.target.block)
         self.assertEqual(offset, instr.target.offset)
コード例 #14
0
 def test_empty_returning_block(self) -> None:
     return_block = InstructionBlock()
     block = InstructionBlock()
     block.return_ip = InstructionPointer(return_block, 7)
     context = {
         return_block: ImmutableInstructionBlock(return_block, dict())
     }
     immutable_block = ImmutableInstructionBlock(block, context)
     self.__verify_block(block, immutable_block, context)
コード例 #15
0
 def test_equality(self) -> None:
     blocks = [InstructionBlock(), InstructionBlock()]
     for offset in [0, 1, 23]:
         instrA = GOTOInstruction(InstructionPointer(blocks[0], offset))
         instrB = GOTOInstruction(InstructionPointer(blocks[0], offset))
         self.assertEqual(instrA, instrB)
         self.assertEqual(instrB, instrA)
     instrs = []
     for block in blocks:
         for offset in [0, 17]:
             instruction = GOTOInstruction(InstructionPointer(
                 block, offset))
             self.assertEqual(instruction, instruction)
             for other in instrs:
                 self.assertNotEqual(instruction, other)
                 self.assertNotEqual(other, instruction)
                 self.assertNotEqual(hash(instruction), hash(other))
             instrs.append(instruction)
コード例 #16
0
 def test_initialization(self) -> None:
     block = InstructionBlock()
     for count in [0, 1, 47]:
         for offset in [0, 1, 23]:
             instr = REPJInstruction(count,
                                     InstructionPointer(block, offset))
             self.assertEqual(count, instr.count)
             self.assertEqual(block, instr.target.block)
             self.assertEqual(offset, instr.target.offset)
コード例 #17
0
ファイル: conditions_tests.py プロジェクト: peendebak/qupulse
    def test_build_sequence_branch(self) -> None:
        sequencer = DummySequencer()
        block = DummyInstructionBlock()

        delegator = DummySequencingElement()
        if_branch = DummySequencingElement()
        else_branch = DummySequencingElement()

        trigger = Trigger()
        condition = HardwareCondition(trigger)
        condition.build_sequence_branch(delegator,
                                        if_branch,
                                        else_branch,
                                        sequencer, {}, {}, {}, {},
                                        instruction_block=block)

        self.assertEqual(2, len(block.embedded_blocks))
        if_block = block.embedded_blocks[0]
        else_block = block.embedded_blocks[1]

        self.assertEqual(
            [
                CJMPInstruction(trigger, InstructionPointer(if_block)),
                GOTOInstruction(InstructionPointer(else_block))
            ], block.instructions,
            "The expected jump instruction were not generated by HardwareConditon."
        )
        self.assertEqual(
            InstructionPointer(block, 2), if_block.return_ip,
            "The return address of the if branch block was set wrongly by HardwareConditon."
        )
        self.assertEqual(
            InstructionPointer(block, 2), else_block.return_ip,
            "The return address of the else branch block was set wrongly by HardwareConditon."
        )
        self.assertEqual(
            {
                if_block: [(if_branch, {}, {}, {}, {})],
                else_block: [(else_branch, {}, {}, {}, {})]
            }, sequencer.sequencing_stacks,
            "HardwareCondition did not correctly push the branch elements to the stack"
        )
コード例 #18
0
 def test_nested_no_context_argument(self) -> None:
     parent_block = InstructionBlock()
     block = InstructionBlock()
     block.return_ip = InstructionPointer(parent_block, 1)
     parent_block.add_instruction_goto(block)
     immutable_block = ImmutableInstructionBlock(parent_block)
     context = {
         parent_block: immutable_block,
         block: immutable_block.instructions[0].target.block
     }
     self.__verify_block(parent_block, immutable_block, context)
コード例 #19
0
 def test_equality(self) -> None:
     blocks = [InstructionBlock(), InstructionBlock()]
     blocks.append(InstructionBlock())
     ips = []
     for block in blocks:
         for offset in [0, 1, 2352]:
             ip = InstructionPointer(block, offset)
             self.assertEqual(ip, ip)
             for other in ips:
                 self.assertNotEqual(ip, other)
                 self.assertNotEqual(other, ip)
                 self.assertNotEqual(hash(ip), hash(other))
             ips.append(ip)
コード例 #20
0
    def test_multiple_nested_block_construction(self) -> None:
        main_block = InstructionBlock()
        blocks = []
        waveforms = [DummyWaveform(), DummyWaveform(), DummyWaveform()]

        main_block.add_instruction_exec(waveforms[0])

        block = InstructionBlock()
        trigger = Trigger()
        main_block.add_instruction_cjmp(trigger, block)
        block.return_ip = InstructionPointer(main_block, len(main_block))
        blocks.append(block)

        block = InstructionBlock()
        trigger = Trigger()
        main_block.add_instruction_cjmp(trigger, block)
        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]
                block.add_instruction_exec(waveform)

        block = InstructionBlock()
        blocks[0].add_instruction_cjmp(trigger, block)
        block.return_ip = InstructionPointer(blocks[0], len(blocks[0]))
        blocks.append(block)

        for id in [1, 2, 0, 2]:
            waveform = waveforms[id]
            block.add_instruction_exec(waveform)

        context = dict()
        immutable_block = ImmutableInstructionBlock(main_block, context)
        self.__verify_block(main_block, immutable_block, context.copy())
コード例 #21
0
    def test_sliced_item_access(self) -> None:
        wf = DummyWaveform()
        parent_block = InstructionBlock()
        block = AbstractInstructionBlockStub(
            [EXECInstruction(wf), EXECInstruction(wf)],
            InstructionPointer(parent_block, 29))
        for instruction in block[:-1]:
            self.assertEqual(EXECInstruction(wf), instruction)

        expections = [
            EXECInstruction(wf),
            EXECInstruction(wf),
            GOTOInstruction(InstructionPointer(parent_block, 29))
        ]

        for expected, instruction in zip(expections, block[:4]):
            self.assertEqual(expected, instruction)

        for instruction, expected in zip(block[::-1], reversed(expections)):
            self.assertEqual(expected, instruction)

        with self.assertRaises(StopIteration):
            next(iter(block[3:]))
コード例 #22
0
    def test_add_instruction_goto(self) -> None:
        block = InstructionBlock()
        expected_instructions = []

        targets = [InstructionBlock(), InstructionBlock(), InstructionBlock()]
        LOOKUP = [0, 1, 1, 0, 2, 1, 0, 0, 0, 1, 2, 2]
        for id in LOOKUP:
            target = targets[id]
            instruction = GOTOInstruction(InstructionPointer(target))
            expected_instructions.append(instruction)
            block.add_instruction_goto(target)

        expected_compiled_instructions = expected_instructions.copy()
        expected_compiled_instructions.append(STOPInstruction())
        self.__verify_block(block, expected_instructions,
                            expected_compiled_instructions, None)
コード例 #23
0
    def test_str(self) -> None:
        IB = InstructionBlock()
        T = Trigger()
        W = DummyWaveform()

        a = [
            W, T,
            InstructionPointer(IB, 1),
            CJMPInstruction(T, IB),
            GOTOInstruction(IB),
            EXECInstruction(W), IB
        ]

        b = [x.__str__() for x in a]

        for s in b:
            self.assertIsInstance(s, str)
コード例 #24
0
    def test_add_instruction_repj(self) -> None:
        block = InstructionBlock()
        expected_instructions = []
        targets = [InstructionBlock(), InstructionBlock(), InstructionBlock()]
        counts = [3, 8, 857]
        LOOKUP = [(0, 0), (0, 1), (1, 1), (0, 2), (2, 0), (1, 0), (2, 2),
                  (2, 1), (1, 0), (1, 2)]
        for i in LOOKUP:
            block.add_instruction_repj(counts[i[0]], targets[i[1]])
            expected_instructions.append(
                REPJInstruction(counts[i[0]],
                                InstructionPointer(targets[i[1]], 0)))

        expected_compiled_instructions = expected_instructions.copy()
        expected_compiled_instructions.append(STOPInstruction())
        self.__verify_block(block, expected_instructions,
                            expected_compiled_instructions, None)
コード例 #25
0
 def build_sequence_loop(self, 
                         delegator: SequencingElement,
                         body: SequencingElement,
                         sequencer: Sequencer,
                         parameters: Dict[str, Parameter],
                         conditions: Dict[str, Condition],
                         measurement_mapping: Dict[str, str],
                         channel_mapping: Dict[ChannelID, ChannelID],
                         instruction_block: InstructionBlock) -> None:
     body_block = InstructionBlock()
     body_block.return_ip = InstructionPointer(instruction_block,
                                               len(instruction_block.instructions))
     
     instruction_block.add_instruction_cjmp(self.__trigger, body_block)
     sequencer.push(body, parameters, conditions, window_mapping=measurement_mapping,
                    channel_mapping=channel_mapping,
                    target_block=body_block)
コード例 #26
0
    def test_add_instruction_cjmp(self) -> None:
        block = InstructionBlock()
        expected_instructions = []

        targets = [InstructionBlock(), InstructionBlock(), InstructionBlock()]
        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]],
                                InstructionPointer(targets[i[0]], 0)))

        expected_compiled_instructions = expected_instructions.copy()
        expected_compiled_instructions.append(STOPInstruction())
        self.__verify_block(block, expected_instructions,
                            expected_compiled_instructions, None)
コード例 #27
0
ファイル: plotting.py プロジェクト: peendebak/qupulse
def iter_instruction_block(
        instruction_block: AbstractInstructionBlock,
        extract_measurements: bool) -> Tuple[list, list, Real]:
    """Iterates over the instructions contained in an InstructionBlock (thus simulating execution).

    In effect, this function simulates the execution of the control flow represented by the passed InstructionBlock
    and returns all waveforms in the order they would be executed on the hardware, along with all measurements that
    would be made during that execution (if the extract_measurement argument is True). The waveforms are passed back
    as Waveform objects (and are not sampled at anytime during the execution of this function).

    Args:
        instruction_block: The InstructionBlock to iterate over.
        extract_measurements: If True, a list of all measurement simulated during block iteration will be returned.

    Returns:
        A tuple (waveforms, measurements, time) where waveforms is a sequence of Waveform objects in the order they
        would be executed according to the given InstructionBlock, measurements is a similar sequence of measurements
        that would be made (where each measurement is represented by a tuple (name, start_time, duration)) and time is
        the total execution duration of the block (i.e. the accumulated duration of all waveforms).
        measurements is an empty list if extract_measurements is not True.
    """
    block_stack = [(enumerate(instruction_block), None)]
    waveforms = []
    measurements = []
    time = 0

    while block_stack:
        block, expected_return = block_stack.pop()

        for i, instruction in block:
            if isinstance(instruction, EXECInstruction):
                waveforms.append(instruction.waveform)
                time += instruction.waveform.duration
            elif isinstance(instruction, REPJInstruction):
                expected_repj_return = InstructionPointer(
                    instruction_block, i + 1)
                repj_instructions = instruction.target.block.instructions[
                    instruction.target.offset:]

                block_stack.append((block, expected_return))
                block_stack.extend(
                    (enumerate(repj_instructions), expected_repj_return)
                    for _ in range(instruction.count))
                break
            elif isinstance(instruction, MEASInstruction):
                if extract_measurements:
                    measurements.extend(
                        (name, begin + time, length)
                        for name, begin, length in instruction.measurements)
            elif isinstance(instruction, GOTOInstruction):
                if instruction.target != expected_return:
                    raise NotImplementedError(
                        "Instruction block contains an unexpected GOTO instruction."
                    )
                break
            elif isinstance(instruction, STOPInstruction):
                block_stack.clear()
                break
            else:
                raise NotImplementedError(
                    'Rendering cannot handle instructions of type {}.'.format(
                        type(instruction)))

    return waveforms, measurements, time
コード例 #28
0
 def test_initialization_relative_block(self) -> None:
     block = InstructionBlock()
     for offset in [0, 1, 924]:
         ip = InstructionPointer(block, offset)
         self.assertIs(block, ip.block)
         self.assertEqual(offset, ip.offset)
コード例 #29
0
 def test_empty_returning_block(self) -> None:
     return_block = InstructionBlock()
     block = InstructionBlock()
     ip = InstructionPointer(return_block, 7)
     block.return_ip = ip
     self.__verify_block(block, [], [GOTOInstruction(ip)], ip)
コード例 #30
0
    def test_nested_block_construction(self) -> None:
        main_block = InstructionBlock()
        expected_instructions = [[], [], [], []]
        expected_compiled_instructions = [[], [], [], []]
        expected_return_ips = [None]

        blocks = []

        waveforms = [DummyWaveform(), DummyWaveform(), DummyWaveform()]

        main_block.add_instruction_exec(waveforms[0])
        expected_instructions[0].append(EXECInstruction(waveforms[0]))

        block = InstructionBlock()
        trigger = Trigger()
        ip = InstructionPointer(block)
        main_block.add_instruction_cjmp(trigger, block)
        expected_instructions[0].append(CJMPInstruction(trigger, ip))
        block.return_ip = InstructionPointer(main_block, len(main_block))
        expected_return_ips.append(
            InstructionPointer(main_block, len(main_block)))
        blocks.append(block)

        block = InstructionBlock()
        trigger = Trigger()
        ip = InstructionPointer(block)
        main_block.add_instruction_cjmp(trigger, block)
        expected_instructions[0].append(CJMPInstruction(trigger, ip))
        block.return_ip = InstructionPointer(main_block, len(main_block))
        expected_return_ips.append(
            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 = InstructionBlock()
        ip = InstructionPointer(block)
        blocks[0].add_instruction_cjmp(trigger, block)
        expected_instructions[1].append(CJMPInstruction(trigger, ip))
        block.return_ip = InstructionPointer(blocks[0], len(blocks[0]))
        expected_return_ips.append(
            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))

        positions = [0, None, None, None]
        positions[3] = len(expected_compiled_instructions[1])

        self.__verify_block(blocks[2], expected_instructions[3],
                            expected_compiled_instructions[3],
                            expected_return_ips[3])
        self.__verify_block(blocks[1], expected_instructions[2],
                            expected_compiled_instructions[2],
                            expected_return_ips[2])
        self.__verify_block(blocks[0], expected_instructions[1],
                            expected_compiled_instructions[1],
                            expected_return_ips[1])
        self.__verify_block(main_block, expected_instructions[0],
                            expected_compiled_instructions[0],
                            expected_return_ips[0])