Compare commits

..

42 Commits

Author SHA1 Message Date
Jason Turner
1cd9a9098c Update gcc flags for MacOS to ignore sign comparison warnings 2011-06-18 07:34:55 -06:00
Jason Turner
5ff14a54db Commented out code removal 2011-06-16 10:42:26 -06:00
Jason Turner
28e3d442e2 Update version number to 3.1.0 for next release 2011-06-16 10:19:54 -06:00
Jason Turner
bb0edcb62a Add exception_specification and unittests for it. #6 2011-06-16 10:14:52 -06:00
Jonathan Turner
9a015a5c49 Fix typo in unit test and add string literal access 2011-06-13 18:14:41 -07:00
Jonathan Turner
9d20f60903 Update license year 2011-06-13 07:45:11 -07:00
Jonathan Turner
5426496b4f Fix parsing of member access and function calls 2011-06-13 07:43:51 -07:00
Jason Turner
9e9fb3ad7d Fix one more documentation error 2011-06-10 16:42:38 -06:00
Jason Turner
8cc3651c76 Correct copyright date 2011-06-10 16:41:00 -06:00
Jason Turner
4d879afca7 Documentation updates 2011-06-10 16:38:20 -06:00
Jason Turner
afae221cb3 Add tests for more complex uses of the index operator 2011-06-10 11:18:58 -06:00
Jason Turner
b064bb61e9 Finish renaming and cleaning up of Boxed_Number type for dump_system() output 2011-06-10 10:12:09 -06:00
Jason Turner
7a9baeb350 Rename of numeric to number 2011-06-08 13:53:55 -06:00
Jason Turner
6d4041b2a1 Added profile for mathy functions.x 2011-06-07 14:59:43 -06:00
Jason Turner
1932cbfbbc Eliminate duplicate code and reduce Boxed_Value copies necessary 2011-06-04 12:31:33 -06:00
Jonathan Turner
8fecf5c145 Merge branch 'master' of github.com:ChaiScript/ChaiScript 2011-06-04 11:02:07 -07:00
Jonathan Turner
6131a9c4c1 Moved common operators into their own AST nodes and removed the operator child. 2011-06-04 11:01:35 -07:00
Jason Turner
881d569d8e Remove unnecessary loop from Binary_Operator 2011-06-04 10:34:15 -06:00
Jonathan Turner
6c18c197c6 Fixed operator parsing to return trees instead of flat representations. Fixed evaluator to not loop over equations. 2011-06-04 09:15:19 -07:00
Jason Turner
f47ec0d522 Merge pull request #7 from lefticus/master
Merge Number Performance Updates
2011-06-03 17:52:04 -07:00
Jason Turner
4053196188 Reduce creation of new Boxed_Value containers when returning the same value that was passed in 2011-06-04 04:26:06 +08:00
Jason Turner
5b40a85024 Add direct access to Boxed_Value data * for high performance operations 2011-06-04 04:26:00 +08:00
Jason Turner
36faba8ed3 Bypass dispatch during numeric operations. 2x speedup 2011-06-04 04:25:54 +08:00
Jason Turner
7d022c4f0d Add is_prime profile script 2011-06-04 04:25:47 +08:00
Jason Turner
b933bb6c50 Begin move of Operators code out a level so that it can be used before dispatch 2011-06-04 04:25:42 +08:00
Jason Turner
92bfcfdcf3 Wrap up new Boxed_Numeric support 2011-06-04 04:25:36 +08:00
Jason Turner
3b754cfec4 Further simplification and refinement of enhanced Algebraic types support 2011-06-04 04:25:30 +08:00
Jason Turner
3689c01e4b Significant reduction in templates instantiated by grouping of operators - smaller code and compile time 2011-06-04 04:25:24 +08:00
Jason Turner
4b90fbd07a wrap up support for all built in C++ Arithmetic types 2011-06-04 04:25:18 +08:00
Jason Turner
1a225dca67 Progress towards eliminating arithmetic operators on a per-type basis 2011-06-04 04:25:12 +08:00
Jason Turner
226666c2bb Rename Boxed_POD_Value to Boxed_Numeric, which is more correct. 2011-06-04 04:24:57 +08:00
Jason Turner
d4ef226911 Reduce creation of new Boxed_Value containers when returning the same value that was passed in 2011-06-03 13:48:32 -06:00
Jason Turner
6491262491 Add direct access to Boxed_Value data * for high performance operations 2011-06-03 12:41:38 -06:00
Jason Turner
2c4d69bfc0 Bypass dispatch during numeric operations. 2x speedup 2011-06-01 22:12:50 -06:00
Jason Turner
f423969a8e Add is_prime profile script 2011-05-31 08:09:30 -06:00
Jason Turner
36cd4c370a Begin move of Operators code out a level so that it can be used before dispatch 2011-05-31 07:42:30 -06:00
Jason Turner
85f69782b2 Wrap up new Boxed_Numeric support 2011-05-30 19:38:04 -06:00
Jason Turner
1f130c0891 Further simplification and refinement of enhanced Algebraic types support 2011-05-29 17:33:45 -06:00
Jason Turner
fdd1b40a9f Significant reduction in templates instantiated by grouping of operators - smaller code and compile time 2011-05-29 09:14:48 -06:00
Jason Turner
6993d58fdc wrap up support for all built in C++ Arithmetic types 2011-05-28 23:48:17 -06:00
Jason Turner
1845114d36 Progress towards eliminating arithmetic operators on a per-type basis 2011-05-26 05:58:19 -06:00
Jason Turner
bba1ffde38 Rename Boxed_POD_Value to Boxed_Numeric, which is more correct. 2011-05-24 12:39:39 -06:00
28 changed files with 1805 additions and 776 deletions

View File

@@ -17,7 +17,7 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.txt")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 3)
set(CPACK_PACKAGE_VERSION_MINOR 0)
set(CPACK_PACKAGE_VERSION_MINOR 1)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -61,8 +61,12 @@ IF(MSVC)
ADD_DEFINITIONS(/bigobj)
ENDIF()
ELSE()
# -Wno-missing-field-initializers is for boost on macos
ADD_DEFINITIONS(-Wall -Wextra -Wno-missing-field-initializers -Wshadow)
ADD_DEFINITIONS(-Wall -Wextra -Wshadow)
IF (APPLE)
# -Wno-missing-field-initializers is for boost on macos
ADD_DEFINITIONS(-Wno-missing-field-initializers -Wno-sign-compare)
ENDIF()
ENDIF()
include_directories(include)

View File

@@ -0,0 +1,25 @@
def isprime(n)
{
for (var i = 2; i < n; ++i)
{
if (n % i == 0) {return false}
}
return true
}
def primes(n)
{
var count = 0
for (var i = 2; i <= n; ++i)
{
if (isprime(i)) {++count}
}
return count
}
var N = 5000
print("primes: " + primes(N).to_string())

View File

@@ -0,0 +1,9 @@
var something = 0;
for (var i = 1; i < 10000; ++i)
{
something += int(3 % 2 * 4 + 2 / 16.0 - 100 + (10 ^ 19) / 64 + (3 & 12) - (4 | 14)) % i;
}
print(something);

View File

@@ -24,6 +24,8 @@
///
/// \sa chaiscript
/// \sa chaiscript::ChaiScript
/// \sa ChaiScript_Language for Built in Functions
/// \sa \ref LangGettingStarted
/// \sa \ref LangKeywordRef
/// \sa \ref LangInPlaceRef
/// \sa \ref LangObjectSystemRef
@@ -32,11 +34,13 @@
///
/// <hr>
///
/// \section gettingstarted Getting Started
/// \section gettingstarted API Getting Started
///
/// \li \ref basics
/// \li \ref compiling
/// \li \ref eval
/// \li \ref addingitems
/// \li \ref operatoroverloading
/// \li \ref helpermacro
/// \li \ref pointerconversions
/// \li \ref baseclasses
@@ -50,6 +54,7 @@
/// Basic simple example:
///
/// \code
/// //main.cpp
/// #include <chaiscript/chaiscript.hpp>
///
/// double function(int i, double j)
@@ -67,6 +72,27 @@
/// \endcode
///
/// <hr>
/// \subsection compiling Compiling ChaiScript Applications
///
/// ChaiScript is a header only library with only two dependecies. boost::threads (optional) and the
/// operating system provided dynamic library loader, which has to be specified on some platforms.
///
/// \subsubsection compilinggcc Compiling with GCC
///
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
/// both boost::threads and the dynamic loader. For example:
///
/// \code
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -lboost_threads
/// \endcode
///
/// Alternatively, you may compile without threading support.
///
/// \code
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -DCHAISCRIPT_NO_THREADS
/// \endcode
///
/// <hr>
/// \subsection eval Evaluating Scripts
///
/// Scripts can be evaluated with the () operator, eval method or eval_file method.
@@ -114,7 +140,7 @@
///
/// \subsubsection addingobjects Adding Objects
///
/// Named objects can be created with the #var function.
/// Named objects can be created with the chaiscript::var function.
///
/// \code
/// using namespace chaiscript;
@@ -206,6 +232,28 @@
/// \sa chaiscript::Module
///
/// <hr>
/// \subsection operatoroverloading Operator Overloading
///
/// Operators are just like any other function in ChaiScript, to overload an operator, simply register it.
///
/// \code
/// class MyClass {
/// MyClass operator+(const MyClass &) const;
/// };
///
/// chai.add(fun(&MyClass::operator+), "+");
///
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
/// {
/// return t_lhs + boost::lexical_cast<std::string>(t_rhs);
/// }
///
/// chai.add(fun(append_string_int), "+");
/// \endcode
///
/// \sa \ref addingfunctions
///
/// <hr>
/// \subsection helpermacro Class Helper Macro
///
/// Much of the work of adding new classes to ChaiScript can be reduced with the help
@@ -252,7 +300,7 @@
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, boost::shared_ptr<T>,
/// boost::shared_ptr<const T>, boost::reference_wrapper<T>, boost::reference_wrapper<const T> and value types automatically.
///
/// If a var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
/// Const may be added, but never removed.
///
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
@@ -365,6 +413,8 @@
///
/// \subsection exceptions Exception Handling
///
/// \subsubsection exceptionsbasics Exception Handling Basics
///
/// Exceptions can be thrown in ChaiScript and caught in C++ or thrown in C++ and caught in
/// ChaiScript.
///
@@ -376,10 +426,12 @@
///
/// int main()
/// {
/// // Throw in C++, catch in ChaiScript
/// chaiscript::ChaiScript chai;
/// chai.add(chaiscript::fun(&throwexception), "throwexception");
/// chai("try { throwexception(); } catch (e) { print(e.what()); }"); // prints "err"
///
/// // Throw in ChaiScript, catch in C++
/// try {
/// chai("throw(1)");
/// } catch (chaiscript::Boxed_Value bv) {
@@ -388,6 +440,31 @@
/// }
/// }
/// \endcode
///
/// \subsubsection exceptionsautomatic Exception Handling Automatic Unboxing
///
/// As an alternative to the manual unboxing of exceptions shown above, exception specifications allow the user to tell
/// ChaiScript what possible exceptions are expected from the script being executed.
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
///
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
/// } catch (const double e) {
/// } catch (int) {
/// } catch (float) {
/// } catch (const std::string &) {
/// } catch (const std::exception &e) {
/// // This is the one what will be called in the specific throw() above
/// }
/// \endcode
///
/// \sa chaiscript::Exception_Handler for details on automatic exception unboxing
/// \sa chaiscript::exception_specification
/// \page LangObjectSystemRef ChaiScript Language Object Model Reference
///
@@ -429,6 +506,114 @@
/// In-place Map ::= "[" (string ":" expression)+ "]"
/// \endcode
/// \page LangGettingStarted ChaiScript Language Getting Started
///
/// ChaiScript is a simple language that should feel familiar to anyone who knows
/// C++ or ECMAScript (JavaScript).
///
/// <hr>
/// \section chaiscriptloops Loops
///
/// Common looping constructs exist in ChaiScript
///
/// \code
/// var i = 0;
/// while (i < 10)
/// {
/// // do something
/// ++i;
/// }
/// \endcode
///
/// \code
/// for (var i = 0; i < 10; ++i)
/// {
/// // do something
/// }
/// \endcode
///
/// \sa \ref keywordfor
/// \sa \ref keywordwhile
///
/// <hr>
/// \section chaiscriptifs Conditionals
///
/// If statements work as expected
///
/// \code
/// var b = true;
///
/// if (b) {
/// // do something
/// } else if (c < 10) {
/// // do something else
/// } else {
/// // or do this
/// }
/// \endcode
///
/// \sa \ref keywordif
///
/// <hr>
/// \section chaiscriptfunctions Functions
///
/// Functions are defined with the def keyword
///
/// \code
/// def myfun(x) { print(x); }
///
/// myfun(10);
/// \endcode
///
/// Functions may have "guards" which determine if which is called.
///
/// \code
/// eval> def myfun2(x) : x < 10 { print("less than 10"); }
/// eval> def myfun2(x) : x >= 10 { print("10 or greater"); }
/// eval> myfun2(5)
/// less than 10
/// eval> myfun2(12)
/// 10 or greater
/// \endcode
///
/// \sa \ref keyworddef
/// \sa \ref keywordattr
/// \sa \ref LangObjectSystemRef
///
/// <hr>
/// \section chaiscriptfunctionobjects Function Objects
///
/// Functions are first class types in ChaiScript and can be used as variables.
///
/// \code
/// eval> var p = print;
/// eval> p(1);
/// 1
/// \endcode
///
/// They can also be passed to functions.
///
/// \code
/// eval> def callfunc(f, lhs, rhs) { return f(lhs, rhs); }
/// eval> def dosomething(lhs, rhs) { print("lhs: ${lhs}, rhs: ${rhs}"); }
/// eval> callfunc(dosomething, 1, 2);
/// lhs: 1, rhs: 2
/// \endcode
///
/// Operators can also be treated as functions by using the back tick operator. Building on the above example:
///
/// \code
/// eval> callfunc(`+`, 1, 4);
/// 5
/// eval> callfunc(`*`, 3, 2);
/// 6
/// \endcode
///
/// <hr>
/// \sa \ref LangKeywordRef
/// \sa ChaiScript_Language for Built in Functions
/// \page LangKeywordRef ChaiScript Language Keyword Reference
///
///
@@ -563,7 +748,7 @@
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/function_call.hpp"
#include "dispatchkit/dynamic_object.hpp"
#include "dispatchkit/boxed_pod_value.hpp"
#include "dispatchkit/boxed_number.hpp"
#ifdef BOOST_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)

View File

@@ -11,7 +11,7 @@
#include "dynamic_object.hpp"
#include "register_function.hpp"
#include "operators.hpp"
#include "boxed_pod_value.hpp"
#include "boxed_number.hpp"
#include <boost/function_types/result_type.hpp>
namespace chaiscript
@@ -21,189 +21,30 @@ namespace chaiscript
{
namespace detail
{
/// \brief Assigns a POD value from a Boxed_POD_Value. Helps support operators between
/// disparate POD types.
/// \param[in,out] p1 object to assign to
/// \param[in] v Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_pod(P1 &p1, const Boxed_POD_Value &v)
{
if (v.isfloat)
{
return (p1 = P1(v.d));
} else {
return (p1 = P1(v.i));
}
}
/// \brief Constructs a new POD value object from a Boxed_POD_Value
/// \param[in] v Boxed_POD_Value to copy into the new object
/// \brief Constructs a new POD value object from a Boxed_Number
/// \param[in] v Boxed_Number to copy into the new object
/// \returns The newly created object.
template<typename P1>
P1 construct_pod(Boxed_POD_Value v)
boost::shared_ptr<P1> construct_pod(Boxed_Number v)
{
if (v.isfloat)
{
return P1(v.d);
} else {
return P1(v.i);
}
}
/// \brief Performs a bitwise and assignment (&=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to bitwise and assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.isfloat)
{
return p1 &= P1(r.i);
}
throw exception::bad_boxed_cast("&= only valid for integer types");
}
/// \brief Performs a xor assignment (^=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to xor assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.isfloat)
{
return p1 ^= P1(r.i);
}
throw exception::bad_boxed_cast("^= only valid for integer types");
}
/// \brief Performs a bitwise or assignment (|=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to bitwise or assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.isfloat)
{
return p1 |= P1(r.i);
}
throw exception::bad_boxed_cast("&= only valid for integer types");
}
/// \brief Performs an assign difference (-=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to difference assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.isfloat)
{
return p1 -= P1(r.d);
} else {
return p1 -= P1(r.i);
}
}
/// \brief Performs an assign shift left (<<=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign shift left to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.isfloat)
{
return p1 <<= P1(r.i);
}
throw exception::bad_boxed_cast("<<= only valid for integer types");
}
/// \brief Performs an assign product (*=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign product to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.isfloat)
{
return p1 *= P1(r.d);
} else {
return p1 *= P1(r.i);
}
}
/// \brief Performs an assign quotient (/=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign quotient to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.isfloat)
{
return p1 /= P1(r.d);
} else {
return p1 /= P1(r.i);
}
}
/// \brief Performs an assign remainder (%=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign remainder to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.isfloat)
{
return p1 %= P1(r.i);
}
throw exception::bad_boxed_cast("%= only valid for integer types");
}
/// \brief Performs an assign shift right (>>=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to assign shift right to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.isfloat)
{
return p1 >>= P1(r.i);
}
throw exception::bad_boxed_cast(">>= only valid for integer types");
}
/// \brief Performs an assign sum (+=) on the given object with the given Boxed_POD_Value
/// \param[in,out] p1 object to sum assign to
/// \param[in] r Boxed_POD_Value to assign from
/// \returns Reference to p1, to support normal C assignment semantics
template<typename P1>
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.isfloat)
{
return p1 += P1(r.d);
} else {
return p1 += P1(r.i);
}
boost::shared_ptr<P1> p(new P1());
Boxed_Value bv(p);
Boxed_Number nb(bv);
nb = v;
return p;
}
}
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const T &)>(), type);
return m;
}
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
@@ -223,76 +64,6 @@ namespace chaiscript
}
/// \brief Add all arithmetic operators appropriate for integers for the templated type.
/// Used during bootstrap, also available to users.
/// \tparam T Type to create arithmetic operators for
/// \param[in,out] m module to add arithmetic operators to
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
template<typename T>
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
operators::assign_bitwise_and<T>(m);
operators::assign_xor<T>(m);
operators::assign_bitwise_or<T>(m);
operators::assign_difference<T>(m);
operators::assign_left_shift<T>(m);
operators::assign_product<T>(m);
operators::assign_quotient<T>(m);
operators::assign_remainder<T>(m);
operators::assign_right_shift<T>(m);
operators::assign_sum<T>(m);
operators::prefix_decrement<T>(m);
operators::prefix_increment<T>(m);
operators::addition<T>(m);
operators::unary_plus<T>(m);
operators::subtraction<T>(m);
operators::unary_minus<T>(m);
operators::bitwise_and<T>(m);
operators::bitwise_compliment<T>(m);
operators::bitwise_xor<T>(m);
operators::bitwise_or<T>(m);
operators::division<T>(m);
operators::left_shift<T>(m);
operators::multiplication<T>(m);
operators::remainder<T>(m);
operators::right_shift<T>(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>
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
operators::assign_difference<T>(m);
operators::assign_product<T>(m);
operators::assign_quotient<T>(m);
operators::assign_sum<T>(m);
operators::addition<T>(m);
operators::unary_plus<T>(m);
operators::subtraction<T>(m);
operators::unary_minus<T>(m);
operators::division<T>(m);
operators::multiplication<T>(m);
return m;
}
/// \brief Adds a copy constructor for the given type to the given Model
/// \param[in] type The name of the type. The copy constructor will be named "type".
/// \param[in,out] m The Module to add the copy constructor to
/// \tparam T The type to add a copy constructor for
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
template<typename T>
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<T (const T &)>(), type);
return m;
}
/// \brief Adds default and copy constructors for the given type
/// \param[in] type The name of the type to add the constructors for.
@@ -342,15 +113,6 @@ namespace chaiscript
}
/**
* Add assignment operator for T = POD.
*/
template<typename T>
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::assign_pod<T>), "=");
return m;
}
/**
* Add all common functions for a POD type. All operators, and
@@ -360,52 +122,14 @@ namespace chaiscript
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<T>(), name);
basic_constructors<T>(name, m);
operators::assign<T>(m);
oper_assign_pod<T>(m);
m->add(constructor<T ()>(), name);
construct_pod<T>(name, m);
m->add(fun(&detail::assign_sum_pod<T>), "+=");
m->add(fun(&detail::assign_difference_pod<T>), "-=");
m->add(fun(&detail::assign_product_pod<T>), "*=");
m->add(fun(&detail::assign_quotient_pod<T>), "/=");
m->add(fun(&to_string<T>), "to_string");
m->add(fun(&parse_string<T>), "to_" + name);
return m;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T>
ModulePtr bootstrap_integer_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_pod_type<T>(name, m);
m->add(fun(&detail::assign_bitwise_and_pod<T>), "&=");
m->add(fun(&detail::assign_xor_pod<T>), "^=");
m->add(fun(&detail::assign_bitwise_or_pod<T>), "|=");
m->add(fun(&detail::assign_left_shift_pod<T>), "<<=");
m->add(fun(&detail::assign_remainder_pod<T>), "%=");
m->add(fun(&detail::assign_right_shift_pod<T>), ">>=");
opers_integer_arithmetic<T>(m);
return m;
}
/**
* Add all common functions for a POD type. All operators, and
* common conversions
*/
template<typename T>
ModulePtr bootstrap_float_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_pod_type<T>(name, m);
opers_float_arithmetic<T>(m);
return m;
}
/**
* "clone" function for a shared_ptr type. This is used in the case
@@ -480,22 +204,48 @@ namespace chaiscript
std::cout << s << std::endl;
}
/**
* Add all arithmetic operators for PODs
*/
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&operators::addition<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
m->add(fun(&operators::subtraction<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
m->add(fun(&operators::bitwise_and<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "&");
m->add(fun(&operators::bitwise_xor<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "^");
m->add(fun(&operators::bitwise_or<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "|");
m->add(fun(&operators::division<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
m->add(fun(&operators::left_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "<<");
m->add(fun(&operators::multiplication<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
m->add(fun(&operators::remainder<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "%");
m->add(fun(&operators::right_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), ">>");
}
m->add(fun(&Boxed_Number::equals), "==");
m->add(fun(&Boxed_Number::less_than), "<");
m->add(fun(&Boxed_Number::greater_than), ">");
m->add(fun(&Boxed_Number::greater_than_equal), ">=");
m->add(fun(&Boxed_Number::less_than_equal), "<=");
m->add(fun(&Boxed_Number::not_equal), "!=");
m->add(fun(&Boxed_Number::pre_decrement), "--");
m->add(fun(&Boxed_Number::pre_increment), "++");
m->add(fun(&Boxed_Number::sum), "+");
m->add(fun(&Boxed_Number::unary_plus), "+");
m->add(fun(&Boxed_Number::unary_minus), "-");
m->add(fun(&Boxed_Number::difference), "-");
m->add(fun(&Boxed_Number::assign_bitwise_and), "&=");
m->add(fun(&Boxed_Number::assign), "=");
m->add(fun(&Boxed_Number::assign_bitwise_or), "|=");
m->add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
m->add(fun(&Boxed_Number::assign_remainder), "%=");
m->add(fun(&Boxed_Number::assign_shift_left), "<<=");
m->add(fun(&Boxed_Number::assign_shift_right), ">>=");
m->add(fun(&Boxed_Number::bitwise_and), "&");
m->add(fun(&Boxed_Number::bitwise_complement), "~");
m->add(fun(&Boxed_Number::bitwise_xor), "^");
m->add(fun(&Boxed_Number::bitwise_or), "|");
m->add(fun(&Boxed_Number::assign_product), "*=");
m->add(fun(&Boxed_Number::assign_quotient), "/=");
m->add(fun(&Boxed_Number::assign_sum), "+=");
m->add(fun(&Boxed_Number::assign_difference), "-=");
m->add(fun(&Boxed_Number::quotient), "/");
m->add(fun(&Boxed_Number::shift_left), "<<");
m->add(fun(&Boxed_Number::product), "*");
m->add(fun(&Boxed_Number::remainder), "%");
m->add(fun(&Boxed_Number::shift_right), ">>");
}
/**
* Create a bound function object. The first param is the function to bind
@@ -619,7 +369,7 @@ namespace chaiscript
m->add(user_type<void>(), "void");
m->add(user_type<bool>(), "bool");
m->add(user_type<Boxed_Value>(), "Object");
m->add(user_type<Boxed_POD_Value>(), "PODObject");
m->add(user_type<Boxed_Number>(), "Number");
m->add(user_type<Proxy_Function>(), "Function");
m->add(user_type<std::exception>(), "exception");
@@ -679,6 +429,7 @@ namespace chaiscript
basic_constructors<bool>("bool", m);
operators::assign<bool>(m);
operators::equal<bool>(m);
m->add(fun(&to_string<const std::string &>), "internal_to_string");
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
@@ -686,15 +437,25 @@ namespace chaiscript
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
bootstrap_float_type<double>("double", m);
bootstrap_integer_type<int>("int", m);
bootstrap_integer_type<size_t>("size_t", m);
bootstrap_integer_type<char>("char", m);
bootstrap_integer_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<long double>("long_double", m);
bootstrap_pod_type<float>("float", m);
bootstrap_pod_type<int>("int", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<boost::int8_t>("int8_t", m);
bootstrap_pod_type<boost::int16_t>("int16_t", m);
bootstrap_pod_type<boost::int32_t>("int32_t", m);
bootstrap_pod_type<boost::int64_t>("int64_t", m);
bootstrap_pod_type<boost::uint8_t>("uint8_t", m);
bootstrap_pod_type<boost::uint16_t>("uint16_t", m);
bootstrap_pod_type<boost::uint32_t>("uint32_t", m);
bootstrap_pod_type<boost::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m);
opers_comparison<Boxed_POD_Value>(m);
opers_arithmetic_pod(m);

View File

@@ -0,0 +1,689 @@
// 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_BOXED_NUMERIC_HPP_
#define CHAISCRIPT_BOXED_NUMERIC_HPP_
#include "boxed_value.hpp"
#include "../language/chaiscript_algebraic.hpp"
#include <boost/cstdint.hpp>
namespace chaiscript
{
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_Number
{
private:
struct boolean
{
#pragma GCC diagnostic ignored "-Wsign-compare"
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::equals:
return const_var(t == u);
case Operators::less_than:
return const_var(t < u);
case Operators::greater_than:
return const_var(t > u);
case Operators::less_than_equal:
return const_var(t <= u);
case Operators::greater_than_equal:
return const_var(t >= u);
case Operators::not_equal:
return const_var(t != u);
default:
throw boost::bad_any_cast();
}
throw boost::bad_any_cast();
}
};
struct binary
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
{
switch (t_oper)
{
case Operators::assign:
t = u;
break;
case Operators::pre_increment:
++t;
break;
case Operators::pre_decrement:
--t;
break;
case Operators::assign_product:
t *= u;
break;
case Operators::assign_sum:
t += u;
break;
case Operators::assign_quotient:
t /= u;
break;
case Operators::assign_difference:
t -= u;
break;
default:
throw boost::bad_any_cast();
}
return t_lhs;
}
};
struct binary_int
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
{
switch (t_oper)
{
case Operators::assign_bitwise_and:
t &= u;
break;
case Operators::assign_bitwise_or:
t |= u;
break;
case Operators::assign_shift_left:
t <<= u;
break;
case Operators::assign_shift_right:
t >>= u;
break;
case Operators::assign_remainder:
t %= u;
break;
case Operators::assign_bitwise_xor:
t ^= u;
break;
default:
throw boost::bad_any_cast();
}
return t_lhs;
}
};
struct const_binary_int
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::shift_left:
return const_var(t << u);
case Operators::shift_right:
return const_var(t >> u);
case Operators::remainder:
return const_var(t % u);
case Operators::bitwise_and:
return const_var(t & u);
case Operators::bitwise_or:
return const_var(t | u);
case Operators::bitwise_xor:
return const_var(t ^ u);
case Operators::bitwise_complement:
return const_var(~t);
default:
throw boost::bad_any_cast();
}
throw boost::bad_any_cast();
}
};
struct const_binary
{
template<typename T, typename U>
static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &)
{
switch (t_oper)
{
case Operators::sum:
return const_var(t + u);
case Operators::quotient:
return const_var(t / u);
case Operators::product:
return const_var(t * u);
case Operators::difference:
return const_var(t - u);
case Operators::unary_minus:
return const_var(-t);
case Operators::unary_plus:
return const_var(+t);
default:
throw boost::bad_any_cast();
}
throw boost::bad_any_cast();
}
};
template<typename LHS, typename RHS, bool Float>
struct Go
{
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
{
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const()) {
return binary_int::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
return const_binary_int::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw boost::bad_any_cast();
}
}
};
template<typename LHS, typename RHS>
struct Go<LHS, RHS, true>
{
static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
{
return boolean::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
throw boost::bad_any_cast();
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
throw boost::bad_any_cast();
} else if (t_oper > Operators::const_flag) {
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
} else {
throw boost::bad_any_cast();
}
}
};
template<typename LHS, bool Float>
static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
const Type_Info &inp_ = t_rhs.get_type_info();
if (inp_ == typeid(int)) {
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(double)) {
return Go<LHS, double, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(float)) {
return Go<LHS, float, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long double)) {
return Go<LHS, long double, true>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(char)) {
return Go<LHS, char, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {
return Go<LHS, unsigned int, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long)) {
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) {
return Go<LHS, boost::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) {
return Go<LHS, boost::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) {
return Go<LHS, boost::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) {
return Go<LHS, boost::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) {
return Go<LHS, boost::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) {
return Go<LHS, boost::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) {
return Go<LHS, boost::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) {
return Go<LHS, boost::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
} else {
throw boost::bad_any_cast();
}
}
static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
const Type_Info &inp_ = t_lhs.get_type_info();
if (inp_ == typeid(int)) {
return oper_rhs<int, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(double)) {
return oper_rhs<double, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long double)) {
return oper_rhs<long double, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(float)) {
return oper_rhs<float, true>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(char)) {
return oper_rhs<char, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {
return oper_rhs<unsigned int, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(long)) {
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned long)) {
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int8_t)) {
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int16_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int32_t)) {
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::int64_t)) {
return oper_rhs<boost::int64_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint8_t)) {
return oper_rhs<boost::uint8_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint16_t)) {
return oper_rhs<boost::uint16_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint32_t)) {
return oper_rhs<boost::uint32_t, false>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(boost::uint64_t)) {
return oper_rhs<boost::uint64_t, false>(t_oper, t_lhs, t_rhs);
} else {
throw boost::bad_any_cast();
}
}
public:
Boxed_Number(const Boxed_Value &v)
: bv(v)
{
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(bool))
{
throw boost::bad_any_cast();
}
if (!inp_.is_arithmetic())
{
throw boost::bad_any_cast();
}
}
bool operator==(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
}
bool operator<(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
}
bool operator>(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
}
bool operator>=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
}
bool operator<=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
}
bool operator!=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
}
Boxed_Number operator--()
{
return oper(Operators::pre_decrement, this->bv, var(0));
}
Boxed_Number operator++()
{
return oper(Operators::pre_increment, this->bv, var(0));
}
Boxed_Number operator+(const Boxed_Number &t_rhs) const
{
return oper(Operators::sum, this->bv, t_rhs.bv);
}
Boxed_Number operator+() const
{
return oper(Operators::unary_plus, this->bv, Boxed_Value(0));
}
Boxed_Number operator-() const
{
return oper(Operators::unary_minus, this->bv, Boxed_Value(0));
}
Boxed_Number operator-(const Boxed_Number &t_rhs) const
{
return oper(Operators::difference, this->bv, t_rhs.bv);
}
Boxed_Number operator&=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator=(const Boxed_Number &t_rhs) const
{
return oper(Operators::assign, this->bv, t_rhs.bv);
}
Boxed_Number operator|=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator^=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator%=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
}
Boxed_Number operator&(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator~() const
{
return oper(Operators::bitwise_complement, this->bv, Boxed_Value(0));
}
Boxed_Number operator^(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator|(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator*=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, this->bv, t_rhs.bv);
}
Boxed_Number operator/=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator+=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
}
Boxed_Number operator-=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
}
Boxed_Number operator/(const Boxed_Number &t_rhs) const
{
return oper(Operators::quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator*(const Boxed_Number &t_rhs) const
{
return oper(Operators::product, this->bv, t_rhs.bv);
}
Boxed_Number operator%(const Boxed_Number &t_rhs) const
{
return oper(Operators::remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_right, this->bv, t_rhs.bv);
}
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
}
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
{
return oper(Operators::pre_decrement, t_lhs.bv, var(0));
}
static Boxed_Number pre_increment(Boxed_Number t_lhs)
{
return oper(Operators::pre_increment, t_lhs.bv, var(0));
}
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_plus, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_minus, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
{
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
}
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
return oper(t_oper, t_lhs, t_rhs);
}
static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
{
return oper(t_oper, t_lhs, const_var(0));
}
Boxed_Value bv;
};
namespace detail
{
/**
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<>
struct Cast_Helper<Boxed_Number>
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_Number(ob);
}
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<>
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
{
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_Number
*/
template<>
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
{
};
}
}
#endif

View File

@@ -1,260 +0,0 @@
// 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_BOXED_POD_VALUE_HPP_
#define CHAISCRIPT_BOXED_POD_VALUE_HPP_
#include "type_info.hpp"
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include <boost/any.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer_traits.hpp>
namespace chaiscript
{
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
class Boxed_POD_Value
{
public:
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();
}
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();
}
}
bool operator==(const Boxed_POD_Value &r) const
{
return ((isfloat)?d:i) == ((r.isfloat)?r.d:r.i);
}
bool operator<(const Boxed_POD_Value &r) const
{
return ((isfloat)?d:i) < ((r.isfloat)?r.d:r.i);
}
bool operator>(const Boxed_POD_Value &r) const
{
return ((isfloat)?d:i) > ((r.isfloat)?r.d:r.i);
}
bool operator>=(const Boxed_POD_Value &r) const
{
return ((isfloat)?d:i) >= ((r.isfloat)?r.d:r.i);
}
bool operator<=(const Boxed_POD_Value &r) const
{
return ((isfloat)?d:i) <= ((r.isfloat)?r.d:r.i);
}
bool operator!=(const Boxed_POD_Value &r) const
{
return ((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);
}
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);
}
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 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 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 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);
}
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);
}
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
{
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<>
struct Cast_Helper<Boxed_POD_Value>
{
typedef Boxed_POD_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_POD_Value(ob);
}
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<>
struct Cast_Helper<const Boxed_POD_Value &> : Cast_Helper<Boxed_POD_Value>
{
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<>
struct Cast_Helper<const Boxed_POD_Value> : Cast_Helper<Boxed_POD_Value>
{
};
}
}
#endif

View File

@@ -23,6 +23,7 @@
namespace chaiscript
{
/// \brief A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects
/// \sa chaiscript::boxed_cast
class Boxed_Value
@@ -41,19 +42,12 @@ namespace chaiscript
*/
struct Data
{
template<typename T>
static bool is_null(boost::any *a)
{
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
return ptr->get() == 0;
}
Data(const Type_Info &ti,
const boost::any &to,
bool tr,
const boost::function<bool (boost::any*)> &t_is_null = boost::function<bool (boost::any*)>())
: m_type_info(ti), m_obj(to),
m_is_ref(tr), m_is_null(t_is_null)
const void *t_void_ptr)
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?0:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
m_is_ref(tr)
{
}
@@ -62,7 +56,8 @@ namespace chaiscript
m_type_info = rhs.m_type_info;
m_obj = rhs.m_obj;
m_is_ref = rhs.m_is_ref;
m_is_null = rhs.m_is_null;
m_data_ptr = rhs.m_data_ptr;
m_const_data_ptr = rhs.m_const_data_ptr;
return *this;
}
@@ -73,8 +68,9 @@ namespace chaiscript
Type_Info m_type_info;
boost::any m_obj;
void *m_data_ptr;
const void *m_const_data_ptr;
bool m_is_ref;
boost::function<bool (boost::any*)> m_is_null;
std::vector<boost::shared_ptr<Data> > m_dependencies;
};
@@ -85,7 +81,8 @@ namespace chaiscript
return boost::shared_ptr<Data> (new Data(
detail::Get_Type_Info<void>::get(),
boost::any(),
false)
false,
0)
);
}
@@ -102,7 +99,7 @@ namespace chaiscript
detail::Get_Type_Info<T>::get(),
boost::any(obj),
false,
boost::function<bool (boost::any *)>(&Data::is_null<T>))
obj.get())
);
}
@@ -118,18 +115,20 @@ namespace chaiscript
return boost::shared_ptr<Data>(new Data(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
true)
true,
obj.get_pointer())
);
}
template<typename T>
static boost::shared_ptr<Data> get(const T& t)
{
boost::shared_ptr<T> p(new T(t));
return boost::shared_ptr<Data>(new Data(
detail::Get_Type_Info<T>::get(),
boost::any(boost::shared_ptr<T>(new T(t))),
boost::any(p),
false,
boost::function<bool (boost::any *)>(&Data::is_null<T>))
p.get())
);
}
@@ -138,7 +137,8 @@ namespace chaiscript
return boost::shared_ptr<Data> (new Data(
Type_Info(),
boost::any(),
false)
false,
0)
);
}
@@ -224,12 +224,7 @@ namespace chaiscript
bool is_null() const
{
if (m_data->m_is_null)
{
return m_data->m_is_null(&m_data->m_obj);
} else {
return false;
}
return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0);
}
const boost::any & get() const
@@ -265,6 +260,15 @@ namespace chaiscript
}
}
void *get_ptr() const
{
return m_data->m_data_ptr;
}
const void *get_const_ptr() const
{
return m_data->m_const_data_ptr;
}
private:
boost::shared_ptr<Data> m_data;

View File

@@ -811,7 +811,7 @@ namespace chaiscript
const size_t rhssize = rhsparamtypes.size();
const Type_Info boxed_type = user_type<Boxed_Value>();
const Type_Info boxed_pod_type = user_type<Boxed_POD_Value>();
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));

View File

@@ -0,0 +1,176 @@
// 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_EXCEPTION_SPECIFICATION_HPP_
#define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_
#include "boxed_cast.hpp"
namespace chaiscript
{
namespace detail
{
struct Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv) = 0;
protected:
template<typename T>
void throw_type(const Boxed_Value &bv)
{
try { T t = boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
}
};
template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
}
};
template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
}
};
template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
}
};
template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
throw_type<T4>(bv);
}
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv)
{
throw_type<T1>(bv);
throw_type<T2>(bv);
throw_type<T3>(bv);
throw_type<T4>(bv);
throw_type<T5>(bv);
}
};
}
/// \brief Used in the automatic unboxing of exceptions thrown during script evaluation
///
/// Exception specifications allow the user to tell ChaiScript what possible exceptions are expected from the script
/// being executed. Exception_Handler objects are created with the chaiscript::exception_specification() function.
///
/// Example:
/// \code
/// chaiscript::ChaiScript chai;
///
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
/// } catch (const double e) {
/// } catch (int) {
/// } catch (float) {
/// } catch (const std::string &) {
/// } catch (const std::exception &e) {
/// // This is the one what will be called in the specific throw() above
/// }
/// \endcode
///
/// It is recommended that if catching the generic \c std::exception& type that you specifically catch
/// the chaiscript::exception::eval_error type, so that there is no confusion.
///
/// \code
/// try {
/// chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<const std::exception &>());
/// } catch (const chaiscript::exception::eval_error &) {
/// // Error in script parsing / execution
/// } catch (const std::exception &e) {
/// // Error explicitly thrown from script
/// }
/// \endcode
///
/// Similarly, if you are using the ChaiScript::eval form that unboxes the return value, then chaiscript::exception::bad_boxed_cast
/// should be handled as well.
///
/// \code
/// try {
/// chai.eval<int>("1.0", chaiscript::exception_specification<const std::exception &>());
/// } catch (const chaiscript::exception::eval_error &) {
/// // Error in script parsing / execution
/// } catch (const chaiscript::exception::bad_boxed_cast &) {
/// // Error unboxing return value
/// } catch (const std::exception &e) {
/// // Error explicitly thrown from script
/// }
/// \endcode
///
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
/// \sa \ref exceptions
typedef boost::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions
template<typename T1>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
}
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
}
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
}
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
}
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
}
}
#endif

View File

@@ -8,6 +8,7 @@
#define CHAISCRIPT_HANDLE_RETURN_HPP_
#include "boxed_value.hpp"
#include "boxed_number.hpp"
#include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
@@ -135,6 +136,30 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call

View File

@@ -20,7 +20,7 @@
namespace chaiscript
{
class Boxed_POD_Value;
class Boxed_Number;
struct AST_Node;
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
@@ -139,7 +139,7 @@ namespace chaiscript
if (ti.is_undef()
|| ti.bare_equal(user_type<Boxed_Value>())
|| (!bv.get_type_info().is_undef()
&& (ti.bare_equal(user_type<Boxed_POD_Value>())
&& (ti.bare_equal(user_type<Boxed_Number>())
|| ti.bare_equal(bv.get_type_info())
|| chaiscript::detail::dynamic_cast_converts(ti, bv.get_type_info())
|| bv.get_type_info().bare_equal(user_type<boost::shared_ptr<const Proxy_Function_Base> >())

View File

@@ -14,6 +14,8 @@
#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
@@ -36,9 +38,9 @@ namespace chaiscript
{
public:
Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
const std::type_info *t_ti, const std::type_info *t_bareti)
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bareti)
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
m_is_void(t_is_void),
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_type_info(t_ti), m_bare_type_info(t_bareti),
m_is_undef(false)
{
@@ -46,7 +48,7 @@ namespace chaiscript
Type_Info()
: m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_type_info(0), m_bare_type_info(0),
m_is_void(false), m_is_arithmetic(false), m_type_info(0), m_bare_type_info(0),
m_is_undef(true)
{
}
@@ -54,7 +56,8 @@ namespace chaiscript
Type_Info(const Type_Info &ti)
: m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
m_is_pointer(ti.m_is_pointer),
m_is_void(ti.m_is_void), m_type_info(ti.m_type_info),
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
m_type_info(ti.m_type_info),
m_bare_type_info(ti.m_bare_type_info),
m_is_undef(ti.m_is_undef)
{
@@ -66,6 +69,7 @@ namespace chaiscript
m_is_reference = ti.m_is_reference;
m_is_pointer = ti.m_is_pointer;
m_is_void = ti.m_is_void;
m_is_arithmetic = ti.m_is_arithmetic;
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_undef = ti.m_is_undef;
@@ -97,6 +101,7 @@ namespace chaiscript
bool is_const() const { return m_is_const; }
bool is_reference() const { return m_is_reference; }
bool is_void() const { return m_is_void; }
bool is_arithmetic() const { return m_is_arithmetic; }
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; }
bool is_pointer() const { return m_is_pointer; }
@@ -125,6 +130,7 @@ namespace chaiscript
bool m_is_reference;
bool m_is_pointer;
bool m_is_void;
bool m_is_arithmetic;
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_undef;
@@ -144,6 +150,7 @@ namespace chaiscript
{
return Type_Info(boost::is_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(T),
&typeid(typename Bare_Type<T>::type));
}
@@ -158,6 +165,7 @@ namespace chaiscript
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(boost::shared_ptr<T> ),
&typeid(typename Bare_Type<T>::type));
}
@@ -172,6 +180,7 @@ namespace chaiscript
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(const boost::shared_ptr<T> &),
&typeid(typename Bare_Type<T>::type));
}
@@ -186,6 +195,7 @@ namespace chaiscript
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(boost::reference_wrapper<T> ),
&typeid(typename Bare_Type<T>::type));
}
@@ -200,6 +210,7 @@ namespace chaiscript
{
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
boost::is_void<T>::value,
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
&typeid(const boost::reference_wrapper<T> &),
&typeid(typename Bare_Type<T>::type));
}

View File

@@ -0,0 +1,131 @@
// 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_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
namespace chaiscript
{
struct Operators {
enum Opers
{
boolean_flag,
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
non_const_flag,
assign, pre_increment, pre_decrement, assign_product, assign_sum,
assign_quotient, assign_difference,
non_const_int_flag,
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
assign_remainder, assign_bitwise_xor,
const_int_flag,
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
const_flag,
sum, quotient, product, difference, unary_plus, unary_minus,
invalid
};
static const char *to_string(Opers t_oper) {
const char *opers[] = {
"",
"==", "<", ">", "<=", ">=", "!=",
"",
"=", "++", "--", "*=", "+=",
"/=", "-=",
"",
"&=", "|=", "<<=", ">>=",
"%=", "^=",
"",
"<<", ">>", "%", "&", "|", "^", "~",
"",
"+", "/", "*", "-", "+", "-",
""
};
return opers[t_oper];
}
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{
if (t_str == "==")
{
return equals;
} else if (t_str == "<") {
return less_than;
} else if (t_str == ">") {
return greater_than;
} else if (t_str == "<=") {
return less_than_equal;
} else if (t_str == ">=") {
return greater_than_equal;
} else if (t_str == "!=") {
return not_equal;
} else if (t_str == "=") {
return assign;
} else if (t_str == "++") {
return pre_increment;
} else if (t_str == "--") {
return pre_decrement;
} else if (t_str == "*=") {
return assign_product;
} else if (t_str == "+=") {
return assign_sum;
} else if (t_str == "-=") {
return assign_difference;
} else if (t_str == "&=") {
return assign_bitwise_and;
} else if (t_str == "|=") {
return assign_bitwise_or;
} else if (t_str == "<<=") {
return assign_shift_left;
} else if (t_str == ">>=") {
return assign_shift_right;
} else if (t_str == "%=") {
return assign_remainder;
} else if (t_str == "^=") {
return assign_bitwise_xor;
} else if (t_str == "<<") {
return shift_left;
} else if (t_str == ">>") {
return shift_right;
} else if (t_str == "%") {
return remainder;
} else if (t_str == "&") {
return bitwise_and;
} else if (t_str == "|") {
return bitwise_or;
} else if (t_str == "^") {
return bitwise_xor;
} else if (t_str == "~") {
return bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return unary_plus;
} else {
return sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return unary_minus;
} else {
return difference;
}
} else if (t_str == "/") {
return quotient;
} else if (t_str == "*") {
return product;
} else {
return invalid;
}
}
};
}
#endif /* _CHAISCRIPT_ALGEBRAIC_HPP */

View File

@@ -15,11 +15,12 @@ namespace chaiscript
/// Signature of module entry point that all binary loadable modules must implement.
typedef ModulePtr (*Create_Module_Func)();
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Additive, Multiplicative, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or
@@ -33,7 +34,7 @@ namespace chaiscript
*/
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Additive", "Multiplicative", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or"};

View File

@@ -25,6 +25,7 @@
#include <chaiscript/language/chaiscript_prelude.hpp>
#include <chaiscript/language/chaiscript_parser.hpp>
#include "../dispatchkit/exception_specification.hpp"
namespace chaiscript
{
@@ -598,19 +599,28 @@ namespace chaiscript
/// \brief Evaluates a string. Equivalent to ChaiScript::eval.
///
/// \param[in] t_script Script to execute
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
///
/// \return result of the script execution
///
/// \throw exception::eval_error In the case that evaluation fails.
Boxed_Value operator()(const std::string &t_script)
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
{
return do_eval(t_script);
try {
return do_eval(t_script);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv);
}
throw bv;
}
}
/// \brief Evaluates a string and returns a typesafe result.
///
/// \tparam T Type to extract from the result value of the script execution
/// \param[in] t_input Script to execute
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
///
/// \return result of the script execution
///
@@ -618,41 +628,72 @@ namespace chaiscript
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// to the requested type.
template<typename T>
T eval(const std::string &t_input)
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
{
return boxed_cast<T>(do_eval(t_input));
try {
return boxed_cast<T>(do_eval(t_input));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv);
}
throw bv;
}
}
/// \brief Evaluates a string.
///
/// \param[in] t_input Script to execute
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
///
/// \return result of the script execution
///
/// \throw exception::eval_error In the case that evaluation fails.
Boxed_Value eval(const std::string &t_input)
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
{
return do_eval(t_input);
try {
return do_eval(t_input);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv);
}
throw bv;
}
}
/// \brief Loads the file specified by filename, evaluates it, and returns the result.
/// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \return result of the script execution
/// \throw exception::eval_error In the case that evaluation fails.
Boxed_Value eval_file(const std::string &t_filename) {
return do_eval(load_file(t_filename), t_filename);
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return do_eval(load_file(t_filename), t_filename);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv);
}
throw bv;
}
}
/// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result.
/// \tparam T Type to extract from the result value of the script execution
/// \param[in] t_filename File to load and parse.
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
/// \return result of the script execution
/// \throw exception::eval_error In the case that evaluation fails.
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
/// to the requested type.
template<typename T>
T eval_file(const std::string &t_filename) {
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv);
}
throw bv;
}
}
};

View File

@@ -39,25 +39,38 @@ namespace chaiscript
struct Binary_Operator_AST_Node : public AST_Node {
public:
Binary_Operator_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Bitwise_Xor, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col)
{ }
virtual ~Binary_Operator_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval;
retval = this->children[0]->eval(t_ss);
for (size_t i = 1; i < this->children.size(); i += 2) {
try {
retval = t_ss.call_function(this->children[i]->text, retval, this->children[i+1]->eval(t_ss));
}
catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate '" + this->children[i]->text + "'");
}
}
return retval;
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
return do_oper(t_ss, Operators::to_operator(children[1]->text), children[1]->text,
this->children[0]->eval(t_ss),
this->children[2]->eval(t_ss));
}
protected:
Boxed_Value do_oper(chaiscript::detail::Dispatch_Engine &t_ss,
Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
try {
if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
{
// If it's an arithmetic operation we want to short circuit dispatch
try{
return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
} catch (...) {
throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
}
} else {
return t_ss.call_function(t_oper_string, t_lhs, t_rhs);
}
}
catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate '" + t_oper_string + "'");
}
}
};
struct Error_AST_Node : public AST_Node {
@@ -258,47 +271,57 @@ namespace chaiscript
struct Equation_AST_Node : public AST_Node {
public:
Equation_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Equation, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col)
{}
virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
Boxed_Value retval = this->children.back()->eval(t_ss);
if (this->children.size() > 1) {
for (int i = static_cast<int>(this->children.size())-3; i >= 0; i -= 2) {
if (this->children[i+1]->text == "=") {
Boxed_Value lhs = this->children[i]->eval(t_ss);
Boxed_Value lhs = this->children[0]->eval(t_ss);
Operators::Opers oper = Operators::to_operator(this->children[1]->text);
if (oper != Operators::invalid && lhs.get_type_info().is_arithmetic() &&
retval.get_type_info().is_arithmetic())
{
try {
retval = Boxed_Number::do_oper(oper, lhs, retval);
} catch (const std::exception &) {
throw exception::eval_error("Error with unsupported arithmetic assignment operation");
}
} else if (this->children[1]->text == "=") {
try {
if (lhs.is_undef()) {
retval = t_ss.call_function("clone", retval);
retval.clear_dependencies();
}
try {
if (lhs.is_undef()) {
retval = t_ss.call_function("clone", retval);
retval.clear_dependencies();
}
try {
retval = t_ss.call_function(this->children[i+1]->text, lhs, retval);
}
catch(const exception::dispatch_error &){
throw exception::eval_error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."));
}
retval = t_ss.call_function(this->children[1]->text, lhs, retval);
}
catch(const exception::dispatch_error &){
throw exception::eval_error("Can not clone right hand side of equation");
throw exception::eval_error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."));
}
}
else if (this->children[i+1]->text == ":=") {
Boxed_Value lhs = this->children[i]->eval(t_ss);
if (lhs.is_undef() || type_match(lhs, retval)) {
lhs.assign(retval);
} else {
throw exception::eval_error("Mismatched types in equation");
}
catch(const exception::dispatch_error &){
throw exception::eval_error("Can not clone right hand side of equation");
}
else {
try {
retval = t_ss.call_function(this->children[i+1]->text, this->children[i]->eval(t_ss), retval);
} catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate '" + this->children[i+1]->text + "'");
}
}
else if (this->children[1]->text == ":=") {
if (lhs.is_undef() || type_match(lhs, retval)) {
lhs.assign(retval);
} else {
throw exception::eval_error("Mismatched types in equation");
}
}
else {
try {
retval = t_ss.call_function(this->children[1]->text, lhs, retval);
} catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate '" + this->children[1]->text + "'");
}
}
}
@@ -330,18 +353,64 @@ namespace chaiscript
virtual ~Comparison_AST_Node() {}
};
struct Additive_AST_Node : public Binary_Operator_AST_Node {
struct Addition_AST_Node : public Binary_Operator_AST_Node {
public:
Additive_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Additive, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Addition_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Addition,
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(),
int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Additive_AST_Node() {}
virtual ~Addition_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
return do_oper(t_ss, Operators::sum, "+", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
struct Multiplicative_AST_Node : public Binary_Operator_AST_Node {
struct Subtraction_AST_Node : public Binary_Operator_AST_Node {
public:
Multiplicative_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Multiplicative, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Subtraction_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Subtraction,
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Multiplicative_AST_Node() {}
virtual ~Subtraction_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
return do_oper(t_ss, Operators::difference, "-", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
struct Multiplication_AST_Node : public Binary_Operator_AST_Node {
public:
Multiplication_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Multiplication,
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Multiplication_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
return do_oper(t_ss, Operators::product, "*", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
struct Division_AST_Node : public Binary_Operator_AST_Node {
public:
Division_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Division,
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Division_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
return do_oper(t_ss, Operators::quotient, "/", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
struct Modulus_AST_Node : public Binary_Operator_AST_Node {
public:
Modulus_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Modulus,
const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0,
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
Binary_Operator_AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Modulus_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
return do_oper(t_ss, Operators::remainder, "%", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
}
};
struct Array_Call_AST_Node : public AST_Node {
@@ -782,10 +851,24 @@ namespace chaiscript
struct Prefix_AST_Node : public AST_Node {
public:
Prefix_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Prefix, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col)
{ }
virtual ~Prefix_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
return t_ss.call_function(this->children[0]->text, this->children[1]->eval(t_ss));
Boxed_Value bv(this->children[1]->eval(t_ss));
Operators::Opers oper = Operators::to_operator(children[0]->text, true);
try {
if (bv.get_type_info().is_arithmetic() && oper != Operators::invalid)
{
return Boxed_Number::do_oper(oper, bv);
} else {
return t_ss.call_function(this->children[0]->text, bv);
}
} catch (const exception::dispatch_error &) {
throw exception::eval_error("Error with prefix operator evaluation: " + children[0]->text);
}
}
};

View File

@@ -111,23 +111,20 @@ namespace chaiscript
shift.push_back(">>");
m_operator_matches.push_back(shift);
m_operators.push_back(AST_Node_Type::Additive);
std::vector<std::string> additive;
additive.push_back("+");
additive.push_back("-");
m_operator_matches.push_back(additive);
//We share precedence here but then separate them later
m_operators.push_back(AST_Node_Type::Addition);
std::vector<std::string> addition;
addition.push_back("+");
addition.push_back("-");
m_operator_matches.push_back(addition);
m_operators.push_back(AST_Node_Type::Multiplicative);
std::vector<std::string> multiplicative;
multiplicative.push_back("*");
multiplicative.push_back("/");
multiplicative.push_back("%");
m_operator_matches.push_back(multiplicative);
m_operators.push_back(AST_Node_Type::Dot_Access);
std::vector<std::string> dot_access;
dot_access.push_back(".");
m_operator_matches.push_back(dot_access);
//We share precedence here but then separate them later
m_operators.push_back(AST_Node_Type::Multiplication);
std::vector<std::string> multiplication;
multiplication.push_back("*");
multiplication.push_back("/");
multiplication.push_back("%");
m_operator_matches.push_back(multiplication);
for ( int c = 0 ; c < detail::lengthof_alphabet ; ++c ) {
for ( int a = 0 ; a < detail::max_alphabet ; a ++ ) {
@@ -249,7 +246,7 @@ namespace chaiscript
m_match_stack.push_back(t_t);
}
else {
//todo: fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
/// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position
m_match_stack.push_back(t_t);
}
}
@@ -352,7 +349,7 @@ namespace chaiscript
}
/**
* Reads a floating point value from input, without skipping initial whitespace
* Reads a hex value from input, without skipping initial whitespace
*/
bool Hex_() {
bool retval = false;
@@ -385,7 +382,7 @@ namespace chaiscript
}
/**
* Reads a floating point value from input, without skipping initial whitespace
* Reads a binary value from input, without skipping initial whitespace
*/
bool Binary_() {
bool retval = false;
@@ -655,7 +652,6 @@ namespace chaiscript
bool saw_interpolation_marker = false;
size_t prev_stack_top = m_match_stack.size();
//for (std::string::iterator s = start + 1, end = m_input_pos - 1; s != end; ++s) {
std::string::const_iterator s = start + 1, end = m_input_pos - 1;
while (s != end) {
@@ -665,13 +661,11 @@ namespace chaiscript
if (is_interpolated) {
//If we've seen previous interpolation, add on instead of making a new one
AST_NodePtr plus(new eval::Str_AST_Node("+", AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(plus);
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
}
else {
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
@@ -681,9 +675,6 @@ namespace chaiscript
//We've finished with the part of the string up to this point, so clear it
match = "";
AST_NodePtr plus(new eval::Str_AST_Node("+", AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(plus);
std::string eval_match;
++s;
@@ -718,7 +709,7 @@ namespace chaiscript
build_match(AST_NodePtr(new eval::Fun_Call_AST_Node()), tostr_stack_top);
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
}
else {
throw exception::eval_error("Unclosed in-string eval", File_Position(prev_line, prev_col), *m_filename);
@@ -765,13 +756,10 @@ namespace chaiscript
}
}
if (is_interpolated) {
AST_NodePtr plus(new eval::Str_AST_Node("+", AST_Node_Type::Str, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(plus);
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
m_match_stack.push_back(t);
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
}
else {
AST_NodePtr t(new eval::Quoted_String_AST_Node(match, AST_Node_Type::Quoted_String, m_filename, prev_line, prev_col, m_line, m_col));
@@ -1486,14 +1474,15 @@ namespace chaiscript
}
/**
* Reads an identifier, then proceeds to check if it's a function or array call
* Reads a dot expression(member access), then proceeds to check if it's a function or array call
*/
bool Id_Fun_Array() {
bool Dot_Fun_Array() {
bool retval = false;
std::string::const_iterator prev_pos = m_input_pos;
size_t prev_stack_top = m_match_stack.size();
if (Id(true)) {
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
Paren_Expression() || Inline_Container() || Id(true)) {
retval = true;
bool has_more = true;
@@ -1509,6 +1498,19 @@ namespace chaiscript
}
build_match(AST_NodePtr(new eval::Fun_Call_AST_Node()), prev_stack_top);
/// \todo Work around for method calls until we have a better solution
if (!m_match_stack.back()->children.empty()) {
if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Dot_Access) {
AST_NodePtr dot_access = m_match_stack.back()->children[0];
AST_NodePtr func_call = m_match_stack.back();
m_match_stack.pop_back();
func_call->children.erase(func_call->children.begin());
func_call->children.insert(func_call->children.begin(), dot_access->children.back());
dot_access->children.pop_back();
dot_access->children.push_back(func_call);
m_match_stack.push_back(dot_access);
}
}
}
else if (Char('[')) {
has_more = true;
@@ -1519,6 +1521,14 @@ namespace chaiscript
build_match(AST_NodePtr(new eval::Array_Call_AST_Node()), prev_stack_top);
}
else if (Symbol(".", true)) {
has_more = true;
if (!(Id(true))) {
throw exception::eval_error("Incomplete array access", File_Position(m_line, m_col), *m_filename);
}
build_match(AST_NodePtr(new eval::Dot_Access_AST_Node()), prev_stack_top);
}
}
}
@@ -1683,8 +1693,7 @@ namespace chaiscript
* Parses any of a group of 'value' style ast_node groups from input
*/
bool Value() {
if (Var_Decl() || Lambda() || Id_Fun_Array() || Num(true) || Prefix() || Quoted_String(true) || Single_Quoted_String(true) ||
Paren_Expression() || Inline_Container()) {
if (Var_Decl() || Dot_Fun_Array() || Prefix()) {
return true;
}
else {
@@ -1703,7 +1712,7 @@ namespace chaiscript
bool Operator(size_t t_precedence = 0) {
bool retval = false;
AST_NodePtr oper;
size_t prev_stack_top = m_match_stack.size();
if (t_precedence < m_operators.size()) {
@@ -1716,45 +1725,61 @@ namespace chaiscript
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
File_Position(m_line, m_col), *m_filename);
}
} while (Operator_Helper(t_precedence));
switch (m_operators[t_precedence]) {
case(AST_Node_Type::Comparison) :
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Dot_Access) :
build_match(AST_NodePtr(new eval::Dot_Access_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Additive) :
build_match(AST_NodePtr(new eval::Additive_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Multiplicative) :
build_match(AST_NodePtr(new eval::Multiplicative_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Shift) :
build_match(AST_NodePtr(new eval::Shift_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Equality) :
build_match(AST_NodePtr(new eval::Equality_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Bitwise_And) :
build_match(AST_NodePtr(new eval::Bitwise_And_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Bitwise_Xor) :
build_match(AST_NodePtr(new eval::Bitwise_Xor_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Bitwise_Or) :
build_match(AST_NodePtr(new eval::Bitwise_Or_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Logical_And) :
build_match(AST_NodePtr(new eval::Logical_And_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Logical_Or) :
build_match(AST_NodePtr(new eval::Logical_Or_AST_Node()), prev_stack_top);
break;
default:
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename);
}
switch (m_operators[t_precedence]) {
case(AST_Node_Type::Comparison) :
build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Addition) :
oper = m_match_stack.at(m_match_stack.size()-2);
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
m_match_stack.begin() + m_match_stack.size() - 1);
if (oper->text == "+") {
build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top);
}
else if (oper->text == "-") {
build_match(AST_NodePtr(new eval::Subtraction_AST_Node()), prev_stack_top);
}
break;
case(AST_Node_Type::Multiplication) :
oper = m_match_stack.at(m_match_stack.size()-2);
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
m_match_stack.begin() + m_match_stack.size() - 1);
if (oper->text == "*") {
build_match(AST_NodePtr(new eval::Multiplication_AST_Node()), prev_stack_top);
}
else if (oper->text == "/") {
build_match(AST_NodePtr(new eval::Division_AST_Node()), prev_stack_top);
}
else if (oper->text == "%") {
build_match(AST_NodePtr(new eval::Modulus_AST_Node()), prev_stack_top);
}
break;
case(AST_Node_Type::Shift) :
build_match(AST_NodePtr(new eval::Shift_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Equality) :
build_match(AST_NodePtr(new eval::Equality_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Bitwise_And) :
build_match(AST_NodePtr(new eval::Bitwise_And_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Bitwise_Xor) :
build_match(AST_NodePtr(new eval::Bitwise_Xor_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Bitwise_Or) :
build_match(AST_NodePtr(new eval::Bitwise_Or_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Logical_And) :
build_match(AST_NodePtr(new eval::Logical_And_AST_Node()), prev_stack_top);
break;
case(AST_Node_Type::Logical_Or) :
build_match(AST_NodePtr(new eval::Logical_Or_AST_Node()), prev_stack_top);
break;
default:
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename);
}
} while (Operator_Helper(t_precedence));
}
}
}
@@ -1961,7 +1986,7 @@ namespace chaiscript
while ((m_input_pos != m_input_end) && (!Eol())) {
++m_input_pos;
}
// TODO: respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
/// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html)
}
if (Statements()) {

View File

@@ -1,4 +1,4 @@
Copyright 2009-2010 Jason Turner and Jonathan Turner. All Rights Reserved.
Copyright 2009-2011 Jason Turner and Jonathan Turner. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

View File

@@ -1,11 +1,11 @@
ChaiScript v2.3.3
ChaiScript
http://www.chaiscript.com
(c) 2009-2010 Jason Turner and Jonathan Turner
(c) 2009-2011 Jason Turner and Jonathan Turner
Release under the BSD license, see "license.txt" for details.
[Introduction]
ChaiScript is the only embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques, working with the developer like he expects it to work. Being a native C++ application, it has some advantages over existing embedded scripting languages:
ChaiScript is one of the only embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques, working with the developer like he expects it to work. Being a native C++ application, it has some advantages over existing embedded scripting languages:
1) It uses a header-only approach, which makes it easy to integrate with existing projects.
2) It maintains type safety between your C++ application and the user scripts.
@@ -25,7 +25,7 @@ Once instantiated, the engine is ready to start running ChaiScript source. You
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call add:
chai.add(&my_function, "my_function_name");
chai.add(chaiscript::fun(&my_function), "my_function_name");
Once registered the function will be visible to scripts as "my_function_name"
@@ -49,7 +49,7 @@ double function(int i, double j)
int main()
{
chaiscript::ChaiScript chai;
chai.add(&function, "function");
chai.add(chaiscript::fun(&function), "function");
double d = chai.eval<double>("function(3, 4.75);");
}

View File

@@ -58,8 +58,8 @@ bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTR
bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef,
bool BoostRef, bool BoostConstRef, bool ConstBoostRef, bool ConstBoostConstRef,
bool ConstBoostRefRef, bool ConstBoostConstRefRef, bool PODValue,
bool ConstPODValue, bool ConstPODValueRef, bool TPtrConstRef, bool ConstTPtrConstRef)
bool ConstBoostRefRef, bool ConstBoostConstRefRef, bool Number,
bool ConstNumber, bool ConstNumberRef, bool TPtrConstRef, bool ConstTPtrConstRef)
{
bool passed = true;
passed &= test_type_conversion<Type>(bv, T);
@@ -86,14 +86,14 @@ bool do_test(const Boxed_Value &bv, bool T, bool ConstT, bool TRef, bool ConstTR
passed &= test_type_conversion<const boost::reference_wrapper<const Type> >(bv, ConstBoostConstRef);
passed &= test_type_conversion<const boost::reference_wrapper<Type> &>(bv, ConstBoostRefRef);
passed &= test_type_conversion<const boost::reference_wrapper<const Type> &>(bv, ConstBoostConstRefRef);
passed &= test_type_conversion<Boxed_POD_Value>(bv, PODValue);
passed &= test_type_conversion<const Boxed_POD_Value>(bv, ConstPODValue);
passed &= test_type_conversion<Boxed_POD_Value &>(bv, false);
passed &= test_type_conversion<const Boxed_POD_Value &>(bv, ConstPODValueRef);
passed &= test_type_conversion<Boxed_POD_Value *>(bv, false);
passed &= test_type_conversion<const Boxed_POD_Value *>(bv, false);
passed &= test_type_conversion<Boxed_POD_Value * const>(bv, false);
passed &= test_type_conversion<const Boxed_POD_Value *const>(bv, false);
passed &= test_type_conversion<Boxed_Number>(bv, Number);
passed &= test_type_conversion<const Boxed_Number>(bv, ConstNumber);
passed &= test_type_conversion<Boxed_Number &>(bv, false);
passed &= test_type_conversion<const Boxed_Number &>(bv, ConstNumberRef);
passed &= test_type_conversion<Boxed_Number *>(bv, false);
passed &= test_type_conversion<const Boxed_Number *>(bv, false);
passed &= test_type_conversion<Boxed_Number * const>(bv, false);
passed &= test_type_conversion<const Boxed_Number *const>(bv, false);
passed &= test_type_conversion<Type *&>(bv, false);
passed &= test_type_conversion<const Type *&>(bv, false);
passed &= test_type_conversion<Type * const&>(bv, TPtrConstRef);
@@ -295,13 +295,15 @@ int main()
bool ConstTPtr, bool TPtrConst, bool ConstTPtrConst, bool SharedPtrT, bool SharedConstPtrT,
bool ConstSharedPtrT, bool ConstSharedConstPtrT, bool ConstSharedPtrTRef, bool ConstSharedPtrTConstRef, bool BoostRef,
bool BoostConstRef, bool ConstBoostRef, bool ConstBoostConstRef, bool ConstBoostRefRef, bool ConstBoostConstRefRef,
bool PODValue, bool ConstPODValue, bool ConstPODValueRef
bool Number, bool ConstNumber, bool ConstNumberRef
*/
passed &= built_in_type_test<int>(5, true);
passed &= built_in_type_test<double>(1.1, true);
passed &= built_in_type_test<char>('a', true);
passed &= built_in_type_test<bool>(false, true);
passed &= built_in_type_test<uint8_t>('a', true);
passed &= built_in_type_test<int64_t>('a', true);
passed &= built_in_type_test<bool>(false, false);
passed &= built_in_type_test<std::string>("Hello World", false);
// storing a pointer

View File

@@ -2,8 +2,7 @@
#include <chaiscript/chaiscript.hpp>
int main()
int test_generic()
{
chaiscript::ChaiScript chai;
@@ -17,5 +16,107 @@ int main()
}
}
std::cout << "test_generic failed" << std::endl;
return EXIT_FAILURE;
}
int test_1()
{
chaiscript::ChaiScript chai;
try {
chai.eval("throw(1)", chaiscript::exception_specification<int>());
} catch (int e) {
if (e == 1)
{
return EXIT_SUCCESS;
}
}
std::cout << "test_1 failed" << std::endl;
return EXIT_FAILURE;
}
int test_2()
{
chaiscript::ChaiScript chai;
try {
chai.eval("throw(1.0)", chaiscript::exception_specification<int, double>());
} catch (const double e) {
if (e == 1.0)
{
return EXIT_SUCCESS;
}
}
std::cout << "test_2 failed" << std::endl;
return EXIT_FAILURE;
}
int test_5()
{
chaiscript::ChaiScript chai;
try {
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
} catch (const double e) {
std::cout << "test_5 failed with double" << std::endl;
return EXIT_FAILURE;
} catch (int) {
std::cout << "test_5 failed with int" << std::endl;
return EXIT_FAILURE;
} catch (float) {
std::cout << "test_5 failed with float" << std::endl;
return EXIT_FAILURE;
} catch (const std::string &) {
std::cout << "test_5 failed with string" << std::endl;
return EXIT_FAILURE;
} catch (const std::exception &e) {
return EXIT_SUCCESS;
}
std::cout << "test_5 failed" << std::endl;
return EXIT_FAILURE;
}
int test_unhandled()
{
chaiscript::ChaiScript chai;
try {
chai.eval("throw(\"error\")", chaiscript::exception_specification<int, double, float, const std::exception &>());
} catch (double) {
std::cout << "test_unhandled failed with double" << std::endl;
return EXIT_FAILURE;
} catch (int) {
std::cout << "test_unhandled failed with int" << std::endl;
return EXIT_FAILURE;
} catch (float) {
std::cout << "test_unhandled failed with float" << std::endl;
return EXIT_FAILURE;
} catch (const std::exception &e) {
std::cout << "test_unhandled failed with std::exception" << std::endl;
return EXIT_FAILURE;
} catch (const chaiscript::Boxed_Value &bv) {
return EXIT_SUCCESS;
}
std::cout << "test_unhandled failed" << std::endl;
return EXIT_FAILURE;
}
int main()
{
if (test_generic() == EXIT_SUCCESS
&& test_1() == EXIT_SUCCESS
&& test_2() == EXIT_SUCCESS
&& test_5() == EXIT_SUCCESS
&& test_unhandled() == EXIT_SUCCESS)
{
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}

View File

@@ -0,0 +1 @@
assert_equal(2, `+`.get_contained_functions()[0].get_arity())

View File

@@ -0,0 +1,10 @@
// tests more complex parses of the index operator
def Bob::bob3() { return [1,2,3]; }
def Bob::Bob() {}
var b = Bob();
assert_equal(b.bob3()[0], 1);
assert_equal((b.bob3())[1], 2);

View File

@@ -0,0 +1 @@
assert_equal('b', "abc"[1])

View File

@@ -0,0 +1 @@
assert_equal(1, [1,2,3][0])

View File

@@ -0,0 +1,2 @@
var x = [1]
assert_equal(1, x[0])

View File

@@ -0,0 +1 @@
assert_equal(1, ([1,2,3])[0])