Merge branch '2011-03-15-DocumentationUpdates'

Conflicts:
	include/chaiscript/language/chaiscript_engine.hpp
This commit is contained in:
Jason Turner
2011-03-29 20:24:17 -06:00
38 changed files with 5314 additions and 5315 deletions

View File

@@ -1357,7 +1357,7 @@ PERLMOD_MAKEVAR_PREFIX =
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
ENABLE_PREPROCESSING = NO
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional

View File

@@ -1,21 +1,34 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_HPP_
#define CHAISCRIPT_HPP_
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <stdexcept>
#include <iostream>
#include <map>
#include <fstream>
#include <boost/shared_ptr.hpp>
/// \mainpage
/// <a href="http://www.chaiscript.com">ChaiScript</a> is a scripting language designed specifically for integration with C++. It provides
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
///
/// The parts of the ChaiScript API that the average user will be concerned with are contained in the
/// chaiscript namespace and the chaiscript::ChaiScript class.
///
/// The end user parts of the API are extremely simple both in size and ease of use.
///
/// Currently, all source control and project management aspects of ChaiScript occur on <a href="http://www.github.com">github</a>.
///
/// \sa chaiscript
/// \sa chaiscript::ChaiScript
/// \sa http://www.chaiscript.com
/// \sa http://www.github.com/ChaiScript/ChaiScript
/// \namespace chaiscript
/// The chaiscript namespace contains every API call that the average user will be concerned with.
#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/bootstrap.hpp"

View File

@@ -1,3 +1,9 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_THREADING_HPP_
#define CHAISCRIPT_THREADING_HPP_
@@ -7,15 +13,34 @@
#pragma message ("ChaiScript is compiling without thread safety.")
#endif
/// \file
///
/// This file contains code necessary for thread support in ChaiScript.
/// If the compiler definition CHAISCRIPT_NO_THREADS is defined then thread safety
/// is disabled in ChaiScript. This has the result that some code is faster, because mutex locks are not required.
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
/// one thread simultaneously.
namespace chaiscript
{
namespace detail
{
/// If threading is enabled, then this namespace contains boost::thread classes.
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
/// This allows us to avoid #ifdef code in the sections that need thread safety.
namespace threading
{
#ifndef CHAISCRIPT_NO_THREADS
using boost::unique_lock;
using boost::shared_lock;
using boost::lock_guard;
using boost::shared_mutex;
using boost::recursive_mutex;
/// Typesafe thread specific storage. If threading is enabled, this class uses boost::thread_specific_ptr<T>. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
template<typename T>
class Thread_Storage
{
@@ -45,6 +70,32 @@ namespace chaiscript
};
#else
template<typename T>
class unique_lock
{
public:
unique_lock(T &) {}
};
template<typename T>
class shared_lock
{
public:
shared_lock(T &) {}
void unlock() {}
};
template<typename T>
class lock_guard
{
public:
lock_guard(T &) {}
};
class shared_mutex { };
class recursive_mutex {};
template<typename T>
class Thread_Storage

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -13,10 +13,11 @@ namespace chaiscript
{
namespace exception
{
/**
* 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
*/
/// \brief Thrown in the event that a Boxed_Value cannot be cast to the desired type
///
/// It is used internally during function dispatch and may be used by the end user.
///
/// \sa chaiscript::boxed_cast
class bad_boxed_cast : public std::bad_cast
{
public:
@@ -38,13 +39,14 @@ namespace chaiscript
virtual ~bad_boxed_cast() throw() {}
/// \brief Description of what error occured
virtual const char * what() const throw()
{
return m_what.c_str();
}
Type_Info from;
const std::type_info *to;
Type_Info from; ///< Type_Info contained in the Boxed_Value
const std::type_info *to; ///< std::type_info of the desired (but failed) result type
private:
std::string m_what;

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -30,9 +30,14 @@
namespace chaiscript
{
namespace detail
{
/// \brief Helper function for binding the first parameter of a class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
@@ -40,13 +45,25 @@ namespace chaiscript
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
/// \brief Helper function for binding the first parameter of a const class method pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const O &o)
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)) const, const O &o)
{
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
/// \brief Helper function for binding the first parameter of a function pointer. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
@@ -54,6 +71,12 @@ namespace chaiscript
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
}
/// \brief Helper function for binding the first parameter of a boost::function object. Used in chaiscript::fun overloads
/// that take 1 or 2 parameters to pre-bind to the function.
///
/// \param[in] f method pointer to bind
/// \param[in] o object to bind as first parameter
/// \returns a new boost::function object with one fewer parameters than the function passed in.
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -21,17 +21,15 @@ namespace chaiscript
namespace detail
{
/* Special helpers for generating generic "POD" type operators
* The POD operators are needed for general support of C++ POD
* types without iterating out all possible combinations of operators
* (<, >, +, +=, *=, \=, -, <=, >=, ==) and types
* (char, uint8_t, int8_t, uint16_t, int16_t...)
*/
/// \brief Assigns a POD value from a Boxed_POD_Value. Helps support operators between
/// disparate POD types.
/// \param[in,out] p1 object to assign to
/// \param[in] v Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_pod(P1 &p1, Boxed_POD_Value v)
P1 &assign_pod(P1 &p1, const Boxed_POD_Value &v)
{
if (v.m_isfloat)
if (v.isfloat)
{
return (p1 = P1(v.d));
} else {
@@ -39,10 +37,13 @@ namespace chaiscript
}
}
/// \brief Constructs a new POD value object from a Boxed_POD_Value
/// \param[in] v Boxed_POD_Value to copy into the new object
/// \returns The newly created object.
template<typename P1>
P1 construct_pod(Boxed_POD_Value v)
{
if (v.m_isfloat)
if (v.isfloat)
{
return P1(v.d);
} else {
@@ -50,10 +51,14 @@ namespace chaiscript
}
}
/// \brief Performs a bitwise and assignment (&=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to bitwise and assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
if (!r.isfloat)
{
return p1 &= P1(r.i);
}
@@ -61,10 +66,14 @@ namespace chaiscript
throw exception::bad_boxed_cast("&= only valid for integer types");
}
/// \brief Performs a xor assignment (^=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to xor assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
if (!r.isfloat)
{
return p1 ^= P1(r.i);
}
@@ -72,10 +81,14 @@ namespace chaiscript
throw exception::bad_boxed_cast("^= only valid for integer types");
}
/// \brief Performs a bitwise or assignment (|=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to bitwise or assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
if (!r.isfloat)
{
return p1 |= P1(r.i);
}
@@ -83,10 +96,14 @@ namespace chaiscript
throw exception::bad_boxed_cast("&= only valid for integer types");
}
/// \brief Performs an assign difference (-=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to difference assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
if (r.isfloat)
{
return p1 -= P1(r.d);
} else {
@@ -94,10 +111,14 @@ namespace chaiscript
}
}
/// \brief Performs an assign shift left (<<=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign shift left to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
if (!r.isfloat)
{
return p1 <<= P1(r.i);
}
@@ -106,10 +127,14 @@ namespace chaiscript
}
/// \brief Performs an assign product (*=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign product to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
if (r.isfloat)
{
return p1 *= P1(r.d);
} else {
@@ -117,10 +142,14 @@ namespace chaiscript
}
}
/// \brief Performs an assign quotient (/=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign quotient to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
if (r.isfloat)
{
return p1 /= P1(r.d);
} else {
@@ -128,10 +157,14 @@ namespace chaiscript
}
}
/// \brief Performs an assign remainder (%=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign remainder to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
if (!r.isfloat)
{
return p1 %= P1(r.i);
}
@@ -140,10 +173,14 @@ namespace chaiscript
}
/// \brief Performs an assign shift right (>>=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign shift right to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
if (!r.isfloat)
{
return p1 >>= P1(r.i);
}
@@ -151,11 +188,14 @@ namespace chaiscript
throw exception::bad_boxed_cast(">>= only valid for integer types");
}
/// \brief Performs an assign sum (+=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to sum assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
if (r.isfloat)
{
return p1 += P1(r.d);
} else {
@@ -165,6 +205,10 @@ namespace chaiscript
}
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
/// \tparam T Type to create comparison operators for
/// \param[in,out] m module to add comparison operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
{
@@ -177,6 +221,12 @@ namespace chaiscript
return m;
}
/// \brief Add all arithmetic operators appropriate for integers for the templated type.
/// Used during bootstrap, also available to users.
/// \tparam T Type to create arithmetic operators for
/// \param[in,out] m module to add arithmetic operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
@@ -209,6 +259,11 @@ namespace chaiscript
return m;
}
/// \brief Add all arithmetic operators appropriate for floating point numbers for the templated type.
/// Used during bootstrap, also available to users.
/// \tparam T Type to create arithmetic operators for
/// \param[in,out] m module to add arithmetic operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
@@ -226,9 +281,11 @@ namespace chaiscript
return m;
}
/**
* Add a copy constructor for type T
*/
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -236,9 +293,13 @@ namespace chaiscript
return m;
}
/**
* Add default and copy constructors for type T
*/
/// \brief Adds default and copy constructors for the given type
/// \param[in] type The name of the type to add the constructors for.
/// \param[in,out] m The Module to add the basic constructors to
/// \tparam T Type to generate basic constructors for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
/// \sa copy_constructor
/// \sa constructor
template<typename T>
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -247,9 +308,10 @@ namespace chaiscript
return m;
}
/**
* Add POD type constructor for type T. ie: T = type(POD)
*/
/// \brief Adds a constructor for a POD type
/// \tparam T The type to add the constructor for
/// \param[in] T The name of the type
/// \param[in,out] m The Module to add the constructor to
template<typename T>
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
@@ -257,16 +319,6 @@ namespace chaiscript
return m;
}
/**
* add user defined single parameter constructor for type T.
* T = type(const U &)
*/
template<typename T, typename U>
ModulePtr constructor_overload(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const U &)>(), type);
return m;
}
/**
* to_string function for internal use. Uses ostream operator<<
@@ -458,7 +510,7 @@ namespace chaiscript
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(Const_Proxy_Function(new Bound_Function(f,
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
}
@@ -480,7 +532,7 @@ namespace chaiscript
static bool has_guard(const Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const Dynamic_Proxy_Function>(t_pf);
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
return pf->get_guard();
@@ -491,7 +543,7 @@ namespace chaiscript
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const Dynamic_Proxy_Function>(t_pf);
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_guard())
@@ -509,7 +561,7 @@ namespace chaiscript
throw bv;
}
static boost::shared_ptr<Dispatch_Engine> bootstrap2(boost::shared_ptr<Dispatch_Engine> e = boost::shared_ptr<Dispatch_Engine> (new Dispatch_Engine()))
static boost::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(boost::shared_ptr<chaiscript::detail::Dispatch_Engine> e = boost::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
{
e->add(user_type<void>(), "void");
return e;
@@ -535,7 +587,7 @@ namespace chaiscript
template<typename FunctionType>
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
const Proxy_Function_Base *b)
const dispatch::Proxy_Function_Base *b)
{
typedef typename boost::function_types::result_type<FunctionType>::type Vector;
Vector v = (b->*f)();
@@ -552,15 +604,15 @@ namespace chaiscript
}
template<typename Function>
static boost::function<std::vector<Boxed_Value> (const Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
static boost::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
{
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1);
}
public:
/**
* perform all common bootstrap functions for std::string, void and POD types
*/
/// \brief perform all common bootstrap functions for std::string, void and POD types
/// \param[in,out] m Module to add bootstrapped functions to
/// \returns passed in ModulePtr, or newly created one if default argument is used
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<void>(), "void");
@@ -570,14 +622,14 @@ namespace chaiscript
m->add(user_type<Proxy_Function>(), "function");
m->add(user_type<std::exception>(), "exception");
m->add(fun(&Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&Proxy_Function_Base::operator()), "call");
m->add(fun(&Proxy_Function_Base::operator==), "==");
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m->add(fun(return_boxed_value_vector(&Proxy_Function_Base::get_param_types)), "get_param_types");
m->add(fun(return_boxed_value_vector(&Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m->add(user_type<std::runtime_error>(), "runtime_error");
@@ -587,11 +639,11 @@ namespace chaiscript
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
m->add(user_type<Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<Dynamic_Object (const std::string &)>(), "Dynamic_Object");
m->add(fun(&Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&Dynamic_Object::get_attr), "get_attr");
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::get_attr), "get_attr");
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
@@ -648,14 +700,14 @@ namespace chaiscript
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
"bind");
m->add(fun(&shared_ptr_unconst_clone<Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<boost::remove_const<Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<boost::add_const<Proxy_Function_Base>::type>), "=");
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
"call_exists");
m->add(fun(&type_match), "type_match");

View File

@@ -1,14 +1,17 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.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
*/
* \file
* 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 CHAISCRIPT_BOOTSTRAP_STL_HPP_
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -49,7 +49,7 @@ namespace chaiscript
try {
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(boxed_dynamic_cast<Type>(bv));
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv));
} catch (const boost::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -21,205 +21,205 @@ namespace chaiscript
* Object which attempts to convert a Boxed_Value into a generic
* POD type and provide generic POD type operations
*/
struct Boxed_POD_Value
class Boxed_POD_Value
{
Boxed_POD_Value(const Boxed_Value &v)
: d(0), i(0), m_isfloat(false)
{
if (v.get_type_info().is_undef())
public:
Boxed_POD_Value(const Boxed_Value &v)
: d(0), i(0), isfloat(false)
{
throw boost::bad_any_cast();
if (v.get_type_info().is_undef())
{
throw boost::bad_any_cast();
}
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(double))
{
d = boxed_cast<double>(v);
isfloat = true;
} else if (inp_ == typeid(float)) {
d = boxed_cast<float>(v);
isfloat = true;
} else if (inp_ == typeid(bool)) {
i = boxed_cast<bool>(v);
} else if (inp_ == typeid(char)) {
i = boxed_cast<char>(v);
} else if (inp_ == typeid(int)) {
i = boxed_cast<int>(v);
} else if (inp_ == typeid(unsigned int)) {
i = boxed_cast<unsigned int>(v);
} else if (inp_ == typeid(long)) {
i = boxed_cast<long>(v);
} else if (inp_ == typeid(unsigned long)) {
i = boxed_cast<unsigned long>(v);
} else if (inp_ == typeid(boost::int8_t)) {
i = boxed_cast<boost::int8_t>(v);
} else if (inp_ == typeid(boost::int16_t)) {
i = boxed_cast<boost::int16_t>(v);
} else if (inp_ == typeid(boost::int32_t)) {
i = boxed_cast<boost::int32_t>(v);
} else if (inp_ == typeid(boost::int64_t)) {
i = boxed_cast<boost::int64_t>(v);
} else if (inp_ == typeid(boost::uint8_t)) {
i = boxed_cast<boost::uint8_t>(v);
} else if (inp_ == typeid(boost::uint16_t)) {
i = boxed_cast<boost::uint16_t>(v);
} else if (inp_ == typeid(boost::uint32_t)) {
i = boxed_cast<boost::uint32_t>(v);
} else {
throw boost::bad_any_cast();
}
}
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(double))
bool operator==(const Boxed_POD_Value &r) const
{
d = boxed_cast<double>(v);
m_isfloat = true;
} else if (inp_ == typeid(float)) {
d = boxed_cast<float>(v);
m_isfloat = true;
} else if (inp_ == typeid(bool)) {
i = boxed_cast<bool>(v);
} else if (inp_ == typeid(char)) {
i = boxed_cast<char>(v);
} else if (inp_ == typeid(int)) {
i = boxed_cast<int>(v);
} else if (inp_ == typeid(unsigned int)) {
i = boxed_cast<unsigned int>(v);
} else if (inp_ == typeid(long)) {
i = boxed_cast<long>(v);
} else if (inp_ == typeid(unsigned long)) {
i = boxed_cast<unsigned long>(v);
} else if (inp_ == typeid(boost::int8_t)) {
i = boxed_cast<boost::int8_t>(v);
} else if (inp_ == typeid(boost::int16_t)) {
i = boxed_cast<boost::int16_t>(v);
} else if (inp_ == typeid(boost::int32_t)) {
i = boxed_cast<boost::int32_t>(v);
} else if (inp_ == typeid(boost::int64_t)) {
i = boxed_cast<boost::int64_t>(v);
} else if (inp_ == typeid(boost::uint8_t)) {
i = boxed_cast<boost::uint8_t>(v);
} else if (inp_ == typeid(boost::uint16_t)) {
i = boxed_cast<boost::uint16_t>(v);
} else if (inp_ == typeid(boost::uint32_t)) {
i = boxed_cast<boost::uint32_t>(v);
} else {
throw boost::bad_any_cast();
}
}
bool operator==(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i);
}
bool operator<(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) < ((r.m_isfloat)?r.d:r.i);
}
bool operator>(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) > ((r.m_isfloat)?r.d:r.i);
}
bool operator>=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) >= ((r.m_isfloat)?r.d:r.i);
}
bool operator<=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) <= ((r.m_isfloat)?r.d:r.i);
}
bool operator!=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) != ((r.m_isfloat)?r.d:r.i);
}
Boxed_Value operator+(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i + r.i);
return ((isfloat)?d:i) == ((r.isfloat)?r.d:r.i);
}
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator-(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
bool operator<(const Boxed_POD_Value &r) const
{
return smart_size(i - r.i);
return ((isfloat)?d:i) < ((r.isfloat)?r.d:r.i);
}
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator&(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
bool operator>(const Boxed_POD_Value &r) const
{
return Boxed_Value(i & r.i);
return ((isfloat)?d:i) > ((r.isfloat)?r.d:r.i);
}
throw exception::bad_boxed_cast("& only valid for integer types");
}
Boxed_Value operator^(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
bool operator>=(const Boxed_POD_Value &r) const
{
return Boxed_Value(i ^ r.i);
return ((isfloat)?d:i) >= ((r.isfloat)?r.d:r.i);
}
throw exception::bad_boxed_cast("^ only valid for integer types");
}
Boxed_Value operator|(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
bool operator<=(const Boxed_POD_Value &r) const
{
return Boxed_Value(i | r.i);
return ((isfloat)?d:i) <= ((r.isfloat)?r.d:r.i);
}
throw exception::bad_boxed_cast("| only valid for integer types");
}
Boxed_Value operator/(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
bool operator!=(const Boxed_POD_Value &r) const
{
return smart_size(i / r.i);
return ((isfloat)?d:i) != ((r.isfloat)?r.d:r.i);
}
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator<<(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
Boxed_Value operator+(const Boxed_POD_Value &r) const
{
return smart_size(i << r.i);
if (!isfloat && !r.isfloat)
{
return smart_size(i + r.i);
}
return Boxed_Value(((isfloat)?d:i) + ((r.isfloat)?r.d:r.i));
}
throw exception::bad_boxed_cast("<< only valid for integer types");
}
Boxed_Value operator*(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
Boxed_Value operator-(const Boxed_POD_Value &r) const
{
return smart_size(i * r.i);
if (!isfloat && !r.isfloat)
{
return smart_size(i - r.i);
}
return Boxed_Value(((isfloat)?d:i) - ((r.isfloat)?r.d:r.i));
}
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator%(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
Boxed_Value operator&(const Boxed_POD_Value &r) const
{
return smart_size(i % r.i);
if (!isfloat && !r.isfloat)
{
return Boxed_Value(i & r.i);
}
throw exception::bad_boxed_cast("& only valid for integer types");
}
throw exception::bad_boxed_cast("% only valid for integer types");
}
Boxed_Value operator>>(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
Boxed_Value operator^(const Boxed_POD_Value &r) const
{
return smart_size(i >> r.i);
if (!isfloat && !r.isfloat)
{
return Boxed_Value(i ^ r.i);
}
throw exception::bad_boxed_cast("^ only valid for integer types");
}
throw exception::bad_boxed_cast(">> only valid for integer types");
}
Boxed_Value smart_size(boost::int64_t t_i) const
{
if (t_i < boost::integer_traits<int>::const_min
|| t_i > boost::integer_traits<int>::const_max)
Boxed_Value operator|(const Boxed_POD_Value &r) const
{
return Boxed_Value(t_i);
} else {
return Boxed_Value(static_cast<int>(t_i));
if (!isfloat && !r.isfloat)
{
return Boxed_Value(i | r.i);
}
throw exception::bad_boxed_cast("| only valid for integer types");
}
Boxed_Value operator/(const Boxed_POD_Value &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i / r.i);
}
return Boxed_Value(((isfloat)?d:i) / ((r.isfloat)?r.d:r.i));
}
Boxed_Value operator<<(const Boxed_POD_Value &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i << r.i);
}
throw exception::bad_boxed_cast("<< only valid for integer types");
}
}
Boxed_Value operator*(const Boxed_POD_Value &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i * r.i);
}
double d;
boost::int64_t i;
return Boxed_Value(((isfloat)?d:i) * ((r.isfloat)?r.d:r.i));
}
bool m_isfloat;
Boxed_Value operator%(const Boxed_POD_Value &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i % r.i);
}
throw exception::bad_boxed_cast("% only valid for integer types");
}
Boxed_Value operator>>(const Boxed_POD_Value &r) const
{
if (!isfloat && !r.isfloat)
{
return smart_size(i >> r.i);
}
throw exception::bad_boxed_cast(">> only valid for integer types");
}
Boxed_Value smart_size(boost::int64_t t_i) const
{
if (t_i < boost::integer_traits<int>::const_min
|| t_i > boost::integer_traits<int>::const_max)
{
return Boxed_Value(t_i);
} else {
return Boxed_Value(static_cast<int>(t_i));
}
}
double d;
boost::int64_t i;
bool isfloat;
};
namespace detail

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,9 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
@@ -9,10 +15,6 @@
#include <boost/type_traits/is_polymorphic.hpp>
#include <boost/type_traits/is_base_of.hpp>
#ifndef CHAISCRIPT_NO_THREADS
#include <boost/thread/shared_mutex.hpp>
#endif
namespace chaiscript
{
namespace exception
@@ -150,9 +152,7 @@ namespace chaiscript
template<typename InItr>
void cleanup(InItr begin, const InItr &end)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
while (begin != end)
{
@@ -167,28 +167,22 @@ namespace chaiscript
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion.get());
}
bool has_conversion(const Type_Info &base, const Type_Info &derived)
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{
#ifndef CHAISCRIPT_NO_THREADS
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end();
}
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived)
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
{
#ifndef CHAISCRIPT_NO_THREADS
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<Dynamic_Conversion *>::const_iterator itr =
find(base, derived);
@@ -205,7 +199,7 @@ namespace chaiscript
Dynamic_Conversions() {}
std::set<Dynamic_Conversion *>::const_iterator find(
const Type_Info &base, const Type_Info &derived)
const Type_Info &base, const Type_Info &derived) const
{
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
itr != m_conversions.end();
@@ -219,9 +213,8 @@ namespace chaiscript
return m_conversions.end();
}
#ifndef CHAISCRIPT_NO_THREADS
boost::shared_mutex m_mutex;
#endif
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<Dynamic_Conversion *> m_conversions;
};
}
@@ -248,29 +241,31 @@ namespace chaiscript
return detail::Dynamic_Conversions::create<Base, Derived>();
}
template<typename Base, typename Derived>
bool dynamic_cast_converts()
namespace detail
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
template<typename Base, typename Derived>
bool dynamic_cast_converts()
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
{
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
{
try {
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
{
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
}
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
{
try {
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
}
}

View File

@@ -1,3 +1,9 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
@@ -5,270 +11,273 @@
namespace chaiscript
{
class Dynamic_Object
namespace dispatch
{
public:
Dynamic_Object(const std::string &t_type_name)
: m_type_name(t_type_name)
{
}
std::string get_type_name() const
{
return m_type_name;
}
Boxed_Value get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
}
std::map<std::string, Boxed_Value> get_attrs()
{
return m_attrs;
}
private:
std::string m_type_name;
std::map<std::string, Boxed_Value> m_attrs;
};
namespace detail
{
struct Dynamic_Object_Attribute
{
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
Dynamic_Object &t_do)
{
if (t_do.get_type_name() != t_type_name)
{
throw exception::bad_boxed_cast("Dynamic object type mismatch");
}
return t_do.get_attr(t_attr_name);
}
};
/**
* A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Function : public Proxy_Function_Base
class Dynamic_Object
{
public:
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func,
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
Dynamic_Object(const std::string &t_type_name)
: m_type_name(t_type_name)
{
}
std::string get_type_name() const
{
return m_type_name;
}
Boxed_Value get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
}
std::map<std::string, Boxed_Value> get_attrs()
{
return m_attrs;
}
private:
std::string m_type_name;
std::map<std::string, Boxed_Value> m_attrs;
};
namespace detail
{
struct Dynamic_Object_Attribute
{
static Boxed_Value func(const std::string &t_type_name, const std::string &t_attr_name,
Dynamic_Object &t_do)
{
if (t_do.get_type_name() != t_type_name)
{
throw exception::bad_boxed_cast("Dynamic object type mismatch");
}
return t_do.get_attr(t_attr_name);
}
};
/**
* A Proxy_Function implementation designed for calling a function
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
const std::string &t_type_name,
const Proxy_Function &t_func,
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
virtual ~Dynamic_Object_Function() {}
virtual bool operator==(const Proxy_Function_Base &f) const
{
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
if (df)
virtual bool operator==(const Proxy_Function_Base &f) const
{
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
{
return m_func->call_match(vals);
} else {
return false;
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
{
std::vector<Const_Proxy_Function> fs;
fs.push_back(m_func);
return fs;
}
virtual int get_arity() const
{
return m_func->get_arity();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
if (dynamic_object_typename_match(params, m_type_name, m_ti))
{
return (*m_func)(params);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv) const
{
return dynamic_object_typename_match(bv, m_type_name, m_ti);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
{
if (t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = *t_objectti;
return types;
} else {
return t_inner_types;
}
}
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const boost::optional<Type_Info> &ti)
{
static Type_Info doti = user_type<Dynamic_Object>();
if (bv.get_type_info().bare_equal(doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
if (ti)
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
if (df)
{
return bv.get_type_info().bare_equal(*ti);
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
} else {
return false;
}
}
}
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const boost::optional<Type_Info> &ti)
{
if (bvs.size() > 0)
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
return dynamic_object_typename_match(bvs[0], name, ti);
} else {
return false;
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
{
return m_func->call_match(vals);
} else {
return false;
}
}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
{
std::vector<Const_Proxy_Function> fs;
fs.push_back(m_func);
return fs;
}
}
std::string m_type_name;
Proxy_Function m_func;
boost::optional<Type_Info> m_ti;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
const std::string &t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
m_type_name(t_type_name), m_func(t_func)
virtual int get_arity() const
{
return m_func->get_arity();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
if (dynamic_object_typename_match(params, m_type_name, m_ti))
{
return (*m_func)(params);
} else {
throw exception::guard_error();
}
}
virtual bool compare_first_type(const Boxed_Value &bv) const
{
return dynamic_object_typename_match(bv, m_type_name, m_ti);
}
private:
static std::vector<Type_Info> build_param_types(
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
{
if (t_objectti)
{
std::vector<Type_Info> types(t_inner_types);
assert(types.size() > 1);
assert(types[1].bare_equal(user_type<Boxed_Value>()));
types[1] = *t_objectti;
return types;
} else {
return t_inner_types;
}
}
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
const boost::optional<Type_Info> &ti)
{
static Type_Info doti = user_type<Dynamic_Object>();
if (bv.get_type_info().bare_equal(doti))
{
try {
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv);
return name == "Dynamic_Object" || d.get_type_name() == name;
} catch (const std::bad_cast &) {
return false;
}
} else {
if (ti)
{
return bv.get_type_info().bare_equal(*ti);
} else {
return false;
}
}
}
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
const boost::optional<Type_Info> &ti)
{
if (bvs.size() > 0)
{
return dynamic_object_typename_match(bvs[0], name, ti);
} else {
return false;
}
}
std::string m_type_name;
Proxy_Function m_func;
boost::optional<Type_Info> m_ti;
};
/**
* A Proxy_Function implementation designed for creating a new
* Dynamic_Object
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
const std::string &t_type_name,
const Proxy_Function &t_func)
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
m_type_name(t_type_name), m_func(t_func)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
std::vector<Type_Info>::const_iterator begin = tl.begin();
std::vector<Type_Info>::const_iterator end = tl.end();
if (begin != end)
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
{
++begin;
std::vector<Type_Info>::const_iterator begin = tl.begin();
std::vector<Type_Info>::const_iterator end = tl.end();
if (begin != end)
{
++begin;
}
return std::vector<Type_Info>(begin, end);
}
return std::vector<Type_Info>(begin, end);
}
virtual ~Dynamic_Object_Constructor() {}
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
if (dc)
virtual bool operator==(const Proxy_Function_Base &f) const
{
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} else {
return false;
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
if (dc)
{
return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} else {
return false;
}
}
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals);
}
return m_func->call_match(new_vals);
}
virtual int get_arity() const
{
// "this" is not considered part of the arity
return m_func->get_arity() - 1;
}
virtual int get_arity() const
{
// "this" is not considered part of the arity
return m_func->get_arity() - 1;
}
virtual std::string annotation() const
{
return m_func->annotation();
}
virtual std::string annotation() const
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params);
(*m_func)(new_params);
return bv;
}
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;
private:
std::string m_type_name;
Proxy_Function m_func;
};
};
}
}
}
#endif

View File

@@ -4,8 +4,8 @@
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef __function_call_hpp__
#define __function_call_hpp__
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
#define CHAISCRIPT_FUNCTION_CALL_HPP_
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
@@ -20,37 +20,39 @@
namespace chaiscript
{
/**
* 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>
boost::function<FunctionType>
namespace dispatch
{
/**
* 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>
boost::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs)
{
FunctionType *p=0;
return detail::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(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>
boost::function<FunctionType>
/**
* 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(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>
boost::function<FunctionType>
functor(Const_Proxy_Function func)
{
std::vector<Const_Proxy_Function> funcs;
@@ -58,76 +60,76 @@ namespace chaiscript
return functor<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>
boost::function<FunctionType>
/**
* Helper for automatically unboxing a Boxed_Value that contains a function object
* and creating a typesafe C++ function caller from it.
*/
template<typename FunctionType>
boost::function<FunctionType>
functor(const Boxed_Value &bv)
{
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
}
}
namespace detail{
/**
* Cast helper to handle automatic casting to const boost::function &
*/
* Cast helper to handle automatic casting to const boost::function &
*/
template<typename Signature>
struct Cast_Helper<const boost::function<Signature> &>
{
typedef boost::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return functor<Signature>(ob);
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob);
}
}
};
/**
* Cast helper to handle automatic casting to boost::function
*/
* Cast helper to handle automatic casting to boost::function
*/
template<typename Signature>
struct Cast_Helper<boost::function<Signature> >
{
typedef boost::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return functor<Signature>(ob);
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob);
}
}
};
/**
* Cast helper to handle automatic casting to const boost::function
*/
* Cast helper to handle automatic casting to const boost::function
*/
template<typename Signature>
struct Cast_Helper<const boost::function<Signature> >
{
typedef boost::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
return functor<Signature>(ob);
return dispatch::functor<Signature>(ob);
} else {
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
}
}
};
}
}
#endif

View File

@@ -1,12 +1,12 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#include <boost/preprocessor.hpp>
#define addparam(z,n,text) params.push_back(boost::is_reference<Param ## n>::value?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define addparam(z,n,text) params.push_back((boost::is_reference<Param ## n>::value&&!(boost::is_same<chaiscript::Boxed_Value, typename boost::remove_const<typename boost::remove_reference<Param ## n>::type>::type>::value))?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
@@ -23,34 +23,38 @@
namespace chaiscript
{
namespace detail
namespace dispatch
{
/**
* Internal helper class for handling the return
* value of a build_function_caller
*/
template<typename Ret>
struct Function_Caller_Ret
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params)
{
return boxed_cast<Ret>(dispatch(t_funcs, params));
}
};
namespace detail
{
/**
* Specialization for void return types
*/
template<>
struct Function_Caller_Ret<void>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params)
/**
* Internal helper class for handling the return
* value of a build_function_caller
*/
template<typename Ret>
struct Function_Caller_Ret
{
dispatch(t_funcs, params);
}
};
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params)
{
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params));
}
};
/**
* Specialization for void return types
*/
template<>
struct Function_Caller_Ret<void>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params)
{
dispatch::dispatch(t_funcs, params);
}
};
}
}
}
@@ -64,47 +68,49 @@ namespace chaiscript
namespace chaiscript
{
namespace detail
namespace dispatch
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
std::vector<Boxed_Value> params;
BOOST_PP_REPEAT(n, addparam, ~)
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) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs)
{
if (funcs.size() == 1)
namespace detail
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
(funcs[0]);
std::vector<Boxed_Value> params;
if (pfi)
{
return pfi->internal_function();
}
// looks like this either wasn't a Proxy_Function_Impl or the types didn't match
// we cannot make any other guesses or assumptions really, so continuing
BOOST_PP_REPEAT(n, addparam, ~)
return Function_Caller_Ret<Ret>::call(funcs, params);
}
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
BOOST_PP_ENUM_TRAILING(n, curry, ~));
}
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs)
{
if (funcs.size() == 1)
{
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
(funcs[0]);
if (pfi)
{
return pfi->internal_function();
}
// looks like this either wasn't a Proxy_Function_Impl or the types didn't match
// we cannot make any other guesses or assumptions really, so continuing
}
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
BOOST_PP_ENUM_TRAILING(n, curry, ~));
}
}
}
}
#undef n

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -27,7 +27,7 @@ namespace chaiscript
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(r);
return const_var(r);
}
};
@@ -40,6 +40,15 @@ namespace chaiscript
}
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> >
{
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
{
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &>
{
@@ -88,6 +97,18 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/

View File

@@ -1,3 +1,9 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_OPERATORS_HPP_
#define CHAISCRIPT_OPERATORS_HPP_

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -26,7 +26,7 @@ namespace chaiscript
Proxy_Function constructor()
{
T *f = 0;
return (detail::build_constructor_(f));
return (dispatch::detail::build_constructor_(f));
}
}
@@ -35,30 +35,33 @@ namespace chaiscript
namespace chaiscript
{
namespace detail
namespace dispatch
{
/**
* 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) >
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) ));
}
namespace detail
{
/**
* 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) >
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) ));
}
/**
* 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) >
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
/**
* 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) >
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
}
}
}
#undef n

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -49,29 +49,6 @@ namespace chaiscript
};
}
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
return Handle_Return<Ret>::handle(call_func(fun, params));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
call_func(fun, params);
return Handle_Return<void>::handle();
}
};
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
@@ -143,3 +120,35 @@ namespace chaiscript
#undef n
#endif
#ifndef BOOST_PP_IS_ITERATING
namespace chaiscript
{
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
return Handle_Return<Ret>::handle(chaiscript::detail::call_func(fun, params));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> &params)
{
chaiscript::detail::call_func(fun, params);
return Handle_Return<void>::handle();
}
};
}
}
#endif

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -18,61 +18,63 @@
namespace chaiscript
{
namespace detail
namespace dispatch
{
template<bool Object, bool MemFn>
struct Fun_Helper
{
template<typename T>
static Proxy_Function go(T t)
namespace detail
{
template<bool Object, bool MemFn>
struct Fun_Helper
{
return Proxy_Function(
new Proxy_Function_Impl<
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
};
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
};
template<>
struct Fun_Helper<false, true>
{
template<typename T>
static Proxy_Function go(T t)
template<>
struct Fun_Helper<false, true>
{
return Proxy_Function(
new Proxy_Function_Impl<
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(boost::mem_fn(t))));
}
};
}
};
template<>
struct Fun_Helper<true, false>
{
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
template<>
struct Fun_Helper<true, false>
{
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
}
}
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
}
template<typename T>
Proxy_Function fun(T t)
{
return detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t);
return dispatch::detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t);
}
template<typename T, typename Q>

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -22,12 +22,14 @@
namespace chaiscript
{
template<typename T>
struct Bare_Type
{
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
};
namespace detail
{
template<typename T>
struct Bare_Type
{
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
};
}
/**
* compile time deduced information about a type

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -8,6 +8,7 @@
#define CHAISCRIPT_COMMON_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
namespace chaiscript
{
@@ -57,110 +58,155 @@ namespace chaiscript
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
namespace exception
{
/**
* Errors generated during parsing or evaluation
*/
struct eval_error : public std::runtime_error {
std::string reason;
File_Position start_position;
File_Position end_position;
std::string filename;
std::vector<AST_NodePtr> call_stack;
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) throw() :
std::runtime_error("Error: \"" + t_why + "\" " +
(t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(t_where.line) + ", " +
boost::lexical_cast<std::string>(t_where.column) + ")"),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
{ }
eval_error(const std::string &t_why) throw()
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
virtual ~eval_error() throw() {}
};
/**
* Errors generated when loading a file
*/
struct file_not_found_error : public std::runtime_error {
file_not_found_error(const std::string &t_filename) throw()
: std::runtime_error("File Not Found: " + t_filename)
{ }
virtual ~file_not_found_error() throw() {}
};
}
/**
* The struct that doubles as both a parser ast_node and an AST node
*/
struct AST_Node {
std::string text;
int identifier;
boost::shared_ptr<std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
public:
const std::string text;
const int identifier;
boost::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(t_ast_node_text), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
/**
* Prints the contents of an AST node, including its children, recursively
*/
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss;
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
/**
* Prints the contents of an AST node, including its children, recursively
*/
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss;
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
for (unsigned int j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
for (unsigned int j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
}
return oss.str();
}
return oss.str();
}
std::string internal_to_string() {
return to_string();
}
std::string internal_to_string() {
return to_string();
}
virtual Boxed_Value eval(Dispatch_Engine &) {
Boxed_Value bv;
throw std::runtime_error("Undispatched ast_node (internal error)");
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
{
try {
return eval_internal(t_e);
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this());
throw ee;
}
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
protected:
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(t_ast_node_text), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &)
{
throw std::runtime_error("Undispatched ast_node (internal error)");
}
};
/**
* Errors generated during parsing or evaluation
*/
struct Eval_Error : public std::runtime_error {
std::string reason;
File_Position start_position;
File_Position end_position;
std::string filename;
std::vector<AST_NodePtr> call_stack;
Eval_Error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) :
std::runtime_error("Error: \"" + t_why + "\" " +
(t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(t_where.line) + ", " +
boost::lexical_cast<std::string>(t_where.column) + ")"),
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
{ }
namespace detail
{
/**
* Special type for returned values
*/
struct Return_Value {
Boxed_Value retval;
Eval_Error(const std::string &t_why)
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
};
virtual ~Eval_Error() throw() {}
};
/**
* Special type indicating a call to 'break'
*/
struct Break_Loop {
Break_Loop() { }
};
/**
* Errors generated when loading a file
*/
struct File_Not_Found_Error : public std::runtime_error {
File_Not_Found_Error(const std::string &t_filename)
: std::runtime_error("File Not Found: " + t_filename)
{ }
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_scope();
}
virtual ~File_Not_Found_Error() throw() {}
};
~Scope_Push_Pop()
{
m_de.pop_scope();
}
/**
* Special type for returned values
*/
struct Return_Value {
Boxed_Value retval;
private:
chaiscript::detail::Dispatch_Engine &m_de;
};
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
};
/**
* Special type indicating a call to 'break'
*/
struct Break_Loop {
Break_Loop() { }
};
}
}
#endif /* _CHAISCRIPT_COMMON_HPP */

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
@@ -28,205 +28,210 @@
namespace chaiscript
{
struct load_module_error : std::runtime_error
namespace exception
{
load_module_error(const std::string &t_reason) throw()
: std::runtime_error(t_reason)
struct load_module_error : std::runtime_error
{
}
load_module_error(const std::string &t_reason) throw()
: std::runtime_error(t_reason)
{
}
virtual ~load_module_error() throw()
{
}
};
virtual ~load_module_error() throw()
{
}
};
}
namespace detail
{
#ifdef _POSIX_VERSION
struct Loadable_Module
{
struct DLModule
struct Loadable_Module
{
DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
struct DLModule
{
if (!m_data)
DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
{
if (!m_data)
{
throw load_module_error(dlerror());
throw exception::load_module_error(dlerror());
}
}
}
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
~DLModule()
{
dlclose(m_data);
}
~DLModule()
{
dlclose(m_data);
}
void *m_data;
};
void *m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
{
throw load_module_error(dlerror());
if (!m_symbol)
{
throw exception::load_module_error(dlerror());
}
}
}
T m_symbol;
};
T m_symbol;
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
#ifdef WIN32
struct Loadable_Module
{
template<typename T>
static std::wstring towstring(const T &t_str)
struct Loadable_Module
{
return std::wstring(t_str.begin(), t_str.end());
}
template<typename T>
static std::wstring towstring(const T &t_str)
{
return std::wstring(t_str.begin(), t_str.end());
}
template<typename T>
static std::string tostring(const T &t_str)
{
return std::string(t_str.begin(), t_str.end());
}
template<typename T>
static std::string tostring(const T &t_str)
{
return std::string(t_str.begin(), t_str.end());
}
#ifdef _UNICODE
template<typename T>
static std::wstring toproperstring(const T &t_str)
{
return towstring(t_str);
}
template<typename T>
static std::wstring toproperstring(const T &t_str)
{
return towstring(t_str);
}
#else
template<typename T>
static std::string toproperstring(const T &t_str)
{
return tostring(t_str);
}
template<typename T>
static std::string toproperstring(const T &t_str)
{
return tostring(t_str);
}
#endif
static std::string GetErrorMessage(DWORD t_err)
{
static std::string GetErrorMessage(DWORD t_err)
{
#ifdef _UNICODE
typedef LPWSTR StringType;
std::wstring retval = L"Unknown Error";
typedef LPWSTR StringType;
std::wstring retval = L"Unknown Error";
#else
typedef LPSTR StringType;
std::string retval = "Unknown Error";
typedef LPSTR StringType;
std::string retval = "Unknown Error";
#endif
StringType lpMsgBuf = 0;
StringType lpMsgBuf = 0;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(StringType)&lpMsgBuf,
0, NULL );
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(StringType)&lpMsgBuf,
0, NULL );
if (lpMsgBuf)
{
retval = lpMsgBuf;
if (lpMsgBuf)
{
retval = lpMsgBuf;
}
LocalFree(lpMsgBuf);
return tostring(retval);
}
LocalFree(lpMsgBuf);
return tostring(retval);
}
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(LoadLibrary(toproperstring(t_filename).c_str()))
struct DLModule
{
if (!m_data)
DLModule(const std::string &t_filename)
: m_data(LoadLibrary(toproperstring(t_filename).c_str()))
{
if (!m_data)
{
throw load_module_error(GetErrorMessage(GetLastError()));
throw exception::load_module_error(GetErrorMessage(GetLastError()));
}
}
}
~DLModule()
{
FreeLibrary(m_data);
}
~DLModule()
{
FreeLibrary(m_data);
}
HMODULE m_data;
};
HMODULE m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
{
throw load_module_error(GetErrorMessage(GetLastError()));
if (!m_symbol)
{
throw exception::load_module_error(GetErrorMessage(GetLastError()));
}
}
}
T m_symbol;
};
T m_symbol;
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
struct Loadable_Module
{
Loadable_Module(const std::string &, const std::string &)
struct Loadable_Module
{
throw load_module_error("Loadable module support not available for your platform");
}
Loadable_Module(const std::string &, const std::string &)
{
throw exception::load_module_error("Loadable module support not available for your platform");
}
ModulePtr m_moduleptr;
};
ModulePtr m_moduleptr;
};
#endif
#endif
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
}
class ChaiScript {
#ifndef CHAISCRIPT_NO_THREADS
mutable boost::shared_mutex m_mutex;
mutable boost::recursive_mutex m_use_mutex;
#endif
mutable chaiscript::detail::threading::shared_mutex m_mutex;
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
std::set<std::string> m_used_files;
std::map<std::string, Loadable_Module_Ptr> m_loaded_modules;
std::map<std::string, detail::Loadable_Module_Ptr> m_loaded_modules;
std::set<std::string> m_active_loaded_modules;
std::vector<std::string> m_modulepaths;
std::vector<std::string> m_usepaths;
Dispatch_Engine m_engine;
chaiscript::detail::Dispatch_Engine m_engine;
/**
@@ -235,7 +240,7 @@ namespace chaiscript
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
{
try {
ChaiScript_Parser parser;
parser::ChaiScript_Parser parser;
if (parser.parse(t_input, t_filename)) {
//parser.show_match_stack();
return parser.ast()->eval(m_engine);
@@ -243,7 +248,7 @@ namespace chaiscript
return Boxed_Value();
}
}
catch (const Return_Value &rv) {
catch (const detail::Return_Value &rv) {
return rv.retval;
}
}
@@ -271,23 +276,19 @@ namespace chaiscript
try {
const std::string appendedpath = m_usepaths[i] + t_filename;
#ifndef CHAISCRIPT_NO_THREADS
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
boost::shared_lock<boost::shared_mutex> l2(m_mutex);
#endif
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
if (m_used_files.count(appendedpath) == 0)
{
#ifndef CHAISCRIPT_NO_THREADS
m_used_files.insert(appendedpath);
l2.unlock();
#endif
eval_file(appendedpath);
}
} catch (const File_Not_Found_Error &) {
} catch (const exception::file_not_found_error &) {
if (i == m_usepaths.size() - 1)
{
throw File_Not_Found_Error(t_filename);
throw exception::file_not_found_error(t_filename);
}
// failed to load, try the next path
@@ -295,6 +296,63 @@ namespace chaiscript
}
}
/**
* Returns the current evaluation m_engine
*/
chaiscript::detail::Dispatch_Engine &get_eval_engine() {
return m_engine;
}
/**
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
*/
void build_eval_system() {
using namespace bootstrap;
m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while");
m_engine.add_reserved_word("for");
m_engine.add_reserved_word("if");
m_engine.add_reserved_word("else");
m_engine.add_reserved_word("&&");
m_engine.add_reserved_word("||");
m_engine.add_reserved_word(",");
m_engine.add_reserved_word(":=");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("return");
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("_");
add(Bootstrap::bootstrap());
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, boost::ref(m_engine)), "dump_system");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, boost::ref(m_engine)), "dump_object");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
typedef void (ChaiScript::*load_mod_1)(const std::string&);
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
add(standard_library::string_type<std::string>("string"));
add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
m_engine.add(fun(&ChaiScript::use, this), "use");
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
do_eval(chaiscript_prelude, "standard prelude");
}
public:
ChaiScript(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
@@ -326,7 +384,7 @@ namespace chaiscript
struct State
{
std::set<std::string> used_files;
Dispatch_Engine::State engine_state;
chaiscript::detail::Dispatch_Engine::State engine_state;
std::set<std::string> active_loaded_modules;
};
@@ -337,10 +395,8 @@ namespace chaiscript
*/
State get_state()
{
#ifndef CHAISCRIPT_NO_THREADS
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
boost::shared_lock<boost::shared_mutex> l2(m_mutex);
#endif
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
State s;
s.used_files = m_used_files;
@@ -354,10 +410,8 @@ namespace chaiscript
*/
void set_state(const State &t_state)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
boost::shared_lock<boost::shared_mutex> l2(m_mutex);
#endif
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
m_used_files = t_state.used_files;
m_active_loaded_modules = t_state.active_loaded_modules;
@@ -388,7 +442,7 @@ namespace chaiscript
*/
void load_module(const std::string &t_module_name)
{
std::vector<load_module_error> errors;
std::vector<exception::load_module_error> errors;
std::vector<std::string> prefixes;
prefixes.push_back("lib");
@@ -409,7 +463,7 @@ namespace chaiscript
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
load_module(t_module_name, name);
return;
} catch (const load_module_error &e) {
} catch (const exception::load_module_error &e) {
errors.push_back(e);
// Try next set
}
@@ -419,7 +473,7 @@ namespace chaiscript
std::string errstring;
for (std::vector<load_module_error>::const_iterator itr = errors.begin();
for (std::vector<exception::load_module_error>::const_iterator itr = errors.begin();
itr != errors.end();
++itr)
{
@@ -431,7 +485,7 @@ namespace chaiscript
errstring += itr->what();
}
throw load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
}
/**
@@ -439,13 +493,11 @@ namespace chaiscript
*/
void load_module(const std::string &t_module_name, const std::string &t_filename)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
#endif
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
if (m_loaded_modules.count(t_module_name) == 0)
{
Loadable_Module_Ptr lm(new Loadable_Module(t_module_name, t_filename));
detail::Loadable_Module_Ptr lm(new detail::Loadable_Module(t_module_name, t_filename));
m_loaded_modules[t_module_name] = lm;
m_active_loaded_modules.insert(t_module_name);
add(lm->m_moduleptr);
@@ -456,19 +508,6 @@ namespace chaiscript
}
/**
* 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] script Script code to build a function from
*/
template<typename FunctionType>
boost::function<FunctionType> functor(const std::string &t_script)
{
return chaiscript::functor<FunctionType>(eval(t_script));
}
/**
* Evaluate a string via eval method
*/
@@ -478,13 +517,6 @@ namespace chaiscript
}
/**
* Returns the current evaluation m_engine
*/
Dispatch_Engine &get_eval_engine() {
return m_engine;
}
/**
* Helper function for loading a file
*/
@@ -492,7 +524,7 @@ namespace chaiscript
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
if (!infile.is_open()) {
throw File_Not_Found_Error(t_filename);
throw exception::file_not_found_error(t_filename);
}
std::streampos size = infile.tellg();
@@ -510,56 +542,6 @@ namespace chaiscript
}
}
/**
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
*/
void build_eval_system() {
using namespace bootstrap;
m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while");
m_engine.add_reserved_word("for");
m_engine.add_reserved_word("if");
m_engine.add_reserved_word("else");
m_engine.add_reserved_word("&&");
m_engine.add_reserved_word("||");
m_engine.add_reserved_word(",");
m_engine.add_reserved_word(":=");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("return");
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("_");
add(Bootstrap::bootstrap());
m_engine.add(fun(&Dispatch_Engine::dump_system, boost::ref(m_engine)), "dump_system");
m_engine.add(fun(&Dispatch_Engine::dump_object, boost::ref(m_engine)), "dump_object");
m_engine.add(fun(&Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
m_engine.add(fun(&Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
m_engine.add(fun(&Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
m_engine.add(fun(&Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
typedef void (ChaiScript::*load_mod_1)(const std::string&);
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
add(standard_library::string_type<std::string>("string"));
add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
m_engine.add(fun(&ChaiScript::use, this), "use");
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
do_eval(chaiscript_prelude, "standard prelude");
}
template<typename T>
T eval(const std::string &t_input)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com

View File

@@ -1,5 +1,11 @@
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP__
#define CHAISCRIPT_UTILITY_UTILITY_HPP__
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
#include "../chaiscript.hpp"
#include <boost/preprocessor.hpp>

View File

@@ -45,7 +45,7 @@ struct System
void add_callback(const std::string &t_name,
const chaiscript::Proxy_Function &t_func)
{
m_callbacks[t_name] = chaiscript::functor<std::string (const std::string &)>(t_func);
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func);
}
@@ -115,7 +115,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//Call bound version of do_callbacks
chai("do_callbacks()");
boost::function<void ()> caller = chai.functor<void ()>("fun() { system.do_callbacks(\"From Functor\"); }");
boost::function<void ()> caller = chai.eval<boost::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
caller();
@@ -139,7 +139,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//To do: Add examples of handling Boxed_Values directly when needed
//Creating a functor on the stack and using it immediatly
int x = chai.functor<int (int, int)>("fun (x, y) { return x + y; }")(5, 6);
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
log("Functor test output", boost::lexical_cast<std::string>(x));
@@ -163,9 +163,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
//Dynamic objects test
chai.add(chaiscript::Proxy_Function(new detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
chai.add(fun(boost::function<Boxed_Value (Dynamic_Object &)>(boost::bind(&detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
chai.eval("var x = TestType()");
// chai.eval("x.attr = \"hi\"");

View File

@@ -52,10 +52,10 @@ void version(int){
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
}
bool throws_exception(const chaiscript::Proxy_Function &f)
bool throws_exception(const boost::function<void ()> &f)
{
try {
chaiscript::functor<void ()>(f)();
f();
} catch (...) {
return true;
}
@@ -63,6 +63,17 @@ bool throws_exception(const chaiscript::Proxy_Function &f)
return false;
}
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f)
{
try {
f();
} catch (const chaiscript::exception::eval_error &e) {
return e;
}
throw std::runtime_error("no exception throw");
}
std::string get_next_command() {
std::string retval("quit");
if ( ! std::cin.eof() ) {
@@ -102,19 +113,19 @@ void interactive(chaiscript::ChaiScript& chai)
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
chaiscript::dispatch(chai.get_eval_engine().get_function("print"), chaiscript::Param_List_Builder() << val);
std::cout << chai.eval<boost::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
}
catch (...) {} //If we can't, do nothing
}
}
catch (chaiscript::Eval_Error &ee) {
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what();
if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
}
std::cout << std::endl;
}
catch (std::exception &e) {
catch (const std::exception &e) {
std::cout << e.what();
std::cout << std::endl;
}
@@ -158,6 +169,7 @@ int main(int argc, char *argv[])
chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
for (int i = 0; i < argc; ++i) {
if ( i == 0 && argc > 1 ) {
@@ -205,13 +217,17 @@ int main(int argc, char *argv[])
case eFile : val = chai.eval_file(arg); break;
}
}
catch (chaiscript::Eval_Error &ee) {
catch (const chaiscript::exception::eval_error &ee) {
std::cout << ee.what();
if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
for (unsigned int j = 1; j < ee.call_stack.size(); ++j) {
std::cout << std::endl;
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
for (size_t j = 1; j < ee.call_stack.size(); ++j) {
if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
&& ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File)
{
std::cout << std::endl;
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
}
}
}
std::cout << std::endl;

View File

@@ -14,7 +14,8 @@
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const chaiscript::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const chaiscript::Dynamic_Proxy_Function>(t_pf);
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
return pf->get_parse_tree();
@@ -25,7 +26,8 @@ bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
{
boost::shared_ptr<const chaiscript::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const chaiscript::Dynamic_Proxy_Function>(t_pf);
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
if (pf)
{
if (pf->get_parse_tree())
@@ -50,6 +52,13 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
CHAISCRIPT_CLASS( m,
chaiscript::exception::eval_error,
,
((reason))
((call_stack))
);
CHAISCRIPT_CLASS( m,
chaiscript::File_Position,
(chaiscript::File_Position())
@@ -60,7 +69,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
CHAISCRIPT_CLASS( m,
chaiscript::AST_Node,
(chaiscript::AST_Node (const std::string &, int, const boost::shared_ptr<std::string> &)),
,
((text))
((identifier))
((filename))
@@ -68,11 +77,12 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
((end))
((internal_to_string))
((children))
((replace_child))
);
CHAISCRIPT_CLASS( m,
chaiscript::ChaiScript_Parser,
(chaiscript::ChaiScript_Parser ()),
chaiscript::parser::ChaiScript_Parser,
(chaiscript::parser::ChaiScript_Parser ()),
((parse))
((ast))
);

View File

@@ -0,0 +1,2 @@
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );

View File

@@ -19,7 +19,7 @@ int main()
chai("attr bob::z; def bob::bob() { this.z = 10 }; var x = bob()");
chaiscript::Dynamic_Object &mydo = chai.eval<chaiscript::Dynamic_Object &>("x");
chaiscript::dispatch::Dynamic_Object &mydo = chai.eval<chaiscript::dispatch::Dynamic_Object &>("x");
assert_equal(mydo.get_type_name(), "bob");

39
unittests/eval_error.chai Normal file
View File

@@ -0,0 +1,39 @@
load_module("reflection")
def deep()
{
try {
} catch {
} finally {
if (2)
{
}
}
}
def func()
{
deep();
}
def doing()
{
for (var i = 0; i < 10; ++i)
{
func();
}
}
def while_doing()
{
while (true)
{
doing();
}
}
var f = fun() { while_doing(); }
assert_equal(get_eval_error(f).call_stack.size(), 16)

View File

@@ -7,10 +7,20 @@ int main()
chai.eval("def func() { print(\"Hello World\"); } ");
boost::function<void ()> f = chai.functor<void ()>("func");
boost::function<void ()> f = chai.eval<boost::function<void ()> >("func");
f();
return EXIT_SUCCESS;
if (chai.eval<boost::function<std::string (int)> >("to_string")(6) != "6")
{
return EXIT_FAILURE;
}
if (chai.eval<boost::function<std::string (const chaiscript::Boxed_Value &)> >("to_string")(chaiscript::var(6)) == "6")
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}

View File

@@ -8,7 +8,11 @@ assert_equal(eval(a), 7)
var childs := a.children.front().children
var node := childs[0]
node.text = "9"
var parser2 := ChaiScript_Parser()
parser2.parse("9", "INPUT")
a.children.front().replace_child(childs[0], parser2.ast())
assert_equal(eval(a), 13)
assert_equal(node.filename, "INPUT")

View File

@@ -10,6 +10,24 @@ def assert_equal(x, y)
}
}
def assert_false(f)
{
if (f)
{
print("assert_false failure");
exit(-1);
}
}
def assert_true(f)
{
if (!f)
{
print("assert_false failure");
exit(-1);
}
}
def assert_not_equal(x, y)
{
if (!(x == y))