示例#1
0
  /**
   * The read-eval-print loop, which can take input from a console, command line expression or a
   * file. There are two ways the repl can terminate:
   *
   * <ol>
   *   <li>A {@code quit} command is executed successfully, which case the system exits from the
   *       {@link Quit} {@code .Internal} .
   *   <li>EOF on the input.
   * </ol>
   *
   * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before exiting.
   * So,in either case, we never return.
   */
  static int readEvalPrint(PolyglotEngine vm) {
    int lastStatus = 0;
    ContextInfo contextInfo = ContextInfo.getContextInfo(vm);
    ConsoleHandler consoleHandler = contextInfo.getConsoleHandler();
    try {
      // console.println("initialize time: " + (System.currentTimeMillis() - start));
      REPL:
      for (; ; ) {
        boolean doEcho = doEcho(vm);
        consoleHandler.setPrompt(doEcho ? "> " : null);
        try {
          String input = consoleHandler.readLine();
          if (input == null) {
            throw new EOFException();
          }
          String trInput = input.trim();
          if (trInput.equals("") || trInput.charAt(0) == '#') {
            // nothing to parse
            continue;
          }

          String continuePrompt = getContinuePrompt();
          StringBuffer sb = new StringBuffer(input);
          Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
          while (true) {
            lastStatus = 0;
            try {
              try {
                vm.eval(source);
                // checked exceptions are wrapped in RuntimeExceptions
              } catch (RuntimeException e) {
                if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) {
                  throw e.getCause().getCause();
                }
                throw e;
              }
            } catch (IncompleteSourceException e) {
              // read another line of input
              consoleHandler.setPrompt(doEcho ? continuePrompt : null);
              String additionalInput = consoleHandler.readLine();
              if (additionalInput == null) {
                throw new EOFException();
              }
              sb.append(additionalInput);
              source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
              // The only continuation in the while loop
              continue;
            } catch (ParseException e) {
              e.report(consoleHandler);
              lastStatus = 1;
            } catch (RError e) {
              // drop through to continue REPL and remember last eval was an error
              lastStatus = 1;
            } catch (JumpToTopLevelException e) {
              // drop through to continue REPL
            } catch (DebugExitException e) {
              throw (RuntimeException) e.getCause();
            } catch (ExitException e) {
              // usually from quit
              int status = e.getStatus();
              if (contextInfo.getParent() == null) {
                vm.dispose();
                Utils.systemExit(status);
              } else {
                return status;
              }
            } catch (Throwable e) {
              RInternalError.reportErrorAndConsoleLog(e, consoleHandler, 0);
              // We continue the repl even though the system may be broken
              lastStatus = 1;
            }
            continue REPL;
          }
        } catch (UserInterruptException e) {
          // interrupted by ctrl-c
        }
      }
    } catch (JumpToTopLevelException | EOFException ex) {
      // JumpToTopLevelException can happen if user profile invokes browser (unlikely but
      // possible)
      try {
        vm.eval(QUIT_EOF);
      } catch (JumpToTopLevelException e) {
        Utils.systemExit(0);
      } catch (ExitException e) {
        // normal quit, but with exit code based on lastStatus
        if (contextInfo.getParent() == null) {
          Utils.systemExit(lastStatus);
        } else {
          return lastStatus;
        }
      } catch (Throwable e) {
        throw RInternalError.shouldNotReachHere(e);
      }
    } finally {
      vm.dispose();
    }
    return 0;
  }