Documentation updates.

This commit is contained in:
Jason Turner 2009-07-12 03:07:45 +00:00
parent c9e67f2063
commit a70dc12b2a
14 changed files with 649 additions and 81 deletions

View File

@ -1,5 +1,8 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See LICENSE.TXT for details. // 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_ #ifndef CHAISCRIPT_HPP_
#define CHAISCRIPT_HPP_ #define CHAISCRIPT_HPP_

View File

@ -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 #ifndef __bootstrap_hpp
#define __bootstrap_hpp__ #define __bootstrap_hpp__
@ -15,28 +21,24 @@ namespace dispatchkit
return p1 + p2; return p1 + p2;
} }
template<typename Ret, typename P1, typename P2> template<typename Ret, typename P1, typename P2>
Ret subtract(P1 p1, P2 p2) Ret subtract(P1 p1, P2 p2)
{ {
return p1 - p2; return p1 - p2;
} }
template<typename Ret, typename P1, typename P2> template<typename Ret, typename P1, typename P2>
Ret divide(P1 p1, P2 p2) Ret divide(P1 p1, P2 p2)
{ {
return p1 / p2; return p1 / p2;
} }
template<typename Ret, typename P1, typename P2> template<typename Ret, typename P1, typename P2>
Ret multiply(P1 p1, P2 p2) Ret multiply(P1 p1, P2 p2)
{ {
return p1 * p2; return p1 * p2;
} }
template<typename Ret, typename P1, typename P2> template<typename Ret, typename P1, typename P2>
Ret modulus(P1 p1, P2 p2) Ret modulus(P1 p1, P2 p2)
{ {
@ -49,16 +51,12 @@ namespace dispatchkit
return (p1 = p2); return (p1 = p2);
} }
template<typename P1, typename P2> template<typename P1, typename P2>
bool equals(P1 p1, P2 p2) bool equals(P1 p1, P2 p2)
{ {
return p1 == p2; return p1 == p2;
} }
template<typename P1, typename P2> template<typename P1, typename P2>
bool not_equals(P1 p1, P2 p2) bool not_equals(P1 p1, P2 p2)
{ {
@ -102,7 +100,6 @@ namespace dispatchkit
return (p1 /= p2); return (p1 /= p2);
} }
template<typename P1, typename P2> template<typename P1, typename P2>
P1 &addsequal(P1 &p1, const P2 &p2) P1 &addsequal(P1 &p1, const P2 &p2)
{ {
@ -115,8 +112,6 @@ namespace dispatchkit
return (p1 -= p2); return (p1 -= p2);
} }
template<typename P1> template<typename P1>
P1 &prefixincrement(P1 &p1) P1 &prefixincrement(P1 &p1)
{ {
@ -259,18 +254,27 @@ namespace dispatchkit
register_function(s, &divide<T, const T&, const T&>, "/"); register_function(s, &divide<T, const T&, const T&>, "/");
} }
/**
* Add canonical form of "*" for type T
*/
template<typename T> template<typename T>
void add_oper_multiply(Dispatch_Engine &s) void add_oper_multiply(Dispatch_Engine &s)
{ {
register_function(s, &multiply<T, const T&, const T&>, "*"); register_function(s, &multiply<T, const T&, const T&>, "*");
} }
/**
* Add canonical form of "!=" for type T
*/
template<typename T> template<typename T>
void add_oper_not_equals(Dispatch_Engine &s) void add_oper_not_equals(Dispatch_Engine &s)
{ {
register_function(s, &not_equals<const T&, const T&>, "!="); register_function(s, &not_equals<const T&, const T&>, "!=");
} }
/**
* Add user defined assignment operator for T = U
*/
template<typename T, typename U> template<typename T, typename U>
void add_oper_assign_overload(Dispatch_Engine &s) void add_oper_assign_overload(Dispatch_Engine &s)
{ {
@ -278,6 +282,9 @@ namespace dispatchkit
} }
/**
* Add canonical form of "=" for type T
*/
template<typename T> template<typename T>
void add_oper_assign(Dispatch_Engine &s) void add_oper_assign(Dispatch_Engine &s)
{ {
@ -285,6 +292,9 @@ namespace dispatchkit
} }
/**
* Add assignment operator for T = POD.
*/
template<typename T> template<typename T>
void add_oper_assign_pod(Dispatch_Engine &s) void add_oper_assign_pod(Dispatch_Engine &s)
{ {
@ -292,31 +302,46 @@ namespace dispatchkit
} }
/**
* Add canonical form of "<" for type T
*/
template<typename T> template<typename T>
void add_oper_less_than(Dispatch_Engine &s) void add_oper_less_than(Dispatch_Engine &s)
{ {
register_function(s, &less_than<const T&, const T&>, "<"); register_function(s, &less_than<const T&, const T&>, "<");
} }
/**
* Add canonical form of ">" for type T
*/
template<typename T> template<typename T>
void add_oper_greater_than(Dispatch_Engine &s) void add_oper_greater_than(Dispatch_Engine &s)
{ {
register_function(s, &greater_than<const T&, const T&>, ">"); register_function(s, &greater_than<const T&, const T&>, ">");
} }
/**
* Add canonical form of "<=" for type T
*/
template<typename T> template<typename T>
void add_oper_less_than_equals(Dispatch_Engine &s) void add_oper_less_than_equals(Dispatch_Engine &s)
{ {
register_function(s, &less_than_equals<const T&, const T&>, "<="); register_function(s, &less_than_equals<const T&, const T&>, "<=");
} }
/**
* Add canonical form of ">=" for type T
*/
template<typename T> template<typename T>
void add_oper_greater_than_equals(Dispatch_Engine &s) void add_oper_greater_than_equals(Dispatch_Engine &s)
{ {
register_function(s, &greater_than_equals<const T&, const T&>, ">="); register_function(s, &greater_than_equals<const T&, const T&>, ">=");
} }
/**
* Add user defined comparison operators for T and R.
* Examples: T < R, T == R, etc.
*/
template<typename T, typename R> template<typename T, typename R>
void add_opers_comparison_overload(Dispatch_Engine &s) void add_opers_comparison_overload(Dispatch_Engine &s)
{ {
@ -328,12 +353,22 @@ namespace dispatchkit
register_function(s, &greater_than_equals<const T&, const R&>, ">="); register_function(s, &greater_than_equals<const T&, const R&>, ">=");
} }
/**
* Add canonical forms of all comparison operators for type T
*/
template<typename T> template<typename T>
void add_opers_comparison(Dispatch_Engine &s) void add_opers_comparison(Dispatch_Engine &s)
{ {
add_opers_comparison_overload<T, T>(s); add_opers_comparison_overload<T, T>(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<typename Ret, typename T, typename R> template<typename Ret, typename T, typename R>
void add_opers_arithmetic_overload(Dispatch_Engine &s) void add_opers_arithmetic_overload(Dispatch_Engine &s)
{ {
@ -351,6 +386,10 @@ namespace dispatchkit
register_function(s, &prefixnot<T>, "!"); register_function(s, &prefixnot<T>, "!");
} }
/**
* Add arithmetic assign operators for POD types:
* example: POD *= T, POD /= T
*/
template<typename T> template<typename T>
void add_opers_arithmetic_modify_pod(Dispatch_Engine &s) void add_opers_arithmetic_modify_pod(Dispatch_Engine &s)
{ {
@ -360,6 +399,11 @@ namespace dispatchkit
register_function(s, &addsequal_pod<T>, "+="); register_function(s, &addsequal_pod<T>, "+=");
} }
/**
* 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<typename T> template<typename T>
void add_copy_constructor(Dispatch_Engine &s, const std::string &type) void add_copy_constructor(Dispatch_Engine &s, const std::string &type)
{ {
@ -367,6 +411,9 @@ namespace dispatchkit
s.register_function(build_constructor<T, const T &>(), "clone"); s.register_function(build_constructor<T, const T &>(), "clone");
} }
/**
* Add default and copy constructors (including "clone") for type T
*/
template<typename T> template<typename T>
void add_basic_constructors(Dispatch_Engine &s, const std::string &type) void add_basic_constructors(Dispatch_Engine &s, const std::string &type)
{ {
@ -374,18 +421,28 @@ namespace dispatchkit
add_copy_constructor<T>(s, type); add_copy_constructor<T>(s, type);
} }
/**
* Add POD type constructor for type T. ie: T = type(POD)
*/
template<typename T> template<typename T>
void add_construct_pod(Dispatch_Engine &s, const std::string &type) void add_construct_pod(Dispatch_Engine &s, const std::string &type)
{ {
register_function(s, &construct_pod<T>, type); register_function(s, &construct_pod<T>, type);
} }
/**
* add user defined single parameter constructor for type T.
* T = type(const U &)
*/
template<typename T, typename U> template<typename T, typename U>
void add_constructor_overload(Dispatch_Engine &s, const std::string &type) void add_constructor_overload(Dispatch_Engine &s, const std::string &type)
{ {
s.register_function(build_constructor<T, const U &>(), type); s.register_function(build_constructor<T, const U &>(), type);
} }
/**
* Add canonical forms of all arithmetic operators for type T
*/
template<typename T> template<typename T>
void add_opers_arithmetic(Dispatch_Engine &s) void add_opers_arithmetic(Dispatch_Engine &s)
{ {
@ -393,15 +450,18 @@ namespace dispatchkit
} }
/**
* to_string function for internal use. Uses ostream operator<<
//Built in to_string operator */
template<typename Input> template<typename Input>
std::string to_string(Input i) std::string to_string(Input i)
{ {
return boost::lexical_cast<std::string>(i); return boost::lexical_cast<std::string>(i);
} }
/**
* Boolean specialization of internal to_string function
*/
template<> std::string to_string(bool b) template<> std::string to_string(bool b)
{ {
if (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<typename Input> template<typename Input>
Input parse_string(const std::string &i) Input parse_string(const std::string &i)
{ {
return boost::lexical_cast<Input>(i); return boost::lexical_cast<Input>(i);
} }
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T> template<typename T>
void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name) void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name)
{ {
@ -434,12 +500,24 @@ namespace dispatchkit
register_function(s, &parse_string<T>, "to_" + name); register_function(s, &parse_string<T>, "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<Proxy_Function> object (that is,
* function variables.
*/
template<typename Type> template<typename Type>
boost::shared_ptr<Type> shared_ptr_clone(boost::shared_ptr<Type> f) boost::shared_ptr<Type> shared_ptr_clone(boost::shared_ptr<Type> f)
{ {
return 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<typename Type> template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, boost::shared_ptr<Type> rhs) Boxed_Value ptr_assign(Boxed_Value lhs, boost::shared_ptr<Type> rhs)
{ {
@ -448,9 +526,15 @@ namespace dispatchkit
return lhs; return lhs;
} }
/**
* Class consisting of only static functions. All default bootstrapping occurs
* from this class.
*/
struct Bootstrap 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) static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
{ {
if (lhs.is_unknown()) if (lhs.is_unknown())
@ -471,6 +555,9 @@ namespace dispatchkit
std::cout << s << std::endl; std::cout << s << std::endl;
} }
/**
* Add all comparison operators for POD types
*/
static void add_opers_comparison_pod(Dispatch_Engine &s) static void add_opers_comparison_pod(Dispatch_Engine &s)
{ {
register_function(s, &equals<Boxed_POD_Value, Boxed_POD_Value>, "=="); register_function(s, &equals<Boxed_POD_Value, Boxed_POD_Value>, "==");
@ -481,6 +568,9 @@ namespace dispatchkit
register_function(s, &greater_than_equals<Boxed_POD_Value, Boxed_POD_Value>, ">="); register_function(s, &greater_than_equals<Boxed_POD_Value, Boxed_POD_Value>, ">=");
} }
/**
* Add all arithmetic operators for PODs
*/
static void add_opers_arithmetic_pod(Dispatch_Engine &s) static void add_opers_arithmetic_pod(Dispatch_Engine &s)
{ {
register_function(s, &add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "+"); register_function(s, &add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "+");
@ -489,11 +579,17 @@ namespace dispatchkit
register_function(s, &multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "*"); register_function(s, &multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "*");
} }
/**
* Return true if the two Boxed_Value's share the same internal type
*/
static bool type_match(Boxed_Value l, Boxed_Value r) static bool type_match(Boxed_Value l, Boxed_Value r)
{ {
return l.get_type_info() == r.get_type_info(); 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) static bool is_type(const Dispatch_Engine &e, const std::string &type_name, Boxed_Value r)
{ {
try { 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<Boxed_Value> &params) static Boxed_Value bind_function(const std::vector<Boxed_Value> &params)
{ {
if (params.size() < 2) if (params.size() < 2)
@ -516,6 +617,10 @@ namespace dispatchkit
std::vector<Boxed_Value>(params.begin() + 1, params.end())))); std::vector<Boxed_Value>(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<Boxed_Value> &params) static Boxed_Value call_exists(const std::vector<Boxed_Value> &params)
{ {
if (params.size() < 1) if (params.size() < 1)
@ -528,6 +633,9 @@ namespace dispatchkit
return Boxed_Value(f->types_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()))); return Boxed_Value(f->types_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
} }
/**
* perform all common bootstrap functions for std::string, void and POD types
*/
static void bootstrap(Dispatch_Engine &s) static void bootstrap(Dispatch_Engine &s)
{ {
s.register_type<void>("void"); s.register_type<void>("void");

View File

@ -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 #ifndef __bootstrap_stl_hpp
#define __bootstrap_stl_hpp__ #define __bootstrap_stl_hpp__
@ -7,6 +20,11 @@
namespace dispatchkit 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<typename Container> template<typename Container>
struct Input_Range struct Input_Range
{ {
@ -52,6 +70,10 @@ namespace dispatchkit
typename Container::iterator m_end; typename Container::iterator m_end;
}; };
/**
* Add Input_Range support for the given ContainerType
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_input_range(Dispatch_Engine &system, const std::string &type) void bootstrap_input_range(Dispatch_Engine &system, const std::string &type)
{ {
@ -75,11 +97,19 @@ namespace dispatchkit
system.register_function(build_constructor<Input_Range<ContainerType>, const Input_Range<ContainerType> &>(), "clone"); system.register_function(build_constructor<Input_Range<ContainerType>, const Input_Range<ContainerType> &>(), "clone");
} }
/**
* Add reversible_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ReversibleContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_reversible_container(Dispatch_Engine &/*system*/, const std::string &/*type*/) 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<typename ContainerType> template<typename ContainerType>
void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type) 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, //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. //to throw an exception in an out of bounds condition.
system.register_function( register_function(system, indexoper(&ContainerType::at), "[]");
boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::at)), "[]"); register_function(system, indexoper(&ContainerType::operator[]), "at");
system.register_function(
boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::operator[])), "at");
} }
template<typename Assignable> /**
* Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType>
void bootstrap_assignable(Dispatch_Engine &system, const std::string &type) void bootstrap_assignable(Dispatch_Engine &system, const std::string &type)
{ {
add_basic_constructors<Assignable>(system, type); add_basic_constructors<ContainerType>(system, type);
add_oper_assign<Assignable>(system); add_oper_assign<ContainerType>(system);
} }
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_container(Dispatch_Engine &system, const std::string &type) void bootstrap_container(Dispatch_Engine &system, const std::string &type)
{ {
@ -112,6 +148,10 @@ namespace dispatchkit
register_function(system, &ContainerType::empty, "empty"); register_function(system, &ContainerType::empty, "empty");
} }
/**
* Add forward container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ForwardContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type) void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type)
{ {
@ -119,12 +159,19 @@ namespace dispatchkit
bootstrap_container<ContainerType>(system, type); bootstrap_container<ContainerType>(system, type);
} }
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type> template<typename Type>
void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type) void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type)
{ {
system.register_function(build_constructor<Type>(), type); system.register_function(build_constructor<Type>(), type);
} }
/**
* Algorithm for inserting at a specific position into a container
*/
template<typename Type> template<typename Type>
void insert_at(Type &container, int pos, const typename Type::value_type &v) void insert_at(Type &container, int pos, const typename Type::value_type &v)
{ {
@ -140,6 +187,9 @@ namespace dispatchkit
container.insert(itr, v); container.insert(itr, v);
} }
/**
* Algorithm for erasing a specific position from a container
*/
template<typename Type> template<typename Type>
void erase_at(Type &container, int pos) void erase_at(Type &container, int pos)
{ {
@ -155,46 +205,58 @@ namespace dispatchkit
container.erase(itr); container.erase(itr);
} }
template<typename SequenceType> /**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
void bootstrap_sequence(Dispatch_Engine &system, const std::string &type) void bootstrap_sequence(Dispatch_Engine &system, const std::string &type)
{ {
bootstrap_forward_container<SequenceType>(system, type); bootstrap_forward_container<ContainerType>(system, type);
bootstrap_default_constructible<SequenceType>(system, type); bootstrap_default_constructible<ContainerType>(system, type);
std::string insert_name; 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"; insert_name = "insert_ref_at";
} else { } else {
insert_name = "insert_at"; insert_name = "insert_at";
} }
register_function(system, &insert_at<SequenceType>, insert_name); register_function(system, &insert_at<ContainerType>, insert_name);
register_function(system, &erase_at<SequenceType>, "erase_at"); register_function(system, &erase_at<ContainerType>, "erase_at");
} }
template<typename SequenceType> /**
* Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type) void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type)
{ {
bootstrap_sequence<SequenceType>(system, type); bootstrap_sequence<ContainerType>(system, type);
typedef typename SequenceType::reference (SequenceType::*backptr)(); typedef typename ContainerType::reference (ContainerType::*backptr)();
system.register_function(boost::function<typename SequenceType::reference (SequenceType *)>(backptr(&SequenceType::back)), "back"); register_function(system, (backptr(&ContainerType::back)), "back");
std::string push_back_name; 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"; push_back_name = "push_back_ref";
} else { } else {
push_back_name = "push_back"; push_back_name = "push_back";
} }
register_function(system, &SequenceType::push_back, push_back_name); register_function(system, &ContainerType::push_back, push_back_name);
register_function(system, &SequenceType::pop_back, "pop_back"); register_function(system, &ContainerType::pop_back, "pop_back");
} }
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType> template<typename VectorType>
void bootstrap_vector(Dispatch_Engine &system, const std::string &type) void bootstrap_vector(Dispatch_Engine &system, const std::string &type)
{ {
@ -203,6 +265,10 @@ namespace dispatchkit
bootstrap_back_insertion_sequence<VectorType>(system, type); bootstrap_back_insertion_sequence<VectorType>(system, type);
} }
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type) void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type)
{ {
@ -210,6 +276,10 @@ namespace dispatchkit
bootstrap_default_constructible<ContainerType>(system, type); bootstrap_default_constructible<ContainerType>(system, type);
} }
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType> template<typename PairType>
void bootstrap_pair(Dispatch_Engine &system, const std::string &type) 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<typename ContainerType> template<typename ContainerType>
void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type) void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type)
{ {
@ -232,6 +306,10 @@ namespace dispatchkit
bootstrap_pair<typename ContainerType::value_type>(system, type + "_Pair"); bootstrap_pair<typename ContainerType::value_type>(system, type + "_Pair");
} }
/**
* Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type) void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type)
{ {
@ -239,6 +317,10 @@ namespace dispatchkit
register_function(system, &ContainerType::count, "count"); register_function(system, &ContainerType::count, "count");
} }
/**
* Add sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
*/
template<typename ContainerType> template<typename ContainerType>
void bootstrap_sorted_associative_container(Dispatch_Engine &system, const std::string &type) 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"); 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<typename ContainerType> template<typename ContainerType>
void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type) void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type)
{ {
@ -257,6 +343,10 @@ namespace dispatchkit
bootstrap_unique_associative_container<ContainerType>(system, type); bootstrap_unique_associative_container<ContainerType>(system, type);
} }
/**
* Add a MapType container
* http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType> template<typename MapType>
void bootstrap_map(Dispatch_Engine &system, const std::string &type) void bootstrap_map(Dispatch_Engine &system, const std::string &type)
{ {
@ -266,6 +356,10 @@ namespace dispatchkit
bootstrap_pair_associative_container<MapType>(system, type); bootstrap_pair_associative_container<MapType>(system, type);
} }
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String> template<typename String>
void bootstrap_string(Dispatch_Engine &system, const std::string &type) 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_first_not_of), "find_first_not_of");
register_function(system, find_func(&String::find_last_not_of), "find_last_not_of"); register_function(system, find_func(&String::find_last_not_of), "find_last_not_of");
} }
} }
#endif #endif

View File

@ -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__ #ifndef __boxed_value_hpp__
#define __boxed_value_hpp__ #define __boxed_value_hpp__
@ -13,16 +19,32 @@
namespace dispatchkit 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 class Boxed_Value
{ {
public: public:
/**
* used for explicitly creating a "void" object
*/
struct Void_Type struct Void_Type
{ {
}; };
private: private:
/**
* structure which holds the internal state of a Boxed_Value
*/
struct Data struct Data
{ {
/**
* used to provide type-erased access to the internal boost::shared_ptr
* reference count information
*/
struct Shared_Ptr_Proxy struct Shared_Ptr_Proxy
{ {
virtual ~Shared_Ptr_Proxy() virtual ~Shared_Ptr_Proxy()
@ -33,6 +55,9 @@ namespace dispatchkit
virtual long use_count(boost::any *) = 0; virtual long use_count(boost::any *) = 0;
}; };
/**
* Typed implementation of the Shared_Ptr_Proxy
*/
template<typename T> template<typename T>
struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
{ {
@ -83,6 +108,12 @@ namespace dispatchkit
boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy; boost::shared_ptr<Shared_Ptr_Proxy> 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 struct Object_Cache
{ {
boost::shared_ptr<Data> get(Boxed_Value::Void_Type) boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
@ -131,7 +162,6 @@ namespace dispatchkit
if (itr != m_ptrs.end()) if (itr != m_ptrs.end())
{ {
// std::cout << "Reference wrapper ptr found, using it" << std::endl;
(*data) = (itr->second); (*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() void cull()
{ {
std::map<void *, Data >::iterator itr = m_ptrs.begin(); std::map<void *, Data >::iterator itr = m_ptrs.begin();
@ -172,22 +206,21 @@ namespace dispatchkit
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1) if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
{ {
std::map<void *, Data >::iterator todel = itr; std::map<void *, Data >::iterator todel = itr;
// std::cout << "Releasing unique ptr " << std::endl;
++itr; ++itr;
m_ptrs.erase(todel); m_ptrs.erase(todel);
} else { } else {
++itr; ++itr;
} }
} }
// std::cout << "References held: " << m_ptrs.size() << std::endl;
} }
std::map<void *, Data > m_ptrs; std::map<void *, Data > m_ptrs;
}; };
public: public:
/**
* Basic Boxed_Value constructor
*/
template<typename T> template<typename T>
explicit Boxed_Value(T t) explicit Boxed_Value(T t)
: m_data(get_object_cache().get(t)) : m_data(get_object_cache().get(t))
@ -195,11 +228,17 @@ namespace dispatchkit
get_object_cache().cull(); get_object_cache().cull();
} }
/**
* Copy constructor - each copy shares the same data pointer
*/
Boxed_Value(const Boxed_Value &t_so) Boxed_Value(const Boxed_Value &t_so)
: m_data(t_so.m_data) : m_data(t_so.m_data)
{ {
} }
/**
* Unknown-type constructor
*/
Boxed_Value() Boxed_Value()
: m_data(get_object_cache().get()) : 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() Object_Cache &get_object_cache()
{ {
static Object_Cache oc; static Object_Cache oc;
return 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) Boxed_Value assign(const Boxed_Value &rhs)
{ {
(*m_data) = (*rhs.m_data); (*m_data) = (*rhs.m_data);
return *this; return *this;
} }
/**
* shared data assignment, same as copy construction
*/
Boxed_Value &operator=(const Boxed_Value &rhs) Boxed_Value &operator=(const Boxed_Value &rhs)
{ {
m_data = rhs.m_data; m_data = rhs.m_data;
@ -234,6 +281,9 @@ namespace dispatchkit
return m_data->m_type_info; return m_data->m_type_info;
} }
/**
* return true if the object is uninitialized
*/
bool is_unknown() const bool is_unknown() const
{ {
return m_data->m_type_info.m_is_unknown; 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<typename Result> template<typename Result>
struct Cast_Helper struct Cast_Helper
{ {
@ -271,6 +325,9 @@ namespace dispatchkit
} }
}; };
/**
* Cast_Helper for casting to a const & type
*/
template<typename Result> template<typename Result>
struct Cast_Helper<const Result &> struct Cast_Helper<const Result &>
{ {
@ -287,6 +344,9 @@ namespace dispatchkit
} }
}; };
/**
* Cast_Helper for casting to a const * type
*/
template<typename Result> template<typename Result>
struct Cast_Helper<const Result *> struct Cast_Helper<const Result *>
{ {
@ -303,6 +363,9 @@ namespace dispatchkit
} }
}; };
/**
* Cast_Helper for casting to a * type
*/
template<typename Result> template<typename Result>
struct Cast_Helper<Result *> struct Cast_Helper<Result *>
{ {
@ -319,6 +382,9 @@ namespace dispatchkit
} }
}; };
/**
* Cast_Helper for casting to a & type
*/
template<typename Result> template<typename Result>
struct Cast_Helper<Result &> struct Cast_Helper<Result &>
{ {
@ -335,6 +401,9 @@ namespace dispatchkit
} }
}; };
/**
* Cast_Helper for casting to a boost::shared_ptr<> type
*/
template<typename Result> template<typename Result>
struct Cast_Helper<typename boost::shared_ptr<Result> > struct Cast_Helper<typename boost::shared_ptr<Result> >
{ {
@ -347,6 +416,9 @@ namespace dispatchkit
}; };
/**
* Cast_Helper for casting to a Boxed_Value type
*/
template<> template<>
struct Cast_Helper<Boxed_Value> struct Cast_Helper<Boxed_Value>
{ {
@ -358,6 +430,9 @@ namespace dispatchkit
} }
}; };
/**
* Cast_Helper for casting to a const Boxed_Value & type
*/
template<> template<>
struct Cast_Helper<const Boxed_Value &> struct Cast_Helper<const Boxed_Value &>
{ {
@ -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 class bad_boxed_cast : public std::bad_cast
{ {
public: public:
@ -396,6 +474,11 @@ namespace dispatchkit
std::string m_what; std::string m_what;
}; };
/**
* boxed_cast function for casting a Boxed_Value into a given type
* example:
* int &i = boxed_cast<int &>(boxedvalue);
*/
template<typename Type> template<typename Type>
typename Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) typename Cast_Helper<Type>::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 struct Boxed_POD_Value
{ {
Boxed_POD_Value(const Boxed_Value &v) Boxed_POD_Value(const Boxed_Value &v)
@ -456,7 +543,6 @@ namespace dispatchkit
} }
} }
bool operator==(const Boxed_POD_Value &r) const bool operator==(const Boxed_POD_Value &r) const
{ {
return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i); return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i);
@ -533,6 +619,9 @@ namespace dispatchkit
bool m_isfloat; bool m_isfloat;
}; };
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<> template<>
struct Cast_Helper<Boxed_POD_Value> struct Cast_Helper<Boxed_POD_Value>
{ {

View File

@ -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__ #ifndef __dispatchkit_hpp__
#define __dispatchkit_hpp__ #define __dispatchkit_hpp__
@ -19,6 +25,11 @@
namespace dispatchkit 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 class Dispatch_Function : public Proxy_Function
{ {
public: public:
@ -73,7 +84,11 @@ namespace dispatchkit
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > m_funcs; std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > m_funcs;
}; };
/**
* Main class for the dispatchkit. Handles management
* of the object stack, functions and registered types.
*/
class Dispatch_Engine class Dispatch_Engine
{ {
public: public:
@ -87,18 +102,27 @@ namespace dispatchkit
m_scopes.push_back(Scope()); m_scopes.push_back(Scope());
} }
/**
* Add a new named Proxy_Function to the system
*/
bool register_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &name) bool register_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &name)
{ {
return add_function(f, name); return add_function(f, name);
} }
/**
* Add a generic, named boost::function() to the system
*/
template<typename Function> template<typename Function>
bool register_function(const Function &func, const std::string &name) bool register_function(const Function &func, const std::string &name)
{ {
return add_function(boost::shared_ptr<Proxy_Function>(new Proxy_Function_Impl<Function>(func)), name); return add_function(boost::shared_ptr<Proxy_Function>(new Proxy_Function_Impl<Function>(func)), name);
} }
/**
* Set the value of an object, by name. If the object
* is not available in the current scope it is created
*/
template<typename Class> template<typename Class>
void set_object(const std::string &name, const Class &obj) void set_object(const std::string &name, const Class &obj)
{ {
@ -115,17 +139,26 @@ namespace dispatchkit
add_object(name, obj); add_object(name, obj);
} }
/**
* Adds a named object to the current scope
*/
template<typename Class> template<typename Class>
void add_object(const std::string &name, const Class &obj) void add_object(const std::string &name, const Class &obj)
{ {
m_scopes.back()[name] = Boxed_Value(obj); m_scopes.back()[name] = Boxed_Value(obj);
} }
/**
* Adds a new scope to the stack
*/
void new_scope() void new_scope()
{ {
m_scopes.push_back(Scope()); m_scopes.push_back(Scope());
} }
/**
* Pops the current scope from the stack
*/
void pop_scope() void pop_scope()
{ {
if (m_scopes.size() > 1) if (m_scopes.size() > 1)
@ -136,18 +169,30 @@ namespace dispatchkit
} }
} }
/**
* Returns the current stack
*/
Stack get_stack() Stack get_stack()
{ {
return m_scopes; 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) Stack set_stack(Stack s)
{ {
std::swap(s, m_scopes); std::swap(s, m_scopes);
return s; 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 Boxed_Value get_object(const std::string &name) const
{ {
if (name == "_") if (name == "_")
@ -174,13 +219,18 @@ namespace dispatchkit
} }
} }
/**
* Registers a new named type
*/
template<typename Type> template<typename Type>
void register_type(const std::string &name) void register_type(const std::string &name)
{ {
m_types.insert(std::make_pair(name, Get_Type_Info<Type>::get())); m_types.insert(std::make_pair(name, Get_Type_Info<Type>::get()));
} }
/**
* Returns the type info for a named type
*/
Type_Info get_type(const std::string &name) const Type_Info get_type(const std::string &name) const
{ {
Type_Name_Map::const_iterator itr = m_types.find(name); Type_Name_Map::const_iterator itr = m_types.find(name);
@ -193,6 +243,11 @@ namespace dispatchkit
throw std::range_error("Type Not Known"); 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 std::string get_type_name(const Type_Info &ti) const
{ {
for (Type_Name_Map::const_iterator itr = m_types.begin(); for (Type_Name_Map::const_iterator itr = m_types.begin();
@ -208,11 +263,37 @@ namespace dispatchkit
return ti.m_bare_type_info->name(); return ti.m_bare_type_info->name();
} }
/**
* Return all registered types
*/
std::vector<std::pair<std::string, Type_Info> > get_types() const std::vector<std::pair<std::string, Type_Info> > get_types() const
{ {
return std::vector<std::pair<std::string, Type_Info> >(m_types.begin(), m_types.end()); return std::vector<std::pair<std::string, Type_Info> >(m_types.begin(), m_types.end());
} }
/**
* Return a function by name
*/
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::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<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > get_functions() const
{
return std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >(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<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> > std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> >
get_function_impl(const std::string &t_name, bool include_objects) const get_function_impl(const std::string &t_name, bool include_objects) const
{ {
@ -238,18 +319,11 @@ namespace dispatchkit
return funcs; return funcs;
} }
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> > /**
get_function(const std::string &t_name) const * Implementation detail for adding a function. Returns
{ * true if the function was added, false if a function with the
return get_function_impl(t_name, true); * same signature and name already exists.
} */
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > get_functions() const
{
return std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >(m_functions.begin(), m_functions.end());
}
private:
bool add_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &t_name) bool add_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &t_name)
{ {
std::pair<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator> range std::pair<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator> range
@ -275,16 +349,25 @@ namespace dispatchkit
Boxed_Value m_place_holder; Boxed_Value m_place_holder;
}; };
/**
* Dump object info to stdout
*/
void dump_object(Boxed_Value o, const Dispatch_Engine &e) void dump_object(Boxed_Value o, const Dispatch_Engine &e)
{ {
std::cout << e.get_type_name(o.get_type_info()) << std::endl; 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) void dump_type(const Type_Info &type, const Dispatch_Engine &e)
{ {
std::cout << e.get_type_name(type); std::cout << e.get_type_name(type);
} }
/**
* Dump function to stdout
*/
void dump_function(const std::pair<const std::string, boost::shared_ptr<Proxy_Function> > &f, const Dispatch_Engine &e) void dump_function(const std::pair<const std::string, boost::shared_ptr<Proxy_Function> > &f, const Dispatch_Engine &e)
{ {
std::vector<Type_Info> params = f.second->get_param_types(); std::vector<Type_Info> params = f.second->get_param_types();
@ -307,12 +390,14 @@ namespace dispatchkit
{ {
std::cout << ", "; std::cout << ", ";
} }
} }
std::cout << ") " << std::endl; std::cout << ") " << std::endl;
} }
/**
* Dump all system info to stdout
*/
void dump_system(const Dispatch_Engine &s) void dump_system(const Dispatch_Engine &s)
{ {
std::cout << "Registered Types: " << std::endl; std::cout << "Registered Types: " << std::endl;
@ -326,7 +411,6 @@ namespace dispatchkit
std::cout << std::endl; std::cout << std::endl;
} }
std::cout << std::endl; std::cout << std::endl;
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > funcs = s.get_functions(); std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > funcs = s.get_functions();
@ -339,8 +423,6 @@ namespace dispatchkit
} }
std::cout << std::endl; std::cout << std::endl;
} }
} }
#endif #endif

View File

@ -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 <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
#define addparam(z,n,text) params.push_back(Boxed_Value(BOOST_PP_CAT(p, n) )); #define addparam(z,n,text) params.push_back(Boxed_Value(BOOST_PP_CAT(p, n) ));
@ -17,6 +23,10 @@
namespace dispatchkit namespace dispatchkit
{ {
/**
* Internal helper class for handling the return
* value of a build_function_caller
*/
template<typename Ret> template<typename Ret>
class Function_Caller_Ret class Function_Caller_Ret
{ {
@ -32,6 +42,9 @@ namespace dispatchkit
} }
}; };
/**
* Specialization for void return types
*/
template<> template<>
class Function_Caller_Ret<void> class Function_Caller_Ret<void>
{ {
@ -53,7 +66,15 @@ namespace dispatchkit
#include BOOST_PP_ITERATE() #include BOOST_PP_ITERATE()
namespace dispatchkit namespace dispatchkit
{ {
/**
* Build a function caller that knows how to dispatch on a set of functions
* example:
* boost::function<void (int)> 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<typename FunctionType> template<typename FunctionType>
boost::function<FunctionType> boost::function<FunctionType>
build_function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs) build_function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs)
@ -62,6 +83,19 @@ namespace dispatchkit
return build_function_caller_helper(p, funcs); 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<Proxy_Function> f)
* {
* boost::function<void (int)> local_f =
* build_function_caller(f);
* }
* \returns A boost::function object for dispatching
* \param[in] func A function to execute.
*/
template<typename FunctionType> template<typename FunctionType>
boost::function<FunctionType> boost::function<FunctionType>
build_function_caller(boost::shared_ptr<Proxy_Function> func) build_function_caller(boost::shared_ptr<Proxy_Function> func)
@ -71,6 +105,10 @@ namespace dispatchkit
return build_function_caller<FunctionType>(funcs); return build_function_caller<FunctionType>(funcs);
} }
/**
* Helper for automatically unboxing a Boxed_Value that contains a function object
* and creating a typesafe C++ function caller from it.
*/
template<typename FunctionType> template<typename FunctionType>
boost::function<FunctionType> boost::function<FunctionType>
build_function_caller(const Boxed_Value &bv) build_function_caller(const Boxed_Value &bv)
@ -78,7 +116,14 @@ namespace dispatchkit
return build_function_caller<FunctionType>(boxed_cast<boost::shared_ptr<Proxy_Function> >(bv)); return build_function_caller<FunctionType>(boxed_cast<boost::shared_ptr<Proxy_Function> >(bv));
} }
/**
* Helper for calling script code as if it were native C++ code
* example:
* boost::function<int (int, int)> 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<typename FunctionType, typename ScriptEngine> template<typename FunctionType, typename ScriptEngine>
boost::function<FunctionType> build_functor(ScriptEngine &e, const std::string &script) boost::function<FunctionType> build_functor(ScriptEngine &e, const std::string &script)
{ {
@ -92,6 +137,9 @@ namespace dispatchkit
namespace dispatchkit namespace dispatchkit
{ {
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs Ret function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
@ -103,6 +151,9 @@ namespace dispatchkit
return Function_Caller_Ret<Ret>().call(funcs, params); return Function_Caller_Ret<Ret>().call(funcs, params);
} }
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) > boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs) build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs)

View File

@ -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 <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
#ifndef BOOST_PP_IS_ITERATING #ifndef BOOST_PP_IS_ITERATING
@ -18,12 +24,22 @@
namespace dispatchkit namespace dispatchkit
{ {
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::shared_ptr<Class> constructor( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) boost::shared_ptr<Class> constructor( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{ {
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) )); return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
} }
/**
* Helper function for build a constructor function
* example:
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
* \todo See if it is possible to make this not be a variadic function
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<boost::shared_ptr<Class> (BOOST_PP_ENUM_PARAMS(n, Param))> build_constructor() boost::function<boost::shared_ptr<Class> (BOOST_PP_ENUM_PARAMS(n, Param))> build_constructor()
{ {

View File

@ -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 <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
#define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info<Param ## n>::get()); #define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info<Param ## n>::get());
@ -22,7 +28,9 @@
namespace dispatchkit namespace dispatchkit
{ {
// handle_return implementations /**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret> template<typename Ret>
struct Handle_Return struct Handle_Return
{ {
@ -32,6 +40,9 @@ namespace dispatchkit
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret> template<typename Ret>
struct Handle_Return<Ret &> struct Handle_Return<Ret &>
{ {
@ -41,6 +52,9 @@ namespace dispatchkit
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<Boxed_Value> struct Handle_Return<Boxed_Value>
{ {
@ -50,6 +64,9 @@ namespace dispatchkit
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<Boxed_Value &> struct Handle_Return<Boxed_Value &>
{ {
@ -59,6 +76,9 @@ namespace dispatchkit
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<void> struct Handle_Return<void>
{ {
@ -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 struct Param_List_Builder
{ {
Param_List_Builder &operator<<(const Boxed_Value &so) Param_List_Builder &operator<<(const Boxed_Value &so)
@ -93,6 +120,10 @@ namespace dispatchkit
std::vector<Boxed_Value> objects; std::vector<Boxed_Value> objects;
}; };
/**
* Exception thrown when there is a mismatch in number of
* parameters during Proxy_Function execution
*/
struct arity_error : std::range_error struct arity_error : std::range_error
{ {
arity_error(int t_got, int t_expected) arity_error(int t_got, int t_expected)
@ -105,7 +136,6 @@ namespace dispatchkit
int got; int got;
int expected; int expected;
}; };
} }
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 ) #define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
@ -114,6 +144,14 @@ namespace dispatchkit
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 class Proxy_Function
{ {
public: public:
@ -125,6 +163,9 @@ namespace dispatchkit
virtual std::string annotation() const = 0; virtual std::string annotation() const = 0;
}; };
/**
* Exception thrown if a function's guard fails to execute
*/
class guard_error : public std::runtime_error class guard_error : public std::runtime_error
{ {
public: public:
@ -136,6 +177,10 @@ namespace dispatchkit
{ } { }
}; };
/**
* A Proxy_Function implementation that is not type safe, the called function
* is expecting a vector<Boxed_Value> that it works with how it chooses.
*/
class Dynamic_Proxy_Function : public Proxy_Function class Dynamic_Proxy_Function : public Proxy_Function
{ {
public: public:
@ -225,10 +270,20 @@ namespace dispatchkit
boost::shared_ptr<Proxy_Function> m_guard; boost::shared_ptr<Proxy_Function> m_guard;
}; };
/**
* An object used by Bound_Function to represent "_" parameters
* of a binding. This allows for unbound parameters during bind.
*/
struct Placeholder_Object 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 class Bound_Function : public Proxy_Function
{ {
public: public:
@ -291,7 +346,6 @@ namespace dispatchkit
break; break;
} }
} }
return args; return args;
} }
@ -305,12 +359,16 @@ namespace dispatchkit
return ""; return "";
} }
private: private:
boost::shared_ptr<Proxy_Function> m_f; boost::shared_ptr<Proxy_Function> m_f;
std::vector<Boxed_Value> m_args; std::vector<Boxed_Value> 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<typename Func> template<typename Func>
class Proxy_Function_Impl : public Proxy_Function class Proxy_Function_Impl : public Proxy_Function
{ {
@ -352,11 +410,16 @@ namespace dispatchkit
return ""; return "";
} }
private: private:
Func m_f; 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 struct dispatch_error : std::runtime_error
{ {
dispatch_error() throw() dispatch_error() throw()
@ -367,6 +430,11 @@ namespace dispatchkit
virtual ~dispatch_error() throw() {} 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<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs, Boxed_Value dispatch(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs,
const std::vector<Boxed_Value> &plist) const std::vector<Boxed_Value> &plist)
{ {
@ -385,7 +453,6 @@ namespace dispatchkit
//try again //try again
} }
} }
throw dispatch_error(); throw dispatch_error();
} }
} }
@ -396,7 +463,10 @@ namespace dispatchkit
namespace dispatchkit namespace dispatchkit
{ {
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) > template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
std::vector<Type_Info> build_param_type_list(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &) std::vector<Type_Info> build_param_type_list(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &)
{ {
@ -408,6 +478,12 @@ namespace dispatchkit
return ti; 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<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f, Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params)
@ -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<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
bool compare_types(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &, bool compare_types(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params)
@ -440,8 +521,6 @@ namespace dispatchkit
return true; return true;
} }
} }
} }
#endif #endif

View File

@ -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 <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
#ifndef BOOST_PP_IS_ITERATING #ifndef BOOST_PP_IS_ITERATING
@ -10,12 +16,20 @@
namespace dispatchkit namespace dispatchkit
{ {
/**
* Helper function for register_member function
*/
template<typename T, typename Class> template<typename T, typename Class>
T &get_member(T Class::* m, Class *obj) T &get_member(T Class::* m, Class *obj)
{ {
return obj->*m; 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<typename T, typename Class> template<typename T, typename Class>
void register_member(Dispatch_Engine &s, T Class::* m, const std::string &name) void register_member(Dispatch_Engine &s, T Class::* m, const std::string &name)
{ {
@ -33,18 +47,27 @@ namespace dispatchkit
namespace dispatchkit namespace dispatchkit
{ {
/**
* Register a global function of n parameters with name
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
void register_function(Dispatch_Engine &s, Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name) void register_function(Dispatch_Engine &s, Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name)
{ {
s.register_function(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f), name); s.register_function(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
} }
/**
* Register a class method of n parameters with name
*/
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name) void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name)
{ {
s.register_function(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f), name); s.register_function(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
} }
/**
* Register a const class method of n parameters with name
*/
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const std::string &name) void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const std::string &name)
{ {

View File

@ -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__ #ifndef __type_info_hpp__
#define __type_info_hpp__ #define __type_info_hpp__
@ -12,6 +18,9 @@
namespace dispatchkit namespace dispatchkit
{ {
/**
* compile time deduced information about a type
*/
struct Type_Info struct Type_Info
{ {
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, 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; bool m_is_unknown;
}; };
/**
* Helper used to create a Type_Info object
*/
template<typename T> template<typename T>
struct Get_Type_Info struct Get_Type_Info
{ {

View File

@ -1,5 +1,8 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See LICENSE.TXT for details. // 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_ #ifndef CHAISCRIPT_ENGINE_HPP_
#define CHAISCRIPT_ENGINE_HPP_ #define CHAISCRIPT_ENGINE_HPP_

View File

@ -1,5 +1,8 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See LICENSE.TXT for details. // 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_ #ifndef CHAISCRIPT_EVAL_HPP_
#define CHAISCRIPT_EVAL_HPP_ #define CHAISCRIPT_EVAL_HPP_

View File

@ -1,5 +1,8 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See LICENSE.TXT for details. // 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_ #ifndef CHAISCRIPT_PARSER_HPP_
#define CHAISCRIPT_PARSER_HPP_ #define CHAISCRIPT_PARSER_HPP_

View File

@ -1,5 +1,8 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See LICENSE.TXT for details. // 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_ #ifndef CHAISCRIPT_PRELUDE_HPP_
#define CHAISCRIPT_PRELUDE_HPP_ #define CHAISCRIPT_PRELUDE_HPP_