mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-02-08 18:56:48 +08:00
Merge branch '2011-03-15-DocumentationUpdates'
Conflicts: include/chaiscript/language/chaiscript_engine.hpp
This commit is contained in:
commit
8dec35ba19
@ -1357,7 +1357,7 @@ PERLMOD_MAKEVAR_PREFIX =
|
|||||||
# evaluate all C-preprocessor directives found in the sources and include
|
# evaluate all C-preprocessor directives found in the sources and include
|
||||||
# files.
|
# files.
|
||||||
|
|
||||||
ENABLE_PREPROCESSING = YES
|
ENABLE_PREPROCESSING = NO
|
||||||
|
|
||||||
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
|
# 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
|
# names in the source code. If set to NO (the default) only conditional
|
||||||
|
|||||||
@ -1,21 +1,34 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_HPP_
|
#ifndef CHAISCRIPT_HPP_
|
||||||
#define CHAISCRIPT_HPP_
|
#define CHAISCRIPT_HPP_
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/function.hpp>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
/// \mainpage
|
||||||
#include <map>
|
/// <a href="http://www.chaiscript.com">ChaiScript</a> is a scripting language designed specifically for integration with C++. It provides
|
||||||
#include <fstream>
|
/// seamless integration with C++ on all levels, including shared_ptr objects, functors and exceptions.
|
||||||
#include <boost/shared_ptr.hpp>
|
///
|
||||||
|
/// 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/dispatchkit.hpp"
|
||||||
#include "dispatchkit/bootstrap.hpp"
|
#include "dispatchkit/bootstrap.hpp"
|
||||||
|
|||||||
@ -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_
|
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||||
#define CHAISCRIPT_THREADING_HPP_
|
#define CHAISCRIPT_THREADING_HPP_
|
||||||
|
|
||||||
@ -7,15 +13,34 @@
|
|||||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||||
#endif
|
#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 chaiscript
|
||||||
{
|
{
|
||||||
namespace detail
|
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
|
namespace threading
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#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>
|
template<typename T>
|
||||||
class Thread_Storage
|
class Thread_Storage
|
||||||
{
|
{
|
||||||
@ -45,6 +70,32 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#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>
|
template<typename T>
|
||||||
class Thread_Storage
|
class Thread_Storage
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -13,10 +13,11 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
namespace exception
|
namespace exception
|
||||||
{
|
{
|
||||||
/**
|
/// \brief Thrown in the event that a Boxed_Value cannot be cast to the desired type
|
||||||
* 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
|
/// 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
|
class bad_boxed_cast : public std::bad_cast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -38,13 +39,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
virtual ~bad_boxed_cast() throw() {}
|
virtual ~bad_boxed_cast() throw() {}
|
||||||
|
|
||||||
|
/// \brief Description of what error occured
|
||||||
virtual const char * what() const throw()
|
virtual const char * what() const throw()
|
||||||
{
|
{
|
||||||
return m_what.c_str();
|
return m_what.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Info from;
|
Type_Info from; ///< Type_Info contained in the Boxed_Value
|
||||||
const std::type_info *to;
|
const std::type_info *to; ///< std::type_info of the desired (but failed) result type
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_what;
|
std::string m_what;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -30,9 +30,14 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace detail
|
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) >
|
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))>
|
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
|
||||||
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
|
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, _));
|
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) >
|
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))>
|
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, _));
|
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) >
|
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))>
|
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
|
||||||
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
|
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, _));
|
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) >
|
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))>
|
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)
|
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -21,17 +21,15 @@ namespace chaiscript
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Special helpers for generating generic "POD" type operators
|
/// \brief Assigns a POD value from a Boxed_POD_Value. Helps support operators between
|
||||||
* The POD operators are needed for general support of C++ POD
|
/// disparate POD types.
|
||||||
* types without iterating out all possible combinations of operators
|
/// \param[in,out] p1 object to assign to
|
||||||
* (<, >, +, +=, *=, \=, -, <=, >=, ==) and types
|
/// \param[in] v Boxed_POD_Value to assign from
|
||||||
* (char, uint8_t, int8_t, uint16_t, int16_t...)
|
/// \returns Reference to p1, to support normal C assignment semantics
|
||||||
*/
|
|
||||||
template<typename P1>
|
template<typename P1>
|
||||||
P1 &assign_pod(P1 &p1, Boxed_POD_Value v)
|
P1 &assign_pod(P1 &p1, const Boxed_POD_Value &v)
|
||||||
{
|
{
|
||||||
|
if (v.isfloat)
|
||||||
if (v.m_isfloat)
|
|
||||||
{
|
{
|
||||||
return (p1 = P1(v.d));
|
return (p1 = P1(v.d));
|
||||||
} else {
|
} 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>
|
template<typename P1>
|
||||||
P1 construct_pod(Boxed_POD_Value v)
|
P1 construct_pod(Boxed_POD_Value v)
|
||||||
{
|
{
|
||||||
if (v.m_isfloat)
|
if (v.isfloat)
|
||||||
{
|
{
|
||||||
return P1(v.d);
|
return P1(v.d);
|
||||||
} else {
|
} 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>
|
template<typename P1>
|
||||||
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (!r.m_isfloat)
|
if (!r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 &= P1(r.i);
|
return p1 &= P1(r.i);
|
||||||
}
|
}
|
||||||
@ -61,10 +66,14 @@ namespace chaiscript
|
|||||||
throw exception::bad_boxed_cast("&= only valid for integer types");
|
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>
|
template<typename P1>
|
||||||
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (!r.m_isfloat)
|
if (!r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 ^= P1(r.i);
|
return p1 ^= P1(r.i);
|
||||||
}
|
}
|
||||||
@ -72,10 +81,14 @@ namespace chaiscript
|
|||||||
throw exception::bad_boxed_cast("^= only valid for integer types");
|
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>
|
template<typename P1>
|
||||||
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (!r.m_isfloat)
|
if (!r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 |= P1(r.i);
|
return p1 |= P1(r.i);
|
||||||
}
|
}
|
||||||
@ -83,10 +96,14 @@ namespace chaiscript
|
|||||||
throw exception::bad_boxed_cast("&= only valid for integer types");
|
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>
|
template<typename P1>
|
||||||
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (r.m_isfloat)
|
if (r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 -= P1(r.d);
|
return p1 -= P1(r.d);
|
||||||
} else {
|
} 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>
|
template<typename P1>
|
||||||
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (!r.m_isfloat)
|
if (!r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 <<= P1(r.i);
|
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>
|
template<typename P1>
|
||||||
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (r.m_isfloat)
|
if (r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 *= P1(r.d);
|
return p1 *= P1(r.d);
|
||||||
} else {
|
} 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>
|
template<typename P1>
|
||||||
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (r.m_isfloat)
|
if (r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 /= P1(r.d);
|
return p1 /= P1(r.d);
|
||||||
} else {
|
} 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>
|
template<typename P1>
|
||||||
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (!r.m_isfloat)
|
if (!r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 %= P1(r.i);
|
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>
|
template<typename P1>
|
||||||
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (!r.m_isfloat)
|
if (!r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 >>= P1(r.i);
|
return p1 >>= P1(r.i);
|
||||||
}
|
}
|
||||||
@ -151,11 +188,14 @@ namespace chaiscript
|
|||||||
throw exception::bad_boxed_cast(">>= only valid for integer types");
|
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>
|
template<typename P1>
|
||||||
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
|
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
|
||||||
{
|
{
|
||||||
if (r.m_isfloat)
|
if (r.isfloat)
|
||||||
{
|
{
|
||||||
return p1 += P1(r.d);
|
return p1 += P1(r.d);
|
||||||
} else {
|
} 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>
|
template<typename T>
|
||||||
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
|
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@ -177,6 +221,12 @@ namespace chaiscript
|
|||||||
return m;
|
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>
|
template<typename T>
|
||||||
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@ -209,6 +259,11 @@ namespace chaiscript
|
|||||||
return m;
|
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>
|
template<typename T>
|
||||||
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@ -226,9 +281,11 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// \brief Adds a copy constructor for the given type to the given Model
|
||||||
* Add a copy constructor for type T
|
/// \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>
|
template<typename T>
|
||||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@ -236,9 +293,13 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// \brief Adds default and copy constructors for the given type
|
||||||
* Add default and copy constructors for type T
|
/// \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>
|
template<typename T>
|
||||||
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@ -247,9 +308,10 @@ namespace chaiscript
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// \brief Adds a constructor for a POD type
|
||||||
* Add POD type constructor for type T. ie: T = type(POD)
|
/// \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>
|
template<typename T>
|
||||||
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
@ -257,16 +319,6 @@ namespace chaiscript
|
|||||||
return m;
|
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<<
|
* 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]);
|
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()))));
|
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)
|
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)
|
if (pf)
|
||||||
{
|
{
|
||||||
return pf->get_guard();
|
return pf->get_guard();
|
||||||
@ -491,7 +543,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
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)
|
||||||
{
|
{
|
||||||
if (pf->get_guard())
|
if (pf->get_guard())
|
||||||
@ -509,7 +561,7 @@ namespace chaiscript
|
|||||||
throw bv;
|
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");
|
e->add(user_type<void>(), "void");
|
||||||
return e;
|
return e;
|
||||||
@ -535,7 +587,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
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;
|
typedef typename boost::function_types::result_type<FunctionType>::type Vector;
|
||||||
Vector v = (b->*f)();
|
Vector v = (b->*f)();
|
||||||
@ -552,15 +604,15 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Function>
|
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);
|
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||||
* 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()))
|
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
m->add(user_type<void>(), "void");
|
m->add(user_type<void>(), "void");
|
||||||
@ -570,14 +622,14 @@ namespace chaiscript
|
|||||||
m->add(user_type<Proxy_Function>(), "function");
|
m->add(user_type<Proxy_Function>(), "function");
|
||||||
m->add(user_type<std::exception>(), "exception");
|
m->add(user_type<std::exception>(), "exception");
|
||||||
|
|
||||||
m->add(fun(&Proxy_Function_Base::get_arity), "get_arity");
|
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||||
m->add(fun(&Proxy_Function_Base::annotation), "get_annotation");
|
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
|
||||||
m->add(fun(&Proxy_Function_Base::operator()), "call");
|
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
|
||||||
m->add(fun(&Proxy_Function_Base::operator==), "==");
|
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(&dispatch::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_contained_functions)), "get_contained_functions");
|
||||||
|
|
||||||
|
|
||||||
m->add(user_type<std::runtime_error>(), "runtime_error");
|
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(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||||
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
|
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||||
|
|
||||||
m->add(user_type<Dynamic_Object>(), "Dynamic_Object");
|
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||||
m->add(constructor<Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||||
m->add(fun(&Dynamic_Object::get_type_name), "get_type_name");
|
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
||||||
m->add(fun(&Dynamic_Object::get_attrs), "get_attrs");
|
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||||
m->add(fun(&Dynamic_Object::get_attr), "get_attr");
|
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; }");
|
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(&print), "print_string");
|
||||||
m->add(fun(&println), "println_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");
|
"bind");
|
||||||
|
|
||||||
m->add(fun(&shared_ptr_unconst_clone<Proxy_Function_Base>), "clone");
|
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||||
m->add(fun(&ptr_assign<boost::remove_const<Proxy_Function_Base>::type>), "=");
|
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||||
m->add(fun(&ptr_assign<boost::add_const<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");
|
"call_exists");
|
||||||
|
|
||||||
m->add(fun(&type_match), "type_match");
|
m->add(fun(&type_match), "type_match");
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file contains utility functions for registration of STL container
|
* \file
|
||||||
* classes. The methodology used is based on the SGI STL concepts.
|
* This file contains utility functions for registration of STL container
|
||||||
* http://www.sgi.com/tech/stl/table_of_contents.html
|
* 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_
|
#ifndef CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
// 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
|
// 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 &) {
|
} catch (const boost::bad_any_cast &) {
|
||||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -21,205 +21,205 @@ namespace chaiscript
|
|||||||
* Object which attempts to convert a Boxed_Value into a generic
|
* Object which attempts to convert a Boxed_Value into a generic
|
||||||
* POD type and provide generic POD type operations
|
* POD type and provide generic POD type operations
|
||||||
*/
|
*/
|
||||||
struct Boxed_POD_Value
|
class Boxed_POD_Value
|
||||||
{
|
{
|
||||||
Boxed_POD_Value(const Boxed_Value &v)
|
public:
|
||||||
: d(0), i(0), m_isfloat(false)
|
Boxed_POD_Value(const Boxed_Value &v)
|
||||||
{
|
: d(0), i(0), isfloat(false)
|
||||||
if (v.get_type_info().is_undef())
|
|
||||||
{
|
{
|
||||||
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();
|
bool operator==(const Boxed_POD_Value &r) const
|
||||||
|
|
||||||
if (inp_ == typeid(double))
|
|
||||||
{
|
{
|
||||||
d = boxed_cast<double>(v);
|
return ((isfloat)?d:i) == ((r.isfloat)?r.d:r.i);
|
||||||
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 Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
|
bool operator<(const Boxed_POD_Value &r) const
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
bool operator>(const Boxed_POD_Value &r) const
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value operator&(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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");
|
bool operator>=(const Boxed_POD_Value &r) const
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value operator^(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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");
|
bool operator<=(const Boxed_POD_Value &r) const
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value operator|(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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");
|
bool operator!=(const Boxed_POD_Value &r) const
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value operator<<(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Boxed_Value operator*(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Boxed_Value operator%(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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
|
||||||
}
|
|
||||||
|
|
||||||
Boxed_Value operator>>(const Boxed_POD_Value &r) const
|
|
||||||
{
|
|
||||||
if (!m_isfloat && !r.m_isfloat)
|
|
||||||
{
|
{
|
||||||
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
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
if (!isfloat && !r.isfloat)
|
||||||
} else {
|
{
|
||||||
return Boxed_Value(static_cast<int>(t_i));
|
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;
|
return Boxed_Value(((isfloat)?d:i) * ((r.isfloat)?r.d:r.i));
|
||||||
boost::int64_t 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
|
namespace detail
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -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_
|
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||||
#define 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_polymorphic.hpp>
|
||||||
#include <boost/type_traits/is_base_of.hpp>
|
#include <boost/type_traits/is_base_of.hpp>
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
|
||||||
#include <boost/thread/shared_mutex.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
namespace exception
|
namespace exception
|
||||||
@ -150,9 +152,7 @@ namespace chaiscript
|
|||||||
template<typename InItr>
|
template<typename InItr>
|
||||||
void cleanup(InItr begin, const InItr &end)
|
void cleanup(InItr begin, const InItr &end)
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
@ -167,28 +167,22 @@ namespace chaiscript
|
|||||||
|
|
||||||
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
|
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_conversions.insert(conversion.get());
|
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
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return find(base, derived) != m_conversions.end();
|
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
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::set<Dynamic_Conversion *>::const_iterator itr =
|
std::set<Dynamic_Conversion *>::const_iterator itr =
|
||||||
find(base, derived);
|
find(base, derived);
|
||||||
@ -205,7 +199,7 @@ namespace chaiscript
|
|||||||
Dynamic_Conversions() {}
|
Dynamic_Conversions() {}
|
||||||
|
|
||||||
std::set<Dynamic_Conversion *>::const_iterator find(
|
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();
|
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
|
||||||
itr != m_conversions.end();
|
itr != m_conversions.end();
|
||||||
@ -219,9 +213,8 @@ namespace chaiscript
|
|||||||
|
|
||||||
return m_conversions.end();
|
return m_conversions.end();
|
||||||
}
|
}
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
|
||||||
boost::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
#endif
|
|
||||||
std::set<Dynamic_Conversion *> m_conversions;
|
std::set<Dynamic_Conversion *> m_conversions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -248,29 +241,31 @@ namespace chaiscript
|
|||||||
return detail::Dynamic_Conversions::create<Base, Derived>();
|
return detail::Dynamic_Conversions::create<Base, Derived>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Base, typename Derived>
|
namespace detail
|
||||||
bool dynamic_cast_converts()
|
|
||||||
{
|
{
|
||||||
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)
|
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
|
||||||
{
|
{
|
||||||
return detail::Dynamic_Conversions::get().has_conversion(base, 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");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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_
|
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||||
|
|
||||||
@ -5,270 +11,273 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
class Dynamic_Object
|
namespace dispatch
|
||||||
{
|
{
|
||||||
public:
|
class Dynamic_Object
|
||||||
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:
|
public:
|
||||||
Dynamic_Object_Function(
|
Dynamic_Object(const std::string &t_type_name)
|
||||||
const std::string &t_type_name,
|
: m_type_name(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)
|
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)
|
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
&& "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
|
virtual bool operator==(const Proxy_Function_Base &f) const
|
||||||
{
|
|
||||||
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
|
|
||||||
if (df)
|
|
||||||
{
|
{
|
||||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
|
||||||
} else {
|
if (df)
|
||||||
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> ¶ms) 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);
|
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
|
|
||||||
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);
|
if (dynamic_object_typename_match(vals, m_type_name, m_ti))
|
||||||
} else {
|
{
|
||||||
return false;
|
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;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
virtual int get_arity() const
|
||||||
* A Proxy_Function implementation designed for creating a new
|
{
|
||||||
* Dynamic_Object
|
return m_func->get_arity();
|
||||||
* that is automatically guarded based on the first param based on the
|
}
|
||||||
* param's type name
|
|
||||||
*/
|
virtual std::string annotation() const
|
||||||
class Dynamic_Object_Constructor : public Proxy_Function_Base
|
{
|
||||||
{
|
return m_func->annotation();
|
||||||
public:
|
}
|
||||||
Dynamic_Object_Constructor(
|
|
||||||
const std::string &t_type_name,
|
|
||||||
const Proxy_Function &t_func)
|
protected:
|
||||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||||
m_type_name(t_type_name), m_func(t_func)
|
{
|
||||||
|
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)
|
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
&& "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)
|
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)
|
|
||||||
{
|
{
|
||||||
++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
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function_Base &f) const
|
|
||||||
{
|
|
||||||
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);
|
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||||
} else {
|
if (dc)
|
||||||
return false;
|
{
|
||||||
|
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
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> new_vals;
|
std::vector<Boxed_Value> new_vals;
|
||||||
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
||||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
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
|
virtual int get_arity() const
|
||||||
{
|
{
|
||||||
// "this" is not considered part of the arity
|
// "this" is not considered part of the arity
|
||||||
return m_func->get_arity() - 1;
|
return m_func->get_arity() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const
|
virtual std::string annotation() const
|
||||||
{
|
{
|
||||||
return m_func->annotation();
|
return m_func->annotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> new_params;
|
std::vector<Boxed_Value> new_params;
|
||||||
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
||||||
new_params.push_back(bv);
|
new_params.push_back(bv);
|
||||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||||
|
|
||||||
(*m_func)(new_params);
|
(*m_func)(new_params);
|
||||||
|
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_type_name;
|
std::string m_type_name;
|
||||||
Proxy_Function m_func;
|
Proxy_Function m_func;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#ifndef __function_call_hpp__
|
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
#define __function_call_hpp__
|
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
@ -20,37 +20,39 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/**
|
namespace dispatch
|
||||||
* Build a function caller that knows how to dispatch on a set of functions
|
{
|
||||||
* example:
|
/**
|
||||||
* boost::function<void (int)> f =
|
* Build a function caller that knows how to dispatch on a set of functions
|
||||||
* build_function_caller(dispatchkit.get_function("print"));
|
* example:
|
||||||
* \returns A boost::function object for dispatching
|
* boost::function<void (int)> f =
|
||||||
* \param[in] funcs the set of functions to dispatch on.
|
* build_function_caller(dispatchkit.get_function("print"));
|
||||||
*/
|
* \returns A boost::function object for dispatching
|
||||||
template<typename FunctionType>
|
* \param[in] funcs the set of functions to dispatch on.
|
||||||
boost::function<FunctionType>
|
*/
|
||||||
|
template<typename FunctionType>
|
||||||
|
boost::function<FunctionType>
|
||||||
functor(const std::vector<Const_Proxy_Function> &funcs)
|
functor(const std::vector<Const_Proxy_Function> &funcs)
|
||||||
{
|
{
|
||||||
FunctionType *p=0;
|
FunctionType *p=0;
|
||||||
return detail::build_function_caller_helper(p, funcs);
|
return detail::build_function_caller_helper(p, funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a function caller for a particular Proxy_Function object
|
* Build a function caller for a particular Proxy_Function object
|
||||||
* useful in the case that a function is being pass out from scripting back
|
* useful in the case that a function is being pass out from scripting back
|
||||||
* into code
|
* into code
|
||||||
* example:
|
* example:
|
||||||
* void my_function(Proxy_Function f)
|
* void my_function(Proxy_Function f)
|
||||||
* {
|
* {
|
||||||
* boost::function<void (int)> local_f =
|
* boost::function<void (int)> local_f =
|
||||||
* build_function_caller(f);
|
* build_function_caller(f);
|
||||||
* }
|
* }
|
||||||
* \returns A boost::function object for dispatching
|
* \returns A boost::function object for dispatching
|
||||||
* \param[in] func A function to execute.
|
* \param[in] func A function to execute.
|
||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(Const_Proxy_Function func)
|
functor(Const_Proxy_Function func)
|
||||||
{
|
{
|
||||||
std::vector<Const_Proxy_Function> funcs;
|
std::vector<Const_Proxy_Function> funcs;
|
||||||
@ -58,76 +60,76 @@ namespace chaiscript
|
|||||||
return functor<FunctionType>(funcs);
|
return functor<FunctionType>(funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for automatically unboxing a Boxed_Value that contains a function object
|
* Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||||
* and creating a typesafe C++ function caller from it.
|
* and creating a typesafe C++ function caller from it.
|
||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(const Boxed_Value &bv)
|
functor(const Boxed_Value &bv)
|
||||||
{
|
{
|
||||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
|
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace detail{
|
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>
|
template<typename Signature>
|
||||||
struct Cast_Helper<const boost::function<Signature> &>
|
struct Cast_Helper<const boost::function<Signature> &>
|
||||||
{
|
{
|
||||||
typedef boost::function<Signature> Result_Type;
|
typedef boost::function<Signature> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
return functor<Signature>(ob);
|
return dispatch::functor<Signature>(ob);
|
||||||
} else {
|
} else {
|
||||||
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob);
|
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>
|
template<typename Signature>
|
||||||
struct Cast_Helper<boost::function<Signature> >
|
struct Cast_Helper<boost::function<Signature> >
|
||||||
{
|
{
|
||||||
typedef boost::function<Signature> Result_Type;
|
typedef boost::function<Signature> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
return functor<Signature>(ob);
|
return dispatch::functor<Signature>(ob);
|
||||||
} else {
|
} else {
|
||||||
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob);
|
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>
|
template<typename Signature>
|
||||||
struct Cast_Helper<const boost::function<Signature> >
|
struct Cast_Helper<const boost::function<Signature> >
|
||||||
{
|
{
|
||||||
typedef boost::function<Signature> Result_Type;
|
typedef boost::function<Signature> Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||||
{
|
{
|
||||||
return functor<Signature>(ob);
|
return dispatch::functor<Signature>(ob);
|
||||||
} else {
|
} else {
|
||||||
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
|
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
#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))
|
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
|
||||||
|
|
||||||
|
|
||||||
@ -23,34 +23,38 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace dispatch
|
||||||
{
|
{
|
||||||
/**
|
namespace detail
|
||||||
* 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> ¶ms)
|
|
||||||
{
|
|
||||||
return boxed_cast<Ret>(dispatch(t_funcs, params));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialization for void return types
|
* Internal helper class for handling the return
|
||||||
*/
|
* value of a build_function_caller
|
||||||
template<>
|
*/
|
||||||
struct Function_Caller_Ret<void>
|
template<typename Ret>
|
||||||
{
|
struct Function_Caller_Ret
|
||||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
|
||||||
{
|
{
|
||||||
dispatch(t_funcs, params);
|
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
}
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
};
|
{
|
||||||
|
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> ¶ms)
|
||||||
|
{
|
||||||
|
dispatch::dispatch(t_funcs, params);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,47 +68,49 @@ namespace chaiscript
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace dispatch
|
||||||
{
|
{
|
||||||
/**
|
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) >
|
* used internally for unwrapping a function call's types
|
||||||
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
|
*/
|
||||||
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
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
|
||||||
std::vector<Boxed_Value> params;
|
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
|
std::vector<Boxed_Value> params;
|
||||||
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
|
|
||||||
(funcs[0]);
|
|
||||||
|
|
||||||
if (pfi)
|
BOOST_PP_REPEAT(n, addparam, ~)
|
||||||
{
|
|
||||||
return pfi->internal_function();
|
return Function_Caller_Ret<Ret>::call(funcs, params);
|
||||||
}
|
|
||||||
// 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, ~));
|
* 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
|
#undef n
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
static Boxed_Value handle(const Ret &r)
|
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>
|
template<typename Ret>
|
||||||
struct Handle_Return<const boost::shared_ptr<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
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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_
|
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||||
#define CHAISCRIPT_OPERATORS_HPP_
|
#define CHAISCRIPT_OPERATORS_HPP_
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ namespace chaiscript
|
|||||||
Proxy_Function constructor()
|
Proxy_Function constructor()
|
||||||
{
|
{
|
||||||
T *f = 0;
|
T *f = 0;
|
||||||
return (detail::build_constructor_(f));
|
return (dispatch::detail::build_constructor_(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,30 +35,33 @@ namespace chaiscript
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace dispatch
|
||||||
{
|
{
|
||||||
/**
|
namespace detail
|
||||||
* A constructor function, used for creating a new object
|
{
|
||||||
* of a given type with a given set of params
|
/**
|
||||||
*/
|
* A constructor function, used for creating a new object
|
||||||
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
* of a given type with a given set of params
|
||||||
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
*/
|
||||||
{
|
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
|
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||||
}
|
{
|
||||||
|
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function for build a constructor function
|
* Helper function for build a constructor function
|
||||||
* example:
|
* example:
|
||||||
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
|
* 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
|
* \todo See if it is possible to make this not be a variadic function
|
||||||
*/
|
*/
|
||||||
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||||
{
|
{
|
||||||
typedef boost::shared_ptr<Class> (sig)(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)>))));
|
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
|
#undef n
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.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> ¶ms)
|
|
||||||
{
|
|
||||||
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> ¶ms)
|
|
||||||
{
|
|
||||||
call_func(fun, params);
|
|
||||||
return Handle_Return<void>::handle();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||||
@ -143,3 +120,35 @@ namespace chaiscript
|
|||||||
#undef n
|
#undef n
|
||||||
|
|
||||||
#endif
|
#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> ¶ms)
|
||||||
|
{
|
||||||
|
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> ¶ms)
|
||||||
|
{
|
||||||
|
chaiscript::detail::call_func(fun, params);
|
||||||
|
return Handle_Return<void>::handle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -18,61 +18,63 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace dispatch
|
||||||
{
|
{
|
||||||
template<bool Object, bool MemFn>
|
namespace detail
|
||||||
struct Fun_Helper
|
{
|
||||||
{
|
template<bool Object, bool MemFn>
|
||||||
template<typename T>
|
struct Fun_Helper
|
||||||
static Proxy_Function go(T t)
|
|
||||||
{
|
{
|
||||||
return Proxy_Function(
|
template<typename T>
|
||||||
new Proxy_Function_Impl<
|
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> (
|
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
|
||||||
boost::function<
|
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
|
||||||
>(t)));
|
>(t)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Fun_Helper<false, true>
|
struct Fun_Helper<false, true>
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
static Proxy_Function go(T t)
|
|
||||||
{
|
{
|
||||||
return Proxy_Function(
|
template<typename T>
|
||||||
new Proxy_Function_Impl<
|
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> (
|
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
|
||||||
boost::function<
|
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))));
|
>(boost::mem_fn(t))));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Fun_Helper<true, false>
|
struct Fun_Helper<true, false>
|
||||||
{
|
{
|
||||||
template<typename T, typename Class>
|
template<typename T, typename Class>
|
||||||
static Proxy_Function go(T Class::* m)
|
static Proxy_Function go(T Class::* m)
|
||||||
{
|
{
|
||||||
return Proxy_Function(new Attribute_Access<T, Class>(m));
|
return Proxy_Function(new Attribute_Access<T, Class>(m));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Proxy_Function fun(const boost::function<T> &f)
|
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>
|
template<typename T>
|
||||||
Proxy_Function fun(T 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>
|
template<typename T, typename Q>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -22,12 +22,14 @@
|
|||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T>
|
namespace detail
|
||||||
struct Bare_Type
|
{
|
||||||
{
|
template<typename T>
|
||||||
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
|
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
|
* compile time deduced information about a type
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -8,6 +8,7 @@
|
|||||||
#define CHAISCRIPT_COMMON_HPP_
|
#define CHAISCRIPT_COMMON_HPP_
|
||||||
|
|
||||||
#include <chaiscript/dispatchkit/dispatchkit.hpp>
|
#include <chaiscript/dispatchkit/dispatchkit.hpp>
|
||||||
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
@ -57,110 +58,155 @@ namespace chaiscript
|
|||||||
|
|
||||||
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
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
|
* The struct that doubles as both a parser ast_node and an AST node
|
||||||
*/
|
*/
|
||||||
struct AST_Node {
|
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
|
||||||
std::string text;
|
public:
|
||||||
int identifier;
|
const std::string text;
|
||||||
boost::shared_ptr<std::string> filename;
|
const int identifier;
|
||||||
File_Position start, end;
|
boost::shared_ptr<const std::string> filename;
|
||||||
std::vector<AST_NodePtr> children;
|
File_Position start, end;
|
||||||
AST_NodePtr annotation;
|
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) :
|
* Prints the contents of an AST node, including its children, recursively
|
||||||
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)
|
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) :
|
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||||
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
|
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
|
||||||
|
|
||||||
virtual ~AST_Node() {}
|
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||||
|
oss << this->children[j]->to_string(t_prepend + " ");
|
||||||
/**
|
}
|
||||||
* Prints the contents of an AST node, including its children, recursively
|
return oss.str();
|
||||||
*/
|
|
||||||
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 + " ");
|
|
||||||
}
|
}
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string internal_to_string() {
|
std::string internal_to_string() {
|
||||||
return to_string();
|
return to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Boxed_Value eval(Dispatch_Engine &) {
|
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
|
||||||
Boxed_Value bv;
|
{
|
||||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
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) :
|
namespace detail
|
||||||
std::runtime_error("Error: \"" + t_why + "\" " +
|
{
|
||||||
(t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") +
|
/**
|
||||||
+ "at (" + boost::lexical_cast<std::string>(t_where.line) + ", " +
|
* Special type for returned values
|
||||||
boost::lexical_cast<std::string>(t_where.column) + ")"),
|
*/
|
||||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
|
struct Return_Value {
|
||||||
{ }
|
Boxed_Value retval;
|
||||||
|
|
||||||
Eval_Error(const std::string &t_why)
|
Return_Value(const Boxed_Value &t_return_value) : retval(t_return_value) { }
|
||||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
};
|
||||||
reason(t_why)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual ~Eval_Error() throw() {}
|
/**
|
||||||
};
|
* Special type indicating a call to 'break'
|
||||||
|
*/
|
||||||
|
struct Break_Loop {
|
||||||
|
Break_Loop() { }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/// Creates a new scope then pops it on destruction
|
||||||
* Errors generated when loading a file
|
struct Scope_Push_Pop
|
||||||
*/
|
{
|
||||||
struct File_Not_Found_Error : public std::runtime_error {
|
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||||
File_Not_Found_Error(const std::string &t_filename)
|
: m_de(t_de)
|
||||||
: std::runtime_error("File Not Found: " + t_filename)
|
{
|
||||||
{ }
|
m_de.new_scope();
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~File_Not_Found_Error() throw() {}
|
~Scope_Push_Pop()
|
||||||
};
|
{
|
||||||
|
m_de.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
private:
|
||||||
* Special type for returned values
|
chaiscript::detail::Dispatch_Engine &m_de;
|
||||||
*/
|
};
|
||||||
struct Return_Value {
|
|
||||||
Boxed_Value retval;
|
|
||||||
|
|
||||||
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 */
|
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
@ -28,205 +28,210 @@
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
struct load_module_error : std::runtime_error
|
namespace exception
|
||||||
{
|
{
|
||||||
load_module_error(const std::string &t_reason) throw()
|
struct load_module_error : std::runtime_error
|
||||||
: std::runtime_error(t_reason)
|
|
||||||
{
|
{
|
||||||
}
|
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
|
#ifdef _POSIX_VERSION
|
||||||
struct Loadable_Module
|
struct Loadable_Module
|
||||||
{
|
|
||||||
struct DLModule
|
|
||||||
{
|
{
|
||||||
DLModule(const std::string &t_filename)
|
struct DLModule
|
||||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
|
||||||
{
|
{
|
||||||
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(const DLModule &); // Explicitly unimplemented copy constructor
|
||||||
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
|
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
|
||||||
|
|
||||||
~DLModule()
|
~DLModule()
|
||||||
{
|
{
|
||||||
dlclose(m_data);
|
dlclose(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *m_data;
|
void *m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct DLSym
|
struct DLSym
|
||||||
{
|
{
|
||||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||||
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
|
: m_symbol(reinterpret_cast<T>(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||||
{
|
|
||||||
if (!m_symbol)
|
|
||||||
{
|
{
|
||||||
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)
|
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_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||||
m_moduleptr(m_func.m_symbol())
|
m_moduleptr(m_func.m_symbol())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DLModule m_dlmodule;
|
DLModule m_dlmodule;
|
||||||
DLSym<Create_Module_Func> m_func;
|
DLSym<Create_Module_Func> m_func;
|
||||||
ModulePtr m_moduleptr;
|
ModulePtr m_moduleptr;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
|
|
||||||
struct Loadable_Module
|
struct Loadable_Module
|
||||||
{
|
|
||||||
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::wstring towstring(const T &t_str)
|
||||||
|
{
|
||||||
|
return std::wstring(t_str.begin(), t_str.end());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string tostring(const T &t_str)
|
static std::string tostring(const T &t_str)
|
||||||
{
|
{
|
||||||
return std::string(t_str.begin(), t_str.end());
|
return std::string(t_str.begin(), t_str.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::wstring toproperstring(const T &t_str)
|
static std::wstring toproperstring(const T &t_str)
|
||||||
{
|
{
|
||||||
return towstring(t_str);
|
return towstring(t_str);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::string toproperstring(const T &t_str)
|
static std::string toproperstring(const T &t_str)
|
||||||
{
|
{
|
||||||
return tostring(t_str);
|
return tostring(t_str);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string GetErrorMessage(DWORD t_err)
|
static std::string GetErrorMessage(DWORD t_err)
|
||||||
{
|
{
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
typedef LPWSTR StringType;
|
typedef LPWSTR StringType;
|
||||||
std::wstring retval = L"Unknown Error";
|
std::wstring retval = L"Unknown Error";
|
||||||
#else
|
#else
|
||||||
typedef LPSTR StringType;
|
typedef LPSTR StringType;
|
||||||
std::string retval = "Unknown Error";
|
std::string retval = "Unknown Error";
|
||||||
#endif
|
#endif
|
||||||
StringType lpMsgBuf = 0;
|
StringType lpMsgBuf = 0;
|
||||||
|
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
NULL,
|
NULL,
|
||||||
t_err,
|
t_err,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(StringType)&lpMsgBuf,
|
(StringType)&lpMsgBuf,
|
||||||
0, NULL );
|
0, NULL );
|
||||||
|
|
||||||
if (lpMsgBuf)
|
if (lpMsgBuf)
|
||||||
{
|
{
|
||||||
retval = lpMsgBuf;
|
retval = lpMsgBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
return tostring(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalFree(lpMsgBuf);
|
struct DLModule
|
||||||
return tostring(retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DLModule
|
|
||||||
{
|
|
||||||
DLModule(const std::string &t_filename)
|
|
||||||
: m_data(LoadLibrary(toproperstring(t_filename).c_str()))
|
|
||||||
{
|
{
|
||||||
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()
|
~DLModule()
|
||||||
{
|
{
|
||||||
FreeLibrary(m_data);
|
FreeLibrary(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE m_data;
|
HMODULE m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct DLSym
|
struct DLSym
|
||||||
{
|
{
|
||||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||||
{
|
|
||||||
if (!m_symbol)
|
|
||||||
{
|
{
|
||||||
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)
|
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_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||||
m_moduleptr(m_func.m_symbol())
|
m_moduleptr(m_func.m_symbol())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DLModule m_dlmodule;
|
DLModule m_dlmodule;
|
||||||
DLSym<Create_Module_Func> m_func;
|
DLSym<Create_Module_Func> m_func;
|
||||||
ModulePtr m_moduleptr;
|
ModulePtr m_moduleptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
struct Loadable_Module
|
struct Loadable_Module
|
||||||
{
|
|
||||||
Loadable_Module(const std::string &, const std::string &)
|
|
||||||
{
|
{
|
||||||
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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
class ChaiScript {
|
class ChaiScript {
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
|
||||||
mutable boost::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
mutable boost::recursive_mutex m_use_mutex;
|
mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
|
||||||
#endif
|
|
||||||
|
|
||||||
std::set<std::string> m_used_files;
|
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::set<std::string> m_active_loaded_modules;
|
||||||
|
|
||||||
std::vector<std::string> m_modulepaths;
|
std::vector<std::string> m_modulepaths;
|
||||||
std::vector<std::string> m_usepaths;
|
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)
|
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
ChaiScript_Parser parser;
|
parser::ChaiScript_Parser parser;
|
||||||
if (parser.parse(t_input, t_filename)) {
|
if (parser.parse(t_input, t_filename)) {
|
||||||
//parser.show_match_stack();
|
//parser.show_match_stack();
|
||||||
return parser.ast()->eval(m_engine);
|
return parser.ast()->eval(m_engine);
|
||||||
@ -243,7 +248,7 @@ namespace chaiscript
|
|||||||
return Boxed_Value();
|
return Boxed_Value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const Return_Value &rv) {
|
catch (const detail::Return_Value &rv) {
|
||||||
return rv.retval;
|
return rv.retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,23 +276,19 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||||
|
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
boost::shared_lock<boost::shared_mutex> l2(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_used_files.count(appendedpath) == 0)
|
if (m_used_files.count(appendedpath) == 0)
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
|
||||||
m_used_files.insert(appendedpath);
|
m_used_files.insert(appendedpath);
|
||||||
l2.unlock();
|
l2.unlock();
|
||||||
#endif
|
|
||||||
eval_file(appendedpath);
|
eval_file(appendedpath);
|
||||||
}
|
}
|
||||||
} catch (const File_Not_Found_Error &) {
|
} catch (const exception::file_not_found_error &) {
|
||||||
if (i == m_usepaths.size() - 1)
|
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
|
// 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:
|
public:
|
||||||
ChaiScript(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
ChaiScript(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||||
@ -326,7 +384,7 @@ namespace chaiscript
|
|||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
std::set<std::string> used_files;
|
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;
|
std::set<std::string> active_loaded_modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -337,10 +395,8 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
State get_state()
|
State get_state()
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
boost::shared_lock<boost::shared_mutex> l2(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
State s;
|
State s;
|
||||||
s.used_files = m_used_files;
|
s.used_files = m_used_files;
|
||||||
@ -354,10 +410,8 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
void set_state(const State &t_state)
|
void set_state(const State &t_state)
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||||
boost::shared_lock<boost::shared_mutex> l2(m_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_used_files = t_state.used_files;
|
m_used_files = t_state.used_files;
|
||||||
m_active_loaded_modules = t_state.active_loaded_modules;
|
m_active_loaded_modules = t_state.active_loaded_modules;
|
||||||
@ -388,7 +442,7 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
void load_module(const std::string &t_module_name)
|
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;
|
std::vector<std::string> prefixes;
|
||||||
prefixes.push_back("lib");
|
prefixes.push_back("lib");
|
||||||
@ -409,7 +463,7 @@ namespace chaiscript
|
|||||||
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
|
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
|
||||||
load_module(t_module_name, name);
|
load_module(t_module_name, name);
|
||||||
return;
|
return;
|
||||||
} catch (const load_module_error &e) {
|
} catch (const exception::load_module_error &e) {
|
||||||
errors.push_back(e);
|
errors.push_back(e);
|
||||||
// Try next set
|
// Try next set
|
||||||
}
|
}
|
||||||
@ -419,7 +473,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
std::string errstring;
|
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 != errors.end();
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
@ -431,7 +485,7 @@ namespace chaiscript
|
|||||||
errstring += itr->what();
|
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)
|
void load_module(const std::string &t_module_name, const std::string &t_filename)
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||||
boost::lock_guard<boost::recursive_mutex> l(m_use_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_loaded_modules.count(t_module_name) == 0)
|
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_loaded_modules[t_module_name] = lm;
|
||||||
m_active_loaded_modules.insert(t_module_name);
|
m_active_loaded_modules.insert(t_module_name);
|
||||||
add(lm->m_moduleptr);
|
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
|
* 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
|
* 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 );
|
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
||||||
|
|
||||||
if (!infile.is_open()) {
|
if (!infile.is_open()) {
|
||||||
throw File_Not_Found_Error(t_filename);
|
throw exception::file_not_found_error(t_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::streampos size = infile.tellg();
|
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>
|
template<typename T>
|
||||||
T eval(const std::string &t_input)
|
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
@ -1,6 +1,6 @@
|
|||||||
// This file is distributed under the BSD License.
|
// This file is distributed under the BSD License.
|
||||||
// See "license.txt" for details.
|
// See "license.txt" for details.
|
||||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
// Copyright 2009-2011, Jonathan Turner (jonathan@emptycrate.com)
|
||||||
// and Jason Turner (jason@emptycrate.com)
|
// and Jason Turner (jason@emptycrate.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
#ifndef CHAISCRIPT_UTILITY_UTILITY_HPP__
|
// This file is distributed under the BSD License.
|
||||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP__
|
// 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 "../chaiscript.hpp"
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
|
|||||||
@ -45,7 +45,7 @@ struct System
|
|||||||
void add_callback(const std::string &t_name,
|
void add_callback(const std::string &t_name,
|
||||||
const chaiscript::Proxy_Function &t_func)
|
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
|
//Call bound version of do_callbacks
|
||||||
chai("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();
|
caller();
|
||||||
|
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
//To do: Add examples of handling Boxed_Values directly when needed
|
//To do: Add examples of handling Boxed_Values directly when needed
|
||||||
|
|
||||||
//Creating a functor on the stack and using it immediatly
|
//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));
|
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");
|
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
|
||||||
|
|
||||||
//Dynamic objects test
|
//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 dispatch::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(chaiscript::Proxy_Function(new dispatch::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(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("var x = TestType()");
|
||||||
// chai.eval("x.attr = \"hi\"");
|
// chai.eval("x.attr = \"hi\"");
|
||||||
|
|||||||
34
src/main.cpp
34
src/main.cpp
@ -52,10 +52,10 @@ void version(int){
|
|||||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
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 {
|
try {
|
||||||
chaiscript::functor<void ()>(f)();
|
f();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -63,6 +63,17 @@ bool throws_exception(const chaiscript::Proxy_Function &f)
|
|||||||
return false;
|
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 get_next_command() {
|
||||||
std::string retval("quit");
|
std::string retval("quit");
|
||||||
if ( ! std::cin.eof() ) {
|
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
|
//Then, we try to print the result of the evaluation to the user
|
||||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||||
try {
|
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 (...) {} //If we can't, do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (chaiscript::Eval_Error &ee) {
|
catch (const chaiscript::exception::eval_error &ee) {
|
||||||
std::cout << ee.what();
|
std::cout << ee.what();
|
||||||
if (ee.call_stack.size() > 0) {
|
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 << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (const std::exception &e) {
|
||||||
std::cout << e.what();
|
std::cout << e.what();
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
@ -158,6 +169,7 @@ int main(int argc, char *argv[])
|
|||||||
chai.add(chaiscript::fun(&help), "help");
|
chai.add(chaiscript::fun(&help), "help");
|
||||||
chai.add(chaiscript::fun(&version), "version");
|
chai.add(chaiscript::fun(&version), "version");
|
||||||
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
|
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) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
if ( i == 0 && argc > 1 ) {
|
if ( i == 0 && argc > 1 ) {
|
||||||
@ -205,13 +217,17 @@ int main(int argc, char *argv[])
|
|||||||
case eFile : val = chai.eval_file(arg); break;
|
case eFile : val = chai.eval_file(arg); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (chaiscript::Eval_Error &ee) {
|
catch (const chaiscript::exception::eval_error &ee) {
|
||||||
std::cout << ee.what();
|
std::cout << ee.what();
|
||||||
if (ee.call_stack.size() > 0) {
|
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 << ")";
|
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) {
|
for (size_t j = 1; j < ee.call_stack.size(); ++j) {
|
||||||
std::cout << std::endl;
|
if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
|
||||||
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
|
&& 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;
|
std::cout << std::endl;
|
||||||
|
|||||||
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
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)
|
if (pf)
|
||||||
{
|
{
|
||||||
return pf->get_parse_tree();
|
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)
|
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)
|
||||||
{
|
{
|
||||||
if (pf->get_parse_tree())
|
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::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_CLASS( m,
|
||||||
chaiscript::File_Position,
|
chaiscript::File_Position,
|
||||||
(chaiscript::File_Position())
|
(chaiscript::File_Position())
|
||||||
@ -60,7 +69,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
|
|
||||||
CHAISCRIPT_CLASS( m,
|
CHAISCRIPT_CLASS( m,
|
||||||
chaiscript::AST_Node,
|
chaiscript::AST_Node,
|
||||||
(chaiscript::AST_Node (const std::string &, int, const boost::shared_ptr<std::string> &)),
|
,
|
||||||
((text))
|
((text))
|
||||||
((identifier))
|
((identifier))
|
||||||
((filename))
|
((filename))
|
||||||
@ -68,11 +77,12 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
|||||||
((end))
|
((end))
|
||||||
((internal_to_string))
|
((internal_to_string))
|
||||||
((children))
|
((children))
|
||||||
|
((replace_child))
|
||||||
);
|
);
|
||||||
|
|
||||||
CHAISCRIPT_CLASS( m,
|
CHAISCRIPT_CLASS( m,
|
||||||
chaiscript::ChaiScript_Parser,
|
chaiscript::parser::ChaiScript_Parser,
|
||||||
(chaiscript::ChaiScript_Parser ()),
|
(chaiscript::parser::ChaiScript_Parser ()),
|
||||||
((parse))
|
((parse))
|
||||||
((ast))
|
((ast))
|
||||||
);
|
);
|
||||||
|
|||||||
2
unittests/assign_const.chai
Normal file
2
unittests/assign_const.chai
Normal 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 } );
|
||||||
@ -19,7 +19,7 @@ int main()
|
|||||||
|
|
||||||
chai("attr bob::z; def bob::bob() { this.z = 10 }; var x = bob()");
|
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");
|
assert_equal(mydo.get_type_name(), "bob");
|
||||||
|
|
||||||
|
|||||||
39
unittests/eval_error.chai
Normal file
39
unittests/eval_error.chai
Normal 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)
|
||||||
@ -7,10 +7,20 @@ int main()
|
|||||||
|
|
||||||
chai.eval("def func() { print(\"Hello World\"); } ");
|
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();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,11 @@ assert_equal(eval(a), 7)
|
|||||||
var childs := a.children.front().children
|
var childs := a.children.front().children
|
||||||
var node := childs[0]
|
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(eval(a), 13)
|
||||||
assert_equal(node.filename, "INPUT")
|
assert_equal(node.filename, "INPUT")
|
||||||
|
|||||||
@ -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)
|
def assert_not_equal(x, y)
|
||||||
{
|
{
|
||||||
if (!(x == y))
|
if (!(x == y))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user