Add the ability to save and restore the state of local variables #25

This commit is contained in:
Jason Turner 2012-07-16 21:27:42 -06:00
parent f5b7be3743
commit 1155720b14
5 changed files with 117 additions and 4 deletions

View File

@ -196,6 +196,10 @@ if(BUILD_TESTING)
target_link_libraries(expected_eval_errors_test ${LIBS}) target_link_libraries(expected_eval_errors_test ${LIBS})
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test) add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
add_executable(set_state_test unittests/set_state_test.cpp)
target_link_libraries(set_state_test ${LIBS})
add_test(NAME Set_State_Test COMMAND set_state_test)
if (MULTITHREAD_SUPPORT_ENABLED) if (MULTITHREAD_SUPPORT_ENABLED)
add_executable(multithreaded_test unittests/multithreaded_test.cpp) add_executable(multithreaded_test unittests/multithreaded_test.cpp)
target_link_libraries(multithreaded_test ${LIBS}) target_link_libraries(multithreaded_test ${LIBS})

View File

@ -140,7 +140,10 @@
/// ///
/// \subsubsection addingobjects Adding Objects /// \subsubsection addingobjects Adding Objects
/// ///
/// Named objects can be created with the chaiscript::var function. /// Named objects can be created with the chaiscript::var function. Note: adding a object
/// adds it to the current thread scope, not to a global scope. If you have multiple
/// threads that need to access the same variables you will need to add them
/// separately for each thread, from the thread itself.
/// ///
/// \code /// \code
/// using namespace chaiscript; /// using namespace chaiscript;

View File

@ -666,6 +666,27 @@ namespace chaiscript
return functions.find(name) != functions.end(); return functions.find(name) != functions.end();
} }
/// \returns All values in the local thread state, added through the add() function
std::map<std::string, Boxed_Value> get_locals() const
{
StackData &stack = get_stack_data();
Scope &scope = stack.front();
return scope;
}
/// \brief Sets all of the locals for the current thread state.
///
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
///
/// Any existing locals are removed and the given set of variables is added
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
{
StackData &stack = get_stack_data();
Scope &scope = stack.front();
scope = t_locals;
}
/// ///
/// Get a map of all objects that can be seen from the current scope in a scripting context /// Get a map of all objects that can be seen from the current scope in a scripting context

View File

@ -456,8 +456,12 @@ namespace chaiscript
std::set<std::string> active_loaded_modules; std::set<std::string> active_loaded_modules;
}; };
/// \brief Returns a state object that represents the current state of the system /// \brief Returns a state object that represents the current state of the global system
/// \return Current state of the system ///
/// The global system includes the reserved words, global const objects, functions and types.
/// local variables are thread specific and not included.
///
/// \return Current state of the global system
/// ///
/// \b Example: /// \b Example:
/// ///
@ -478,6 +482,10 @@ namespace chaiscript
} }
/// \brief Sets the state of the system /// \brief Sets the state of the system
///
/// The global system includes the reserved words, global objects, functions and types.
/// local variables are thread specific and not included.
///
/// \param[in] t_state New state to set /// \param[in] t_state New state to set
/// ///
/// \b Example: /// \b Example:
@ -497,7 +505,23 @@ namespace chaiscript
m_engine.set_state(t_state.engine_state); m_engine.set_state(t_state.engine_state);
} }
/// \brief Adds a type, function or object to ChaiScript /// \returns All values in the local thread state, added through the add() function
std::map<std::string, Boxed_Value> get_locals() const
{
return m_engine.get_locals();
}
/// \brief Sets all of the locals for the current thread state.
///
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
///
/// Any existing locals are removed and the given set of variables is added
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
{
m_engine.set_locals(t_locals);
}
/// \brief Adds a type, function or object to ChaiScript. Objects are added to the local thread state.
/// \param[in] t_t Item to add /// \param[in] t_t Item to add
/// \param[in] t_name Name of item to add /// \param[in] t_name Name of item to add
/// \returns Reference to current ChaiScript object /// \returns Reference to current ChaiScript object

View File

@ -0,0 +1,61 @@
#include <chaiscript/chaiscript.hpp>
int myfun()
{
return 2;
}
int main()
{
chaiscript::ChaiScript chai;
// save the initial state of globals and locals
chaiscript::ChaiScript::State firststate = chai.get_state();
std::map<std::string, chaiscript::Boxed_Value> locals = chai.get_locals();
// add some new globals and locals
chai.add(chaiscript::var(1), "i");
chai.add(chaiscript::fun(&myfun), "myfun");
bool didcall = chai.eval<int>("myfun()") == 2;
bool hadi = chai.eval<int>("i") == 1;
chai.set_state(firststate);
// set state should have reverted the state of the functions and dropped
// the 'myfun'
bool didnotcall = false;
try {
chai.eval<int>("myfun()");
} catch (const chaiscript::exception::eval_error &) {
didnotcall = true;
}
// set state should not affect the local variables
bool stillhasid = chai.eval<int>("i") == 1;
// After resetting the locals we expect the 'i' to be gone
chai.set_locals(locals);
bool nolongerhasid = false;
try {
chai.eval<int>("i");
} catch (const chaiscript::exception::eval_error &) {
nolongerhasid = true;
}
if (didcall && hadi && didnotcall && stillhasid && nolongerhasid)
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}