From e42497a8b328d681d9bb7b427210ac917adb17a1 Mon Sep 17 00:00:00 2001 From: leftibot Date: Sat, 11 Apr 2026 07:57:09 -0600 Subject: [PATCH] Fix #256: ChaiScript::get_locals() does not show functions (#640) * Fix #256: Expose get_function_objects() and get_scripting_objects() in public API The ChaiScript_Basic public API only exposed get_locals() for inspecting runtime state from C++, requiring users to work around this via chai.eval("get_functions()") to access function objects. Added get_function_objects() and get_scripting_objects() as public methods on ChaiScript_Basic, delegating to the existing Dispatch_Engine methods, matching the pattern already used by get_locals(). Co-Authored-By: Claude Opus 4.6 (1M context) * Address review: add tests for get_scripting_objects() Requested by @lefticus in PR #640 review. Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: leftibot Co-authored-by: Claude Opus 4.6 (1M context) --- .../chaiscript/language/chaiscript_engine.hpp | 6 +++ unittests/compiled_tests.cpp | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index d3b245ce..c9f22e58 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -473,6 +473,12 @@ namespace chaiscript { /// \returns All values in the local thread state, added through the add() function std::map get_locals() const { return m_engine.get_locals(); } + /// \returns All accessible function objects, as a map of name to Boxed_Value + std::map get_function_objects() const { return m_engine.get_function_objects(); } + + /// \returns All accessible scripting objects (locals + globals), as a map of name to Boxed_Value + std::map get_scripting_objects() const { return m_engine.get_scripting_objects(); } + /// \brief Sets all of the locals for the current thread state. /// /// \param[in] t_locals The map set of variables to replace the current state with diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 950a5e18..27a99585 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -412,6 +412,44 @@ TEST_CASE("Set and restore chai state") { CHECK_THROWS_AS(chai.eval("i"), chaiscript::exception::eval_error); } +TEST_CASE("Get function objects from public API") { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser()); + + // Add a custom function + chai.add(chaiscript::fun(&set_state_test_myfun), "myfun"); + + // get_function_objects should be accessible from the public API + auto funcs = chai.get_function_objects(); + + // Our custom function should be in the map + CHECK(funcs.count("myfun") == 1); + + // Built-in functions should also be present + CHECK(funcs.count("to_string") == 1); + + // The function should be callable + CHECK(chai.eval("myfun()") == 2); +} + +TEST_CASE("Get scripting objects from public API") { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser()); + + // Define some variables in script + chai.eval("var x = 42"); + chai.eval("var name = \"hello\""); + + // get_scripting_objects should be accessible from the public API + auto objects = chai.get_scripting_objects(); + + // Our scripting variables should be in the map + CHECK(objects.count("x") == 1); + CHECK(objects.count("name") == 1); + + // Verify the values are correct + CHECK(chaiscript::boxed_cast(objects["x"]) == 42); + CHECK(chaiscript::boxed_cast(objects["name"]) == "hello"); +} + //// Short comparisons class Short_Comparison_Test {