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;
}