diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 504c0ea..fdf4a04 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -1,5 +1,8 @@ // This file is distributed under the BSD License. // See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com #ifndef CHAISCRIPT_HPP_ #define CHAISCRIPT_HPP_ diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index c518333..ba24bef 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #ifndef __bootstrap_hpp #define __bootstrap_hpp__ @@ -15,28 +21,24 @@ namespace dispatchkit 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) { @@ -49,16 +51,12 @@ namespace dispatchkit return (p1 = p2); } - - template bool equals(P1 p1, P2 p2) { return p1 == p2; } - - template bool not_equals(P1 p1, P2 p2) { @@ -102,7 +100,6 @@ namespace dispatchkit return (p1 /= p2); } - template P1 &addsequal(P1 &p1, const P2 &p2) { @@ -115,8 +112,6 @@ namespace dispatchkit return (p1 -= p2); } - - template P1 &prefixincrement(P1 &p1) { @@ -259,18 +254,27 @@ namespace dispatchkit register_function(s, ÷, "/"); } + /** + * Add canonical form of "*" for type T + */ template void add_oper_multiply(Dispatch_Engine &s) { register_function(s, &multiply, "*"); } + /** + * Add canonical form of "!=" for type T + */ template void add_oper_not_equals(Dispatch_Engine &s) { register_function(s, ¬_equals, "!="); } + /** + * Add user defined assignment operator for T = U + */ template void add_oper_assign_overload(Dispatch_Engine &s) { @@ -278,6 +282,9 @@ namespace dispatchkit } + /** + * Add canonical form of "=" for type T + */ template void add_oper_assign(Dispatch_Engine &s) { @@ -285,6 +292,9 @@ namespace dispatchkit } + /** + * Add assignment operator for T = POD. + */ template void add_oper_assign_pod(Dispatch_Engine &s) { @@ -292,31 +302,46 @@ namespace dispatchkit } + /** + * Add canonical form of "<" for type T + */ template void add_oper_less_than(Dispatch_Engine &s) { register_function(s, &less_than, "<"); } + /** + * Add canonical form of ">" for type T + */ template void add_oper_greater_than(Dispatch_Engine &s) { register_function(s, &greater_than, ">"); } + /** + * Add canonical form of "<=" for type T + */ template void add_oper_less_than_equals(Dispatch_Engine &s) { register_function(s, &less_than_equals, "<="); } + /** + * Add canonical form of ">=" for type T + */ template void add_oper_greater_than_equals(Dispatch_Engine &s) { register_function(s, &greater_than_equals, ">="); } - + /** + * Add user defined comparison operators for T and R. + * Examples: T < R, T == R, etc. + */ template void add_opers_comparison_overload(Dispatch_Engine &s) { @@ -328,12 +353,22 @@ namespace dispatchkit register_function(s, &greater_than_equals, ">="); } + /** + * Add canonical forms of all comparison operators for type T + */ template void add_opers_comparison(Dispatch_Engine &s) { add_opers_comparison_overload(s); } + /** + * Add all arithmetic operators that return a type of Ret, taking + * a lhs of T and a rhs of R, when possible. + * examples: Ret = T + R; + * ++T + * T *= R; + */ template void add_opers_arithmetic_overload(Dispatch_Engine &s) { @@ -351,6 +386,10 @@ namespace dispatchkit register_function(s, &prefixnot, "!"); } + /** + * Add arithmetic assign operators for POD types: + * example: POD *= T, POD /= T + */ template void add_opers_arithmetic_modify_pod(Dispatch_Engine &s) { @@ -360,6 +399,11 @@ namespace dispatchkit register_function(s, &addsequal_pod, "+="); } + /** + * Add a copy constructor for type T, also creates the standard + * function "clone" for the type. "clone" is a synonym for + * the copy constructor. + */ template void add_copy_constructor(Dispatch_Engine &s, const std::string &type) { @@ -367,6 +411,9 @@ namespace dispatchkit s.register_function(build_constructor(), "clone"); } + /** + * Add default and copy constructors (including "clone") for type T + */ template void add_basic_constructors(Dispatch_Engine &s, const std::string &type) { @@ -374,18 +421,28 @@ namespace dispatchkit add_copy_constructor(s, type); } + /** + * Add POD type constructor for type T. ie: T = type(POD) + */ template void add_construct_pod(Dispatch_Engine &s, const std::string &type) { register_function(s, &construct_pod, type); } + /** + * add user defined single parameter constructor for type T. + * T = type(const U &) + */ template void add_constructor_overload(Dispatch_Engine &s, const std::string &type) { s.register_function(build_constructor(), type); } + /** + * Add canonical forms of all arithmetic operators for type T + */ template void add_opers_arithmetic(Dispatch_Engine &s) { @@ -393,15 +450,18 @@ namespace dispatchkit } - - - //Built in to_string operator + /** + * to_string function for internal use. Uses ostream operator<< + */ template std::string to_string(Input i) { return boost::lexical_cast(i); } + /** + * Boolean specialization of internal to_string function + */ template<> std::string to_string(bool b) { if (b) @@ -412,14 +472,20 @@ namespace dispatchkit } } + /** + * Internal function for converting from a string to a value + * uses ostream operator >> to perform the conversion + */ template Input parse_string(const std::string &i) { return boost::lexical_cast(i); } - - + /** + * Add all common functions for a POD type. All operators, and + * common conversions + */ template void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name) { @@ -434,12 +500,24 @@ namespace dispatchkit register_function(s, &parse_string, "to_" + name); } + /** + * "clone" function for a shared_ptr type. This is used in the case + * where you do not want to make a deep copy of an object during cloning + * but want to instead maintain the shared_ptr. It is needed internally + * for handling of boost::shared_ptr object (that is, + * function variables. + */ template boost::shared_ptr shared_ptr_clone(boost::shared_ptr f) { return f; } + /** + * Assignment function for shared_ptr objects, does not perform a copy of the + * object pointed to, instead maintains the shared_ptr concept. + * Similar to shared_ptr_clone. Used for Proxy_Function. + */ template Boxed_Value ptr_assign(Boxed_Value lhs, boost::shared_ptr rhs) { @@ -448,9 +526,15 @@ namespace dispatchkit return lhs; } - + /** + * Class consisting of only static functions. All default bootstrapping occurs + * from this class. + */ struct 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()) @@ -471,6 +555,9 @@ namespace dispatchkit std::cout << s << std::endl; } + /** + * Add all comparison operators for POD types + */ static void add_opers_comparison_pod(Dispatch_Engine &s) { register_function(s, &equals, "=="); @@ -481,6 +568,9 @@ namespace dispatchkit register_function(s, &greater_than_equals, ">="); } + /** + * Add all arithmetic operators for PODs + */ static void add_opers_arithmetic_pod(Dispatch_Engine &s) { register_function(s, &add, "+"); @@ -489,11 +579,17 @@ namespace dispatchkit register_function(s, &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 &type_name, Boxed_Value r) { try { @@ -503,6 +599,11 @@ namespace dispatchkit } } + /** + * 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) @@ -516,6 +617,10 @@ namespace dispatchkit 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) @@ -528,6 +633,9 @@ namespace dispatchkit return Boxed_Value(f->types_match(std::vector(params.begin() + 1, params.end()))); } + /** + * perform all common bootstrap functions for std::string, void and POD types + */ static void bootstrap(Dispatch_Engine &s) { s.register_type("void"); diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index cd225ce..1b8c674 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -1,3 +1,16 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + + +/** + * This file contains utility functions for registration of STL container + * classes. The methodology used is based on the SGI STL concepts. + * http://www.sgi.com/tech/stl/table_of_contents.html + */ + #ifndef __bootstrap_stl_hpp #define __bootstrap_stl_hpp__ @@ -7,6 +20,11 @@ namespace dispatchkit { + /** + * 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 + */ template struct Input_Range { @@ -52,6 +70,10 @@ namespace dispatchkit typename Container::iterator m_end; }; + + /** + * Add Input_Range support for the given ContainerType + */ template void bootstrap_input_range(Dispatch_Engine &system, const std::string &type) { @@ -75,11 +97,19 @@ namespace dispatchkit system.register_function(build_constructor, const Input_Range &>(), "clone"); } + /** + * Add reversible_container concept to the given ContainerType + * http://www.sgi.com/tech/stl/ReversibleContainer.html + */ template void bootstrap_reversible_container(Dispatch_Engine &/*system*/, const std::string &/*type*/) { } + /** + * Add random_access_container concept to the given ContainerType + * http://www.sgi.com/tech/stl/RandomAccessContainer.html + */ template void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type) { @@ -89,19 +119,25 @@ namespace dispatchkit //In the interest of runtime safety for the system, we prefer the at() method for [] access, //to throw an exception in an out of bounds condition. - system.register_function( - boost::function(indexoper(&ContainerType::at)), "[]"); - system.register_function( - boost::function(indexoper(&ContainerType::operator[])), "at"); + register_function(system, indexoper(&ContainerType::at), "[]"); + register_function(system, indexoper(&ContainerType::operator[]), "at"); } - template + /** + * Add assignable concept to the given ContainerType + * http://www.sgi.com/tech/stl/Assignable.html + */ + template void bootstrap_assignable(Dispatch_Engine &system, const std::string &type) { - add_basic_constructors(system, type); - add_oper_assign(system); + add_basic_constructors(system, type); + add_oper_assign(system); } + /** + * Add container concept to the given ContainerType + * http://www.sgi.com/tech/stl/Container.html + */ template void bootstrap_container(Dispatch_Engine &system, const std::string &type) { @@ -112,6 +148,10 @@ namespace dispatchkit register_function(system, &ContainerType::empty, "empty"); } + /** + * Add forward container concept to the given ContainerType + * http://www.sgi.com/tech/stl/ForwardContainer.html + */ template void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type) { @@ -119,12 +159,19 @@ namespace dispatchkit bootstrap_container(system, type); } + /** + * Add default constructable concept to the given Type + * http://www.sgi.com/tech/stl/DefaultConstructible.html + */ template void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type) { system.register_function(build_constructor(), type); } + /** + * Algorithm for inserting at a specific position into a container + */ template void insert_at(Type &container, int pos, const typename Type::value_type &v) { @@ -140,6 +187,9 @@ namespace dispatchkit container.insert(itr, v); } + /** + * Algorithm for erasing a specific position from a container + */ template void erase_at(Type &container, int pos) { @@ -155,46 +205,58 @@ namespace dispatchkit container.erase(itr); } - template + /** + * Add sequence concept to the given ContainerType + * http://www.sgi.com/tech/stl/Sequence.html + */ + template void bootstrap_sequence(Dispatch_Engine &system, const std::string &type) { - bootstrap_forward_container(system, type); - bootstrap_default_constructible(system, type); + bootstrap_forward_container(system, type); + bootstrap_default_constructible(system, type); std::string insert_name; - if (typeid(typename SequenceType::value_type) == typeid(Boxed_Value)) + if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { insert_name = "insert_ref_at"; } else { insert_name = "insert_at"; } - register_function(system, &insert_at, insert_name); - register_function(system, &erase_at, "erase_at"); + register_function(system, &insert_at, insert_name); + register_function(system, &erase_at, "erase_at"); } - template + /** + * Add back insertion sequence concept to the given ContainerType + * http://www.sgi.com/tech/stl/BackInsertionSequence.html + */ + template void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type) { - bootstrap_sequence(system, type); + bootstrap_sequence(system, type); - typedef typename SequenceType::reference (SequenceType::*backptr)(); + typedef typename ContainerType::reference (ContainerType::*backptr)(); - system.register_function(boost::function(backptr(&SequenceType::back)), "back"); + register_function(system, (backptr(&ContainerType::back)), "back"); std::string push_back_name; - if (typeid(typename SequenceType::value_type) == typeid(Boxed_Value)) + if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { push_back_name = "push_back_ref"; } else { push_back_name = "push_back"; } - register_function(system, &SequenceType::push_back, push_back_name); - register_function(system, &SequenceType::pop_back, "pop_back"); + register_function(system, &ContainerType::push_back, push_back_name); + register_function(system, &ContainerType::pop_back, "pop_back"); } + /** + * Create a vector type with associated concepts + * http://www.sgi.com/tech/stl/Vector.html + */ template void bootstrap_vector(Dispatch_Engine &system, const std::string &type) { @@ -203,6 +265,10 @@ namespace dispatchkit bootstrap_back_insertion_sequence(system, type); } + /** + * Create a vector type with associated concepts + * http://www.sgi.com/tech/stl/Vector.html + */ template void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type) { @@ -210,6 +276,10 @@ namespace dispatchkit bootstrap_default_constructible(system, type); } + /** + * bootstrap a given PairType + * http://www.sgi.com/tech/stl/pair.html + */ template void bootstrap_pair(Dispatch_Engine &system, const std::string &type) { @@ -225,6 +295,10 @@ namespace dispatchkit } + /** + * Add pair associative container concept to the given ContainerType + * http://www.sgi.com/tech/stl/PairAssociativeContainer.html + */ template void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type) { @@ -232,6 +306,10 @@ namespace dispatchkit bootstrap_pair(system, type + "_Pair"); } + /** + * Add unique associative container concept to the given ContainerType + * http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html + */ template void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type) { @@ -239,6 +317,10 @@ namespace dispatchkit register_function(system, &ContainerType::count, "count"); } + /** + * Add sorted associative container concept to the given ContainerType + * http://www.sgi.com/tech/stl/SortedAssociativeContainer.html + */ template void bootstrap_sorted_associative_container(Dispatch_Engine &system, const std::string &type) { @@ -250,6 +332,10 @@ namespace dispatchkit register_function(system, eq_range(&ContainerType::equal_range), "equal_range"); } + /** + * Add unique sorted associative container concept to the given ContainerType + * http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html + */ template void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type) { @@ -257,6 +343,10 @@ namespace dispatchkit bootstrap_unique_associative_container(system, type); } + /** + * Add a MapType container + * http://www.sgi.com/tech/stl/Map.html + */ template void bootstrap_map(Dispatch_Engine &system, const std::string &type) { @@ -266,6 +356,10 @@ namespace dispatchkit bootstrap_pair_associative_container(system, type); } + /** + * Add a String container + * http://www.sgi.com/tech/stl/basic_string.html + */ template void bootstrap_string(Dispatch_Engine &system, const std::string &type) { @@ -283,7 +377,6 @@ namespace dispatchkit register_function(system, find_func(&String::find_first_not_of), "find_first_not_of"); register_function(system, find_func(&String::find_last_not_of), "find_last_not_of"); } - } #endif diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 924216e..2183f93 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #ifndef __boxed_value_hpp__ #define __boxed_value_hpp__ @@ -13,16 +19,32 @@ namespace dispatchkit { + /** + * Boxed_Value is the main tool of the dispatchkit. It allows + * for boxed / untyped containment of any C++ object. It uses + * boost::any internally but also provides user access the underlying + * stored type information + */ class Boxed_Value { public: + /** + * used for explicitly creating a "void" object + */ struct Void_Type { }; private: + /** + * structure which holds the internal state of a Boxed_Value + */ struct Data { + /** + * used to provide type-erased access to the internal boost::shared_ptr + * reference count information + */ struct Shared_Ptr_Proxy { virtual ~Shared_Ptr_Proxy() @@ -33,6 +55,9 @@ namespace dispatchkit virtual long use_count(boost::any *) = 0; }; + /** + * Typed implementation of the Shared_Ptr_Proxy + */ template struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy { @@ -83,6 +108,12 @@ namespace dispatchkit boost::shared_ptr m_ptr_proxy; }; + /** + * Cache of all created objects in the dispatch kit. Used to return the + * same shared_ptr if the same object is created more than once. + * Also used for acquiring a shared_ptr of a reference object, if the + * value of the shared_ptr is known + */ struct Object_Cache { boost::shared_ptr get(Boxed_Value::Void_Type) @@ -131,7 +162,6 @@ namespace dispatchkit if (itr != m_ptrs.end()) { -// std::cout << "Reference wrapper ptr found, using it" << std::endl; (*data) = (itr->second); } @@ -163,6 +193,10 @@ namespace dispatchkit ); } + /** + * Drop objects from the cache where there is only one (ie, our) + * reference to it, so it may be destructed + */ void cull() { std::map::iterator itr = m_ptrs.begin(); @@ -172,22 +206,21 @@ namespace dispatchkit if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1) { std::map::iterator todel = itr; - // std::cout << "Releasing unique ptr " << std::endl; ++itr; m_ptrs.erase(todel); } else { ++itr; } } - - // std::cout << "References held: " << m_ptrs.size() << std::endl; } - std::map m_ptrs; }; public: + /** + * Basic Boxed_Value constructor + */ template explicit Boxed_Value(T t) : m_data(get_object_cache().get(t)) @@ -195,11 +228,17 @@ namespace dispatchkit get_object_cache().cull(); } + /** + * Copy constructor - each copy shares the same data pointer + */ Boxed_Value(const Boxed_Value &t_so) : m_data(t_so.m_data) { } + /** + * Unknown-type constructor + */ Boxed_Value() : m_data(get_object_cache().get()) { @@ -209,20 +248,28 @@ namespace dispatchkit { } - + /** + * Return a reference to the static global Object_Cache + */ Object_Cache &get_object_cache() { static Object_Cache oc; return oc; } - + /** + * copy the values stored in rhs.m_data to m_data + * m_data pointers are not shared in this case + */ Boxed_Value assign(const Boxed_Value &rhs) { (*m_data) = (*rhs.m_data); return *this; } + /** + * shared data assignment, same as copy construction + */ Boxed_Value &operator=(const Boxed_Value &rhs) { m_data = rhs.m_data; @@ -234,6 +281,9 @@ namespace dispatchkit return m_data->m_type_info; } + /** + * return true if the object is uninitialized + */ bool is_unknown() const { return m_data->m_type_info.m_is_unknown; @@ -254,7 +304,11 @@ namespace dispatchkit }; - //cast_help specializations + // Cast_Helper helper classes + + /** + * Generic Cast_Helper, for casting to any type + */ template struct Cast_Helper { @@ -271,6 +325,9 @@ namespace dispatchkit } }; + /** + * Cast_Helper for casting to a const & type + */ template struct Cast_Helper { @@ -287,6 +344,9 @@ namespace dispatchkit } }; + /** + * Cast_Helper for casting to a const * type + */ template struct Cast_Helper { @@ -303,6 +363,9 @@ namespace dispatchkit } }; + /** + * Cast_Helper for casting to a * type + */ template struct Cast_Helper { @@ -319,6 +382,9 @@ namespace dispatchkit } }; + /** + * Cast_Helper for casting to a & type + */ template struct Cast_Helper { @@ -335,6 +401,9 @@ namespace dispatchkit } }; + /** + * Cast_Helper for casting to a boost::shared_ptr<> type + */ template struct Cast_Helper > { @@ -347,6 +416,9 @@ namespace dispatchkit }; + /** + * Cast_Helper for casting to a Boxed_Value type + */ template<> struct Cast_Helper { @@ -358,6 +430,9 @@ namespace dispatchkit } }; + /** + * Cast_Helper for casting to a const Boxed_Value & type + */ template<> struct Cast_Helper { @@ -369,7 +444,10 @@ namespace dispatchkit } }; - + /** + * class that is thrown in the event of a bad_boxed_cast. That is, + * in the case that a Boxed_Value cannot be cast to the desired type + */ class bad_boxed_cast : public std::bad_cast { public: @@ -396,6 +474,11 @@ namespace dispatchkit std::string m_what; }; + /** + * boxed_cast function for casting a Boxed_Value into a given type + * example: + * int &i = boxed_cast(boxedvalue); + */ template typename Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv) { @@ -406,6 +489,10 @@ namespace dispatchkit } } + /** + * Object which attempts to convert a Boxed_Value into a generic + * POD type and provide generic POD type operations + */ struct Boxed_POD_Value { Boxed_POD_Value(const Boxed_Value &v) @@ -456,7 +543,6 @@ namespace dispatchkit } } - bool operator==(const Boxed_POD_Value &r) const { return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i); @@ -533,6 +619,9 @@ namespace dispatchkit bool m_isfloat; }; + /** + * Cast_Helper for converting from Boxed_Value to Boxed_POD_Value + */ template<> struct Cast_Helper { diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 2741819..ababb23 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #ifndef __dispatchkit_hpp__ #define __dispatchkit_hpp__ @@ -19,6 +25,11 @@ namespace dispatchkit { + /** + * A Proxy_Function implementation that is able to take + * a vector of Proxy_Functions and perform a dispatch on them. It is + * used specifically in the case of dealing with Function object variables + */ class Dispatch_Function : public Proxy_Function { public: @@ -73,7 +84,11 @@ namespace dispatchkit std::vector > > m_funcs; }; - + + /** + * Main class for the dispatchkit. Handles management + * of the object stack, functions and registered types. + */ class Dispatch_Engine { public: @@ -87,18 +102,27 @@ namespace dispatchkit m_scopes.push_back(Scope()); } + /** + * Add a new named Proxy_Function to the system + */ bool register_function(const boost::shared_ptr &f, const std::string &name) { return add_function(f, name); } + /** + * Add a generic, named boost::function() to the system + */ template bool register_function(const Function &func, const std::string &name) { return add_function(boost::shared_ptr(new Proxy_Function_Impl(func)), name); } - + /** + * Set the value of an object, by name. If the object + * is not available in the current scope it is created + */ template void set_object(const std::string &name, const Class &obj) { @@ -115,17 +139,26 @@ namespace dispatchkit add_object(name, obj); } + /** + * Adds a named object to the current scope + */ template void add_object(const std::string &name, const Class &obj) { m_scopes.back()[name] = Boxed_Value(obj); } + /** + * Adds a new scope to the stack + */ void new_scope() { m_scopes.push_back(Scope()); } + /** + * Pops the current scope from the stack + */ void pop_scope() { if (m_scopes.size() > 1) @@ -136,18 +169,30 @@ namespace dispatchkit } } + /** + * Returns the current stack + */ Stack get_stack() { return m_scopes; } + /** + * Swaps out the stack with a new stack + * \returns the old stack + * \param[in] s The new stack + */ Stack set_stack(Stack s) { std::swap(s, m_scopes); return s; } - + /** + * Searches the current stack for an object of the given name + * includes a special overload for the _ place holder object to + * ensure that it is always in scope. + */ Boxed_Value get_object(const std::string &name) const { if (name == "_") @@ -174,13 +219,18 @@ namespace dispatchkit } } + /** + * Registers a new named type + */ template void register_type(const std::string &name) { m_types.insert(std::make_pair(name, Get_Type_Info::get())); } - + /** + * Returns the type info for a named type + */ Type_Info get_type(const std::string &name) const { Type_Name_Map::const_iterator itr = m_types.find(name); @@ -193,6 +243,11 @@ namespace dispatchkit throw std::range_error("Type Not Known"); } + /** + * Returns the registered name of a known type_info object + * compares the "bare_type_info" for the broadest possible + * match + */ std::string get_type_name(const Type_Info &ti) const { for (Type_Name_Map::const_iterator itr = m_types.begin(); @@ -208,11 +263,37 @@ namespace dispatchkit return ti.m_bare_type_info->name(); } + /** + * Return all registered types + */ std::vector > get_types() const { return std::vector >(m_types.begin(), m_types.end()); } + /** + * Return a function by name + */ + std::vector >::mapped_type> > + get_function(const std::string &t_name) const + { + return get_function_impl(t_name, true); + } + + /** + * Get a vector of all registered functions + */ + std::vector > > get_functions() const + { + return std::vector > >(m_functions.begin(), m_functions.end()); + } + + private: + /** + * Implementation detail for searching for a function by name. + * Looks for all registered global functions and optionally for an object + * in scope with the same name + */ std::vector >::mapped_type> > get_function_impl(const std::string &t_name, bool include_objects) const { @@ -238,18 +319,11 @@ namespace dispatchkit return funcs; } - std::vector >::mapped_type> > - get_function(const std::string &t_name) const - { - return get_function_impl(t_name, true); - } - - std::vector > > get_functions() const - { - return std::vector > >(m_functions.begin(), m_functions.end()); - } - - private: + /** + * Implementation detail for adding a function. Returns + * true if the function was added, false if a function with the + * same signature and name already exists. + */ bool add_function(const boost::shared_ptr &f, const std::string &t_name) { std::pair >::const_iterator, std::multimap >::const_iterator> range @@ -275,16 +349,25 @@ namespace dispatchkit Boxed_Value m_place_holder; }; + /** + * Dump object info to stdout + */ void dump_object(Boxed_Value o, const Dispatch_Engine &e) { std::cout << e.get_type_name(o.get_type_info()) << std::endl; } + /** + * Dump type info to stdout + */ void dump_type(const Type_Info &type, const Dispatch_Engine &e) { std::cout << e.get_type_name(type); } + /** + * Dump function to stdout + */ void dump_function(const std::pair > &f, const Dispatch_Engine &e) { std::vector params = f.second->get_param_types(); @@ -307,12 +390,14 @@ namespace dispatchkit { std::cout << ", "; } - } std::cout << ") " << std::endl; } + /** + * Dump all system info to stdout + */ void dump_system(const Dispatch_Engine &s) { std::cout << "Registered Types: " << std::endl; @@ -326,7 +411,6 @@ namespace dispatchkit std::cout << std::endl; } - std::cout << std::endl; std::vector > > funcs = s.get_functions(); @@ -339,8 +423,6 @@ namespace dispatchkit } std::cout << std::endl; } - - } #endif diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 1c16e46..ee99cab 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #include #define addparam(z,n,text) params.push_back(Boxed_Value(BOOST_PP_CAT(p, n) )); @@ -17,6 +23,10 @@ namespace dispatchkit { + /** + * Internal helper class for handling the return + * value of a build_function_caller + */ template class Function_Caller_Ret { @@ -32,6 +42,9 @@ namespace dispatchkit } }; + /** + * Specialization for void return types + */ template<> class Function_Caller_Ret { @@ -53,7 +66,15 @@ namespace dispatchkit #include BOOST_PP_ITERATE() namespace dispatchkit -{ +{ + /** + * Build a function caller that knows how to dispatch on a set of functions + * example: + * boost::function f = + * build_function_caller(dispatchkit.get_function("print")); + * \returns A boost::function object for dispatching + * \param[in] funcs the set of functions to dispatch on. + */ template boost::function build_function_caller(const std::vector > > &funcs) @@ -62,6 +83,19 @@ namespace dispatchkit return build_function_caller_helper(p, funcs); } + /** + * Build a function caller for a particular Proxy_Function object + * useful in the case that a function is being pass out from scripting back + * into code + * example: + * void my_function(boost::shared_ptr f) + * { + * boost::function local_f = + * build_function_caller(f); + * } + * \returns A boost::function object for dispatching + * \param[in] func A function to execute. + */ template boost::function build_function_caller(boost::shared_ptr func) @@ -71,6 +105,10 @@ namespace dispatchkit return build_function_caller(funcs); } + /** + * Helper for automatically unboxing a Boxed_Value that contains a function object + * and creating a typesafe C++ function caller from it. + */ template boost::function build_function_caller(const Boxed_Value &bv) @@ -78,7 +116,14 @@ namespace dispatchkit return build_function_caller(boxed_cast >(bv)); } - + /** + * Helper for calling script code as if it were native C++ code + * example: + * boost::function f = build_functor(chai, "func(x, y){x+y}"); + * \return a boost::function representing the passed in script + * \param[in] e ScriptEngine to build the script execution from + * \param[in] script Script code to build a function from + */ template boost::function build_functor(ScriptEngine &e, const std::string &script) { @@ -92,6 +137,9 @@ namespace dispatchkit namespace dispatchkit { + /** + * used internally for unwrapping a function call's types + */ template Ret function_caller(const std::vector > > &funcs BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) @@ -103,6 +151,9 @@ namespace dispatchkit return Function_Caller_Ret().call(funcs, params); } + /** + * used internally for unwrapping a function call's types + */ template boost::function build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector > > &funcs) diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp index 65901e0..da9a772 100644 --- a/include/chaiscript/dispatchkit/proxy_constructors.hpp +++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #include #ifndef BOOST_PP_IS_ITERATING @@ -18,12 +24,22 @@ namespace dispatchkit { + /** + * A constructor function, used for creating a new object + * of a given type with a given set of params + */ template boost::shared_ptr constructor( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) { return boost::shared_ptr(new Class( BOOST_PP_ENUM_PARAMS(n, p) )); } + /** + * Helper function for build a constructor function + * example: + * dispatchengine.register_function(build_constructor, "MyClass"); + * \todo See if it is possible to make this not be a variadic function + */ template boost::function (BOOST_PP_ENUM_PARAMS(n, Param))> build_constructor() { diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index fff5bbd..a1bd48a 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #include #define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info::get()); @@ -22,7 +28,9 @@ namespace dispatchkit { - // handle_return implementations + /** + * Used internally for handling a return value from a Proxy_Function call + */ template struct Handle_Return { @@ -32,6 +40,9 @@ namespace dispatchkit } }; + /** + * Used internally for handling a return value from a Proxy_Function call + */ template struct Handle_Return { @@ -41,6 +52,9 @@ namespace dispatchkit } }; + /** + * Used internally for handling a return value from a Proxy_Function call + */ template<> struct Handle_Return { @@ -50,6 +64,9 @@ namespace dispatchkit } }; + /** + * Used internally for handling a return value from a Proxy_Function call + */ template<> struct Handle_Return { @@ -59,6 +76,9 @@ namespace dispatchkit } }; + /** + * Used internally for handling a return value from a Proxy_Function call + */ template<> struct Handle_Return { @@ -69,7 +89,14 @@ namespace dispatchkit } }; - + /** + * Helper for building a list of parameters for calling a Proxy_Function + * it does automatic conversion to Boxed_Value types via operator<< + * + * example usage: + * Boxed_Value retval = dispatch(dispatchengine.get_function("+"), + * dispatchkit::Param_List_Builder() << 5 << 6); + */ struct Param_List_Builder { Param_List_Builder &operator<<(const Boxed_Value &so) @@ -93,6 +120,10 @@ namespace dispatchkit std::vector objects; }; + /** + * Exception thrown when there is a mismatch in number of + * parameters during Proxy_Function execution + */ struct arity_error : std::range_error { arity_error(int t_got, int t_expected) @@ -105,7 +136,6 @@ namespace dispatchkit int got; int expected; }; - } #define BOOST_PP_ITERATION_LIMITS ( 0, 10 ) @@ -114,6 +144,14 @@ namespace dispatchkit namespace dispatchkit { + /** + * Pure virtual base class for all Proxy_Function implementations + * Proxy_Functions are a type erasure of type safe C++ + * function calls. At runtime parameter types are expected to be + * tested against passed in types. + * Dispatch_Engine only knows how to work with Proxy_Function, no other + * function classes. + */ class Proxy_Function { public: @@ -125,6 +163,9 @@ namespace dispatchkit virtual std::string annotation() const = 0; }; + /** + * Exception thrown if a function's guard fails to execute + */ class guard_error : public std::runtime_error { public: @@ -136,6 +177,10 @@ namespace dispatchkit { } }; + /** + * A Proxy_Function implementation that is not type safe, the called function + * is expecting a vector that it works with how it chooses. + */ class Dynamic_Proxy_Function : public Proxy_Function { public: @@ -225,10 +270,20 @@ namespace dispatchkit boost::shared_ptr m_guard; }; + /** + * An object used by Bound_Function to represent "_" parameters + * of a binding. This allows for unbound parameters during bind. + */ struct Placeholder_Object { }; + /** + * An implementation of Proxy_Function that takes a Proxy_Function + * and substitutes bound parameters into the parameter list + * at runtime, when call() is executed. + * it is used for bind(function, param1, _, param2) style calls + */ class Bound_Function : public Proxy_Function { public: @@ -291,7 +346,6 @@ namespace dispatchkit break; } } - return args; } @@ -305,12 +359,16 @@ namespace dispatchkit return ""; } - private: boost::shared_ptr m_f; std::vector m_args; }; + /** + * The standard typesafe function call implementation of Proxy_Function + * It takes a boost::function<> object and performs runtime + * type checking of Boxed_Value parameters, in a type safe manner + */ template class Proxy_Function_Impl : public Proxy_Function { @@ -352,11 +410,16 @@ namespace dispatchkit return ""; } - private: Func m_f; }; + /** + * Exception thrown in the case that a multi method dispatch fails + * because no matching function was found + * at runtime due to either an arity_error, a guard_error or a bad_boxed_cast + * exception + */ struct dispatch_error : std::runtime_error { dispatch_error() throw() @@ -367,6 +430,11 @@ namespace dispatchkit virtual ~dispatch_error() throw() {} }; + /** + * Take a vector of functions and a vector of parameters. Attempt to execute + * each function against the set of parameters, in order, until a matching + * function is found or throw dispatch_error if no matching function is found + */ Boxed_Value dispatch(const std::vector > > &funcs, const std::vector &plist) { @@ -385,7 +453,6 @@ namespace dispatchkit //try again } } - throw dispatch_error(); } } @@ -396,7 +463,10 @@ namespace dispatchkit namespace dispatchkit { - + /** + * Used by Proxy_Function_Impl to return a list of all param types + * it contains. + */ template std::vector build_param_type_list(const boost::function &) { @@ -408,6 +478,12 @@ namespace dispatchkit return ti; } + /** + * Used by Proxy_Function_Impl to perform typesafe execution of a function. + * The function attempts to unbox each paramter to the expected type. + * if any unboxing fails the execution of the function fails and + * the bad_boxed_cast is passed up to the caller. + */ template Boxed_Value call_func(const boost::function &f, const std::vector ¶ms) @@ -420,6 +496,11 @@ namespace dispatchkit } } + /** + * Used by Proxy_Function_Impl to determine if it is equivalent to another + * Proxy_Function_Impl object. This function is primarly used to prevent + * registration of two functions with the exact same signatures + */ template bool compare_types(const boost::function &, const std::vector ¶ms) @@ -440,8 +521,6 @@ namespace dispatchkit return true; } } - } #endif - diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 265a63b..bccdfd0 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #include #ifndef BOOST_PP_IS_ITERATING @@ -10,12 +16,20 @@ namespace dispatchkit { + /** + * Helper function for register_member function + */ template T &get_member(T Class::* m, Class *obj) { return obj->*m; } + /** + * Automatically create a get_member helper function for an object + * to allow for runtime dispatched access to public data members + * for example, the case of std::pair<>::first and std::pair<>::second + */ template void register_member(Dispatch_Engine &s, T Class::* m, const std::string &name) { @@ -33,18 +47,27 @@ namespace dispatchkit namespace dispatchkit { + /** + * Register a global function of n parameters with name + */ template void register_function(Dispatch_Engine &s, Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name) { s.register_function(boost::function(f), name); } + /** + * Register a class method of n parameters with name + */ template void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name) { s.register_function(boost::function(f), name); } + /** + * Register a const class method of n parameters with name + */ template void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const std::string &name) { diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index e47c025..53f9884 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -1,3 +1,9 @@ +// This file is distributed under the BSD License. +// See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + #ifndef __type_info_hpp__ #define __type_info_hpp__ @@ -12,6 +18,9 @@ namespace dispatchkit { + /** + * compile time deduced information about a type + */ struct Type_Info { Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, @@ -68,6 +77,9 @@ namespace dispatchkit bool m_is_unknown; }; + /** + * Helper used to create a Type_Info object + */ template struct Get_Type_Info { diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index f4324df..4eb3c25 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -1,5 +1,8 @@ // This file is distributed under the BSD License. // See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com #ifndef CHAISCRIPT_ENGINE_HPP_ #define CHAISCRIPT_ENGINE_HPP_ diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index a019f3f..3c1b2b0 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1,5 +1,8 @@ // This file is distributed under the BSD License. // See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com #ifndef CHAISCRIPT_EVAL_HPP_ #define CHAISCRIPT_EVAL_HPP_ diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 8dee612..9a2f49c 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1,5 +1,8 @@ // This file is distributed under the BSD License. // See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com #ifndef CHAISCRIPT_PARSER_HPP_ #define CHAISCRIPT_PARSER_HPP_ diff --git a/include/chaiscript/language/chaiscript_prelude.hpp b/include/chaiscript/language/chaiscript_prelude.hpp index 6409e0e..037b613 100644 --- a/include/chaiscript/language/chaiscript_prelude.hpp +++ b/include/chaiscript/language/chaiscript_prelude.hpp @@ -1,5 +1,8 @@ // This file is distributed under the BSD License. // See LICENSE.TXT for details. +// Copyright 2009, Jonathan Turner (jonathan.d.turner@gmail.com) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com #ifndef CHAISCRIPT_PRELUDE_HPP_ #define CHAISCRIPT_PRELUDE_HPP_