From a5a1e3ee1bef15f35960b18a67ab4dc6b511fd65 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 19 Jul 2009 03:04:46 +0000 Subject: [PATCH] Revamped method for bootstrapping of types, using a new Module class that collects everything related to a type or group of types --- include/chaiscript/dispatchkit/bootstrap.hpp | 785 +++++++++--------- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 206 +++-- .../chaiscript/dispatchkit/boxed_value.hpp | 9 + .../chaiscript/dispatchkit/dispatchkit.hpp | 60 ++ .../chaiscript/language/chaiscript_engine.hpp | 28 +- .../chaiscript/language/chaiscript_eval.hpp | 2 +- src/example.cpp | 12 +- 7 files changed, 616 insertions(+), 486 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index d08910d..06ce0f8 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -12,273 +12,283 @@ namespace chaiscript { - /** - * Set of helper functions for common operators - */ - template - Ret add(P1 p1, P2 p2) + namespace detail { - return p1 + p2; - } - - template - Ret subtract(P1 p1, P2 p2) - { - return p1 - p2; - } - - template - Ret divide(P1 p1, P2 p2) - { - return p1 / p2; - } - - template - Ret multiply(P1 p1, P2 p2) - { - return p1 * p2; - } - - template - Ret modulus(P1 p1, P2 p2) - { - return p1 % p2; - } - - template - P1 &assign(P1 &p1, const P2 &p2) - { - return (p1 = p2); - } - - template - bool equals(P1 p1, P2 p2) - { - return p1 == p2; - } - - template - bool not_equals(P1 p1, P2 p2) - { - return p1 != p2; - } - - - template - bool less_than(P1 p1, P2 p2) - { - return p1 < p2; - } - - template - bool greater_than(P1 p1, P2 p2) - { - return p1 > p2; - } - - template - bool less_than_equals(P1 p1, P2 p2) - { - return p1 <= p2; - } - - template - bool greater_than_equals(P1 p1, P2 p2) - { - return p1 >= p2; - } - - template - P1 ×equal(P1 &p1, const P2 &p2) - { - return (p1 *= p2); - } - - template - P1 ÷sequal(P1 &p1, const P2 &p2) - { - return (p1 /= p2); - } - - template - P1 &addsequal(P1 &p1, const P2 &p2) - { - return (p1 += p2); - } - - template - P1 &subtractsequal(P1 &p1, const P2 &p2) - { - return (p1 -= p2); - } - - template - P1 &prefixincrement(P1 &p1) - { - return (++p1); - } - - template - P1 &prefixdecrement(P1 &p1) - { - return (--p1); - } - - template - P1 &prefixnegate(P1 &p1) - { - return (p1); - } - - template - P1 &prefixnot(P1 &p1) - { - return (p1); - } - - /* Special helpers for generating generic "POD" type operators - * The POD operators are needed for general support of C++ POD - * types without iterating out all possible combinations of operators - * (<, >, +, +=, *=, \=, -, <=, >=, ==) and types - * (char, uint8_t, int8_t, uint16_t, int16_t...) - */ - template - P1 &assign_pod(P1 &p1, Boxed_POD_Value v) - { - if (v.m_isfloat) + /** + * Set of helper functions for common operators + */ + template + Ret add(P1 p1, P2 p2) { - return (p1 = P1(v.d)); - } else { - return (p1 = P1(v.i)); + return p1 + p2; } - } - template - P1 construct_pod(Boxed_POD_Value v) - { - if (v.m_isfloat) + template + Ret subtract(P1 p1, P2 p2) { - return P1(v.d); - } else { - return P1(v.i); - } - } - - template - P1 ×equal_pod(P1 &p1, Boxed_POD_Value r) - { - if (r.m_isfloat) - { - return p1 *= P1(r.d); - } else { - return p1 *= P1(r.i); + return p1 - p2; } - } - template - P1 ÷sequal_pod(P1 &p1, Boxed_POD_Value r) - { - if (r.m_isfloat) + template + Ret divide(P1 p1, P2 p2) { - return p1 /= P1(r.d); - } else { - return p1 /= P1(r.i); + return p1 / p2; } - } - template - P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r) - { - if (r.m_isfloat) + template + Ret multiply(P1 p1, P2 p2) { - return p1 += P1(r.d); - } else { - return p1 += P1(r.i); + return p1 * p2; } - } - template - P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r) - { - if (r.m_isfloat) + template + Ret modulus(P1 p1, P2 p2) { - return p1 -= P1(r.d); - } else { - return p1 -= P1(r.i); + return p1 % p2; } - } + template + P1 &assign(P1 &p1, const P2 &p2) + { + return (p1 = p2); + } + + template + bool equals(P1 p1, P2 p2) + { + return p1 == p2; + } + + template + bool not_equals(P1 p1, P2 p2) + { + return p1 != p2; + } + + + template + bool less_than(P1 p1, P2 p2) + { + return p1 < p2; + } + + template + bool greater_than(P1 p1, P2 p2) + { + return p1 > p2; + } + + template + bool less_than_equals(P1 p1, P2 p2) + { + return p1 <= p2; + } + + template + bool greater_than_equals(P1 p1, P2 p2) + { + return p1 >= p2; + } + + template + P1 ×equal(P1 &p1, const P2 &p2) + { + return (p1 *= p2); + } + + template + P1 ÷sequal(P1 &p1, const P2 &p2) + { + return (p1 /= p2); + } + + template + P1 &addsequal(P1 &p1, const P2 &p2) + { + return (p1 += p2); + } + + template + P1 &subtractsequal(P1 &p1, const P2 &p2) + { + return (p1 -= p2); + } + + template + P1 &prefixincrement(P1 &p1) + { + return (++p1); + } + + template + P1 &prefixdecrement(P1 &p1) + { + return (--p1); + } + + template + P1 &prefixnegate(P1 &p1) + { + return (p1); + } + + template + P1 &prefixnot(P1 &p1) + { + return (p1); + } + + /* Special helpers for generating generic "POD" type operators + * The POD operators are needed for general support of C++ POD + * types without iterating out all possible combinations of operators + * (<, >, +, +=, *=, \=, -, <=, >=, ==) and types + * (char, uint8_t, int8_t, uint16_t, int16_t...) + */ + template + P1 &assign_pod(P1 &p1, Boxed_POD_Value v) + { + if (v.m_isfloat) + { + return (p1 = P1(v.d)); + } else { + return (p1 = P1(v.i)); + } + } + + template + P1 construct_pod(Boxed_POD_Value v) + { + if (v.m_isfloat) + { + return P1(v.d); + } else { + return P1(v.i); + } + } + + template + P1 ×equal_pod(P1 &p1, Boxed_POD_Value r) + { + if (r.m_isfloat) + { + return p1 *= P1(r.d); + } else { + return p1 *= P1(r.i); + } + } + + template + P1 ÷sequal_pod(P1 &p1, Boxed_POD_Value r) + { + if (r.m_isfloat) + { + return p1 /= P1(r.d); + } else { + return p1 /= P1(r.i); + } + } + + template + P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r) + { + if (r.m_isfloat) + { + return p1 += P1(r.d); + } else { + return p1 += P1(r.i); + } + } + + template + P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r) + { + if (r.m_isfloat) + { + return p1 -= P1(r.d); + } else { + return p1 -= P1(r.i); + } + } + } /** * Add canonical form of "=" for type T */ template - void add_oper_equals(Dispatch_Engine &s) + ModulePtr add_oper_equals(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&equals), "="); + m->add(fun(&detail::equals), "="); + return m; } /** * Add canonical form of "+" for type T */ template - void add_oper_add(Dispatch_Engine &s) + ModulePtr add_oper_add(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&add), "+"); + m->add(fun(&detail::add), "+"); + return m; } /** * Add canonical form of "+=" for type T */ template - void add_oper_add_equals(Dispatch_Engine &s) + ModulePtr add_oper_add_equals(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&addsequal), "+="); + m->add(fun(&detail::addsequal), "+="); + return m; } /** * Add canonical form of "-" for type T */ template - void add_oper_subtract(Dispatch_Engine &s) + ModulePtr add_oper_subtract(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&subtract), "-"); + m->add(fun(&detail::subtract), "-"); + return m; } /** * Add canonical form of "/" for type T */ template - void add_oper_divide(Dispatch_Engine &s) + ModulePtr add_oper_divide(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(÷), "/"); + m->add(fun(&detail::divide), "/"); + return m; } /** * Add canonical form of "*" for type T */ template - void add_oper_multiply(Dispatch_Engine &s) + ModulePtr add_oper_multiply(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&multiply), "*"); + m->add(fun(&detail::multiply), "*"); + return m; } /** * Add canonical form of "!=" for type T */ template - void add_oper_not_equals(Dispatch_Engine &s) + ModulePtr add_oper_not_equals(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(¬_equals), "!="); + m->add(fun(&detail::not_equals), "!="); + return m; } /** * Add user defined assignment operator for T = U */ template - void add_oper_assign_overload(Dispatch_Engine &s) + ModulePtr add_oper_assign_overload(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&assign), "="); + m->add(fun(&detail::assign), "="); + return m; } @@ -286,9 +296,10 @@ namespace chaiscript * Add canonical form of "=" for type T */ template - void add_oper_assign(Dispatch_Engine &s) + ModulePtr add_oper_assign(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&assign), "="); + m->add(fun(&detail::assign), "="); + return m; } @@ -296,9 +307,10 @@ namespace chaiscript * Add assignment operator for T = POD. */ template - void add_oper_assign_pod(Dispatch_Engine &s) + ModulePtr add_oper_assign_pod(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&assign_pod), "="); + m->add(fun(&detail::assign_pod), "="); + return m; } @@ -306,36 +318,40 @@ namespace chaiscript * Add canonical form of "<" for type T */ template - void add_oper_less_than(Dispatch_Engine &s) + ModulePtr add_oper_less_than(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&less_than), "<"); + m->add(fun(&detail::less_than), "<"); + return m; } /** * Add canonical form of ">" for type T */ template - void add_oper_greater_than(Dispatch_Engine &s) + ModulePtr add_oper_greater_than(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&greater_than), ">"); + m->add(fun(&detail::greater_than), ">"); + return m; } /** * Add canonical form of "<=" for type T */ template - void add_oper_less_than_equals(Dispatch_Engine &s) + ModulePtr add_oper_less_than_equals(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&less_than_equals), "<="); + m->add(fun(&detail::less_than_equals), "<="); + return m; } /** * Add canonical form of ">=" for type T */ template - void add_oper_greater_than_equals(Dispatch_Engine &s) + ModulePtr add_oper_greater_than_equals(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&greater_than_equals), ">="); + m->add(fun(&detail::greater_than_equals), ">="); + return m; } /** @@ -343,23 +359,25 @@ namespace chaiscript * Examples: T < R, T == R, etc. */ template - void add_opers_comparison_overload(Dispatch_Engine &s) + ModulePtr add_opers_comparison_overload(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&equals), "=="); - s.add(fun(¬_equals), "!="); - s.add(fun(&less_than), "<"); - s.add(fun(&greater_than), ">"); - s.add(fun(&less_than_equals), "<="); - s.add(fun(&greater_than_equals), ">="); + m->add(fun(&detail::equals), "=="); + m->add(fun(&detail::not_equals), "!="); + m->add(fun(&detail::less_than), "<"); + m->add(fun(&detail::greater_than), ">"); + m->add(fun(&detail::less_than_equals), "<="); + m->add(fun(&detail::greater_than_equals), ">="); + return m; } /** * Add canonical forms of all comparison operators for type T */ template - void add_opers_comparison(Dispatch_Engine &s) + ModulePtr add_opers_comparison(ModulePtr m = ModulePtr(new Module())) { - add_opers_comparison_overload(s); + add_opers_comparison_overload(m); + return m; } /** @@ -370,20 +388,21 @@ namespace chaiscript * T *= R; */ template - void add_opers_arithmetic_overload(Dispatch_Engine &s) + ModulePtr add_opers_arithmetic_overload(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&add), "+"); - s.add(fun(&subtract), "-"); - s.add(fun(÷), "/"); - s.add(fun(&multiply), "*"); - s.add(fun(×equal), "*="); - s.add(fun(÷sequal), "/="); - s.add(fun(&subtractsequal), "-="); - s.add(fun(&addsequal), "+="); - s.add(fun(&prefixincrement), "++"); - s.add(fun(&prefixdecrement), "--"); - s.add(fun(&prefixnegate), "-"); - s.add(fun(&prefixnot), "!"); + m->add(fun(&detail::add), "+"); + m->add(fun(&detail::subtract), "-"); + m->add(fun(&detail::divide), "/"); + m->add(fun(&detail::multiply), "*"); + m->add(fun(&detail::timesequal), "*="); + m->add(fun(&detail::dividesequal), "/="); + m->add(fun(&detail::subtractsequal), "-="); + m->add(fun(&detail::addsequal), "+="); + m->add(fun(&detail::prefixincrement), "++"); + m->add(fun(&detail::prefixdecrement), "--"); + m->add(fun(&detail::prefixnegate), "-"); + m->add(fun(&detail::prefixnot), "!"); + return m; } /** @@ -391,12 +410,13 @@ namespace chaiscript * example: POD *= T, POD /= T */ template - void add_opers_arithmetic_modify_pod(Dispatch_Engine &s) + ModulePtr add_opers_arithmetic_modify_pod(ModulePtr m = ModulePtr(new Module())) { - s.add(fun(×equal_pod), "*="); - s.add(fun(÷sequal_pod), "/="); - s.add(fun(&subtractsequal_pod), "-="); - s.add(fun(&addsequal_pod), "+="); + m->add(fun(&detail::timesequal_pod), "*="); + m->add(fun(&detail::dividesequal_pod), "/="); + m->add(fun(&detail::subtractsequal_pod), "-="); + m->add(fun(&detail::addsequal_pod), "+="); + return m; } /** @@ -405,29 +425,32 @@ namespace chaiscript * the copy constructor. */ template - void add_copy_constructor(Dispatch_Engine &s, const std::string &type) + ModulePtr add_copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - s.add(constructor(), type); - s.add(constructor(), "clone"); + m->add(constructor(), type); + m->add(constructor(), "clone"); + return m; } /** * Add default and copy constructors (including "clone") for type T */ template - void add_basic_constructors(Dispatch_Engine &s, const std::string &type) + ModulePtr add_basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - s.add(constructor(), type); - add_copy_constructor(s, type); + m->add(constructor(), type); + add_copy_constructor(type, m); + return m; } /** * Add POD type constructor for type T. ie: T = type(POD) */ template - void add_construct_pod(Dispatch_Engine &s, const std::string &type) + ModulePtr add_construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - s.add(fun(&construct_pod), type); + m->add(fun(&detail::construct_pod), type); + return m; } /** @@ -435,19 +458,20 @@ namespace chaiscript * T = type(const U &) */ template - void add_constructor_overload(Dispatch_Engine &s, const std::string &type) + ModulePtr add_constructor_overload(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - s.add(constructor(), type); + m->add(constructor(), type); + return m; } /** * Add canonical forms of all arithmetic operators for type T */ template - void add_opers_arithmetic(Dispatch_Engine &s) + ModulePtr add_opers_arithmetic(ModulePtr m = ModulePtr(new Module())) { - add_opers_arithmetic_overload(s); - + add_opers_arithmetic_overload(m); + return m; } /** @@ -487,17 +511,18 @@ namespace chaiscript * common conversions */ template - void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name) + ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module())) { - s.add(user_type(), name); - add_basic_constructors(s, name); - add_oper_assign(s); - add_oper_assign_pod(s); - add_construct_pod(s, name); - add_opers_arithmetic(s); - add_opers_arithmetic_modify_pod(s); - s.add(fun(&to_string), "to_string"); - s.add(fun(&parse_string), "to_" + name); + m->add(user_type(), name); + add_basic_constructors(name, m); + add_oper_assign(m); + add_oper_assign_pod(m); + add_construct_pod(name, m); + add_opers_arithmetic(m); + add_opers_arithmetic_modify_pod(m); + m->add(fun(&to_string), "to_string"); + m->add(fun(&parse_string), "to_" + name); + return m; } /** @@ -530,157 +555,143 @@ namespace chaiscript * Class consisting of only static functions. All default bootstrapping occurs * from this class. */ - struct Bootstrap + class Bootstrap { - /** - * Function allowing for assignment of an unknown type to any other value - */ - static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) - { - if (lhs.is_unknown()) + private: + /** + * Function allowing for assignment of an unknown type to any other value + */ + static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) { - return (lhs.assign(rhs)); - } else { - throw bad_boxed_cast("boxed_value has a set type already"); + if (lhs.is_unknown()) + { + return (lhs.assign(rhs)); + } else { + throw bad_boxed_cast("boxed_value has a set type already"); + } } - } - static void print(const std::string &s) - { - std::cout << s; - } - - static void println(const std::string &s) - { - std::cout << s << std::endl; - } - - /** - * Add all comparison operators for POD types - */ - static void add_opers_comparison_pod(Dispatch_Engine &s) - { - s.add(fun(&equals), "=="); - s.add(fun(¬_equals), "!="); - s.add(fun(&less_than), "<"); - s.add(fun(&greater_than), ">"); - s.add(fun(&less_than_equals), "<="); - s.add(fun(&greater_than_equals), ">="); - } - - /** - * Add all arithmetic operators for PODs - */ - static void add_opers_arithmetic_pod(Dispatch_Engine &s) - { - s.add(fun(&add), "+"); - s.add(fun(&subtract), "-"); - s.add(fun(÷), "/"); - s.add(fun(&multiply), "*"); - } - - /** - * Return true if the two Boxed_Value's share the same internal type - */ - static bool type_match(Boxed_Value l, Boxed_Value r) - { - return l.get_type_info() == r.get_type_info(); - } - - /** - * return true if the Boxed_Value matches the registered type by name - */ - static bool is_type(const Dispatch_Engine &e, const std::string &user_typename, Boxed_Value r) - { - try { - return e.get_type(user_typename) == r.get_type_info(); - } catch (const std::range_error &) { - return false; - } - } - - /** - * Create a bound function object. The first param is the function to bind - * the remaining parameters are the args to bind into the - * result - */ - static Boxed_Value bind_function(const std::vector ¶ms) - { - if (params.size() < 2) + static void print(const std::string &s) { - throw arity_error(params.size(), 2); + std::cout << s; } - Proxy_Function f = boxed_cast(params[0]); - - return Boxed_Value(Proxy_Function(new Bound_Function(f, - std::vector(params.begin() + 1, params.end())))); - } - - /** - * Returns true if a call can be made that consists of the first parameter - * (the function) with the remaining parameters as its arguments. - */ - static Boxed_Value call_exists(const std::vector ¶ms) - { - if (params.size() < 1) + static void println(const std::string &s) { - throw arity_error(params.size(), 1); + std::cout << s << std::endl; } - Proxy_Function f = boxed_cast(params[0]); + /** + * Add all comparison operators for POD types + */ + static void add_opers_comparison_pod(ModulePtr m = ModulePtr(new Module())) + { + m->add(fun(&detail::equals), "=="); + m->add(fun(&detail::not_equals), "!="); + m->add(fun(&detail::less_than), "<"); + m->add(fun(&detail::greater_than), ">"); + m->add(fun(&detail::less_than_equals), "<="); + m->add(fun(&detail::greater_than_equals), ">="); + } - return Boxed_Value(f->types_match(std::vector(params.begin() + 1, params.end()))); - } + /** + * Add all arithmetic operators for PODs + */ + static void add_opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module())) + { + m->add(fun(&detail::add), "+"); + m->add(fun(&detail::subtract), "-"); + m->add(fun(&detail::divide), "/"); + m->add(fun(&detail::multiply), "*"); + } - /** - * perform all common bootstrap functions for std::string, void and POD types - */ - static void bootstrap(Dispatch_Engine &s) - { - 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"); + /** + * Create a bound function object. The first param is the function to bind + * the remaining parameters are the args to bind into the + * result + */ + static Boxed_Value bind_function(const std::vector ¶ms) + { + if (params.size() < 2) + { + throw arity_error(params.size(), 2); + } - add_basic_constructors(s, "bool"); - add_oper_assign(s); - add_oper_assign(s); + Proxy_Function f = boxed_cast(params[0]); - s.add(fun(&to_string), "internal_to_string"); - s.add(fun(&to_string), "internal_to_string"); - s.add(fun(&unknown_assign), "="); + return Boxed_Value(Proxy_Function(new Bound_Function(f, + std::vector(params.begin() + 1, params.end())))); + } - bootstrap_pod_type(s, "double"); - bootstrap_pod_type(s, "int"); - bootstrap_pod_type(s, "size_t"); - bootstrap_pod_type(s, "char"); - bootstrap_pod_type(s, "int64_t"); + /** + * Returns true if a call can be made that consists of the first parameter + * (the function) with the remaining parameters as its arguments. + */ + static Boxed_Value call_exists(const std::vector ¶ms) + { + if (params.size() < 1) + { + throw arity_error(params.size(), 1); + } - add_opers_comparison_pod(s); - add_opers_arithmetic_pod(s); - s.add(fun(&modulus), "%"); + Proxy_Function f = boxed_cast(params[0]); - s.add(fun(&print), "print_string"); - s.add(fun(&println), "println_string"); + return Boxed_Value(f->types_match(std::vector(params.begin() + 1, params.end()))); + } - s.add(fun(boost::function(boost::bind(&dump_system, boost::ref(s)))), "dump_system"); - s.add(fun(boost::function(boost::bind(&dump_object, _1, boost::ref(s)))), "dump_object"); - s.add(fun(boost::function(boost::bind(&is_type, boost::ref(s), _2, _1))), - "is_type"); + static boost::shared_ptr bootstrap2(boost::shared_ptr e = boost::shared_ptr (new Dispatch_Engine())) + { + e->add(user_type(), "void"); + return e; + } - s.add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))), - "bind"); + public: + /** + * perform all common bootstrap functions for std::string, void and POD types + */ + static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module())) + { + m->add(user_type(), "void"); + m->add(user_type(), "bool"); + m->add(user_type(), "Object"); + m->add(user_type(), "PODObject"); + m->add(user_type(), "function"); - s.add(fun(&shared_ptr_clone), "clone"); - s.add(fun(&ptr_assign), "="); + add_basic_constructors("bool", m); + add_oper_assign(m); + add_oper_assign(m); - s.add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))), - "call_exists"); + m->add(fun(&to_string), "internal_to_string"); + m->add(fun(&to_string), "internal_to_string"); + m->add(fun(&unknown_assign), "="); - s.add(fun(&type_match), "type_match"); - } + bootstrap_pod_type("double", m); + bootstrap_pod_type("int", m); + bootstrap_pod_type("size_t", m); + bootstrap_pod_type("char", m); + bootstrap_pod_type("int64_t", m); + + add_opers_comparison_pod(m); + add_opers_arithmetic_pod(m); + + m->add(fun(&detail::modulus), "%"); + + m->add(fun(&print), "print_string"); + m->add(fun(&println), "println_string"); + + m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))), + "bind"); + + m->add(fun(&shared_ptr_clone), "clone"); + m->add(fun(&ptr_assign), "="); + + m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))), + "call_exists"); + + m->add(fun(&type_match), "type_match"); + + return m; + } }; } diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 3a2b78f..cc26d3e 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -10,8 +10,8 @@ * http://www.sgi.com/tech/stl/table_of_contents.html */ -#ifndef __bootstrap_stl_hpp -#define __bootstrap_stl_hpp__ +#ifndef __stl_hpp_type +#define __stl_hpp___type #include "dispatchkit.hpp" #include "register_function.hpp" @@ -74,24 +74,25 @@ namespace chaiscript * Add Input_Range support for the given ContainerType */ template - void bootstrap_input_range(Dispatch_Engine &system, const std::string &type) + ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - system.add(user_type >(), type + "_Range"); - system.add(user_type(), type+"_Iterator"); + m->add(user_type >(), type + "_Range"); + m->add(user_type(), type+"_Iterator"); - system.add(constructor (ContainerType &)>(), "range"); - system.add(constructor (typename ContainerType::iterator)>(), "range"); + m->add(constructor (ContainerType &)>(), "range"); + m->add(constructor (typename ContainerType::iterator)>(), "range"); typedef std::pair ItrPair; - system.add(constructor (const ItrPair &)>(), "range"); + m->add(constructor (const ItrPair &)>(), "range"); - system.add(user_type(), type+"_Iterator_Pair"); + m->add(user_type(), type+"_Iterator_Pair"); - system.add(fun(&Input_Range::empty), "empty"); - system.add(fun(&Input_Range::pop_front), "pop_front"); - system.add(fun(&Input_Range::front), "front"); - system.add(constructor (const Input_Range &)>(), "clone"); + m->add(fun(&Input_Range::empty), "empty"); + m->add(fun(&Input_Range::pop_front), "pop_front"); + m->add(fun(&Input_Range::front), "front"); + m->add(constructor (const Input_Range &)>(), "clone"); + return m; } /** @@ -99,8 +100,9 @@ namespace chaiscript * http://www.sgi.com/tech/stl/ReversibleContainer.html */ template - void bootstrap_reversible_container(Dispatch_Engine &/*system*/, const std::string &/*type*/) + ModulePtr reversible_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { + return m; } /** @@ -108,18 +110,19 @@ namespace chaiscript * http://www.sgi.com/tech/stl/RandomAccessContainer.html */ template - void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type) + ModulePtr random_access_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_reversible_container(system, type); + reversible_container_type(type, m); typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t); - //In the interest of runtime safety for the system, we prefer the at() method for [] access, + //In the interest of runtime safety for the m, we prefer the at() method for [] access, //to throw an exception in an out of bounds condition. - system.add( + m->add( fun(boost::function(indexoper(&ContainerType::at))), "[]"); - system.add( + m->add( fun(boost::function(indexoper(&ContainerType::operator[]))), "at"); + return m; } /** @@ -127,10 +130,11 @@ namespace chaiscript * http://www.sgi.com/tech/stl/Assignable.html */ template - void bootstrap_assignable(Dispatch_Engine &system, const std::string &type) + ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - add_basic_constructors(system, type); - add_oper_assign(system); + add_basic_constructors(type, m); + add_oper_assign(m); + return m; } /** @@ -138,13 +142,15 @@ namespace chaiscript * http://www.sgi.com/tech/stl/Container.html */ template - void bootstrap_container(Dispatch_Engine &system, const std::string &type) + ModulePtr container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_assignable(system, type); + assignable_type(type, m); - system.add(fun(&ContainerType::size), "size"); - system.add(fun(&ContainerType::max_size), "max_size"); - system.add(fun(&ContainerType::empty), "empty"); + m->add(fun(&ContainerType::size), "size"); + m->add(fun(&ContainerType::max_size), "max_size"); + m->add(fun(&ContainerType::empty), "empty"); + + return m; } /** @@ -152,10 +158,12 @@ namespace chaiscript * http://www.sgi.com/tech/stl/ForwardContainer.html */ template - void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type) + ModulePtr forward_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_input_range(system, type); - bootstrap_container(system, type); + input_range_type(type, m); + container_type(type, m); + + return m; } /** @@ -163,9 +171,10 @@ namespace chaiscript * http://www.sgi.com/tech/stl/DefaultConstructible.html */ template - void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type) + ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - system.add(constructor(), type); + m->add(constructor(), type); + return m; } /** @@ -209,10 +218,10 @@ namespace chaiscript * http://www.sgi.com/tech/stl/Sequence.html */ template - void bootstrap_sequence(Dispatch_Engine &system, const std::string &type) + ModulePtr sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_forward_container(system, type); - bootstrap_default_constructible(system, type); + forward_container_type(type, m); + default_constructible_type(type, m); std::string insert_name; if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) @@ -222,8 +231,10 @@ namespace chaiscript insert_name = "insert_at"; } - system.add(fun(&insert_at), insert_name); - system.add(fun(&erase_at), "erase_at"); + m->add(fun(&insert_at), insert_name); + m->add(fun(&erase_at), "erase_at"); + + return m; } /** @@ -231,14 +242,14 @@ namespace chaiscript * http://www.sgi.com/tech/stl/BackInsertionSequence.html */ template - void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type) + ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_sequence(system, type); + sequence_type(type, m); typedef typename ContainerType::reference (ContainerType::*backptr)(); - system.add(fun(backptr(&ContainerType::back)), "back"); + m->add(fun(backptr(&ContainerType::back)), "back"); std::string push_back_name; if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) @@ -248,8 +259,9 @@ namespace chaiscript push_back_name = "push_back"; } - system.add(fun(&ContainerType::push_back), push_back_name); - system.add(fun(&ContainerType::pop_back), "pop_back"); + m->add(fun(&ContainerType::push_back), push_back_name); + m->add(fun(&ContainerType::pop_back), "pop_back"); + return m; } /** @@ -257,11 +269,12 @@ namespace chaiscript * http://www.sgi.com/tech/stl/Vector.html */ template - void bootstrap_vector(Dispatch_Engine &system, const std::string &type) + ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - system.add(user_type(), type); - bootstrap_random_access_container(system, type); - bootstrap_back_insertion_sequence(system, type); + m->add(user_type(), type); + random_access_container_type(type, m); + back_insertion_sequence_type(type, m); + return m; } /** @@ -269,10 +282,11 @@ namespace chaiscript * http://www.sgi.com/tech/stl/Vector.html */ template - void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type) + ModulePtr associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_forward_container(system, type); - bootstrap_default_constructible(system, type); + forward_container_type(type, m); + default_constructible_type(type, m); + return m; } /** @@ -280,18 +294,20 @@ namespace chaiscript * http://www.sgi.com/tech/stl/pair.html */ template - void bootstrap_pair(Dispatch_Engine &system, const std::string &type) + ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - system.add(user_type(), type); + m->add(user_type(), type); - system.add(fun(&PairType::first), "first"); - system.add(fun(&PairType::second), "second"); + m->add(fun(&PairType::first), "first"); + m->add(fun(&PairType::second), "second"); - system.add(constructor(), type); - system.add(constructor(), type); - system.add(constructor(), "clone"); - system.add(constructor(), type); - } + m->add(constructor(), type); + m->add(constructor(), type); + m->add(constructor(), "clone"); + m->add(constructor(), type); + + return m; + } /** @@ -299,10 +315,12 @@ namespace chaiscript * http://www.sgi.com/tech/stl/PairAssociativeContainer.html */ template - void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type) + ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_associative_container(system, type); - bootstrap_pair(system, type + "_Pair"); + associative_container_type(type, m); + pair_type(type + "_Pair", m); + + return m; } /** @@ -310,10 +328,12 @@ namespace chaiscript * http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html */ template - void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type) + ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_associative_container(system, type); - system.add(fun(&ContainerType::count), "count"); + associative_container_type(type, m); + m->add(fun(&ContainerType::count), "count"); + + return m; } /** @@ -321,14 +341,16 @@ namespace chaiscript * http://www.sgi.com/tech/stl/SortedAssociativeContainer.html */ template - void bootstrap_sorted_associative_container(Dispatch_Engine &system, const std::string &type) + ModulePtr sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { typedef std::pair (ContainerType::*eq_range)(const typename ContainerType::key_type &); - bootstrap_reversible_container(system, type); - bootstrap_associative_container(system, type); - system.add(fun(eq_range(&ContainerType::equal_range)), "equal_range"); + reversible_container_type(type, m); + associative_container_type(type, m); + m->add(fun(eq_range(&ContainerType::equal_range)), "equal_range"); + + return m; } /** @@ -336,10 +358,12 @@ namespace chaiscript * http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html */ template - void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type) + ModulePtr unique_sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - bootstrap_sorted_associative_container(system, type); - bootstrap_unique_associative_container(system, type); + sorted_associative_container_type(type, m); + unique_associative_container_type(type, m); + + return m; } /** @@ -347,12 +371,14 @@ namespace chaiscript * http://www.sgi.com/tech/stl/Map.html */ template - void bootstrap_map(Dispatch_Engine &system, const std::string &type) + ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - system.add(user_type(), type); - system.add(fun(&MapType::operator[]), "[]"); - bootstrap_unique_sorted_associative_container(system, type); - bootstrap_pair_associative_container(system, type); + m->add(user_type(), type); + m->add(fun(&MapType::operator[]), "[]"); + unique_sorted_associative_container_type(type, m); + pair_associative_container_type(type, m); + + return m; } /** @@ -360,21 +386,23 @@ namespace chaiscript * http://www.sgi.com/tech/stl/basic_string.html */ template - void bootstrap_string(Dispatch_Engine &system, const std::string &type) + ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) { - system.add(user_type(), type); - add_oper_add(system); - add_oper_add_equals(system); - add_opers_comparison(system); - bootstrap_random_access_container(system, type); - bootstrap_sequence(system, type); + m->add(user_type(), type); + add_oper_add(m); + add_oper_add_equals(m); + add_opers_comparison(m); + random_access_container_type(type, m); + sequence_type(type, m); typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const; - system.add(fun(find_func(&String::find)), "find"); - system.add(fun(find_func(&String::rfind)), "rfind"); - system.add(fun(find_func(&String::find_first_of)), "find_first_of"); - system.add(fun(find_func(&String::find_last_of)), "find_last_of"); - system.add(fun(find_func(&String::find_first_not_of)), "find_first_not_of"); - system.add(fun(find_func(&String::find_last_not_of)), "find_last_not_of"); + m->add(fun(find_func(&String::find)), "find"); + m->add(fun(find_func(&String::rfind)), "rfind"); + m->add(fun(find_func(&String::find_first_of)), "find_first_of"); + m->add(fun(find_func(&String::find_last_of)), "find_last_of"); + m->add(fun(find_func(&String::find_first_not_of)), "find_first_not_of"); + m->add(fun(find_func(&String::find_last_not_of)), "find_last_not_of"); + + return m; } } diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index f8239d2..3dd7db1 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -682,6 +682,15 @@ namespace chaiscript { return Boxed_Value(t); } + + /** + * Return true if the two Boxed_Value's share the same internal type + */ + static bool type_match(Boxed_Value l, Boxed_Value r) + { + return l.get_type_info() == r.get_type_info(); + } + } #endif diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index c25ca73..7da511a 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -25,6 +25,45 @@ namespace chaiscript { + class Module + { + public: + Module &add(const Type_Info &ti, const std::string &name) + { + m_typeinfos.push_back(std::make_pair(ti, name)); + return *this; + } + + Module &add(const Proxy_Function &f, const std::string &name) + { + m_funcs.push_back(std::make_pair(f, name)); + return *this; + } + + template + void apply(T &t) const + { + apply(m_typeinfos.begin(), m_typeinfos.end(), t); + apply(m_funcs.begin(), m_funcs.end(), t); + } + + private: + std::vector > m_typeinfos; + std::vector > m_funcs; + + template + void apply(InItr begin, InItr end, T &t) const + { + while (begin != end) + { + t.add(begin->first, begin->second); + ++begin; + } + } + }; + + typedef boost::shared_ptr ModulePtr; + /** * A Proxy_Function implementation that is able to take * a vector of Proxy_Functions and perform a dispatch on them. It is @@ -110,6 +149,14 @@ namespace chaiscript return add_function(f, name); } + /** + * Add a module's worth of registrations to the system + */ + void add(const ModulePtr &m) + { + m->apply(*this); + } + /** * Set the value of an object, by name. If the object * is not available in the current scope it is created @@ -411,6 +458,19 @@ namespace chaiscript } std::cout << std::endl; } + + /** + * return true if the Boxed_Value matches the registered type by name + */ + static bool is_type(const Dispatch_Engine &e, const std::string &user_typename, Boxed_Value r) + { + try { + return e.get_type(user_typename) == r.get_type_info(); + } catch (const std::range_error &) { + return false; + } + } + } #endif diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index e5c2149..df46d6d 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -59,11 +59,20 @@ namespace chaiscript * Adds an object to the system: type, function, object */ template - void add(const T &t, const std::string &name) + ChaiScript_System &add(const T &t, const std::string &name) { engine.add(t, name); + return *this; } + /** + * Adds a module object to the system + */ + ChaiScript_System &add(const ModulePtr &p) + { + engine.add(p); + } + /** * Helper for calling script code as if it were native C++ code * example: @@ -129,11 +138,18 @@ namespace chaiscript * Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude. */ void build_eval_system() { - Bootstrap::bootstrap(engine); - bootstrap_vector >(engine, "Vector"); - bootstrap_string(engine, "string"); - bootstrap_map >(engine, "Map"); - bootstrap_pair >(engine, "Pair"); + engine.add(Bootstrap::bootstrap()); + + engine.add(fun(boost::function(boost::bind(&dump_system, boost::ref(engine)))), "dump_system"); + engine.add(fun(boost::function(boost::bind(&dump_object, _1, boost::ref(engine)))), "dump_object"); + engine.add(fun(boost::function(boost::bind(&is_type, boost::ref(engine), _2, _1))), + "is_type"); + + + engine.add(vector_type >("Vector")); + engine.add(string_type("string")); + engine.add(map_type >("Map")); + engine.add(pair_type >("Pair")); engine.add(Proxy_Function( new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System::internal_eval, boost::ref(*this), _1), 1)), "eval"); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 1bb0126..14c14b2 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -138,7 +138,7 @@ namespace chaiscript } else if (node->children[i+1]->text == ":=") { Boxed_Value lhs = eval_token(ss, node->children[i]); - if (lhs.is_unknown() || Bootstrap::type_match(lhs, retval)) { + if (lhs.is_unknown() || type_match(lhs, retval)) { lhs.assign(retval); } else { diff --git a/src/example.cpp b/src/example.cpp index 864600a..c726a82 100644 --- a/src/example.cpp +++ b/src/example.cpp @@ -115,11 +115,17 @@ int main(int argc, char *argv[]) { // Add usage model for mixed use: // chai.eval("call(?, ?)", 5, "hello world"); or something - - // add examples for and clean up usage of bootstrap stuffs - + + + //Creating a functor on the stack and using it immediatly int x = chai.functor("fun (x, y) { return x + y; }")(5, 6); log("Functor test output", boost::lexical_cast(x)); + + + //Ability to create our own container types when needed. std::vector and std::map are + //mostly supported currently + chai.add(vector_type >("IntVector")); + }