'When we\'ve found array expressions in a basic block, rewrite that
block, returning a new, transformed block.'

def apply(self):

    (replace_map, dead_vars, used_vars) = self._handle_matches()
    result = self.crnt_block.copy()
    result.clear()
    delete_map = {}
    for instr in self.crnt_block.body:
        if isinstance(instr, ir.Assign):
            if (instr in replace_map):
                replacement = self._get_final_replacement(replace_map, instr)
                if replacement:
                    result.append(replacement)
                    for var in replacement.value.list_vars():
                        var_name = var.name
                        if (var_name in delete_map):
                            result.append(delete_map.pop(var_name))
                        if (used_vars[var_name] > 0):
                            used_vars[var_name] -= 1
            else:
                result.append(instr)
        elif isinstance(instr, ir.Del):
            instr_value = instr.value
            if (used_vars[instr_value] > 0):
                used_vars[instr_value] -= 1
                delete_map[instr_value] = instr
            elif (instr_value not in dead_vars):
                result.append(instr)
        else:
            result.append(instr)
    if delete_map:
        for instr in delete_map.values():
            result.insert_before_terminator(instr)
    return result
