From 82bd46bb1a6a1cf955c12957c0b3960c93084efc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 18 Jul 2009 23:34:08 +0000 Subject: [PATCH] More usage cleansups --- include/chaiscript/dispatchkit/bootstrap.hpp | 16 ++-- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 16 ++-- include/chaiscript/dispatchkit/type_info.hpp | 4 +- .../chaiscript/language/chaiscript_engine.hpp | 95 ++++++++++++------- src/example.cpp | 37 ++++++-- src/main.cpp | 6 +- 6 files changed, 113 insertions(+), 61 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index b4a59b8..d08910d 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -489,7 +489,7 @@ namespace chaiscript template void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name) { - s.add(type_(), name); + s.add(user_type(), name); add_basic_constructors(s, name); add_oper_assign(s); add_oper_assign_pod(s); @@ -590,10 +590,10 @@ namespace chaiscript /** * return true if the Boxed_Value matches the registered type by name */ - static bool is_type(const Dispatch_Engine &e, const std::string &type_name, Boxed_Value r) + static bool is_type(const Dispatch_Engine &e, const std::string &user_typename, Boxed_Value r) { try { - return e.get_type(type_name) == r.get_type_info(); + return e.get_type(user_typename) == r.get_type_info(); } catch (const std::range_error &) { return false; } @@ -638,11 +638,11 @@ namespace chaiscript */ static void bootstrap(Dispatch_Engine &s) { - s.add(type_(), "void"); - s.add(type_(), "bool"); - s.add(type_(), "Object"); - s.add(type_(), "PODObject"); - s.add(type_(), "function"); + s.add(user_type(), "void"); + s.add(user_type(), "bool"); + s.add(user_type(), "Object"); + s.add(user_type(), "PODObject"); + s.add(user_type(), "function"); add_basic_constructors(s, "bool"); add_oper_assign(s); diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 4a3f0ce..3a2b78f 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -22,7 +22,7 @@ namespace chaiscript /** * Input_Range, based on the D concept of ranges. * \todo Update the Range code to base its capabilities on - * the type_traits of the iterator passed in + * the user_typetraits of the iterator passed in */ template struct Input_Range @@ -76,8 +76,8 @@ namespace chaiscript template void bootstrap_input_range(Dispatch_Engine &system, const std::string &type) { - system.add(type_ >(), type + "_Range"); - system.add(type_(), type+"_Iterator"); + system.add(user_type >(), type + "_Range"); + system.add(user_type(), type+"_Iterator"); system.add(constructor (ContainerType &)>(), "range"); system.add(constructor (typename ContainerType::iterator)>(), "range"); @@ -86,7 +86,7 @@ namespace chaiscript system.add(constructor (const ItrPair &)>(), "range"); - system.add(type_(), type+"_Iterator_Pair"); + system.add(user_type(), type+"_Iterator_Pair"); system.add(fun(&Input_Range::empty), "empty"); system.add(fun(&Input_Range::pop_front), "pop_front"); @@ -259,7 +259,7 @@ namespace chaiscript template void bootstrap_vector(Dispatch_Engine &system, const std::string &type) { - system.add(type_(), type); + system.add(user_type(), type); bootstrap_random_access_container(system, type); bootstrap_back_insertion_sequence(system, type); } @@ -282,7 +282,7 @@ namespace chaiscript template void bootstrap_pair(Dispatch_Engine &system, const std::string &type) { - system.add(type_(), type); + system.add(user_type(), type); system.add(fun(&PairType::first), "first"); system.add(fun(&PairType::second), "second"); @@ -349,7 +349,7 @@ namespace chaiscript template void bootstrap_map(Dispatch_Engine &system, const std::string &type) { - system.add(type_(), type); + system.add(user_type(), type); system.add(fun(&MapType::operator[]), "[]"); bootstrap_unique_sorted_associative_container(system, type); bootstrap_pair_associative_container(system, type); @@ -362,7 +362,7 @@ namespace chaiscript template void bootstrap_string(Dispatch_Engine &system, const std::string &type) { - system.add(type_(), type); + system.add(user_type(), type); add_oper_add(system); add_oper_add_equals(system); add_opers_comparison(system); diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 8688ec9..5b91e6b 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -118,14 +118,14 @@ namespace chaiscript template - Type_Info type_(T) + Type_Info user_type(T) { return Get_Type_Info::get(); } template - Type_Info type_() + Type_Info user_type() { return Get_Type_Info::get(); } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 5f32134..e5c2149 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -21,6 +21,35 @@ namespace chaiscript Eval_Engine engine; ChaiScript_Parser parser; + /** + * Evaluates the given string in by parsing it and running the results through the evaluator + */ + Boxed_Value do_eval(const std::string &input, const char *filename = "__EVAL__") { + //debug_print(tokens); + Boxed_Value value; + parser.clear_match_stack(); + + try { + if (parser.parse(input, filename)) { + //parser.show_match_stack(); + value = eval_token(engine, parser.ast()); + } + } + catch (const Return_Value &rv) { + value = rv.retval; + } + + return value; + } + + /** + * Evaluates the given boxed string, used during eval() inside of a script + */ + const Boxed_Value internal_eval(const std::vector &vals) { + return do_eval(boxed_cast(vals.at(0))); + } + + public: ChaiScript_System() { build_eval_system(); @@ -34,6 +63,7 @@ namespace chaiscript { engine.add(t, name); } + /** * Helper for calling script code as if it were native C++ code * example: @@ -44,9 +74,18 @@ namespace chaiscript template boost::function functor(const std::string &script) { - return chaiscript::functor(evaluate_string(script)); + return chaiscript::functor(eval(script)); } + /** + * Evaluate a string via eval method + */ + Boxed_Value operator()(const std::string &script) + { + return do_eval(script); + } + + /** * Returns the current evaluation engine */ @@ -64,16 +103,6 @@ namespace chaiscript } } - /** - * Evaluates the given boxed string, used during eval() inside of a script - */ - const Boxed_Value eval(const std::vector &vals) { - std::string val; - val = boxed_cast(vals[0]); - - return evaluate_string(val); - } - /** * Helper function for loading a file */ @@ -107,41 +136,39 @@ namespace chaiscript bootstrap_pair >(engine, "Pair"); engine.add(Proxy_Function( - new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System::eval, boost::ref(*this), _1), 1)), "eval"); + new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System::internal_eval, boost::ref(*this), _1), 1)), "eval"); - evaluate_string(chaiscript_prelude, "standard prelude"); + do_eval(chaiscript_prelude, "standard prelude"); } - /** - * Evaluates the given string in by parsing it and running the results through the evaluator - */ - Boxed_Value evaluate_string(const std::string &input, const char *filename = "__EVAL__") { - //debug_print(tokens); - Boxed_Value value; - parser.clear_match_stack(); + template + T eval(const std::string &input) + { + return boxed_cast(do_eval(input)); + } - try { - if (parser.parse(input, filename)) { - //parser.show_match_stack(); - value = eval_token(engine, parser.ast()); - } - } - catch (const Return_Value &rv) { - value = rv.retval; - } - - return value; + Boxed_Value eval(const std::string &input) + { + return do_eval(input); } /** * Loads the file specified by filename, evaluates it, and returns the result */ - Boxed_Value evaluate_file(const char *filename) { - return evaluate_string(load_file(filename), filename); + Boxed_Value eval_file(const char *filename) { + return do_eval(load_file(filename), filename); + } + + /** + * Loads the file specified by filename, evaluates it, and returns the as the specified type + */ + template + T eval_file(const char *filename) { + return boxed_cast(do_eval(load_file(filename), filename)); } }; - typedef ChaiScript_System ChaiScript_Engine; + typedef ChaiScript_System ChaiScript; } #endif /* CHAISCRIPT_ENGINE_HPP_ */ diff --git a/src/example.cpp b/src/example.cpp index bb1ab14..2f23649 100644 --- a/src/example.cpp +++ b/src/example.cpp @@ -49,7 +49,7 @@ struct System int main(int argc, char *argv[]) { using namespace chaiscript; - ChaiScript_Engine chai; + ChaiScript chai; //Create a new system object and share it with the chaiscript engine System system; @@ -63,12 +63,12 @@ int main(int argc, char *argv[]) { // The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application // in the "add_callback" function of struct System the chaiscript function is converted into a // boost::function, so it can be handled and called easily and type-safely - chai.evaluate_string("system.add_callback('#1', fun(x) { 'Callback1 ' + x });"); + chai.eval("system.add_callback('#1', fun(x) { 'Callback1 ' + x });"); // Because we are sharing the "system" object with the chaiscript engine we have equal // access to it both from within chaiscript and from C++ code system.do_callbacks("TestString"); - chai.evaluate_string("system.do_callbacks(\"TestString\");"); + chai.eval("system.do_callbacks(\"TestString\");"); // The log function is overloaded, therefore we have to give the C++ compiler a hint as to which // version we want to register. One way to do this is to create a typedef of the function pointer @@ -78,17 +78,42 @@ int main(int argc, char *argv[]) { chai.add(fun(PlainLog(&log)), "log"); chai.add(fun(ModuleLog(&log)), "log"); - chai.evaluate_string("log('Test Message')"); - chai.evaluate_string("log('Test Module', 'Test Message');"); + chai.eval("log('Test Message')"); + + // A shortcut to using eval is just to use the chai operator() + chai("log('Test Module', 'Test Message');"); //Finally, it is possible to register any boost::function as a system function, in this //way, we can, for instance add a bound member function to the system chai.add(fun(boost::function(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test"))), "do_callbacks"); //Call bound version of do_callbacks - chai.evaluate_string("do_callbacks()"); + chai("do_callbacks()"); boost::function caller = chai.functor("fun() { system.do_callbacks(\"From Functor\"); }"); caller(); + + + //If we would like a type-safe return value from all call, we can use + //the templated version of eval: + int i = chai.eval("5+5"); + + std::cout << "5+5: " << i << std::endl; + + //Add a new variable + chai("var scripti = 15"); + + //We can even get a handle to the variables in the system + int &scripti = chai.eval("scripti"); + + std::cout << "scripti: " << scripti << std::endl; + scripti *= 2; + std::cout << "scripti (updated): " << scripti << std::endl; + chai("print(\"Scripti from chai: \" + to_string(scripti))"); + + // Add examples of handling Boxed_Values directly when needed + + // Add usage model for mixed use: + // chai.eval("call(?, ?)", 5, "hello world"); or something } diff --git a/src/main.cpp b/src/main.cpp index 3003394..3c050ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,7 +17,7 @@ void print_help() { int main(int argc, char *argv[]) { std::string input; - chaiscript::ChaiScript_Engine chai; + chaiscript::ChaiScript chai; if (argc < 2) { std::cout << "eval> "; @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) { else { try { //First, we evaluate it - val = chai.evaluate_string(input); + val = chai.eval(input); //Then, we try to print the result of the evaluation to the user if (val.get_type_info().m_bare_type_info && *(val.get_type_info().m_bare_type_info) != typeid(void)) { @@ -57,7 +57,7 @@ int main(int argc, char *argv[]) { for (int i = 1; i < argc; ++i) { std::string filename(argv[i]); try { - chaiscript::Boxed_Value val = chai.evaluate_file(argv[i]); + chaiscript::Boxed_Value val = chai.eval_file(argv[i]); } catch (std::exception &e) { std::cout << e.what() << std::endl;