From 6f7d3f1aef09f9d7d6e2292775974276abbc5880 Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Fri, 23 May 2025 18:32:39 +0530 Subject: [PATCH 1/2] undo for xeus-cpp --- src/xinterpreter.cpp | 52 +++++++++++++++++++++++++---- test/test_interpreter.cpp | 70 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 7 deletions(-) diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 14972324..e098a9c0 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -133,14 +133,17 @@ __get_cxx_version () auto input_guard = input_redirection(config.allow_stdin); - // Check for magics - for (auto& pre : preamble_manager.preamble) + if(code.find("%undo") != 0) { - if (pre.second.is_match(code)) + // Check for magics + for (auto& pre : preamble_manager.preamble) { - pre.second.apply(code, kernel_res); - cb(kernel_res); - return; + if (pre.second.is_match(code)) + { + pre.second.apply(code, kernel_res); + cb(kernel_res); + return; + } } } @@ -168,7 +171,42 @@ __get_cxx_version () try { StreamRedirectRAII R(err); - compilation_result = Cpp::Process(code.c_str()); + if (code.rfind("%undo", 0) == 0) + { +#ifdef EMSCRIPTEN + throw std::logic_error("Undo is not supported in xeus-cpp-lite"); +#else + int n = 1; // Default value + if (code.length() > 5) + { + try + { + n = std::stoi(code.substr(6)); + } + catch (const std::invalid_argument&) + { + throw std::runtime_error( + "Invalid format for %undo. Expected '%undo n' where n is an integer" + ); + } + catch (const std::out_of_range&) + { + throw std::runtime_error("Number out of range for %undo"); + } + } + compilation_result = static_cast(Cpp::Undo(n)); +#endif + } + else + { + compilation_result = Cpp::Process(code.c_str()); + } + } + catch (std::logic_error& e) + { + errorlevel = 1; + ename = "Logic Error: "; + evalue = e.what(); } catch (std::exception& e) { diff --git a/test/test_interpreter.cpp b/test/test_interpreter.cpp index 61d5f5d7..a8b31ea9 100644 --- a/test/test_interpreter.cpp +++ b/test/test_interpreter.cpp @@ -1076,3 +1076,73 @@ TEST_SUITE("file") { infile.close(); } } + +#if !defined(XEUS_CPP_EMSCRIPTEN_WASM_BUILD) +TEST_SUITE("undo_and_redefinition") +{ + TEST_CASE("RedefinitionAndUndoErrors") + { + std::vector Args = {/*"-v", "resource-dir", "..."*/}; + xcpp::interpreter interpreter((int) Args.size(), Args.data()); + std::string code = R"( + int x = 5; + )"; + nl::json user_expressions = nl::json::object(); + xeus::execute_request_config config; + config.silent = false; + config.store_history = false; + config.allow_stdin = false; + nl::json header = nl::json::object(); + xeus::xrequest_context::guid_list id = {}; + xeus::xrequest_context context(header, id); + + // Execute first code: define int x = 5 + std::promise promise1; + std::future future1 = promise1.get_future(); + auto callback1 = [&promise1](nl::json result) + { + promise1.set_value(result); + }; + interpreter + .execute_request(std::move(context), std::move(callback1), code, std::move(config), user_expressions); + nl::json execute1 = future1.get(); + REQUIRE(execute1["status"] == "ok"); + + code = R"(%undo)"; + std::promise promise2; + std::future future2 = promise2.get_future(); + auto callback2 = [&promise2](nl::json result) + { + promise2.set_value(result); + }; + interpreter + .execute_request(std::move(context), std::move(callback2), code, std::move(config), user_expressions); + nl::json execute2 = future2.get(); + REQUIRE(execute2["status"] == "ok"); + + code = "int x = 10;"; + std::promise promise3; + std::future future3 = promise3.get_future(); + auto callback3 = [&promise3](nl::json result) + { + promise3.set_value(result); + }; + interpreter + .execute_request(std::move(context), std::move(callback3), code, std::move(config), user_expressions); + nl::json execute3 = future3.get(); + REQUIRE(execute3["status"] == "ok"); + + code = "int x = 20;"; + std::promise promise4; + std::future future4 = promise4.get_future(); + auto callback4 = [&promise4](nl::json result) + { + promise4.set_value(result); + }; + interpreter + .execute_request(std::move(context), std::move(callback4), code, std::move(config), user_expressions); + nl::json execute4 = future4.get(); + REQUIRE(execute4["status"] == "error"); + } +} +#endif \ No newline at end of file From 709d86d68db29a471ae87d83ad73bf89ab9098af Mon Sep 17 00:00:00 2001 From: kr-2003 Date: Fri, 23 May 2025 19:18:13 +0530 Subject: [PATCH 2/2] formatting and ems-ubuntu test --- src/xinterpreter.cpp | 2 +- test/test_interpreter.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index e098a9c0..11eb26e8 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -133,7 +133,7 @@ __get_cxx_version () auto input_guard = input_redirection(config.allow_stdin); - if(code.find("%undo") != 0) + if (code.find("%undo") != 0) { // Check for magics for (auto& pre : preamble_manager.preamble) diff --git a/test/test_interpreter.cpp b/test/test_interpreter.cpp index a8b31ea9..01386692 100644 --- a/test/test_interpreter.cpp +++ b/test/test_interpreter.cpp @@ -1077,10 +1077,16 @@ TEST_SUITE("file") { } } -#if !defined(XEUS_CPP_EMSCRIPTEN_WASM_BUILD) + TEST_SUITE("undo_and_redefinition") { +#if defined(XEUS_CPP_EMSCRIPTEN_WASM_BUILD) + TEST_CASE("RedefinitionAndUndoErrors" + * doctest::should_fail(true) + * doctest::description("TODO: Currently fails for the Emscripten build")) +#else TEST_CASE("RedefinitionAndUndoErrors") +#endif { std::vector Args = {/*"-v", "resource-dir", "..."*/}; xcpp::interpreter interpreter((int) Args.size(), Args.data()); @@ -1145,4 +1151,3 @@ TEST_SUITE("undo_and_redefinition") REQUIRE(execute4["status"] == "error"); } } -#endif \ No newline at end of file