This is the logic to run it all.
        Heavily influenced by this post: http://nickdesaulniers.github.io/blog/2015/05/25/interpreter-compiler-jit/
        :return:

def _run(self):
        """
        This is the logic to run it all.
        Heavily influenced by this post: http://nickdesaulniers.github.io/blog/2015/05/25/interpreter-compiler-jit/
        :return:
        """
        i = 0
        try:
            while i < len(self.program):
                if self.program[i] == ">":
                    self._increment_pointer()
                elif self.program[i] == "<":
                    self._decrement_pointer()
                elif self.program[i] == "+":
                    self._increment_current_byte()
                elif self.program[i] == "-":
                    self._decrement_current_byte()
                elif self.program[i] == ".":
                    self._output_current_byte()
                elif self.program[i] == ",":
                    self._read_byte()
                elif self.program[i] == "[":
                    """
                    if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to
                    the next command, jump it forward to the command after the matching ] command
                    - Wikipedia
                    """
                    if self.tape[self.pointer] is None or self.tape[self.pointer] == 0:
                        loop = 1
                        while loop > 0:
                            i += 1
                            current_instruction = self.program[i]
                            if current_instruction == "]":
                                loop -= 1
                            elif current_instruction == "[":
                                loop += 1
                elif self.program[i] == "]":
                    """
                    if the byte at the data pointer is nonzero, then instead of moving the instruction pointer
                    forward to the next command, jump it back to the command after the matching [ command.
                    - Wikipedia
                    """
                    if self.tape[self.pointer] is not None and self.tape[self.pointer] > 0:
                        loop = 1
                        while loop > 0:
                            i -= 1
                            current_instruction = self.program[i]
                            if current_instruction == "[":
                                loop -= 1
                            elif current_instruction == "]":
                                loop += 1
                i += 1
        except PointerOutOfProgramRange as e:
            print e.message
            sys.exit(1)
        except IndexError as e:
            print "The program went out of bounds of its instructions"
            sys.exit(1)