Skip to content

Commit 6f7d3f1

Browse files
committed
undo for xeus-cpp
1 parent 98585e8 commit 6f7d3f1

File tree

2 files changed

+115
-7
lines changed

2 files changed

+115
-7
lines changed

src/xinterpreter.cpp

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,17 @@ __get_cxx_version ()
133133

134134
auto input_guard = input_redirection(config.allow_stdin);
135135

136-
// Check for magics
137-
for (auto& pre : preamble_manager.preamble)
136+
if(code.find("%undo") != 0)
138137
{
139-
if (pre.second.is_match(code))
138+
// Check for magics
139+
for (auto& pre : preamble_manager.preamble)
140140
{
141-
pre.second.apply(code, kernel_res);
142-
cb(kernel_res);
143-
return;
141+
if (pre.second.is_match(code))
142+
{
143+
pre.second.apply(code, kernel_res);
144+
cb(kernel_res);
145+
return;
146+
}
144147
}
145148
}
146149

@@ -168,7 +171,42 @@ __get_cxx_version ()
168171
try
169172
{
170173
StreamRedirectRAII R(err);
171-
compilation_result = Cpp::Process(code.c_str());
174+
if (code.rfind("%undo", 0) == 0)
175+
{
176+
#ifdef EMSCRIPTEN
177+
throw std::logic_error("Undo is not supported in xeus-cpp-lite");
178+
#else
179+
int n = 1; // Default value
180+
if (code.length() > 5)
181+
{
182+
try
183+
{
184+
n = std::stoi(code.substr(6));
185+
}
186+
catch (const std::invalid_argument&)
187+
{
188+
throw std::runtime_error(
189+
"Invalid format for %undo. Expected '%undo n' where n is an integer"
190+
);
191+
}
192+
catch (const std::out_of_range&)
193+
{
194+
throw std::runtime_error("Number out of range for %undo");
195+
}
196+
}
197+
compilation_result = static_cast<bool>(Cpp::Undo(n));
198+
#endif
199+
}
200+
else
201+
{
202+
compilation_result = Cpp::Process(code.c_str());
203+
}
204+
}
205+
catch (std::logic_error& e)
206+
{
207+
errorlevel = 1;
208+
ename = "Logic Error: ";
209+
evalue = e.what();
172210
}
173211
catch (std::exception& e)
174212
{

test/test_interpreter.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,3 +1076,73 @@ TEST_SUITE("file") {
10761076
infile.close();
10771077
}
10781078
}
1079+
1080+
#if !defined(XEUS_CPP_EMSCRIPTEN_WASM_BUILD)
1081+
TEST_SUITE("undo_and_redefinition")
1082+
{
1083+
TEST_CASE("RedefinitionAndUndoErrors")
1084+
{
1085+
std::vector<const char*> Args = {/*"-v", "resource-dir", "..."*/};
1086+
xcpp::interpreter interpreter((int) Args.size(), Args.data());
1087+
std::string code = R"(
1088+
int x = 5;
1089+
)";
1090+
nl::json user_expressions = nl::json::object();
1091+
xeus::execute_request_config config;
1092+
config.silent = false;
1093+
config.store_history = false;
1094+
config.allow_stdin = false;
1095+
nl::json header = nl::json::object();
1096+
xeus::xrequest_context::guid_list id = {};
1097+
xeus::xrequest_context context(header, id);
1098+
1099+
// Execute first code: define int x = 5
1100+
std::promise<nl::json> promise1;
1101+
std::future<nl::json> future1 = promise1.get_future();
1102+
auto callback1 = [&promise1](nl::json result)
1103+
{
1104+
promise1.set_value(result);
1105+
};
1106+
interpreter
1107+
.execute_request(std::move(context), std::move(callback1), code, std::move(config), user_expressions);
1108+
nl::json execute1 = future1.get();
1109+
REQUIRE(execute1["status"] == "ok");
1110+
1111+
code = R"(%undo)";
1112+
std::promise<nl::json> promise2;
1113+
std::future<nl::json> future2 = promise2.get_future();
1114+
auto callback2 = [&promise2](nl::json result)
1115+
{
1116+
promise2.set_value(result);
1117+
};
1118+
interpreter
1119+
.execute_request(std::move(context), std::move(callback2), code, std::move(config), user_expressions);
1120+
nl::json execute2 = future2.get();
1121+
REQUIRE(execute2["status"] == "ok");
1122+
1123+
code = "int x = 10;";
1124+
std::promise<nl::json> promise3;
1125+
std::future<nl::json> future3 = promise3.get_future();
1126+
auto callback3 = [&promise3](nl::json result)
1127+
{
1128+
promise3.set_value(result);
1129+
};
1130+
interpreter
1131+
.execute_request(std::move(context), std::move(callback3), code, std::move(config), user_expressions);
1132+
nl::json execute3 = future3.get();
1133+
REQUIRE(execute3["status"] == "ok");
1134+
1135+
code = "int x = 20;";
1136+
std::promise<nl::json> promise4;
1137+
std::future<nl::json> future4 = promise4.get_future();
1138+
auto callback4 = [&promise4](nl::json result)
1139+
{
1140+
promise4.set_value(result);
1141+
};
1142+
interpreter
1143+
.execute_request(std::move(context), std::move(callback4), code, std::move(config), user_expressions);
1144+
nl::json execute4 = future4.get();
1145+
REQUIRE(execute4["status"] == "error");
1146+
}
1147+
}
1148+
#endif

0 commit comments

Comments
 (0)