[education/rkward] rkward: Adjust to the removal of Rf_addTaskCallback() in R (devel) 4.5
Thomas Friedrichsmeier
null at kde.org
Mon Jul 29 21:39:58 BST 2024
Git commit 11a555b04f8e9ac4986015c1389c089d922b6f9a by Thomas Friedrichsmeier.
Committed on 29/07/2024 at 13:01.
Pushed by tfry into branch 'master'.
Adjust to the removal of Rf_addTaskCallback() in R (devel) 4.5
M +28 -0 rkward/autotests/core_test.cpp
M +0 -1 rkward/rbackend/rkrapi.h
M +7 -40 rkward/rbackend/rkrbackend.cpp
https://invent.kde.org/education/rkward/-/commit/11a555b04f8e9ac4986015c1389c089d922b6f9a
diff --git a/rkward/autotests/core_test.cpp b/rkward/autotests/core_test.cpp
index 5fc995b67..d836daade 100644
--- a/rkward/autotests/core_test.cpp
+++ b/rkward/autotests/core_test.cpp
@@ -306,6 +306,34 @@ private Q_SLOTS:
cleanGlobalenv();
}
+ void userCommandTest() {
+ // Two commands submitted on one user line should both be run
+ runCommandWithTimeout(new RCommand("print('first'); print('second')", RCommand::User), nullptr, [](RCommand *command) {
+ QVERIFY(!command->failed());
+ QVERIFY(command->fullOutput().contains("first"));
+ QVERIFY(command->fullOutput().contains("second"));
+ });
+ // Also, of course for commands on separate lines:
+ runCommandWithTimeout(new RCommand("print('first')\nprint('second')", RCommand::User), nullptr, [](RCommand *command) {
+ QVERIFY(!command->failed());
+ QVERIFY(command->fullOutput().contains("first"));
+ QVERIFY(command->fullOutput().contains("second"));
+ });
+ // or multi-line commands:
+ runCommandWithTimeout(new RCommand("{ print('first')\nprint('second') }", RCommand::User), nullptr, [](RCommand *command) {
+ QVERIFY(!command->failed());
+ QVERIFY(command->fullOutput().contains("first"));
+ QVERIFY(command->fullOutput().contains("second"));
+ });
+ // However, if a partial command fails, the next part should not get parsed:
+ runCommandWithTimeout(new RCommand("stop('first'); print('second')", RCommand::User), nullptr, [](RCommand *command) {
+ QVERIFY(command->failed());
+ QVERIFY(command->fullOutput().contains("first"));
+ QVERIFY(!command->fullOutput().contains("second"));
+ });
+ // TODO: verify that calls to readline() and browser() are handled, correctly
+ }
+
void commandOrderAndOutputTest() {
// commands shall run in the order 1, 3, 2, 5, 4, but also, of course, all different types of output shall be captured
QStringList output;
diff --git a/rkward/rbackend/rkrapi.h b/rkward/rbackend/rkrapi.h
index cb68aa4ad..643ac8983 100644
--- a/rkward/rbackend/rkrapi.h
+++ b/rkward/rbackend/rkrapi.h
@@ -228,7 +228,6 @@ IMPORT_R_API(Rf_GetOption);
IMPORT_R_API(Rf_GetOption1);
IMPORT_R_API(Rf_KillAllDevices);
IMPORT_R_API(Rf_ScalarInteger);
-IMPORT_R_API(Rf_addTaskCallback);
IMPORT_R_API(Rf_allocList);
IMPORT_R_API(Rf_allocVector);
IMPORT_R_API(Rf_asChar);
diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index 94d9288b6..6e94a1925 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -133,38 +133,6 @@ void RKRBackend::clearPendingInterrupt () {
extern SEXP RKWard_RData_Tag;
// ############## R Standard callback overrides BEGIN ####################
-Rboolean RKToplevelStatementFinishedCallback (SEXP expr, SEXP value, Rboolean succeeded, Rboolean visible, void *) {
- RK_TRACE (RBACKEND);
- Q_UNUSED (expr);
- Q_UNUSED (value);
- Q_UNUSED (visible);
-
- if ((RKRBackend::repl_status.eval_depth == 0) && (!RKRBackend::repl_status.browser_context)) { // Yes, toplevel-handlers _do_ get called in a browser context!
- RK_ASSERT (RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandRunning);
- if (succeeded) {
- RKRBackend::repl_status.user_command_successful_up_to = RKRBackend::repl_status.user_command_parsed_up_to;
- if (RKRBackend::repl_status.user_command_completely_transmitted) {
- RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::NoUserCommand;
- RKRBackend::this_pointer->commandFinished ();
- } else RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandTransmitted;
- } else {
- // well, this point of code is never reached with R up to 2.12.0. Instead failed user commands are handled in doError().
- RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandFailed;
- }
- }
-
- return (Rboolean) true;
-}
-
-void RKInsertToplevelStatementFinishedCallback (void *) {
- RK_TRACE (RBACKEND);
-
- if (RKRBackend::this_pointer->r_running) {
- int pos;
- RFn::Rf_addTaskCallback(&RKToplevelStatementFinishedCallback, nullptr, &RKInsertToplevelStatementFinishedCallback, "_rkward_main_callback", &pos);
- }
-}
-
void RKTransmitNextUserCommandChunk (unsigned char* buf, int buflen) {
RK_TRACE (RBACKEND);
@@ -284,7 +252,7 @@ int RReadConsole (const char* prompt, unsigned char* buf, int buflen, int hist)
// This can mean three different things:
// 1) User called readline ()
// 2) User called browser ()
- // 3) R jumped us back to toplevel behind our backs.
+ // 3) The user command has finished (successfully or not)
// Let's find out, which one it is.
if (hist && (RKRBackend::default_global_context != ROb(R_GlobalContext))) {
break; // this looks like a call to browser(). Will be handled below.
@@ -296,13 +264,13 @@ int RReadConsole (const char* prompt, unsigned char* buf, int buflen, int hist)
n_frames = dummy->intVector ().at (0);
}
// What the ??? Why does this simple version always return 0?
- //int n_frames = RKRSupport::SEXPToInt (RKRSupport::callSimpleFun0 (RFn::Rf_install ("sys.nframe"), ROb(R_GlobalEnv)));
+ //int n_frames = RKRSupport::SEXPToInt (RKRSupport::callSimpleFun0 (RFn::Rf_install ("sys.nframe"), ROb(R_GlobalEnv);
if (n_frames < 1) {
- // No active frames? This can't be a call to readline(), then, so probably R jumped us back to toplevel, behind our backs.
- // For safety, let's reset and start over.
- RKRBackend::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
- RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::ReplIterationKilled;
- RFn::Rf_error(""); // to discard the buffer
+ // No active frames? This can't be a call to readline(), so the previous command must have finished.
+ if (RKRBackend::repl_status.user_command_completely_transmitted) {
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::NoUserCommand;
+ RKRBackend::this_pointer->commandFinished ();
+ } else RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandTransmitted;
} else {
// A call to readline(). Will be handled below
break;
@@ -1108,7 +1076,6 @@ bool RKRBackend::startR () {
RFn::R_registerRoutines(RFn::R_getEmbeddingDllInfo(), nullptr, callMethods, nullptr, nullptr);
connectCallbacks();
- RKInsertToplevelStatementFinishedCallback(nullptr);
RKREventLoop::setRKEventHandler(doPendingPriorityCommands);
default_global_context = ROb(R_GlobalContext);
#ifdef Q_OS_WIN
More information about the rkward-tracker
mailing list