Compare commits

..

34 Commits

Author SHA1 Message Date
Jason Turner
0c0df2c982 VS 2008 related corrections. 2009-12-08 15:57:31 +00:00
Jason Turner
4457df9ff5 Fix NO_THREADS related issues 2009-12-06 05:12:02 +00:00
Jason Turner
e601de9d18 Reduce use of Param_List_Builder by providing call_function implementations for 0,1,2 arity 2009-12-06 01:31:58 +00:00
Jason Turner
37b2ac2056 Implement proper swap for Boxed_Value 2009-12-05 19:30:09 +00:00
Jason Turner
645cdddd70 Small but measurable eval performance increase (in optimized builds) by managing the number of Boxed_Values copies and assignments 2009-12-05 18:54:55 +00:00
Jonathan Turner
ac8462fb67 Fix up some broken sample files 2009-12-02 14:29:42 +00:00
Jason Turner
636c55493c Smartly size the integer returned from a Boxed_POD_Value operation to return an "int" if the resulting value is small enough 2009-12-01 03:52:57 +00:00
Jason Turner
e2a2c14c0d Eliminate use of size_t in stl related wrappings 2009-12-01 02:56:02 +00:00
Jonathan Turner
c418644a5b Fix for single-line comments stopping at semicolon. 2009-11-27 22:52:55 +00:00
Jason Turner
fbf8f53e04 Add Type_Info type and add *_type objects at time of type registration. 2009-11-21 22:47:44 +00:00
Jason Turner
a0c6366479 Added introspecition/classification of types 2009-11-21 06:39:35 +00:00
Jason Turner
15ffbd200a Fixed unittests broken by last checkin 2009-11-21 06:39:11 +00:00
Jason Turner
1c6b2725b3 Provide some hints for dispatches with lhs (first param) that is const 2009-11-21 06:02:17 +00:00
Jason Turner
95c124ca35 Support better tracking of loaded modules for saving and setting of state 2009-11-21 05:28:00 +00:00
Jason Turner
1bd73884b2 Add documentation to the set_state get_state functions 2009-11-18 05:05:40 +00:00
Jason Turner
d3e4af433e Add support for saving/restoring of chaiscript engine state. 2009-11-18 04:43:08 +00:00
Jason Turner
9f65303370 Handle case of const & return values (should probably be investigated a bit more) 2009-11-18 04:42:43 +00:00
Jason Turner
391eaa9e11 VC++ 2008 warnings cleanups 2009-11-15 03:26:47 +00:00
Jason Turner
ed11f48847 More robust handling of potential class object member types 2009-11-15 00:37:01 +00:00
Jason Turner
9dddb49850 Added support for const attribute access 2009-11-14 19:02:00 +00:00
Jason Turner
cca477dae6 Only share const globals between threads. Require all globals to be const. 2009-11-11 05:47:54 +00:00
Jason Turner
07352a16a3 Operators unittests 2009-11-11 03:03:24 +00:00
Jonathan Turner
e14931f389 Move completely over to new operators 2009-11-10 14:07:51 +00:00
Jason Turner
f4a680a582 Add missing operators.hpp file 2009-11-10 13:27:44 +00:00
Jason Turner
e6c6223c5b Operator handling rewrite and fleshing out of operators to include all standard C++ operators 2009-11-10 05:55:58 +00:00
Jason Turner
cbc61d898c Add "is_null" for boxed_values to see if they contain a null shared_ptr value 2009-11-08 16:30:12 +00:00
Jason Turner
3a37ceedb7 Rollback to r437 for bind_first implementation. The "cleaned up" version was a no-go in some cases 2009-11-08 16:28:35 +00:00
Jonathan Turner
1bc968e788 Add initial unaries 2009-11-08 16:27:39 +00:00
Jason Turner
fe5a935abd add is_undef functionality to boxed_value 2009-11-08 15:16:15 +00:00
Jason Turner
4e5c972e66 Simplify implementation of bind_first and add some detail namespacing 2009-11-08 14:46:44 +00:00
Jonathan Turner
d946cb7e9d Small fix to the casting of values in boolean logical statements 2009-11-07 14:50:41 +00:00
Jonathan Turner
18bfead387 Move to a better operator parser, add support for most of the C++ binary operators 2009-11-07 14:43:12 +00:00
Jason Turner
4c015d7e44 Simplification of bootstrap_stl code resulting in slightly better engine start up performance and compile time performance 2009-10-21 01:48:21 +00:00
Jason Turner
1122f2c818 Clean up reference counting implementation while improving compile time and compromising runtime slightly 2009-10-20 00:34:15 +00:00
31 changed files with 1586 additions and 955 deletions

View File

@@ -10,6 +10,7 @@
#include "dispatchkit.hpp"
#include "dynamic_object.hpp"
#include "register_function.hpp"
#include "operators.hpp"
namespace chaiscript
{
@@ -17,141 +18,6 @@ namespace chaiscript
{
namespace detail
{
/**
* Set of helper functions for common operators
*/
template<typename Ret, typename P1, typename P2>
Ret add(P1 p1, P2 p2)
{
return p1 + p2;
}
template<typename Ret, typename P1, typename P2>
Ret subtract(P1 p1, P2 p2)
{
return p1 - p2;
}
template<typename Ret, typename P1, typename P2>
Ret divide(P1 p1, P2 p2)
{
return p1 / p2;
}
template<typename Ret, typename P1, typename P2>
Ret multiply(P1 p1, P2 p2)
{
return p1 * p2;
}
template<typename Ret, typename P1, typename P2>
Ret modulus(P1 p1, P2 p2)
{
return p1 % p2;
}
template<typename Ret, typename P1, typename P2>
Ret shift_left(P1 p1, P2 p2)
{
return p1 << p2;
}
template<typename Ret, typename P1, typename P2>
Ret shift_right(P1 p1, P2 p2)
{
return p1 >> p2;
}
template<typename P1, typename P2>
P1 &assign(P1 &p1, const P2 &p2)
{
return (p1 = p2);
}
template<typename P1, typename P2>
bool equals(P1 p1, P2 p2)
{
return p1 == p2;
}
template<typename P1, typename P2>
bool not_equals(P1 p1, P2 p2)
{
return p1 != p2;
}
template<typename P1, typename P2>
bool less_than(P1 p1, P2 p2)
{
return p1 < p2;
}
template<typename P1, typename P2>
bool greater_than(P1 p1, P2 p2)
{
return p1 > p2;
}
template<typename P1, typename P2>
bool less_than_equals(P1 p1, P2 p2)
{
return p1 <= p2;
}
template<typename P1, typename P2>
bool greater_than_equals(P1 p1, P2 p2)
{
return p1 >= p2;
}
template<typename P1, typename P2>
P1 &timesequal(P1 &p1, const P2 &p2)
{
return (p1 *= p2);
}
template<typename P1, typename P2>
P1 &dividesequal(P1 &p1, const P2 &p2)
{
return (p1 /= p2);
}
template<typename P1, typename P2>
P1 &addsequal(P1 &p1, const P2 &p2)
{
return (p1 += p2);
}
template<typename P1, typename P2>
P1 &subtractsequal(P1 &p1, const P2 &p2)
{
return (p1 -= p2);
}
template<typename P1>
P1 &prefixincrement(P1 &p1)
{
return (++p1);
}
template<typename P1>
P1 &prefixdecrement(P1 &p1)
{
return (--p1);
}
template<typename P1>
P1 &prefixnegate(P1 &p1)
{
return (p1);
}
template<typename P1>
P1 &prefixnot(P1 &p1)
{
return (p1);
}
/* Special helpers for generating generic "POD" type operators
* The POD operators are needed for general support of C++ POD
@@ -162,6 +28,7 @@ namespace chaiscript
template<typename P1>
P1 &assign_pod(P1 &p1, Boxed_POD_Value v)
{
if (v.m_isfloat)
{
return (p1 = P1(v.d));
@@ -182,7 +49,63 @@ namespace chaiscript
}
template<typename P1>
P1 &timesequal_pod(P1 &p1, Boxed_POD_Value r)
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 &= P1(r.i);
}
throw bad_boxed_cast("&= only valid for integer types");
}
template<typename P1>
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 ^= P1(r.i);
}
throw bad_boxed_cast("^= only valid for integer types");
}
template<typename P1>
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 |= P1(r.i);
}
throw bad_boxed_cast("&= only valid for integer types");
}
template<typename P1>
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
return p1 -= P1(r.d);
} else {
return p1 -= P1(r.i);
}
}
template<typename P1>
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 <<= P1(r.i);
}
throw bad_boxed_cast("<<= only valid for integer types");
}
template<typename P1>
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
@@ -193,7 +116,7 @@ namespace chaiscript
}
template<typename P1>
P1 &dividesequal_pod(P1 &p1, Boxed_POD_Value r)
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
@@ -204,7 +127,31 @@ namespace chaiscript
}
template<typename P1>
P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r)
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 %= P1(r.i);
}
throw bad_boxed_cast("%= only valid for integer types");
}
template<typename P1>
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
{
if (!r.m_isfloat)
{
return p1 >>= P1(r.i);
}
throw bad_boxed_cast(">>= only valid for integer types");
}
template<typename P1>
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
@@ -214,223 +161,66 @@ namespace chaiscript
}
}
template<typename P1>
P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r)
{
if (r.m_isfloat)
{
return p1 -= P1(r.d);
} else {
return p1 -= P1(r.i);
}
}
}
/**
* Add canonical form of "=" for type T
*/
template<typename T>
ModulePtr oper_equals(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::equals<const T&, const T&>), "=");
return m;
}
/**
* Add canonical form of "+" for type T
*/
template<typename T>
ModulePtr oper_add(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::add<T, const T&, const T&>), "+");
return m;
}
/**
* Add canonical form of "+=" for type T
*/
template<typename T>
ModulePtr oper_add_equals(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::addsequal<T, T>), "+=");
return m;
}
/**
* Add canonical form of "-" for type T
*/
template<typename T>
ModulePtr oper_subtract(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::subtract<T, const T&, const T&>), "-");
return m;
}
/**
* Add canonical form of "/" for type T
*/
template<typename T>
ModulePtr oper_divide(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::divide<T, const T&, const T&>), "/");
return m;
}
/**
* Add canonical form of "*" for type T
*/
template<typename T>
ModulePtr oper_multiply(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::multiply<T, const T&, const T&>), "*");
return m;
}
/**
* Add canonical form of "!=" for type T
*/
template<typename T>
ModulePtr oper_not_equals(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::not_equals<const T&, const T&>), "!=");
return m;
}
/**
* Add user defined assignment operator for T = U
*/
template<typename T, typename U>
ModulePtr oper_assign_overload(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::assign<T,U>), "=");
return m;
}
/**
* Add canonical form of "=" for type T
*/
template<typename T>
ModulePtr oper_assign(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::assign<T,T>), "=");
return m;
}
/**
* 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 canonical form of "<" for type T
*/
template<typename T>
ModulePtr oper_less_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::less_than<const T&, const T&>), "<");
return m;
}
/**
* Add canonical form of ">" for type T
*/
template<typename T>
ModulePtr oper_greater_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::greater_than<const T&, const T&>), ">");
return m;
}
/**
* Add canonical form of "<=" for type T
*/
template<typename T>
ModulePtr oper_less_than_equals(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::less_than_equals<const T&, const T&>), "<=");
return m;
}
/**
* Add canonical form of ">=" for type T
*/
template<typename T>
ModulePtr oper_greater_than_equals(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::greater_than_equals<const T&, const T&>), ">=");
return m;
}
/**
* Add user defined comparison operators for T and R.
* Examples: T < R, T == R, etc.
*/
template<typename T, typename R>
ModulePtr opers_comparison_overload(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::equals<const T&, const R&>), "==");
m->add(fun(&detail::not_equals<const T&, const R&>), "!=");
m->add(fun(&detail::less_than<const T&, const R&>), "<");
m->add(fun(&detail::greater_than<const T&, const R&>), ">");
m->add(fun(&detail::less_than_equals<const T&, const R&>), "<=");
m->add(fun(&detail::greater_than_equals<const T&, const R&>), ">=");
return m;
}
/**
* Add canonical forms of all comparison operators for type T
*/
template<typename T>
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
{
opers_comparison_overload<T, T>(m);
operators::equal<T>(m);
operators::greater_than<T>(m);
operators::greater_than_equal<T>(m);
operators::less_than<T>(m);
operators::less_than_equal<T>(m);
operators::not_equal<T>(m);
return m;
}
/**
* Add all arithmetic operators that return a type of Ret, taking
* a lhs of T and a rhs of R, when possible.
* examples: Ret = T + R;
* ++T
* T *= R;
*/
template<typename Ret, typename T, typename R>
ModulePtr opers_arithmetic_overload(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::add<Ret, T, R>), "+");
m->add(fun(&detail::subtract<Ret, T, R>), "-");
m->add(fun(&detail::divide<Ret, T, R>), "/");
m->add(fun(&detail::multiply<Ret, T, R>), "*");
m->add(fun(&detail::timesequal<T, R>), "*=");
m->add(fun(&detail::dividesequal<T, R>), "/=");
m->add(fun(&detail::subtractsequal<T, R>), "-=");
m->add(fun(&detail::addsequal<T, R>), "+=");
m->add(fun(&detail::prefixincrement<T>), "++");
m->add(fun(&detail::prefixdecrement<T>), "--");
m->add(fun(&detail::prefixnegate<T>), "-");
m->add(fun(&detail::prefixnot<T>), "!");
return m;
}
/**
* Add arithmetic assign operators for POD types:
* example: POD *= T, POD /= T
*/
template<typename T>
ModulePtr opers_arithmetic_modify_pod(ModulePtr m = ModulePtr(new Module()))
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::timesequal_pod<T>), "*=");
m->add(fun(&detail::dividesequal_pod<T>), "/=");
m->add(fun(&detail::subtractsequal_pod<T>), "-=");
m->add(fun(&detail::addsequal_pod<T>), "+=");
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;
}
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;
}
@@ -476,16 +266,6 @@ namespace chaiscript
return m;
}
/**
* Add canonical forms of all arithmetic operators for type T
*/
template<typename T>
ModulePtr opers_arithmetic(ModulePtr m = ModulePtr(new Module()))
{
opers_arithmetic_overload<T, T, T>(m);
return m;
}
/**
* to_string function for internal use. Uses ostream operator<<
*/
@@ -506,6 +286,17 @@ namespace chaiscript
return boost::lexical_cast<Input>(i);
}
/**
* 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
* common conversions
@@ -515,16 +306,52 @@ namespace chaiscript
{
m->add(user_type<T>(), name);
basic_constructors<T>(name, m);
oper_assign<T>(m);
operators::assign<T>(m);
oper_assign_pod<T>(m);
construct_pod<T>(name, m);
opers_arithmetic<T>(m);
opers_arithmetic_modify_pod<T>(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
* where you do not want to make a deep copy of an object during cloning
@@ -558,7 +385,7 @@ namespace chaiscript
template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<typename boost::add_const<Type>::type> &rhs)
{
if (lhs.is_unknown()
if (lhs.is_undef()
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
{
lhs.assign(Boxed_Value(rhs));
@@ -580,7 +407,7 @@ namespace chaiscript
*/
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
{
if (lhs.is_unknown())
if (lhs.is_undef())
{
return (lhs.assign(rhs));
} else {
@@ -598,28 +425,21 @@ namespace chaiscript
std::cout << s << std::endl;
}
/**
* Add all comparison operators for POD types
*/
static void opers_comparison_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::equals<Boxed_POD_Value, Boxed_POD_Value>), "==");
m->add(fun(&detail::not_equals<Boxed_POD_Value, Boxed_POD_Value>), "!=");
m->add(fun(&detail::less_than<Boxed_POD_Value, Boxed_POD_Value>), "<");
m->add(fun(&detail::greater_than<Boxed_POD_Value, Boxed_POD_Value>), ">");
m->add(fun(&detail::less_than_equals<Boxed_POD_Value, Boxed_POD_Value>), "<=");
m->add(fun(&detail::greater_than_equals<Boxed_POD_Value, Boxed_POD_Value>), ">=");
}
/**
* Add all arithmetic operators for PODs
*/
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
m->add(fun(&detail::subtract<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
m->add(fun(&detail::divide<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
m->add(fun(&detail::multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
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>), ">>");
}
/**
@@ -708,10 +528,31 @@ namespace chaiscript
m->add(fun(&Dynamic_Object::get_attr), "get_attr");
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
m->add(fun(&Boxed_Value::is_undef), "is_var_undef");
m->add(fun(&Boxed_Value::is_null), "is_var_null");
m->add(fun(&Boxed_Value::is_const), "is_var_const");
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
operators::equal<Type_Info>(m);
m->add(fun(&Type_Info::is_const), "is_type_const");
m->add(fun(&Type_Info::is_reference), "is_type_reference");
m->add(fun(&Type_Info::is_void), "is_type_void");
m->add(fun(&Type_Info::is_undef), "is_type_undef");
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
m->add(fun(&Type_Info::name), "cpp_name");
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
m->add(fun(&Type_Info::bare_equal), "bare_equal");
basic_constructors<bool>("bool", m);
oper_assign<std::string>(m);
oper_assign<bool>(m);
operators::assign<bool>(m);
m->add(fun(&to_string<const std::string &>), "internal_to_string");
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
@@ -719,18 +560,17 @@ namespace chaiscript
m->add(fun(&throw_exception), "throw");
m->add(fun(&what), "what");
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<int>("int", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<boost::int64_t>("int64_t", m);
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);
opers_comparison_pod(m);
operators::logical_compliment<bool>(m);
opers_comparison<Boxed_POD_Value>(m);
opers_arithmetic_pod(m);
m->add(fun(&detail::modulus<int, int, int>), "%");
m->add(fun(&detail::shift_left<int, int, int>), "<<");
m->add(fun(&detail::shift_right<int, int, int>), ">>");
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");

View File

@@ -122,24 +122,13 @@ namespace chaiscript
return m;
}
/**
* Add reversible_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ReversibleContainer.html
*/
template<typename ContainerType>
ModulePtr reversible_container_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
{
return m;
}
/**
* Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
reversible_container_type<ContainerType>(type, m);
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
@@ -158,7 +147,7 @@ namespace chaiscript
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
basic_constructors<ContainerType>(type, m);
oper_assign<ContainerType>(m);
operators::assign<ContainerType>(m);
return m;
}
@@ -167,30 +156,15 @@ namespace chaiscript
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
ModulePtr container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
assignable_type<ContainerType>(type, m);
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
m->add(fun(boost::function<int (const ContainerType *)>(&ContainerType::size)), "size");
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
return m;
}
/**
* Add forward container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ForwardContainer.html
*/
template<typename ContainerType>
ModulePtr forward_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
input_range_type<ContainerType>(type, m);
container_type<ContainerType>(type, m);
return m;
}
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
@@ -243,11 +217,8 @@ namespace chaiscript
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
ModulePtr sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
forward_container_type<ContainerType>(type, m);
default_constructible_type<ContainerType>(type, m);
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
@@ -267,11 +238,8 @@ namespace chaiscript
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
sequence_type<ContainerType>(type, m);
typedef typename ContainerType::reference (ContainerType::*backptr)();
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
@@ -297,8 +265,6 @@ namespace chaiscript
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
sequence_type<ContainerType>(type, m);
typedef typename ContainerType::reference (ContainerType::*frontptr)();
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
@@ -315,44 +281,6 @@ namespace chaiscript
return m;
}
/**
* hopefully working List type
* http://www.sgi.com/tech/stl/List.html
*/
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<ListType>(), type);
front_insertion_sequence_type<ListType>(type, m);
back_insertion_sequence_type<ListType>(type, m);
return m;
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<VectorType>(), type);
random_access_container_type<VectorType>(type, m);
back_insertion_sequence_type<VectorType>(type, m);
return m;
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename ContainerType>
ModulePtr associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
forward_container_type<ContainerType>(type, m);
default_constructible_type<ContainerType>(type, m);
return m;
}
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
@@ -379,7 +307,6 @@ namespace chaiscript
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
associative_container_type<ContainerType>(type, m);
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
return m;
@@ -390,39 +317,10 @@ namespace chaiscript
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
associative_container_type<ContainerType>(type, m);
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
return m;
}
/**
* Add sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator>
(ContainerType::*eq_range)(const typename ContainerType::key_type &);
reversible_container_type<ContainerType>(type, m);
associative_container_type<ContainerType>(type, m);
return m;
}
/**
* Add unique sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
sorted_associative_container_type<ContainerType>(type, m);
unique_associative_container_type<ContainerType>(type, m);
// m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count)), "count");
return m;
}
@@ -436,12 +334,57 @@ namespace chaiscript
{
m->add(user_type<MapType>(), type);
m->add(fun(&MapType::operator[]), "[]");
unique_sorted_associative_container_type<MapType>(type, m);
container_type<MapType>(type, m);
assignable_type<MapType>(type, m);
unique_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m);
input_range_type<MapType>(type, m);
return m;
}
/**
* hopefully working List type
* http://www.sgi.com/tech/stl/List.html
*/
template<typename ListType>
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<ListType>(), type);
front_insertion_sequence_type<ListType>(type, m);
back_insertion_sequence_type<ListType>(type, m);
sequence_type<ListType>(type, m);
container_type<ListType>(type, m);
default_constructible_type<ListType>(type, m);
assignable_type<ListType>(type, m);
input_range_type<ListType>(type, m);
return m;
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<VectorType>(), type);
back_insertion_sequence_type<VectorType>(type, m);
sequence_type<VectorType>(type, m);
random_access_container_type<VectorType>(type, m);
container_type<VectorType>(type, m);
default_constructible_type<VectorType>(type, m);
assignable_type<VectorType>(type, m);
input_range_type<VectorType>(type, m);
return m;
}
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
@@ -450,11 +393,15 @@ namespace chaiscript
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<String>(), type);
oper_add<String>(m);
oper_add_equals<String>(m);
operators::addition<String>(m);
operators::assign_sum<String>(m);
opers_comparison<String>(m);
random_access_container_type<String>(type, m);
sequence_type<String>(type, m);
default_constructible_type<String>(type, m);
container_type<String>(type, m);
assignable_type<String>(type, m);
input_range_type<String>(type, m);
//Special case: add push_back to string (which doesn't support other back_insertion operations
std::string push_back_name;
@@ -466,13 +413,16 @@ namespace chaiscript
}
m->add(fun(&String::push_back), push_back_name);
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
m->add(fun(static_cast<find_func>(&String::find)), "find");
m->add(fun(static_cast<find_func>(&String::rfind)), "rfind");
m->add(fun(static_cast<find_func>(&String::find_first_of)), "find_first_of");
m->add(fun(static_cast<find_func>(&String::find_last_of)), "find_last_of");
m->add(fun(static_cast<find_func>(&String::find_first_not_of)), "find_first_not_of");
m->add(fun(static_cast<find_func>(&String::find_last_not_of)), "find_last_not_of");
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
typedef boost::function<int (const String *, const String &, int)> find_func;
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find))), "find");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::rfind))), "rfind");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_of))), "find_first_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_of))), "find_last_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_not_of))), "find_first_not_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_not_of))), "find_last_not_of");
return m;
}

View File

@@ -17,6 +17,7 @@
#include <boost/bind.hpp>
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
#include <limits>
namespace chaiscript
{
@@ -42,49 +43,27 @@ namespace chaiscript
*/
struct Data
{
/**
* used to provide type-erased access to the internal boost::shared_ptr
* reference count information
*/
struct Shared_Ptr_Proxy
{
virtual ~Shared_Ptr_Proxy()
{
}
virtual bool unique(boost::any *) = 0;
virtual long use_count(boost::any *) = 0;
};
/**
* Typed implementation of the Shared_Ptr_Proxy
*/
template<typename T>
struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
{
virtual ~Shared_Ptr_Proxy_Impl()
{
}
virtual bool unique(boost::any *a)
static bool unique(boost::any *a)
{
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
return ptr->unique();
}
virtual long use_count(boost::any *a)
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->use_count();
return ptr->get() == 0;
}
};
Data(const Type_Info &ti,
const boost::any &to,
bool tr,
const boost::shared_ptr<Shared_Ptr_Proxy> &t_proxy = boost::shared_ptr<Shared_Ptr_Proxy>())
const boost::function<bool (boost::any*)> &t_unique = boost::function<bool (boost::any*)>(),
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_ptr_proxy(t_proxy)
m_is_ref(tr), m_unique(t_unique), m_is_null(t_is_null)
{
}
@@ -93,7 +72,8 @@ namespace chaiscript
m_type_info = rhs.m_type_info;
m_obj = rhs.m_obj;
m_is_ref = rhs.m_is_ref;
m_ptr_proxy = rhs.m_ptr_proxy;
m_unique = rhs.m_unique;
m_is_null = rhs.m_is_null;
return *this;
}
@@ -101,7 +81,8 @@ namespace chaiscript
Type_Info m_type_info;
boost::any m_obj;
bool m_is_ref;
boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy;
boost::function<bool (boost::any*)> m_unique;
boost::function<bool (boost::any*)> m_is_null;
};
/**
@@ -141,7 +122,8 @@ namespace chaiscript
detail::Get_Type_Info<T>::get(),
boost::any(obj),
false,
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
&Data::unique<T>,
&Data::is_null<T>)
);
std::map<std::pair<const void *, bool>, Data>::iterator itr
@@ -200,7 +182,8 @@ namespace chaiscript
detail::Get_Type_Info<T>::get(),
boost::any(boost::shared_ptr<T>(new T(t))),
false,
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
&Data::unique<T>,
&Data::is_null<T>)
);
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj);
@@ -226,7 +209,7 @@ namespace chaiscript
{
++m_cullcount;
if (force || m_cullcount % 10 != 0)
if (force || m_cullcount % 20 != 0)
{
return;
}
@@ -236,7 +219,7 @@ namespace chaiscript
while (itr != m_ptrs.end())
{
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
if (itr->second.m_unique(&itr->second.m_obj))
{
std::map<std::pair<const void *, bool>, Data >::iterator todel = itr;
++itr;
@@ -247,7 +230,7 @@ namespace chaiscript
}
}
std::map<std::pair<const void *, bool>, Data > m_ptrs;
std::map<std::pair<const void *, bool>, Data> m_ptrs;
int m_cullcount;
};
@@ -282,6 +265,11 @@ namespace chaiscript
{
}
void swap(Boxed_Value &rhs)
{
std::swap(m_data, rhs.m_data);
}
/**
* Return a reference to the static global Object_Cache
*/
@@ -311,7 +299,8 @@ namespace chaiscript
*/
Boxed_Value &operator=(const Boxed_Value &rhs)
{
m_data = rhs.m_data;
Boxed_Value temp(rhs);
swap(temp);
return *this;
}
@@ -323,9 +312,29 @@ namespace chaiscript
/**
* return true if the object is uninitialized
*/
bool is_unknown() const
bool is_undef() const
{
return m_data->m_type_info.is_unknown();
return m_data->m_type_info.is_undef();
}
bool is_const() const
{
return m_data->m_type_info.is_const();
}
bool is_type(const Type_Info &ti) const
{
return m_data->m_type_info.bare_equal(ti);
}
bool is_null() const
{
if (m_data->m_is_null)
{
return m_data->m_is_null(&m_data->m_obj);
} else {
return false;
}
}
boost::any get() const
@@ -338,6 +347,12 @@ namespace chaiscript
return m_data->m_is_ref;
}
bool is_pointer() const
{
return !is_ref();
}
private:
boost::shared_ptr<Data> m_data;
};
@@ -624,7 +639,7 @@ namespace chaiscript
Boxed_POD_Value(const Boxed_Value &v)
: d(0), i(0), m_isfloat(false)
{
if (v.get_type_info().is_unknown())
if (v.get_type_info().is_undef())
{
throw boost::bad_any_cast();
}
@@ -703,42 +718,117 @@ namespace chaiscript
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i + r.i);
return smart_size(i + r.i);
}
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator*(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i * r.i);
}
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator/(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i / r.i);
}
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator-(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i - r.i);
return smart_size(i - r.i);
}
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator&(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i & r.i);
}
throw bad_boxed_cast("& only valid for integer types");
}
Boxed_Value operator^(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i ^ r.i);
}
throw bad_boxed_cast("^ only valid for integer types");
}
Boxed_Value operator|(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i | r.i);
}
throw bad_boxed_cast("| only valid for integer types");
}
Boxed_Value operator/(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i / r.i);
}
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator<<(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i << r.i);
}
throw bad_boxed_cast("<< only valid for integer types");
}
Boxed_Value operator*(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i * r.i);
}
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator%(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i % r.i);
}
throw bad_boxed_cast("% only valid for integer types");
}
Boxed_Value operator>>(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i >> r.i);
}
throw bad_boxed_cast(">> only valid for integer types");
}
Boxed_Value smart_size(boost::int64_t i) const
{
if (i < std::numeric_limits<int>::min()
|| i > std::numeric_limits<int>::max())
{
return Boxed_Value(i);
} else {
return Boxed_Value(static_cast<int>(i));
}
}
double d;
boost::int64_t i;
@@ -755,6 +845,20 @@ namespace chaiscript
{
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 &>
{
typedef Boxed_POD_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_POD_Value(ob);
@@ -799,7 +903,14 @@ namespace chaiscript
{
return l.get_type_info() == r.get_type_info();
}
}
namespace std
{
template<> void swap(chaiscript::Boxed_Value &lhs, chaiscript::Boxed_Value &rhs)
{
lhs.swap(rhs);
}
}
#endif

View File

@@ -43,6 +43,7 @@ namespace chaiscript
return *this;
}
//Add a bit of chaiscript to eval during module implementation
Module &eval(const std::string &str)
{
@@ -50,6 +51,11 @@ namespace chaiscript
return *this;
}
Module &add(const boost::shared_ptr<Module> &m)
{
m->apply(*this, *this);
return *m;
}
template<typename Eval, typename Engine>
void apply(Eval &t_eval, Engine &t_engine) const
@@ -166,6 +172,19 @@ namespace chaiscript
virtual ~reserved_word_error() throw() {}
};
/**
* Exception thrown in the case that a non-const object was added as a shared object
*/
struct global_non_const : std::runtime_error
{
global_non_const() throw()
: std::runtime_error("a global object must be const")
{
}
virtual ~global_non_const() throw() {}
};
/**
* Main class for the dispatchkit. Handles management
@@ -179,6 +198,14 @@ namespace chaiscript
typedef boost::tuples::tuple<std::map<std::string, Boxed_Value>, std::deque<Scope>, bool> StackData;
typedef boost::shared_ptr<StackData> Stack;
struct State
{
std::multimap<std::string, Proxy_Function> m_functions;
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
};
Dispatch_Engine()
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
{
@@ -238,19 +265,24 @@ namespace chaiscript
}
/**
* Adds a new shared object, between all the threads
* Adds a new global shared object, between all the threads
*/
void add_shared_object(const Boxed_Value &obj, const std::string &name)
void add_global_const(const Boxed_Value &obj, const std::string &name)
{
StackData &stack = get_stack_data();
validate_object_name(name);
if (!obj.is_const())
{
throw global_non_const();
}
stack.get<0>().erase(name);
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_shared_object_mutex);
boost::unique_lock<boost::shared_mutex> l(m_global_object_mutex);
#endif
m_shared_objects[name] = obj;
m_state.m_global_objects[name] = obj;
}
/**
@@ -316,7 +348,7 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
get_function_cache() = m_functions;
get_function_cache() = m_state.m_functions;
}
/**
@@ -353,15 +385,14 @@ namespace chaiscript
}
}
// Are we in the 0th stack and should check the shared objects?
if (stack.get<2>())
// Is the value we are looking for a global?
{
#ifndef CHAISCRIPT_NO_THREADS
boost::shared_lock<boost::shared_mutex> l(m_shared_object_mutex);
boost::shared_lock<boost::shared_mutex> l(m_global_object_mutex);
#endif
itr = m_shared_objects.find(name);
if (itr != m_shared_objects.end())
itr = m_state.m_global_objects.find(name);
if (itr != m_state.m_global_objects.end())
{
cache[name] = itr->second;
return itr->second;
@@ -386,11 +417,13 @@ namespace chaiscript
*/
void add(const Type_Info &ti, const std::string &name)
{
add_global_const(const_var(ti), name + "_type");
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif
m_types.insert(std::make_pair(name, ti));
m_state.m_types.insert(std::make_pair(name, ti));
}
/**
@@ -402,9 +435,9 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
Type_Name_Map::const_iterator itr = m_types.find(name);
Type_Name_Map::const_iterator itr = m_state.m_types.find(name);
if (itr != m_types.end())
if (itr != m_state.m_types.end())
{
return itr->second;
}
@@ -423,8 +456,8 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
for (Type_Name_Map::const_iterator itr = m_types.begin();
itr != m_types.end();
for (Type_Name_Map::const_iterator itr = m_state.m_types.begin();
itr != m_state.m_types.end();
++itr)
{
if (itr->second.bare_equal(ti))
@@ -445,7 +478,7 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
return std::vector<std::pair<std::string, Type_Info> >(m_types.begin(), m_types.end());
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
}
/**
@@ -484,7 +517,7 @@ namespace chaiscript
boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif
m_reserved_words.insert(name);
m_state.m_reserved_words.insert(name);
}
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const
@@ -493,7 +526,27 @@ namespace chaiscript
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
= functions.equal_range(t_name);
return dispatch(range.first, range.second, params);
return dispatch(range.first, range.second, params);
}
Boxed_Value call_function(const std::string &t_name) const
{
return call_function(t_name, std::vector<Boxed_Value>());
}
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1) const
{
std::vector<Boxed_Value> params;
params.push_back(p1);
return call_function(t_name, params);
}
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1, const Boxed_Value &p2) const
{
std::vector<Boxed_Value> params;
params.push_back(p1);
params.push_back(p2);
return call_function(t_name, params);
}
/**
@@ -599,6 +652,26 @@ namespace chaiscript
return get_type_name(obj.get_type_info());
}
State get_state()
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
#endif
return m_state;
}
void set_state(const State &t_state)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
#endif
m_state = t_state;
}
private:
/**
@@ -625,7 +698,7 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif
if (m_reserved_words.find(name) != m_reserved_words.end())
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
{
throw reserved_word_error(name);
}
@@ -643,7 +716,7 @@ namespace chaiscript
#endif
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
= m_functions.equal_range(t_name);
= m_state.m_functions.equal_range(t_name);
while (range.first != range.second)
{
@@ -654,7 +727,7 @@ namespace chaiscript
++range.first;
}
m_functions.insert(std::make_pair(t_name, f));
m_state.m_functions.insert(std::make_pair(t_name, f));
get_function_cache().insert(std::make_pair(t_name, f));
return true;
@@ -662,7 +735,7 @@ namespace chaiscript
#ifndef CHAISCRIPT_NO_THREADS
mutable boost::shared_mutex m_mutex;
mutable boost::shared_mutex m_shared_object_mutex;
mutable boost::shared_mutex m_global_object_mutex;
#endif
struct Stack_Holder
@@ -681,13 +754,9 @@ namespace chaiscript
chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder;
std::multimap<std::string, Proxy_Function> m_functions;
std::map<std::string, Boxed_Value> m_shared_objects;
State m_state;
Type_Name_Map m_types;
Boxed_Value m_place_holder;
std::set<std::string> m_reserved_words;
};
}

View File

@@ -46,6 +46,16 @@ namespace chaiscript
return Boxed_Value(r);
}
};
template<typename Ret>
struct Handle_Return<const Ret &>
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(boost::cref(r));
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
@@ -57,6 +67,11 @@ namespace chaiscript
{
return Boxed_Value(boost::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(boost::cref(r));
}
};
/**
@@ -83,6 +98,19 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/

View File

@@ -0,0 +1,442 @@
#ifndef __CHAISCRIPT_OPERATORS_HPP__
#define __CHAISCRIPT_OPERATORS_HPP__
namespace chaiscript
{
namespace operators
{
template<typename Ret, typename L, typename R>
Ret assign(L l, R r)
{
return (l = r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_and(L l, R r)
{
return (l &= r);
}
template<typename Ret, typename L, typename R>
Ret assign_xor(L l, R r)
{
return (l ^= r);
}
template<typename Ret, typename L, typename R>
Ret assign_bitwise_or(L l, R r)
{
return (l |= r);
}
template<typename Ret, typename L, typename R>
Ret assign_difference(L l, R r)
{
return (l -= r);
}
template<typename Ret, typename L, typename R>
Ret assign_left_shift(L l, R r)
{
return (l <<= r);
}
template<typename Ret, typename L, typename R>
Ret assign_product(L l, R r)
{
return (l *= r);
}
template<typename Ret, typename L, typename R>
Ret assign_quotient(L l, R r)
{
return (l /= r);
}
template<typename Ret, typename L, typename R>
Ret assign_remainder(L l, R r)
{
return (l %= r);
}
template<typename Ret, typename L, typename R>
Ret assign_right_shift(L l, R r)
{
return (l >>= r);
}
template<typename Ret, typename L, typename R>
Ret assign_sum(L l, R r)
{
return (l += r);
}
template<typename Ret, typename L>
Ret prefix_decrement(L l)
{
return (--l);
}
template<typename Ret, typename L>
Ret prefix_increment(L l)
{
return (++l);
}
template<typename Ret, typename L, typename R>
Ret equal(L l, R r)
{
return (l == r);
}
template<typename Ret, typename L, typename R>
Ret greater_than(L l, R r)
{
return (l > r);
}
template<typename Ret, typename L, typename R>
Ret greater_than_equal(L l, R r)
{
return (l >= r);
}
template<typename Ret, typename L, typename R>
Ret less_than(L l, R r)
{
return (l < r);
}
template<typename Ret, typename L, typename R>
Ret less_than_equal(L l, R r)
{
return (l <= r);
}
template<typename Ret, typename L>
Ret logical_compliment(L l)
{
return (!l);
}
template<typename Ret, typename L, typename R>
Ret not_equal(L l, R r)
{
return (l != r);
}
template<typename Ret, typename L, typename R>
Ret addition(L l, R r)
{
return (l + r);
}
template<typename Ret, typename L>
Ret unary_plus(L l)
{
return (+l);
}
template<typename Ret, typename L, typename R>
Ret subtraction(L l, R r)
{
return (l - r);
}
template<typename Ret, typename L>
Ret unary_minus(L l)
{
return (-l);
}
template<typename Ret, typename L, typename R>
Ret bitwise_and(L l, R r)
{
return (l & r);
}
template<typename Ret, typename L>
Ret bitwise_compliment(L l)
{
return (~l);
}
template<typename Ret, typename L, typename R>
Ret bitwise_xor(L l, R r)
{
return (l ^ r);
}
template<typename Ret, typename L, typename R>
Ret bitwise_or(L l, R r)
{
return (l | r);
}
template<typename Ret, typename L, typename R>
Ret division(L l, R r)
{
return (l / r);
}
template<typename Ret, typename L, typename R>
Ret left_shift(L l, R r)
{
return l << r;
}
template<typename Ret, typename L, typename R>
Ret multiplication(L l, R r)
{
return l * r;
}
template<typename Ret, typename L, typename R>
Ret remainder(L l, R r)
{
return (l % r);
}
template<typename Ret, typename L, typename R>
Ret right_shift(L l, R r)
{
return (l >> r);
}
template<typename T>
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign<T &, T &, const T&>), "=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
return m;
}
template<typename T>
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
return m;
}
template<typename T>
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
return m;
}
template<typename T>
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
return m;
}
template<typename T>
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
return m;
}
template<typename T>
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
return m;
}
template<typename T>
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
return m;
}
template<typename T>
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
return m;
}
template<typename T>
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
return m;
}
template<typename T>
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
return m;
}
template<typename T>
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&prefix_decrement<T &, T &>), "--");
return m;
}
template<typename T>
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&prefix_increment<T &, T &>), "++");
return m;
}
template<typename T>
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&equal<bool, const T&, const T&>), "==");
return m;
}
template<typename T>
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
return m;
}
template<typename T>
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
return m;
}
template<typename T>
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&less_than<bool, const T&, const T&>), "<");
return m;
}
template<typename T>
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
return m;
}
template<typename T>
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&logical_compliment<bool, const T &>), "!");
return m;
}
template<typename T>
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&not_equal<bool, const T &, const T &>), "!=");
return m;
}
template<typename T>
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&addition<T, const T &, const T &>), "+");
return m;
}
template<typename T>
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&unary_plus<T, const T &>), "+");
return m;
}
template<typename T>
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&subtraction<T, const T &, const T &>), "-");
return m;
}
template<typename T>
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&unary_minus<T, const T &>), "-");
return m;
}
template<typename T>
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
return m;
}
template<typename T>
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_compliment<T, const T &>), "~");
return m;
}
template<typename T>
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
return m;
}
template<typename T>
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
return m;
}
template<typename T>
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&division<T, const T &, const T &>), "/");
return m;
}
template<typename T>
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
return m;
}
template<typename T>
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&multiplication<T, const T &, const T &>), "*");
return m;
}
template<typename T>
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&remainder<T, const T &, const T &>), "%");
return m;
}
template<typename T>
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
return m;
}
}
}
#endif

View File

@@ -13,6 +13,7 @@
#include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <stdexcept>
#include <vector>
#include "proxy_functions_detail.hpp"
@@ -92,7 +93,8 @@ namespace chaiscript
const Type_Info &ti = types[1];
if (ti.is_unknown() || vals[0].get_type_info().is_unknown()
if (ti.is_undef() || vals[0].get_type_info().is_undef()
|| ti.bare_equal(user_type<Boxed_Value>())
|| ti.bare_equal(user_type<Boxed_POD_Value>())
|| ti.bare_equal(vals[0].get_type_info()))
@@ -407,6 +409,81 @@ namespace chaiscript
Func *m_dummy_func;
};
/**
* Attribute getter Proxy_Function implementation
*/
template<typename T, typename Class>
class Attribute_Access : public Proxy_Function_Base
{
public:
Attribute_Access(T Class::* t_attr)
: Proxy_Function_Base(param_types()),
m_attr(t_attr)
{
}
virtual ~Attribute_Access() {}
virtual bool operator==(const Proxy_Function_Base &t_func) const
{
try {
const Attribute_Access<T, Class> &aa
= dynamic_cast<const Attribute_Access<T, Class> &>(t_func);
return m_attr == aa.m_attr;
} catch (const std::bad_cast &) {
return false;
}
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
if (params.size() == 1)
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv);
return Handle_Return<const typename boost::add_reference<T>::type>::handle(o->*m_attr);
} else {
Class *o = boxed_cast<Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
}
} else {
throw arity_error(params.size(), 1);
}
}
virtual int get_arity() const
{
return 1;
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{
if (vals.size() != 1)
{
return false;
}
return vals[0].get_type_info().bare_equal(user_type<Class>());
}
virtual std::string annotation() const
{
return "";
}
private:
static std::vector<Type_Info> param_types()
{
std::vector<Type_Info> v;
v.push_back(user_type<T>());
v.push_back(user_type<Class>());
return v;
}
T Class::* m_attr;
};
/**
* Exception thrown in the case that a multi method dispatch fails
* because no matching function was found
@@ -420,6 +497,11 @@ namespace chaiscript
{
}
dispatch_error(bool is_const) throw()
: std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":""))
{
}
virtual ~dispatch_error() throw() {}
};
@@ -450,7 +532,7 @@ namespace chaiscript
++begin;
}
throw dispatch_error();
throw dispatch_error(plist.empty()?false:plist[0].is_const());
}
/**

View File

@@ -13,74 +13,61 @@
#include <boost/bind.hpp>
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_object_pointer.hpp>
namespace chaiscript
{
namespace detail
{
/**
* Helper function for register_member function
*/
template<typename T, typename Class>
T &get_member(T Class::* m, Class *obj)
template<bool Object>
struct Fun_Helper
{
return (obj->*m);
}
template<typename T>
static Proxy_Function go(T t)
{
return Proxy_Function(
new Proxy_Function_Impl<
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t)));
}
};
template<typename T>
boost::function<T> mk_boost_fun(const boost::function<T> &f)
{
return f;
}
template<typename T>
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
> mk_boost_fun(T t)
{
return
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t);
}
template<typename T, typename Class>
Proxy_Function fun_helper(T Class::* m)
template<>
struct Fun_Helper<true>
{
return fun_helper(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
}
template<typename T, typename Class>
static Proxy_Function go(T Class::* m)
{
return Proxy_Function(new Attribute_Access<T, Class>(m));
}
};
template<typename T>
Proxy_Function fun_helper(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
}
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return detail::fun_helper(f);
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
template<typename T>
Proxy_Function fun(T t)
{
return detail::fun_helper(detail::mk_boost_fun(t));
return detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value>::go(t);
}
template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q)
{
return detail::fun_helper(bind_first(t, q));
return fun(bind_first(t, q));
}
template<typename T, typename Q, typename R>
Proxy_Function fun(T t, const Q &q, const R &r)
{
return detail::fun_helper(bind_first(bind_first(t, q), r));
return fun(bind_first(bind_first(t, q), r));
}
}

View File

@@ -29,14 +29,14 @@ namespace chaiscript
: 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_type_info(t_ti), m_bare_type_info(t_bareti),
m_is_unknown(false)
m_is_undef(false)
{
}
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_unknown(true)
m_is_undef(true)
{
}
@@ -45,7 +45,7 @@ namespace chaiscript
m_is_pointer(ti.m_is_pointer),
m_is_void(ti.m_is_void), m_type_info(ti.m_type_info),
m_bare_type_info(ti.m_bare_type_info),
m_is_unknown(ti.m_is_unknown)
m_is_undef(ti.m_is_undef)
{
}
@@ -57,7 +57,7 @@ namespace chaiscript
m_is_void = ti.m_is_void;
m_type_info = ti.m_type_info;
m_bare_type_info = ti.m_bare_type_info;
m_is_unknown = ti.m_is_unknown;
m_is_undef = ti.m_is_undef;
return *this;
}
@@ -86,7 +86,18 @@ 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_unknown() const { return m_is_unknown || m_bare_type_info == 0; }
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; }
bool is_pointer() const { return m_is_pointer; }
std::string name() const
{
if (m_type_info)
{
return m_type_info->name();
} else {
return "";
}
}
std::string bare_name() const
{
@@ -105,7 +116,7 @@ namespace chaiscript
bool m_is_void;
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_unknown;
bool m_is_undef;
};
namespace detail

View File

@@ -22,9 +22,10 @@ namespace chaiscript
* Types of AST nodes available to the parser and eval
*/
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Expression, Comparison, Additive, Multiplicative, Negate, Not, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Comparison, Additive, Multiplicative, 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 }; };
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or}; };
namespace
{
@@ -33,9 +34,10 @@ namespace chaiscript
*/
const char *token_type_to_string(int tokentype) {
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
"Comparison", "Additive", "Multiplicative", "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"};
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
"Logical_And", "Logical_Or"};
return token_types[tokentype];
}

View File

@@ -78,17 +78,14 @@ namespace chaiscript
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
ModulePtr get()
{
return m_func.m_symbol();
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
@@ -188,17 +185,14 @@ namespace chaiscript
};
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
m_moduleptr(m_func.m_symbol())
{
}
ModulePtr get()
{
return m_func.m_symbol();
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
@@ -229,6 +223,7 @@ namespace chaiscript
std::set<std::string> loaded_files;
std::map<std::string, Loadable_Module_Ptr> loaded_modules;
std::set<std::string> active_loaded_modules;
Eval_Engine engine;
@@ -333,12 +328,53 @@ namespace chaiscript
/**
* Adds a shared object, that can be used by all threads, to the system
*/
ChaiScript_System &add_shared_object(const Boxed_Value &bv, const std::string &name)
ChaiScript_System &add_global_const(const Boxed_Value &bv, const std::string &name)
{
engine.add_shared_object(bv, name);
engine.add_global_const(bv, name);
return *this;
}
struct State
{
std::set<std::string> loaded_files;
typename Eval_Engine::State engine_state;
std::set<std::string> active_loaded_modules;
};
/**
* Returns a state object that represents the current
* set of loaded files, the set of global variables and
* the set of initialized functions
*/
State get_state()
{
#ifndef CHAISCRIPT_NO_THREADS
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
boost::shared_lock<boost::shared_mutex> l2(mutex);
#endif
State s;
s.loaded_files = loaded_files;
s.engine_state = engine.get_state();
s.active_loaded_modules = active_loaded_modules;
return s;
}
/**
* Restores the state from a saved State object.
*/
void set_state(const State &t_state)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
boost::shared_lock<boost::shared_mutex> l2(mutex);
#endif
loaded_files = t_state.loaded_files;
active_loaded_modules = t_state.active_loaded_modules;
engine.set_state(t_state.engine_state);
}
/**
* Adds an object to the system: type, function, object
*/
@@ -402,7 +438,11 @@ namespace chaiscript
{
Loadable_Module_Ptr lm(new Loadable_Module(t_module_name, t_filename));
loaded_modules[t_module_name] = lm;
add(lm->get());
active_loaded_modules.insert(t_module_name);
add(lm->m_moduleptr);
} else if (active_loaded_modules.count(t_module_name) == 0) {
active_loaded_modules.insert(t_module_name);
add(loaded_modules[t_module_name]->m_moduleptr);
} else {
engine.sync_cache();
}
@@ -499,6 +539,8 @@ namespace chaiscript
engine.add(fun(&Eval_Engine::type_name, boost::ref(engine)), "type_name");
engine.add(fun(&Eval_Engine::function_exists, boost::ref(engine)), "function_exists");
engine.add(fun(&Eval_Engine::get_type_name, boost::ref(engine)), "name");
typedef void (ChaiScript_System<Eval_Engine>::*load_mod_1)(const std::string&);
typedef void (ChaiScript_System<Eval_Engine>::*load_mod_2)(const std::string&, const std::string&);

View File

@@ -42,12 +42,15 @@ namespace chaiscript
*/
template <typename Eval_System>
Boxed_Value eval_file(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
unsigned int i;
for (i = 0; i < node->children.size(); ++i) {
retval = eval_token(ss, node->children[i]);
const unsigned int size = node->children.size();
for (unsigned int i = 0; i < size; ++i) {
const Boxed_Value &retval = eval_token(ss, node->children[i]);
if (i + 1 == size)
{
return retval;
}
}
return retval;
return Boxed_Value();
}
template <typename Eval_System>
@@ -171,18 +174,16 @@ namespace chaiscript
Boxed_Value lhs = eval_token(ss, node->children[i]);
try {
if (lhs.is_unknown())
if (lhs.is_undef())
{
retval = ss.call_function("clone", Param_List_Builder() << retval);
retval = ss.call_function("clone", retval);
}
Param_List_Builder plb;
plb << lhs;
plb << retval;
try {
retval = ss.call_function(node->children[i+1]->text, plb);
retval = ss.call_function(node->children[i+1]->text, lhs, retval);
}
catch(const dispatch_error &){
throw Eval_Error("Mismatched types in equation", node->children[i+1]);
throw Eval_Error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."), node->children[i+1]);
}
}
catch(const dispatch_error &){
@@ -191,7 +192,7 @@ namespace chaiscript
}
else if (node->children[i+1]->text == ":=") {
Boxed_Value lhs = eval_token(ss, node->children[i]);
if (lhs.is_unknown() || type_match(lhs, retval)) {
if (lhs.is_undef() || type_match(lhs, retval)) {
lhs.assign(retval);
}
else {
@@ -199,11 +200,8 @@ namespace chaiscript
}
}
else {
Param_List_Builder plb;
plb << eval_token(ss, node->children[i]);
plb << retval;
try {
retval = ss.call_function(node->children[i+1]->text, plb);
retval = ss.call_function(node->children[i+1]->text, eval_token(ss, node->children[i]), retval);
}
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
@@ -248,15 +246,15 @@ namespace chaiscript
* Evaluates binary boolean operators. Respects short-circuiting rules.
*/
template <typename Eval_System>
Boxed_Value eval_expression(Eval_System &ss, const TokenPtr &node) {
Boxed_Value eval_logical(Eval_System &ss, const TokenPtr &node) {
unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
Boxed_Value retval(eval_token(ss, node->children[0]));
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); i += 2) {
bool lhs;
try {
lhs = boxed_cast<bool &>(retval);
lhs = boxed_cast<bool>(retval);
}
catch (const bad_boxed_cast &) {
throw Eval_Error("Condition not boolean", node);
@@ -290,18 +288,12 @@ namespace chaiscript
unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); i += 2) {
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i + 1]);
try {
retval = ss.call_function(node->children[i]->text, plb);
}
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
}
for (i = 1; i < node->children.size(); i += 2) {
try {
retval = ss.call_function(node->children[i]->text, retval, eval_token(ss, node->children[i + 1]));
}
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
}
}
@@ -317,11 +309,8 @@ namespace chaiscript
Boxed_Value retval = eval_token(ss, node->children[0]);
for (i = 1; i < node->children.size(); ++i) {
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i]);
try {
retval = ss.call_function("[]", plb);
retval = ss.call_function("[]", retval, eval_token(ss, node->children[i]));
}
catch(std::out_of_range &) {
throw Eval_Error("Out of bounds exception", node);
@@ -334,50 +323,16 @@ namespace chaiscript
return retval;
}
/**
* Evaluates a unary negation
*/
template <typename Eval_System>
Boxed_Value eval_negate(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval = eval_token(ss, node->children[0]);
Param_List_Builder plb;
plb << retval;
plb << Boxed_Value(-1.0);
try {
return ss.call_function("*", plb);
}
catch(std::exception &){
throw Eval_Error("Can not find appropriate negation", node->children[0]);
}
}
/**
* Evaluates a unary boolean not
*/
template <typename Eval_System>
Boxed_Value eval_not(Eval_System &ss, const TokenPtr &node) {
try {
return Boxed_Value(!boxed_cast<bool>(eval_token(ss, node->children[0])));
}
catch (const bad_boxed_cast &) {
throw Eval_Error("Boolean not('!') condition not boolean", node->children[0]);
}
}
/**
* Evaluates any unary prefix
*/
template <typename Eval_System>
Boxed_Value eval_prefix(Eval_System &ss, const TokenPtr &node) {
Param_List_Builder plb;
plb << eval_token(ss, node->children[1]);
try {
return ss.call_function(node->children[0]->text, plb);
return ss.call_function(node->children[0]->text, eval_token(ss, node->children[1]));
}
catch(std::exception &){
throw Eval_Error("Can not find appropriate prefix", node->children[0]);
throw Eval_Error("Can not find appropriate unary '" + node->children[0]->text + "'", node->children[0]);
}
}
@@ -389,16 +344,13 @@ namespace chaiscript
unsigned int i;
try {
Boxed_Value retval = ss.call_function("Vector", Param_List_Builder());
if (node->children.size() > 0) {
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
ss.call_function("push_back", Param_List_Builder() << retval << tmp);
}
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
}
Boxed_Value retval = ss.call_function("Vector");
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
ss.call_function("push_back", retval, eval_token(ss, node->children[0]->children[i]));
}
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
}
}
@@ -416,9 +368,9 @@ namespace chaiscript
template <typename Eval_System>
Boxed_Value eval_inline_range(Eval_System &ss, const TokenPtr &node) {
try {
return ss.call_function("generate_range", Param_List_Builder()
<< eval_token(ss, node->children[0]->children[0]->children[0])
<< eval_token(ss, node->children[0]->children[0]->children[1]));
return ss.call_function("generate_range",
eval_token(ss, node->children[0]->children[0]->children[0]),
eval_token(ss, node->children[0]->children[0]->children[1]));
}
catch (const dispatch_error &) {
throw Eval_Error("Unable to generate range vector", node);
@@ -433,12 +385,12 @@ namespace chaiscript
unsigned int i;
try {
Boxed_Value retval = ss.call_function("Map", Param_List_Builder());
Boxed_Value retval = ss.call_function("Map");
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
Boxed_Value slot = ss.call_function("[]", Param_List_Builder() << retval << key);
ss.call_function("=", Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
Boxed_Value slot
= ss.call_function("[]", retval, eval_token(ss, node->children[0]->children[i]->children[0]));
ss.call_function("=", slot, eval_token(ss, node->children[0]->children[i]->children[1]));
}
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]);
@@ -472,7 +424,7 @@ namespace chaiscript
try {
ss.set_stack(new_stack);
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
const Boxed_Value &retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
ss.set_stack(prev_stack);
return retval;
}
@@ -514,8 +466,7 @@ namespace chaiscript
Boxed_Value fn = eval_token(ss, node->children[0]);
try {
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb);
return retval;
return (*boxed_cast<Const_Proxy_Function >(fn))(plb);
}
catch(const dispatch_error &e){
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
@@ -544,9 +495,9 @@ namespace chaiscript
//todo: Please extract a single way of doing function calls between this and eval_fun_call
Boxed_Value retval = eval_token(ss, node->children[0]);
Boxed_Value retval(eval_token(ss, node->children[0]));
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); ++i) {
for (i = 2; i < node->children.size(); i+=2) {
Param_List_Builder plb;
plb << retval;
@@ -601,7 +552,6 @@ namespace chaiscript
template <typename Eval_System>
Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
retval = Boxed_Value();
ss.new_scope();
try {
@@ -714,6 +664,7 @@ namespace chaiscript
ss.pop_scope();
throw;
}
if (node->children.back()->identifier == Token_Type::Finally) {
retval = eval_token(ss, node->children.back()->children[0]);
}
@@ -730,35 +681,32 @@ namespace chaiscript
Boxed_Value eval_if(Eval_System &ss, const TokenPtr &node) {
unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
bool cond;
try {
cond = boxed_cast<bool>(retval);
cond = boxed_cast<bool>(eval_token(ss, node->children[0]));
}
catch (const bad_boxed_cast &) {
throw Eval_Error("If condition not boolean", node->children[0]);
}
if (cond) {
retval = eval_token(ss, node->children[1]);
return eval_token(ss, node->children[1]);
}
else {
if (node->children.size() > 2) {
i = 2;
while ((!cond) && (i < node->children.size())) {
if (node->children[i]->text == "else") {
retval = eval_token(ss, node->children[i+1]);
cond = true;
return eval_token(ss, node->children[i+1]);
}
else if (node->children[i]->text == "else if") {
retval = eval_token(ss, node->children[i+1]);
try {
cond = boxed_cast<bool>(retval);
cond = boxed_cast<bool>(eval_token(ss, node->children[i+1]));
}
catch (const bad_boxed_cast &) {
throw Eval_Error("'else if' condition not boolean", node->children[i+1]);
}
if (cond) {
retval = eval_token(ss, node->children[i+2]);
return eval_token(ss, node->children[i+2]);
}
}
i = i + 3;
@@ -766,7 +714,7 @@ namespace chaiscript
}
}
return retval;
return Boxed_Value(false);
}
/**
@@ -1011,17 +959,22 @@ namespace chaiscript
*/
template <typename Eval_System>
Boxed_Value eval_block(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
unsigned int i;
unsigned int num_children = node->children.size();
ss.new_scope();
for (i = 0; i < node->children.size(); ++i) {
for (i = 0; i < num_children; ++i) {
try {
retval = eval_token(ss, node->children[i]);
const Boxed_Value &retval = eval_token(ss, node->children[i]);
if (i + 1 == num_children)
{
ss.pop_scope();
return retval;
}
}
catch (const chaiscript::Return_Value &rv) {
catch (const chaiscript::Return_Value &/*rv*/) {
ss.pop_scope();
retval = rv.retval;
throw;
}
catch (...) {
@@ -1029,9 +982,9 @@ namespace chaiscript
throw;
}
}
ss.pop_scope();
return retval;
ss.pop_scope();
return Boxed_Value();
}
/**
@@ -1093,11 +1046,16 @@ namespace chaiscript
return eval_var_decl(ss, node);
break;
case (Token_Type::Expression) :
return eval_expression(ss, node);
case (Token_Type::Logical_And) :
case (Token_Type::Logical_Or) :
return eval_logical(ss, node);
break;
case (Token_Type::Bitwise_And) :
case (Token_Type::Bitwise_Xor) :
case (Token_Type::Bitwise_Or) :
case (Token_Type::Comparison) :
case (Token_Type::Equality) :
case (Token_Type::Additive) :
case (Token_Type::Multiplicative) :
case (Token_Type::Shift) :
@@ -1108,14 +1066,6 @@ namespace chaiscript
return eval_array_call(ss, node);
break;
case (Token_Type::Negate) :
return eval_negate(ss, node);
break;
case (Token_Type::Not) :
return eval_not(ss, node);
break;
case (Token_Type::Prefix) :
return eval_prefix(ss, node);
break;

View File

@@ -7,11 +7,14 @@
#ifndef CHAISCRIPT_PARSER_HPP_
#define CHAISCRIPT_PARSER_HPP_
#include <boost/assign/std/vector.hpp>
#include <exception>
#include <fstream>
#include <sstream>
#include "chaiscript_prelude.hpp"
#include "chaiscript_common.hpp"
namespace chaiscript
{
@@ -24,16 +27,79 @@ namespace chaiscript
const char *filename;
std::vector<TokenPtr> match_stack;
std::vector<std::vector<std::string> > operator_matches;
std::vector<Token_Type::Type> operators;
public:
ChaiScript_Parser() {
ChaiScript_Parser() {
multiline_comment_begin = "/*";
multiline_comment_end = "*/";
singleline_comment = "//";
setup_operators();
}
ChaiScript_Parser(const ChaiScript_Parser &); // explicitly unimplemented copy constructor
ChaiScript_Parser &operator=(const ChaiScript_Parser &); // explicitly unimplemented assignment operator
void setup_operators() {
using namespace boost::assign;
operators.push_back(Token_Type::Logical_Or);
std::vector<std::string> logical_or;
logical_or += "||";
operator_matches.push_back(logical_or);
operators.push_back(Token_Type::Logical_And);
std::vector<std::string> logical_and;
logical_and += "&&";
operator_matches.push_back(logical_and);
operators.push_back(Token_Type::Bitwise_Or);
std::vector<std::string> bitwise_or;
bitwise_or += "|";
operator_matches.push_back(bitwise_or);
operators.push_back(Token_Type::Bitwise_Xor);
std::vector<std::string> bitwise_xor;
bitwise_xor += "^";
operator_matches.push_back(bitwise_xor);
operators.push_back(Token_Type::Bitwise_And);
std::vector<std::string> bitwise_and;
bitwise_and += "&";
operator_matches.push_back(bitwise_and);
operators.push_back(Token_Type::Equality);
std::vector<std::string> equality;
equality += "==", "!=";
operator_matches.push_back(equality);
operators.push_back(Token_Type::Comparison);
std::vector<std::string> comparison;
comparison += "<", "<=", ">", ">=";
operator_matches.push_back(comparison);
operators.push_back(Token_Type::Shift);
std::vector<std::string> shift;
shift += "<<", ">>";
operator_matches.push_back(shift);
operators.push_back(Token_Type::Additive);
std::vector<std::string> additive;
additive += "+", "-";
operator_matches.push_back(additive);
operators.push_back(Token_Type::Multiplicative);
std::vector<std::string> multiplicative;
multiplicative += "*", "/", "%";
operator_matches.push_back(multiplicative);
operators.push_back(Token_Type::Dot_Access);
std::vector<std::string> dot_access;
dot_access += ".";
operator_matches.push_back(dot_access);
}
/**
* Prints the parsed tokens as a tree
*/
@@ -105,7 +171,9 @@ namespace chaiscript
}
else if (Symbol_(singleline_comment.c_str())) {
while (input_pos != input_end) {
if (Eol_()) {
if (Symbol_("\r\n") || Char_('\n')) {
++line;
col = 1;
break;
}
else {
@@ -797,7 +865,8 @@ namespace chaiscript
bool retval = Symbol_(s);
if (retval) {
//todo: fix this. Hacky workaround for preventing substring matches
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '=') || (*input_pos == '.'))) {
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/')
|| (*input_pos == '|') || (*input_pos == '&') || (*input_pos == '^') || (*input_pos == '=') || (*input_pos == '.') || (*input_pos == '<') || (*input_pos == '>'))) {
input_pos = start;
col = prev_col;
line = prev_line;
@@ -815,7 +884,8 @@ namespace chaiscript
int prev_line = line;
if (Symbol_(s)) {
//todo: fix this. Hacky workaround for preventing substring matches
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '=') || (*input_pos == '.'))) {
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/')
|| (*input_pos == '|') || (*input_pos == '&') || (*input_pos == '^') || (*input_pos == '=') || (*input_pos == '.') || (*input_pos == '<') || (*input_pos == '>'))) {
input_pos = start;
col = prev_col;
line = prev_line;
@@ -1006,7 +1076,7 @@ namespace chaiscript
while (Eol());
if (Char(':')) {
if (!Expression()) {
if (!Operator()) {
throw Eval_Error("Missing guard expression for function", File_Position(line, col), filename);
}
}
@@ -1059,7 +1129,7 @@ namespace chaiscript
throw Eval_Error("Incomplete 'catch' expression", File_Position(line, col), filename);
}
if (Char(':')) {
if (!Expression()) {
if (!Operator()) {
throw Eval_Error("Missing guard expression for catch", File_Position(line, col), filename);
}
}
@@ -1107,7 +1177,7 @@ namespace chaiscript
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
if (!(Operator() && Char(')'))) {
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
}
@@ -1128,7 +1198,7 @@ namespace chaiscript
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
if (!(Operator() && Char(')'))) {
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
}
@@ -1171,7 +1241,7 @@ namespace chaiscript
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
if (!(Operator() && Char(')'))) {
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
}
@@ -1193,7 +1263,7 @@ namespace chaiscript
bool For_Guards() {
Equation();
if (Char(';') && Expression() && Char(';') && Equation()) {
if (Char(';') && Operator() && Char(';') && Equation()) {
return true;
}
else {
@@ -1265,7 +1335,7 @@ namespace chaiscript
if (Keyword("return")) {
retval = true;
Expression();
Operator();
build_match(Token_Type::Return, prev_stack_top);
}
@@ -1317,7 +1387,7 @@ namespace chaiscript
else if (Char('[')) {
has_more = true;
if (!(Expression() && Char(']'))) {
if (!(Operator() && Char(']'))) {
throw Eval_Error("Incomplete array access", File_Position(line, col), filename);
}
@@ -1374,7 +1444,7 @@ namespace chaiscript
if (Char('(')) {
retval = true;
if (!Expression()) {
if (!Operator()) {
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
}
if (!Char(')')) {
@@ -1428,7 +1498,7 @@ namespace chaiscript
if (Symbol("++", true)) {
retval = true;
if (!Dot_Access()) {
if (!Operator(operators.size()-1)) {
throw Eval_Error("Incomplete '++' expression", File_Position(line, col), filename);
}
@@ -1437,29 +1507,47 @@ namespace chaiscript
else if (Symbol("--", true)) {
retval = true;
if (!Dot_Access()) {
if (!Operator(operators.size()-1)) {
throw Eval_Error("Incomplete '--' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Prefix, prev_stack_top);
}
else if (Char('-')) {
else if (Char('-', true)) {
retval = true;
if (!Dot_Access()) {
throw Eval_Error("Incomplete negation expression", File_Position(line, col), filename);
if (!Operator(operators.size()-1)) {
throw Eval_Error("Incomplete unary '-' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Negate, prev_stack_top);
build_match(Token_Type::Prefix, prev_stack_top);
}
else if (Char('!')) {
else if (Char('+', true)) {
retval = true;
if (!Dot_Access()) {
if (!Operator(operators.size()-1)) {
throw Eval_Error("Incomplete unary '+' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Prefix, prev_stack_top);
}
else if (Char('!', true)) {
retval = true;
if (!Operator(operators.size()-1)) {
throw Eval_Error("Incomplete '!' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Not, prev_stack_top);
build_match(Token_Type::Prefix, prev_stack_top);
}
else if (Char('~', true)) {
retval = true;
if (!Operator(operators.size()-1)) {
throw Eval_Error("Incomplete '~' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Prefix, prev_stack_top);
}
return retval;
@@ -1477,146 +1565,38 @@ namespace chaiscript
return false;
}
}
/**
* Reads a string of binary comparisons from input
*/
bool Comparison() {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Shift()) {
retval = true;
if (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)) {
do {
if (!Shift()) {
throw Eval_Error("Incomplete comparison expression", File_Position(line, col), filename);
}
} while (retval && (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)));
build_match(Token_Type::Comparison, prev_stack_top);
bool Operator_Helper(int precedence) {
for (unsigned int i = 0; i < operator_matches[precedence].size(); ++i) {
if (Symbol(operator_matches[precedence][i].c_str(), true)) {
return true;
}
}
return retval;
return false;
}
/**
* Reads a string of binary additions/subtractions from input
*/
bool Additive() {
bool Operator(unsigned int precedence = 0) {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Multiplicative()) {
retval = true;
if (Symbol("+", true) || Symbol("-", true)) {
do {
if (!Multiplicative()) {
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("+", true) || Symbol("-", true)));
if (precedence < operators.size()) {
if (Operator(precedence+1)) {
retval = true;
if (Operator_Helper(precedence)) {
do {
if (!Operator(precedence+1)) {
throw Eval_Error("Incomplete " + std::string(token_type_to_string(operators[precedence])) + " expression",
File_Position(line, col), filename);
}
} while (Operator_Helper(precedence));
build_match(Token_Type::Additive, prev_stack_top);
build_match(operators[precedence], prev_stack_top);
}
}
}
return retval;
}
/**
* Reads a string of multiplication/division/modulus from input
*/
bool Multiplicative() {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Dot_Access()) {
retval = true;
if (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)) {
do {
if (!Dot_Access()) {
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)));
build_match(Token_Type::Multiplicative, prev_stack_top);
}
}
return retval;
}
/**
* Reads a string of dot-notation accesses from input
*/
bool Dot_Access() {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Value()) {
retval = true;
if (Symbol(".")) {
do {
if (!Value()) {
throw Eval_Error("Incomplete dot notation", File_Position(line, col), filename);
}
} while (retval && Symbol("."));
build_match(Token_Type::Dot_Access, prev_stack_top);
}
}
return retval;
}
/**
* Top-level expression, parses a string of binary boolean operators from input
*/
bool Shift() {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Additive()) {
retval = true;
if (Symbol("<<", true) || Symbol(">>", true)) {
do {
if (!Additive()) {
throw Eval_Error("Incomplete shift expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("<<", true) || Symbol(">>", true)));
build_match(Token_Type::Shift, prev_stack_top);
}
}
return retval;
}
/**
* Top-level expression, parses a string of binary boolean operators from input
*/
bool Expression() {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Comparison()) {
retval = true;
if (Symbol("&&", true) || Symbol("||", true)) {
do {
if (!Comparison()) {
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("&&", true) || Symbol("||", true)));
build_match(Token_Type::Expression, prev_stack_top);
}
else {
return Value();
}
return retval;
@@ -1630,11 +1610,11 @@ namespace chaiscript
int prev_stack_top = match_stack.size();
if (Expression()) {
if (Operator()) {
retval = true;
if (Symbol(":")) {
do {
if (!Expression()) {
if (!Operator()) {
throw Eval_Error("Incomplete map pair", File_Position(line, col), filename);
}
} while (retval && Symbol(":"));
@@ -1656,10 +1636,10 @@ namespace chaiscript
std::string::iterator prev_pos = input_pos;
int prev_col = col;
if (Expression()) {
if (Operator()) {
if (Symbol("..")) {
retval = true;
if (!Expression()) {
if (!Operator()) {
throw Eval_Error("Incomplete value range", File_Position(line, col), filename);
}
@@ -1685,10 +1665,12 @@ namespace chaiscript
int prev_stack_top = match_stack.size();
if (Expression()) {
if (Operator()) {
retval = true;
if (Symbol("=", true, true) || Symbol(":=", true, true) || Symbol("+=", true, true) ||
Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true)) {
Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true) ||
Symbol("%=", true, true) || Symbol("<<=", true, true) || Symbol(">>=", true, true) ||
Symbol("&=", true, true) || Symbol("^=", true, true) || Symbol("|=", true, true)) {
if (!Equation()) {
throw Eval_Error("Incomplete equation", match_stack.back());
}

View File

@@ -282,27 +282,27 @@ def zip(x, y) { \n\
}\n\
# Returns the position of the second value string in the first value string\n\
def string::find(substr) : is_type(substr, "string") { \n\
int(find(this, substr, size_t(0))); \n\
int(find(this, substr, 0)); \n\
} \n\
# Returns the position of last match of the second value string in the first value string\n\
def string::rfind(substr) : is_type(substr, "string") { \n\
int(rfind(this, substr, size_t(-1))); \n\
int(rfind(this, substr, -1)); \n\
} \n\
# Returns the position of the first match of elements in the second value string in the first value string\n\
def string::find_first_of(list) : is_type(list, "string") { \n\
int(find_first_of(this, list, size_t(0))); \n\
int(find_first_of(this, list, 0)); \n\
} \n\
# Returns the position of the last match of elements in the second value string in the first value string\n\
def string::find_last_of(list) : is_type(list, "string") { \n\
int(find_last_of(this, list, size_t(-1))); \n\
int(find_last_of(this, list, -1)); \n\
} \n\
# Returns the position of the first non-matching element in the second value string in the first value string\n\
def string::find_first_not_of(list) : is_type(list, "string") { \n\
int(find_first_not_of(this, list, size_t(0))); \n\
int(find_first_not_of(this, list, 0)); \n\
} \n\
# Returns the position of the last non-matching element in the second value string in the first value string\n\
def string::find_last_not_of(list) : is_type(list, "string") { \n\
int(find_last_not_of(this, list, size_t(-1))); \n\
int(find_last_not_of(this, list, -1)); \n\
} \n\
def string::ltrim() { \n\
drop_while(this, fun(x) { x == ' ' || x == '\t' }); \n\

View File

@@ -14,6 +14,6 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories="C:\Boost\lib"
AdditionalLibraryDirectories="C:\Boost\lib;C:\Programming\Boost\lib"
/>
</VisualStudioPropertySheet>

View File

@@ -189,6 +189,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bind_first.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\bootstrap.hpp"
>
@@ -245,6 +249,10 @@
RelativePath="..\..\include\chaiscript\dispatchkit\handle_return.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\operators.hpp"
>
</File>
<File
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
>

View File

@@ -1,3 +1,2 @@
var i = 1
var j = eval("5 + 4")
print(j)

View File

@@ -2,11 +2,11 @@ for (var i = 0; i < 10; ++i) {
print(i)
}
for (i = 10; i >= 0; i -= 2) {
for (var i = 10; i >= 0; i -= 2) {
print(i)
}
i = 0
var i = 0
for (; i < 5; ++i) {
print(i)

View File

@@ -110,7 +110,7 @@ int main(int argc, char *argv[]) {
//Finally, it is possible to register any boost::function as a system function, in this
//way, we can, for instance add a bound member function to the system
chai.add(fun(&System::do_callbacks, boost::ref(system), "Bound Test"), "do_callbacks");
chai.add(fun(&System::do_callbacks, boost::ref(system), std::string("Bound Test")), "do_callbacks");
//Call bound version of do_callbacks
chai("do_callbacks()");
@@ -143,6 +143,14 @@ int main(int argc, char *argv[]) {
log("Functor test output", boost::lexical_cast<std::string>(x));
chai.add(var(boost::shared_ptr<int>()), "nullvar");
chai("print(\"This should be true.\"); print(nullvar.is_null())");
// test the global const action
chai.add_global_const(const_var(1), "constvar");
chai("def getvar() { return constvar; }");
chai("print( getvar() )");
//Ability to create our own container types when needed. std::vector and std::map are
//mostly supported currently

View File

@@ -0,0 +1,7 @@
print(1.is_var_const());
print(1.is_var_reference());
print(1.is_var_pointer());
print(1.is_var_null());
print(1.is_var_undef());
var i;
print(i.is_var_undef());

View File

@@ -0,0 +1,6 @@
true
false
true
false
false
true

View File

@@ -1 +1 @@
Error: "Mismatched types in equation" in 'unittests/invalid_function_assignment.chai' at (1, 7)
Error: "Mismatched types in equation, lhs is const." in 'unittests/invalid_function_assignment.chai' at (1, 7)

View File

@@ -1 +1 @@
Error: "Mismatched types in equation" in 'unittests/invalid_function_reassignment.chai' at (2, 3)
Error: "Mismatched types in equation." in 'unittests/invalid_function_reassignment.chai' at (2, 3)

4
unittests/is_undef.chai Normal file
View File

@@ -0,0 +1,4 @@
var i;
print(i.is_var_undef());
i = 5;
print(i.is_var_undef());

2
unittests/is_undef.txt Normal file
View File

@@ -0,0 +1,2 @@
true
false

View File

@@ -0,0 +1,15 @@
var i = 1.0;
var j = 2.0;
var k = 3.0;
print(i + j);
print(+i);
print(i - j);
print(-i);
print(k / j);
print(j * k);
print(i -= 1);
print(j *= 1.5);
print(j /= 2);
print(j += 1);

View File

@@ -0,0 +1,10 @@
3
1
-1
-1
1.5
6
0
3
1.5
2.5

View File

@@ -0,0 +1,32 @@
var i = 1;
var j = 2;
var k = 3;
print(i + j);
print(+i);
print(i - j);
print(-i);
print(j & k);
print(~j);
print(j ^ k);
print(i | j);
print(j / i);
print(i << j);
print(j * k);
print(k % j);
print(j >> i);
print(i &= 2);
print(j ^= 3);
print(j |= 2);
print(i -= 1);
print(j <<= 1);
print(j *= 2);
print(j /= 2);
print(j %= 4);
print(j >>= 1);
print(j += 1);
print(--j);
print(++j);

View File

@@ -0,0 +1,25 @@
3
1
-1
-1
2
-3
1
3
2
4
6
1
1
0
1
3
-1
6
12
6
2
1
2
1
2

10
unittests/type_info.chai Normal file
View File

@@ -0,0 +1,10 @@
print(string_type.name());
print(string_type.is_type_const());
print(string_type.is_type_reference());
print(string_type.is_type_void());
print(string_type.is_type_undef());
print(string_type.is_type_pointer());
print("string".get_type_info().name());
print(string_type.bare_equal("string".get_type_info()));
print("bob".is_type(string_type));

9
unittests/type_info.txt Normal file
View File

@@ -0,0 +1,9 @@
string
false
false
false
false
false
string
true
true