Status RPIServiceImpl::executeCode()

in src/ExecuteCode.cpp [60:155]


Status RPIServiceImpl::executeCode(ServerContext* context, const ExecuteCodeRequest* request, ServerWriter<ExecuteCodeResponse>* writer) {
  executeOnMainThread([&] {
    std::string const& code = request->code();
    std::string const& sourceFileId = request->sourcefileid();
    int sourceFileLineOffset = request->sourcefilelineoffset();
    int sourceFileFirstLineOffset = request->sourcefilefirstlineoffset();
    bool withEcho = request->withecho();
    bool streamOutput = request->streamoutput() && writer != nullptr;
    bool isRepl = request->isrepl();
    bool isDebug = isRepl && request->isdebug();
    auto firstDebugCommand = request->firstdebugcommand();
    bool setLastValue = request->setlastvalue();

    ScopedAssign<bool> withIsReplOutput(isReplOutput, isRepl && !streamOutput);
    WithOutputHandler withOutputHandler(
        isReplOutput ? replOutputHandler : [&](const char* buf, int len, OutputType type) {
          if (streamOutput) {
            ExecuteCodeResponse response;
            response.mutable_output()->set_type(type == STDOUT ? CommandOutput::STDOUT : CommandOutput::STDERR);
            response.mutable_output()->set_text(buf, len);
            writer->Write(response);
          }
        });

    auto finally = Finally {[&] {
      if (isRepl) {
        AsyncEvent event;
        if (replState == DEBUG_PROMPT) {
          event.mutable_debugprompt()->set_changed(false);
        } else {
          event.mutable_prompt();
          rDebugger.clearSavedStack();
        }
        asyncEvents.push(event);
      }
    }};

    bool disableBytecode = RDebugger::isBytecodeEnabled() && isDebug;
    try {
      if (disableBytecode) RDebugger::setBytecodeEnabled(false);
      ScopedAssign<ReplState> withState(replState, isRepl ? REPL_BUSY : replState);
      if (isRepl) {
        AsyncEvent event;
        event.mutable_busy();
        asyncEvents.push(event);
        rDebugger.resetLastErrorStack();
        if (isDebug) {
          if (firstDebugCommand == ExecuteCodeRequest_DebugCommand_CONTINUE) {
            rDebugger.setCommand(CONTINUE);
          } else if (firstDebugCommand == ExecuteCodeRequest_DebugCommand_STOP) {
            rDebugger.setCommand(STEP_INTO);
          }
        }
      }
      PrSEXP expressions;
      expressions = parseCode(code, isRepl || asBool(RI->getOption("keep.source")));
      if (isRepl) {
        sourceFileManager.registerSrcfile(Rf_getAttrib(expressions, RI->srcfileAttr), sourceFileId,
                                          sourceFileLineOffset, sourceFileFirstLineOffset);
      }
      executeCodeImpl(expressions, currentEnvironment(), withEcho, isDebug, isRepl, setLastValue, isRepl);
    } catch (RError const& e) {
      if (writer != nullptr) {
        ExecuteCodeResponse response;
        response.set_exception(e.what());
        writer->Write(response);
      }
      if (isRepl) {
        AsyncEvent event;
        exceptionToProto(e.getRError(), event.mutable_exception()->mutable_exception());
        lastErrorStack = rDebugger.getLastErrorStack();
        buildStackProto(lastErrorStack, event.mutable_exception()->mutable_stack());
        rpiService->sendAsyncEvent(event);
      } else {
        std::string msg = std::string("\n") + e.what() + "\n";
        myWriteConsoleEx(msg.c_str(), msg.size(), STDERR);
      }
    } catch (RInterruptedException const& e) {
      if (isRepl) {
        AsyncEvent event;
        event.mutable_exception()->mutable_exception()->set_message(
            "Interrupted");
        event.mutable_exception()->mutable_exception()->mutable_interrupted();
        rpiService->sendAsyncEvent(event);
      }
      if (writer != nullptr) {
        ExecuteCodeResponse response;
        response.set_exception(e.what());
        writer->Write(response);
      }
    } catch (RJumpToToplevelException const&) {
    }
    if (disableBytecode) RDebugger::setBytecodeEnabled(true);
  }, context);
  return Status::OK;
}