public boolean run() {
    String line;
    String[] instr;

    while (ip >= 0) {

      line = in.getLine(ip++);
      if (line == null) {
        ip = -1;
        return false;
      }

      instr = line.split(" ");

      // -----------------------------------------------------
      // Blank lines, labels, comments
      // -----------------------------------------------------
      if (instr.length == 0 || "".equals(instr[0])) {
        continue;
      } else if (instr[0].startsWith(":")) {
        continue;
      } else if (instr[0].startsWith(";")) {
        continue;
      }
      String opcode = instr[0];

      // -----------------------------------------------------
      // Stop instructions (2 forms)
      // -----------------------------------------------------
      if ("stop".equals(opcode)) {
        if (instr.length == 1) {
          STOP(); // stop this process
          return false;
        } else if (instr.length > 1) {
          STOP(instr[1]); // stop a named process
        }
      }

      // -----------------------------------------------------
      // Ugly instruction mapping
      // -----------------------------------------------------
      else if ("nop".equals(opcode)) {;
      } else if ("function".equals(opcode)) {;
      } else if ("process".equals(opcode)) {
        in.notifyProcessStarted(this);
      } else if ("push".equals(opcode)) {
        PUSH(instr[1]);
      } else if ("trace".equals(opcode)) {
        TRACE(instr[1]);
      } else if ("remote".equals(opcode)) {
        REMOTE(instr[1]);
      } else if ("start".equals(opcode)) {
        START(instr[1]);
      } else if ("load-address".equals(opcode)) {
        LOAD_ADDRESS(instr[1]);
      } else if ("exit".equals(opcode)) {
        EXIT();
        return false;
      } else if ("yield".equals(opcode)) {
        YIELD();
        return true;
      } else if ("print".equals(opcode)) {
        PRINT();
      } else if ("frame".equals(opcode)) {
        FRAME();
      } else if ("goto".equals(opcode)) {
        GOTO();
      } else if ("call".equals(opcode)) {
        CALL();
      } else if ("return".equals(opcode)) {
        RETURN();
      } else if ("pop".equals(opcode)) {
        POP();
      } else if ("dup".equals(opcode)) {
        DUP();
      } else if ("load-global".equals(opcode)) {
        LOAD_GLOBAL();
      } else if ("store-global".equals(opcode)) {
        STORE_GLOBAL();
      } else if ("load-frame".equals(opcode)) {
        LOAD_FRAME();
      } else if ("store-frame".equals(opcode)) {
        STORE_FRAME();
      } else if ("and".equals(opcode)) {
        AND();
      } else if ("or".equals(opcode)) {
        OR();
      } else if ("not".equals(opcode)) {
        NOT();
      } else if ("=".equals(opcode)) {
        EQ();
      } else if (">".equals(opcode)) {
        GT();
      } else if ("<".equals(opcode)) {
        LT();
      } else if (">=".equals(opcode)) {
        GTE();
      } else if ("<=".equals(opcode)) {
        LTE();
      } else if ("!=".equals(opcode)) {
        NE();
      } else if ("+".equals(opcode)) {
        ADD();
      } else if ("-".equals(opcode)) {
        SUB();
      } else if ("*".equals(opcode)) {
        MULT();
      } else if ("/".equals(opcode)) {
        DIV();
      } else if ("rand".equals(opcode)) {
        RAND();
      } else if ("if-true".equals(opcode)) {
        IF_TRUE();
      } else if ("if-false".equals(opcode)) {
        IF_FALSE();
      } else if ("if-timer".equals(opcode)) {
        IF_TIMER();
      } else if ("timer".equals(opcode)) {
        TIMER();
      } else {
        ERROR("Unknown opcode " + opcode);
        return false;
      }
    }
    return false;
  }