diff --git a/cheatsheet.md b/cheatsheet.md index b8be1a9..fc229ac 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -258,4 +258,15 @@ print(get_value(m)); // prints "Value Is: a" +# Built In Functions + +## Evaluation + +``` +eval("4 + 5") // dynamically eval script string and returns value of last statement +eval_file("filename") // evals file and returns value of last statement +use("filename") // evals file exactly once and returns value of last statement + // if the file had already been 'used' nothing happens and undefined is returned +``` + diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index b4e5269..9ee75d6 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -297,6 +297,15 @@ namespace chaiscript } } + /// Evaluates the given string, used during eval() inside of a script + const Boxed_Value internal_eval_file(const std::string &t_filename) { + try { + return do_eval(load_file(t_filename), t_filename, true); + } catch (const exception::eval_error &t_ee) { + throw Boxed_Value(t_ee); + } + } + /// Evaluates the given string, used during eval() inside of a script @@ -369,6 +378,7 @@ namespace chaiscript m_engine.add(fun(static_cast(&ChaiScript::load_module), this), "load_module"); m_engine.add(fun(&ChaiScript::use, this), "use"); + m_engine.add(fun(&ChaiScript::internal_eval_file, this), "eval_file"); m_engine.add(fun(&ChaiScript::internal_eval, this), "eval"); m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval"); @@ -457,7 +467,7 @@ namespace chaiscript union cast_union { - void (ChaiScript::*in_ptr)(const std::string&); + Boxed_Value (ChaiScript::*in_ptr)(const std::string&); void *out_ptr; }; @@ -531,7 +541,7 @@ namespace chaiscript /// requested file. /// /// \param[in] t_filename Filename to load and evaluate - void use(const std::string &t_filename) + Boxed_Value use(const std::string &t_filename) { for (const auto &path : m_usepaths) { @@ -541,15 +551,17 @@ namespace chaiscript chaiscript::detail::threading::unique_lock l(m_use_mutex); chaiscript::detail::threading::unique_lock l2(m_mutex); + Boxed_Value retval; + if (m_used_files.count(appendedpath) == 0) { l2.unlock(); - eval_file(appendedpath); + retval = eval_file(appendedpath); l2.lock(); m_used_files.insert(appendedpath); - } + } - return; // return, we loaded it, or it was already loaded + return retval; // return, we loaded it, or it was already loaded } catch (const exception::file_not_found_error &) { // failed to load, try the next path } diff --git a/unittests/eval.chai b/unittests/eval.chai index 2f18aa4..4db72da 100644 --- a/unittests/eval.chai +++ b/unittests/eval.chai @@ -1 +1,3 @@ assert_equal(7, eval("3 + 4")) + + diff --git a/unittests/eval_file.chai b/unittests/eval_file.chai new file mode 100644 index 0000000..be9934e --- /dev/null +++ b/unittests/eval_file.chai @@ -0,0 +1,10 @@ + +try { + eval_file("use.inc") + assert(true) + + //we expect this second eval_file to fail because of a function redefinition + eval_file("use.inc") + assert(false) +} catch (e) { +} diff --git a/unittests/use.chai b/unittests/use.chai index efd587d..317cced 100644 --- a/unittests/use.chai +++ b/unittests/use.chai @@ -1,4 +1,5 @@ -use("use.inc") +var newfun = use("use.inc"); + assert_equal("hello", greet()) @@ -7,3 +8,4 @@ use("use.inc") assert_equal("hello", greet()) +assert_equal("world", newfun()) diff --git a/unittests/use.inc b/unittests/use.inc index 2897093..0f9fea7 100644 --- a/unittests/use.inc +++ b/unittests/use.inc @@ -2,3 +2,4 @@ def greet { return("hello") } +fun(){ "world" }