Compare commits
45 Commits
v1.0.0
...
Release-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3a951cea99 | ||
![]() |
8620f4eaf9 | ||
![]() |
59ecf32f9b | ||
![]() |
541e453098 | ||
![]() |
0b780593a6 | ||
![]() |
2e7c5f413e | ||
![]() |
7e5b7cbd7a | ||
![]() |
c539e0b458 | ||
![]() |
1f011f3d5b | ||
![]() |
a136236179 | ||
![]() |
8840f06053 | ||
![]() |
00e4de774f | ||
![]() |
bc3a17b3b7 | ||
![]() |
4a57efde25 | ||
![]() |
cf94817869 | ||
![]() |
6775863415 | ||
![]() |
a3d4b6698a | ||
![]() |
0ff107a818 | ||
![]() |
ba6b392174 | ||
![]() |
5b424be4ed | ||
![]() |
669d6e9495 | ||
![]() |
9f614bba33 | ||
![]() |
0b789004e9 | ||
![]() |
0d3c90a245 | ||
![]() |
2f591a25a6 | ||
![]() |
4127a6ed41 | ||
![]() |
4e412c0f6a | ||
![]() |
370121a9ff | ||
![]() |
00ac8113c0 | ||
![]() |
72b6647718 | ||
![]() |
daacbaa9e0 | ||
![]() |
a5a1e3ee1b | ||
![]() |
5a5b2929b0 | ||
![]() |
82bd46bb1a | ||
![]() |
4d4c26bf73 | ||
![]() |
ac817ff33a | ||
![]() |
689143aba5 | ||
![]() |
9b733b2621 | ||
![]() |
727dc7b0d6 | ||
![]() |
3fc5f8e8e1 | ||
![]() |
aed493322b | ||
![]() |
8dbb43f45f | ||
![]() |
ec2f81c674 | ||
![]() |
724ffdcb20 | ||
![]() |
7c7e437b10 |
@@ -19,5 +19,7 @@ if (Boost_FOUND)
|
|||||||
#add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp)
|
#add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp)
|
||||||
target_link_libraries(chaiscript_eval ${Boost_LIBRARIES})
|
target_link_libraries(chaiscript_eval ${Boost_LIBRARIES})
|
||||||
install(TARGETS chaiscript_eval DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/bin)
|
install(TARGETS chaiscript_eval DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/bin)
|
||||||
|
else(Boost_FOUND)
|
||||||
|
message(FATAL_ERROR "Can not find Boost")
|
||||||
endif(Boost_FOUND)
|
endif(Boost_FOUND)
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
#include "dispatchkit/dispatchkit.hpp"
|
#include "dispatchkit/dispatchkit.hpp"
|
||||||
#include "dispatchkit/bootstrap.hpp"
|
#include "dispatchkit/bootstrap.hpp"
|
||||||
#include "dispatchkit/bootstrap_stl.hpp"
|
#include "dispatchkit/bootstrap_stl.hpp"
|
||||||
|
#include "dispatchkit/function_call.hpp"
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -83,40 +83,29 @@ namespace chaiscript
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Errors generated inside the parser
|
* Errors generated during parsing or evaluation
|
||||||
*/
|
|
||||||
struct Parse_Error : public std::runtime_error {
|
|
||||||
std::string reason;
|
|
||||||
File_Position position;
|
|
||||||
const char *filename;
|
|
||||||
|
|
||||||
Parse_Error(const std::string &why, const File_Position &where, const char *fname) :
|
|
||||||
std::runtime_error("Parse error: \"" + why + "\" in '"
|
|
||||||
+ std::string(fname) + "' at: (" + boost::lexical_cast<std::string>(where.line+1) + ", " +
|
|
||||||
boost::lexical_cast<std::string>(where.column) + ")"),
|
|
||||||
reason(why), position(where), filename(fname)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
Parse_Error(const std::string &why, const TokenPtr &where)
|
|
||||||
: std::runtime_error("Parse error: \"" + why + "\" in '"
|
|
||||||
+ where->filename + "' line: " + boost::lexical_cast<std::string>(where->start.line+1)),
|
|
||||||
reason(why), position(where->start), filename(where->filename) {
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Parse_Error() throw() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Errors generated inside the evaluator
|
|
||||||
*/
|
*/
|
||||||
struct Eval_Error : public std::runtime_error {
|
struct Eval_Error : public std::runtime_error {
|
||||||
std::string reason;
|
std::string reason;
|
||||||
TokenPtr location;
|
File_Position start_position;
|
||||||
|
File_Position end_position;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
Eval_Error(const std::string &why, const TokenPtr where)
|
Eval_Error(const std::string &why, const File_Position &where, const char *fname) :
|
||||||
: std::runtime_error("Eval error: \"" + why + "\" in '"
|
std::runtime_error("Error: \"" + why + "\" " +
|
||||||
+ where->filename + "' line: " + boost::lexical_cast<std::string>(where->start.line+1)),
|
(std::string(fname) != "__EVAL__" ? ("in '" + std::string(fname) + "' ") : "during evaluation ") +
|
||||||
reason(why), location(where) { }
|
+ "at (" + boost::lexical_cast<std::string>(where.line) + ", " +
|
||||||
|
boost::lexical_cast<std::string>(where.column) + ")"),
|
||||||
|
reason(why), start_position(where), end_position(where), filename(fname)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Eval_Error(const std::string &why, const TokenPtr &where)
|
||||||
|
: std::runtime_error("Error: \"" + why + "\" " +
|
||||||
|
(std::string(where->filename) != "__EVAL__" ? ("in '" + std::string(where->filename) + "' ") : "during evaluation ") +
|
||||||
|
"at (" + boost::lexical_cast<std::string>(where->start.line) + ", " +
|
||||||
|
boost::lexical_cast<std::string>(where->start.column) + ")"),
|
||||||
|
reason(why), start_position(where->start), end_position(where->end), filename(where->filename) {
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~Eval_Error() throw() {}
|
virtual ~Eval_Error() throw() {}
|
||||||
};
|
};
|
||||||
@@ -125,10 +114,10 @@ namespace chaiscript
|
|||||||
* Special type for returned values
|
* Special type for returned values
|
||||||
*/
|
*/
|
||||||
struct Return_Value {
|
struct Return_Value {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
TokenPtr location;
|
TokenPtr location;
|
||||||
|
|
||||||
Return_Value(const dispatchkit::Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
|
Return_Value(const Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -10,8 +10,12 @@
|
|||||||
#include "dispatchkit.hpp"
|
#include "dispatchkit.hpp"
|
||||||
#include "register_function.hpp"
|
#include "register_function.hpp"
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
namespace bootstrap
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Set of helper functions for common operators
|
* Set of helper functions for common operators
|
||||||
*/
|
*/
|
||||||
@@ -207,78 +211,86 @@ namespace dispatchkit
|
|||||||
return p1 -= P1(r.i);
|
return p1 -= P1(r.i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "=" for type T
|
* Add canonical form of "=" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_equals(Dispatch_Engine &s)
|
ModulePtr oper_equals(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &equals<const T&, const T&>, "=");
|
m->add(fun(&detail::equals<const T&, const T&>), "=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "+" for type T
|
* Add canonical form of "+" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_add(Dispatch_Engine &s)
|
ModulePtr oper_add(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &add<T, const T&, const T&>, "+");
|
m->add(fun(&detail::add<T, const T&, const T&>), "+");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "+=" for type T
|
* Add canonical form of "+=" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_add_equals(Dispatch_Engine &s)
|
ModulePtr oper_add_equals(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &addsequal<T, T>, "+=");
|
m->add(fun(&detail::addsequal<T, T>), "+=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "-" for type T
|
* Add canonical form of "-" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_subtract(Dispatch_Engine &s)
|
ModulePtr oper_subtract(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &subtract<T, const T&, const T&>, "-");
|
m->add(fun(&detail::subtract<T, const T&, const T&>), "-");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "/" for type T
|
* Add canonical form of "/" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_divide(Dispatch_Engine &s)
|
ModulePtr oper_divide(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, ÷<T, const T&, const T&>, "/");
|
m->add(fun(&detail::divide<T, const T&, const T&>), "/");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "*" for type T
|
* Add canonical form of "*" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_multiply(Dispatch_Engine &s)
|
ModulePtr oper_multiply(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &multiply<T, const T&, const T&>, "*");
|
m->add(fun(&detail::multiply<T, const T&, const T&>), "*");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "!=" for type T
|
* Add canonical form of "!=" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_not_equals(Dispatch_Engine &s)
|
ModulePtr oper_not_equals(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, ¬_equals<const T&, const T&>, "!=");
|
m->add(fun(&detail::not_equals<const T&, const T&>), "!=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add user defined assignment operator for T = U
|
* Add user defined assignment operator for T = U
|
||||||
*/
|
*/
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void add_oper_assign_overload(Dispatch_Engine &s)
|
ModulePtr oper_assign_overload(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &assign<T,U>, "=");
|
m->add(fun(&detail::assign<T,U>), "=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,9 +298,10 @@ namespace dispatchkit
|
|||||||
* Add canonical form of "=" for type T
|
* Add canonical form of "=" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_assign(Dispatch_Engine &s)
|
ModulePtr oper_assign(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &assign<T,T>, "=");
|
m->add(fun(&detail::assign<T,T>), "=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -296,9 +309,10 @@ namespace dispatchkit
|
|||||||
* Add assignment operator for T = POD.
|
* Add assignment operator for T = POD.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_assign_pod(Dispatch_Engine &s)
|
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &assign_pod<T>, "=");
|
m->add(fun(&detail::assign_pod<T>), "=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -306,36 +320,40 @@ namespace dispatchkit
|
|||||||
* Add canonical form of "<" for type T
|
* Add canonical form of "<" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_less_than(Dispatch_Engine &s)
|
ModulePtr oper_less_than(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &less_than<const T&, const T&>, "<");
|
m->add(fun(&detail::less_than<const T&, const T&>), "<");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of ">" for type T
|
* Add canonical form of ">" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_greater_than(Dispatch_Engine &s)
|
ModulePtr oper_greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &greater_than<const T&, const T&>, ">");
|
m->add(fun(&detail::greater_than<const T&, const T&>), ">");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of "<=" for type T
|
* Add canonical form of "<=" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_less_than_equals(Dispatch_Engine &s)
|
ModulePtr oper_less_than_equals(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &less_than_equals<const T&, const T&>, "<=");
|
m->add(fun(&detail::less_than_equals<const T&, const T&>), "<=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical form of ">=" for type T
|
* Add canonical form of ">=" for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_oper_greater_than_equals(Dispatch_Engine &s)
|
ModulePtr oper_greater_than_equals(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &greater_than_equals<const T&, const T&>, ">=");
|
m->add(fun(&detail::greater_than_equals<const T&, const T&>), ">=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,23 +361,25 @@ namespace dispatchkit
|
|||||||
* Examples: T < R, T == R, etc.
|
* Examples: T < R, T == R, etc.
|
||||||
*/
|
*/
|
||||||
template<typename T, typename R>
|
template<typename T, typename R>
|
||||||
void add_opers_comparison_overload(Dispatch_Engine &s)
|
ModulePtr opers_comparison_overload(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &equals<const T&, const R&>, "==");
|
m->add(fun(&detail::equals<const T&, const R&>), "==");
|
||||||
register_function(s, ¬_equals<const T&, const R&>, "!=");
|
m->add(fun(&detail::not_equals<const T&, const R&>), "!=");
|
||||||
register_function(s, &less_than<const T&, const R&>, "<");
|
m->add(fun(&detail::less_than<const T&, const R&>), "<");
|
||||||
register_function(s, &greater_than<const T&, const R&>, ">");
|
m->add(fun(&detail::greater_than<const T&, const R&>), ">");
|
||||||
register_function(s, &less_than_equals<const T&, const R&>, "<=");
|
m->add(fun(&detail::less_than_equals<const T&, const R&>), "<=");
|
||||||
register_function(s, &greater_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
|
* Add canonical forms of all comparison operators for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_opers_comparison(Dispatch_Engine &s)
|
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
add_opers_comparison_overload<T, T>(s);
|
opers_comparison_overload<T, T>(m);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,20 +390,21 @@ namespace dispatchkit
|
|||||||
* T *= R;
|
* T *= R;
|
||||||
*/
|
*/
|
||||||
template<typename Ret, typename T, typename R>
|
template<typename Ret, typename T, typename R>
|
||||||
void add_opers_arithmetic_overload(Dispatch_Engine &s)
|
ModulePtr opers_arithmetic_overload(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &add<Ret, T, R>, "+");
|
m->add(fun(&detail::add<Ret, T, R>), "+");
|
||||||
register_function(s, &subtract<Ret, T, R>, "-");
|
m->add(fun(&detail::subtract<Ret, T, R>), "-");
|
||||||
register_function(s, ÷<Ret, T, R>, "/");
|
m->add(fun(&detail::divide<Ret, T, R>), "/");
|
||||||
register_function(s, &multiply<Ret, T, R>, "*");
|
m->add(fun(&detail::multiply<Ret, T, R>), "*");
|
||||||
register_function(s, ×equal<T, R>, "*=");
|
m->add(fun(&detail::timesequal<T, R>), "*=");
|
||||||
register_function(s, ÷sequal<T, R>, "/=");
|
m->add(fun(&detail::dividesequal<T, R>), "/=");
|
||||||
register_function(s, &subtractsequal<T, R>, "-=");
|
m->add(fun(&detail::subtractsequal<T, R>), "-=");
|
||||||
register_function(s, &addsequal<T, R>, "+=");
|
m->add(fun(&detail::addsequal<T, R>), "+=");
|
||||||
register_function(s, &prefixincrement<T>, "++");
|
m->add(fun(&detail::prefixincrement<T>), "++");
|
||||||
register_function(s, &prefixdecrement<T>, "--");
|
m->add(fun(&detail::prefixdecrement<T>), "--");
|
||||||
register_function(s, &prefixnegate<T>, "-");
|
m->add(fun(&detail::prefixnegate<T>), "-");
|
||||||
register_function(s, &prefixnot<T>, "!");
|
m->add(fun(&detail::prefixnot<T>), "!");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -391,43 +412,44 @@ namespace dispatchkit
|
|||||||
* example: POD *= T, POD /= T
|
* example: POD *= T, POD /= T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_opers_arithmetic_modify_pod(Dispatch_Engine &s)
|
ModulePtr opers_arithmetic_modify_pod(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, ×equal_pod<T>, "*=");
|
m->add(fun(&detail::timesequal_pod<T>), "*=");
|
||||||
register_function(s, ÷sequal_pod<T>, "/=");
|
m->add(fun(&detail::dividesequal_pod<T>), "/=");
|
||||||
register_function(s, &subtractsequal_pod<T>, "-=");
|
m->add(fun(&detail::subtractsequal_pod<T>), "-=");
|
||||||
register_function(s, &addsequal_pod<T>, "+=");
|
m->add(fun(&detail::addsequal_pod<T>), "+=");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a copy constructor for type T, also creates the standard
|
* Add a copy constructor for type T
|
||||||
* function "clone" for the type. "clone" is a synonym for
|
|
||||||
* the copy constructor.
|
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_copy_constructor(Dispatch_Engine &s, const std::string &type)
|
ModulePtr copy_constructor(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
s.register_function(build_constructor<T, const T &>(), type);
|
m->add(constructor<T (const T &)>(), type);
|
||||||
s.register_function(build_constructor<T, const T &>(), "clone");
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add default and copy constructors (including "clone") for type T
|
* Add default and copy constructors for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_basic_constructors(Dispatch_Engine &s, const std::string &type)
|
ModulePtr basic_constructors(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
s.register_function(build_constructor<T>(), type);
|
m->add(constructor<T ()>(), type);
|
||||||
add_copy_constructor<T>(s, type);
|
copy_constructor<T>(type, m);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add POD type constructor for type T. ie: T = type(POD)
|
* Add POD type constructor for type T. ie: T = type(POD)
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_construct_pod(Dispatch_Engine &s, const std::string &type)
|
ModulePtr construct_pod(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &construct_pod<T>, type);
|
m->add(fun(&detail::construct_pod<T>), type);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -435,19 +457,20 @@ namespace dispatchkit
|
|||||||
* T = type(const U &)
|
* T = type(const U &)
|
||||||
*/
|
*/
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
void add_constructor_overload(Dispatch_Engine &s, const std::string &type)
|
ModulePtr constructor_overload(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
s.register_function(build_constructor<T, const U &>(), type);
|
m->add(constructor<T (const U &)>(), type);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add canonical forms of all arithmetic operators for type T
|
* Add canonical forms of all arithmetic operators for type T
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_opers_arithmetic(Dispatch_Engine &s)
|
ModulePtr opers_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
add_opers_arithmetic_overload<T, T, T>(s);
|
opers_arithmetic_overload<T, T, T>(m);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -487,24 +510,25 @@ namespace dispatchkit
|
|||||||
* common conversions
|
* common conversions
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name)
|
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
s.register_type<T>(name);
|
m->add(user_type<T>(), name);
|
||||||
add_basic_constructors<T>(s, name);
|
basic_constructors<T>(name, m);
|
||||||
add_oper_assign<T>(s);
|
oper_assign<T>(m);
|
||||||
add_oper_assign_pod<T>(s);
|
oper_assign_pod<T>(m);
|
||||||
add_construct_pod<T>(s, name);
|
construct_pod<T>(name, m);
|
||||||
add_opers_arithmetic<T>(s);
|
opers_arithmetic<T>(m);
|
||||||
add_opers_arithmetic_modify_pod<T>(s);
|
opers_arithmetic_modify_pod<T>(m);
|
||||||
register_function(s, &to_string<T>, "to_string");
|
m->add(fun(&to_string<T>), "to_string");
|
||||||
register_function(s, &parse_string<T>, "to_" + name);
|
m->add(fun(&parse_string<T>), "to_" + name);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "clone" function for a shared_ptr type. This is used in the case
|
* "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
|
* where you do not want to make a deep copy of an object during cloning
|
||||||
* but want to instead maintain the shared_ptr. It is needed internally
|
* but want to instead maintain the shared_ptr. It is needed internally
|
||||||
* for handling of boost::shared_ptr<Proxy_Function> object (that is,
|
* for handling of Proxy_Function object (that is,
|
||||||
* function variables.
|
* function variables.
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
@@ -530,8 +554,9 @@ namespace dispatchkit
|
|||||||
* Class consisting of only static functions. All default bootstrapping occurs
|
* Class consisting of only static functions. All default bootstrapping occurs
|
||||||
* from this class.
|
* from this class.
|
||||||
*/
|
*/
|
||||||
struct Bootstrap
|
class Bootstrap
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
/**
|
/**
|
||||||
* Function allowing for assignment of an unknown type to any other value
|
* Function allowing for assignment of an unknown type to any other value
|
||||||
*/
|
*/
|
||||||
@@ -558,45 +583,25 @@ namespace dispatchkit
|
|||||||
/**
|
/**
|
||||||
* Add all comparison operators for POD types
|
* Add all comparison operators for POD types
|
||||||
*/
|
*/
|
||||||
static void add_opers_comparison_pod(Dispatch_Engine &s)
|
static void opers_comparison_pod(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &equals<Boxed_POD_Value, Boxed_POD_Value>, "==");
|
m->add(fun(&detail::equals<Boxed_POD_Value, Boxed_POD_Value>), "==");
|
||||||
register_function(s, ¬_equals<Boxed_POD_Value, Boxed_POD_Value>, "!=");
|
m->add(fun(&detail::not_equals<Boxed_POD_Value, Boxed_POD_Value>), "!=");
|
||||||
register_function(s, &less_than<Boxed_POD_Value, Boxed_POD_Value>, "<");
|
m->add(fun(&detail::less_than<Boxed_POD_Value, Boxed_POD_Value>), "<");
|
||||||
register_function(s, &greater_than<Boxed_POD_Value, Boxed_POD_Value>, ">");
|
m->add(fun(&detail::greater_than<Boxed_POD_Value, Boxed_POD_Value>), ">");
|
||||||
register_function(s, &less_than_equals<Boxed_POD_Value, Boxed_POD_Value>, "<=");
|
m->add(fun(&detail::less_than_equals<Boxed_POD_Value, Boxed_POD_Value>), "<=");
|
||||||
register_function(s, &greater_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
|
* Add all arithmetic operators for PODs
|
||||||
*/
|
*/
|
||||||
static void add_opers_arithmetic_pod(Dispatch_Engine &s)
|
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
register_function(s, &add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "+");
|
m->add(fun(&detail::add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
|
||||||
register_function(s, &subtract<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "-");
|
m->add(fun(&detail::subtract<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
|
||||||
register_function(s, ÷<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "/");
|
m->add(fun(&detail::divide<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
|
||||||
register_function(s, &multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>, "*");
|
m->add(fun(&detail::multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the two Boxed_Value's share the same internal type
|
|
||||||
*/
|
|
||||||
static bool type_match(Boxed_Value l, Boxed_Value r)
|
|
||||||
{
|
|
||||||
return l.get_type_info() == r.get_type_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return true if the Boxed_Value matches the registered type by name
|
|
||||||
*/
|
|
||||||
static bool is_type(const Dispatch_Engine &e, const std::string &type_name, Boxed_Value r)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return e.get_type(type_name) == r.get_type_info();
|
|
||||||
} catch (const std::range_error &) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -611,9 +616,9 @@ namespace dispatchkit
|
|||||||
throw arity_error(params.size(), 2);
|
throw arity_error(params.size(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Proxy_Function> f = boxed_cast<boost::shared_ptr<Proxy_Function> >(params[0]);
|
Proxy_Function f = boxed_cast<Proxy_Function >(params[0]);
|
||||||
|
|
||||||
return Boxed_Value(boost::shared_ptr<Proxy_Function>(new Bound_Function(f,
|
return Boxed_Value(Proxy_Function(new Bound_Function(f,
|
||||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,60 +633,66 @@ namespace dispatchkit
|
|||||||
throw arity_error(params.size(), 1);
|
throw arity_error(params.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Proxy_Function> f = boxed_cast<boost::shared_ptr<Proxy_Function> >(params[0]);
|
Proxy_Function f = boxed_cast<Proxy_Function >(params[0]);
|
||||||
|
|
||||||
return Boxed_Value(f->types_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
|
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boost::shared_ptr<Dispatch_Engine> bootstrap2(boost::shared_ptr<Dispatch_Engine> e = boost::shared_ptr<Dispatch_Engine> (new Dispatch_Engine()))
|
||||||
|
{
|
||||||
|
e->add(user_type<void>(), "void");
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* perform all common bootstrap functions for std::string, void and POD types
|
* perform all common bootstrap functions for std::string, void and POD types
|
||||||
*/
|
*/
|
||||||
static void bootstrap(Dispatch_Engine &s)
|
static ModulePtr bootstrap(ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
s.register_type<void>("void");
|
m->add(user_type<void>(), "void");
|
||||||
s.register_type<bool>("bool");
|
m->add(user_type<bool>(), "bool");
|
||||||
s.register_type<Boxed_Value>("Object");
|
m->add(user_type<Boxed_Value>(), "Object");
|
||||||
s.register_type<Boxed_POD_Value>("PODObject");
|
m->add(user_type<Boxed_POD_Value>(), "PODObject");
|
||||||
s.register_type<Proxy_Function>("function");
|
m->add(user_type<Proxy_Function>(), "function");
|
||||||
|
|
||||||
add_basic_constructors<bool>(s, "bool");
|
basic_constructors<bool>("bool", m);
|
||||||
add_oper_assign<std::string>(s);
|
oper_assign<std::string>(m);
|
||||||
add_oper_assign<bool>(s);
|
oper_assign<bool>(m);
|
||||||
|
|
||||||
register_function(s, &to_string<const std::string &>, "internal_to_string");
|
m->add(fun(&to_string<const std::string &>), "internal_to_string");
|
||||||
register_function(s, &to_string<bool>, "internal_to_string");
|
m->add(fun(&to_string<bool>), "internal_to_string");
|
||||||
register_function(s, &unknown_assign, "=");
|
m->add(fun(&unknown_assign), "=");
|
||||||
|
|
||||||
bootstrap_pod_type<double>(s, "double");
|
bootstrap_pod_type<double>("double", m);
|
||||||
bootstrap_pod_type<int>(s, "int");
|
bootstrap_pod_type<int>("int", m);
|
||||||
bootstrap_pod_type<size_t>(s, "size_t");
|
bootstrap_pod_type<size_t>("size_t", m);
|
||||||
bootstrap_pod_type<char>(s, "char");
|
bootstrap_pod_type<char>("char", m);
|
||||||
bootstrap_pod_type<boost::int64_t>(s, "int64_t");
|
bootstrap_pod_type<boost::int64_t>("int64_t", m);
|
||||||
|
|
||||||
add_opers_comparison_pod(s);
|
opers_comparison_pod(m);
|
||||||
add_opers_arithmetic_pod(s);
|
opers_arithmetic_pod(m);
|
||||||
register_function(s, &modulus<int, int, int>, "%");
|
|
||||||
|
|
||||||
register_function(s, &print, "print_string");
|
m->add(fun(&detail::modulus<int, int, int>), "%");
|
||||||
register_function(s, &println, "println_string");
|
|
||||||
|
|
||||||
s.register_function(boost::function<void ()>(boost::bind(&dump_system, boost::ref(s))), "dump_system");
|
m->add(fun(&print), "print_string");
|
||||||
s.register_function(boost::function<void (Boxed_Value)>(boost::bind(&dump_object, _1, boost::ref(s))), "dump_object");
|
m->add(fun(&println), "println_string");
|
||||||
s.register_function(boost::function<bool (Boxed_Value, const std::string &)>(boost::bind(&is_type, boost::ref(s), _2, _1)),
|
|
||||||
"is_type");
|
|
||||||
|
|
||||||
s.register_function(boost::shared_ptr<Proxy_Function>(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
|
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
|
||||||
"bind");
|
"bind");
|
||||||
|
|
||||||
register_function(s, &shared_ptr_clone<Proxy_Function>, "clone");
|
m->add(fun(&shared_ptr_clone<Proxy_Function_Base>), "clone");
|
||||||
register_function(s, &ptr_assign<Proxy_Function>, "=");
|
m->add(fun(&ptr_assign<Proxy_Function_Base>), "=");
|
||||||
|
|
||||||
s.register_function(boost::shared_ptr<Proxy_Function>(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
|
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
|
||||||
"call_exists");
|
"call_exists");
|
||||||
|
|
||||||
register_function(s, &type_match, "type_match");
|
m->add(fun(&type_match), "type_match");
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -5,39 +5,43 @@
|
|||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file contains utility functions for registration of STL container
|
* This file contains utility functions for registration of STL container
|
||||||
* classes. The methodology used is based on the SGI STL concepts.
|
* classes. The methodology used is based on the SGI STL concepts.
|
||||||
* http://www.sgi.com/tech/stl/table_of_contents.html
|
* http://www.sgi.com/tech/stl/table_of_contents.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __bootstrap_stl_hpp
|
#ifndef __bootstrap_stl_hpp__
|
||||||
#define __bootstrap_stl_hpp__
|
#define __bootstrap_stl_hpp__
|
||||||
|
|
||||||
#include "dispatchkit.hpp"
|
#include "dispatchkit.hpp"
|
||||||
#include "register_function.hpp"
|
#include "register_function.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
namespace bootstrap
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Input_Range, based on the D concept of ranges.
|
* Bidir_Range, based on the D concept of ranges.
|
||||||
* \todo Update the Range code to base its capabilities on
|
* \todo Update the Range code to base its capabilities on
|
||||||
* the type_traits of the iterator passed in
|
* the user_typetraits of the iterator passed in
|
||||||
*/
|
*/
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
struct Input_Range
|
struct Bidir_Range
|
||||||
{
|
{
|
||||||
Input_Range(Container &c)
|
typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
|
||||||
|
|
||||||
|
Bidir_Range(Container &c)
|
||||||
: m_begin(c.begin()), m_end(c.end())
|
: m_begin(c.begin()), m_end(c.end())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Input_Range(typename Container::iterator itr)
|
Bidir_Range(typename Container::iterator itr)
|
||||||
: m_begin(itr), m_end(itr)
|
: m_begin(itr), m_end(itr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Input_Range(const std::pair<typename Container::iterator, typename Container::iterator> &t_p)
|
Bidir_Range(const std::pair<typename Container::iterator, typename Container::iterator> &t_p)
|
||||||
: m_begin(t_p.first), m_end(t_p.second)
|
: m_begin(t_p.first), m_end(t_p.second)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -56,7 +60,16 @@ namespace dispatchkit
|
|||||||
++m_begin;
|
++m_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
typename std::iterator_traits<typename Container::iterator>::reference front() const
|
void pop_back()
|
||||||
|
{
|
||||||
|
if (empty())
|
||||||
|
{
|
||||||
|
throw std::range_error("Range empty");
|
||||||
|
}
|
||||||
|
--m_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference_type front() const
|
||||||
{
|
{
|
||||||
if (empty())
|
if (empty())
|
||||||
{
|
{
|
||||||
@@ -65,35 +78,78 @@ namespace dispatchkit
|
|||||||
return *m_begin;
|
return *m_begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reference_type back() const
|
||||||
|
{
|
||||||
|
if (empty())
|
||||||
|
{
|
||||||
|
throw std::range_error("Range empty");
|
||||||
|
}
|
||||||
|
typename Container::iterator pos = m_end;
|
||||||
|
--pos;
|
||||||
|
return *(pos);
|
||||||
|
}
|
||||||
|
|
||||||
typename Container::iterator m_begin;
|
typename Container::iterator m_begin;
|
||||||
typename Container::iterator m_end;
|
typename Container::iterator m_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Range>
|
||||||
|
struct Retro
|
||||||
|
{
|
||||||
|
Retro(const Range &r)
|
||||||
|
: m_r(r)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool empty() { return m_r.empty(); }
|
||||||
|
void pop_front() { m_r.pop_back(); }
|
||||||
|
void pop_back() { m_r.pop_front(); }
|
||||||
|
typename Range::reference_type front() { return m_r.back(); }
|
||||||
|
typename Range::reference_type back() { return m_r.front(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Range m_r;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add Input_Range support for the given ContainerType
|
* Add Bidir_Range support for the given ContainerType
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_input_range(Dispatch_Engine &system, const std::string &type)
|
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
system.register_type<Input_Range<ContainerType> >(type+"_Range");
|
m->add(user_type<Bidir_Range<ContainerType> >(), type + "_Range");
|
||||||
system.register_type<typename ContainerType::iterator>(type+"_Iterator");
|
m->add(user_type<Retro<Bidir_Range<ContainerType> > >(), type + "_Retro_Range");
|
||||||
|
m->add(user_type<typename ContainerType::iterator>(), type+"_Iterator");
|
||||||
|
|
||||||
system.register_function(build_constructor<Input_Range<ContainerType>, ContainerType &>(), "range");
|
copy_constructor<Bidir_Range<ContainerType> >(type + "_Range", m);
|
||||||
system.register_function(build_constructor<Input_Range<ContainerType>,
|
copy_constructor<Retro<Bidir_Range<ContainerType> > >(type + "_Retro_Range", m);
|
||||||
typename ContainerType::iterator>(), "range");
|
|
||||||
|
m->add(constructor<Bidir_Range<ContainerType> (ContainerType &)>(), "range");
|
||||||
|
m->add(constructor<Bidir_Range<ContainerType> (typename ContainerType::iterator)>(), "range");
|
||||||
|
|
||||||
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator> ItrPair;
|
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator> ItrPair;
|
||||||
|
|
||||||
system.register_function(build_constructor<Input_Range<ContainerType>,
|
m->add(constructor<Bidir_Range<ContainerType> (const ItrPair &)>(), "range");
|
||||||
const ItrPair &>(), "range");
|
|
||||||
system.register_type<ItrPair>(type+"_Iterator_Pair");
|
m->add(user_type<ItrPair>(), type+"_Iterator_Pair");
|
||||||
|
|
||||||
|
m->add(fun(&Bidir_Range<ContainerType>::empty), "empty");
|
||||||
|
m->add(fun(&Bidir_Range<ContainerType>::pop_front), "pop_front");
|
||||||
|
m->add(fun(&Bidir_Range<ContainerType>::front), "front");
|
||||||
|
m->add(fun(&Bidir_Range<ContainerType>::pop_back), "pop_back");
|
||||||
|
m->add(fun(&Bidir_Range<ContainerType>::back), "back");
|
||||||
|
|
||||||
|
m->add(fun(&Retro<Bidir_Range<ContainerType> >::empty), "empty");
|
||||||
|
m->add(fun(&Retro<Bidir_Range<ContainerType> >::pop_front), "pop_front");
|
||||||
|
m->add(fun(&Retro<Bidir_Range<ContainerType> >::front), "front");
|
||||||
|
m->add(fun(&Retro<Bidir_Range<ContainerType> >::pop_back), "pop_back");
|
||||||
|
m->add(fun(&Retro<Bidir_Range<ContainerType> >::back), "back");
|
||||||
|
|
||||||
|
m->add(constructor<Retro<Bidir_Range<ContainerType> > (const Bidir_Range<ContainerType> &)>(), "retro");
|
||||||
|
|
||||||
|
|
||||||
register_function(system, &Input_Range<ContainerType>::empty, "empty");
|
|
||||||
register_function(system, &Input_Range<ContainerType>::pop_front, "pop_front");
|
return m;
|
||||||
register_function(system, &Input_Range<ContainerType>::front, "front");
|
|
||||||
system.register_function(build_constructor<Input_Range<ContainerType>, const Input_Range<ContainerType> &>(), "clone");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,8 +157,9 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/ReversibleContainer.html
|
* http://www.sgi.com/tech/stl/ReversibleContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_reversible_container(Dispatch_Engine &/*system*/, const std::string &/*type*/)
|
ModulePtr reversible_container_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,18 +167,19 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr random_access_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_reversible_container<ContainerType>(system, type);
|
reversible_container_type<ContainerType>(type, m);
|
||||||
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
|
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
|
||||||
|
|
||||||
//In the interest of runtime safety for the system, we prefer the at() method for [] access,
|
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||||
//to throw an exception in an out of bounds condition.
|
//to throw an exception in an out of bounds condition.
|
||||||
system.register_function(
|
m->add(
|
||||||
boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::at)), "[]");
|
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::at))), "[]");
|
||||||
system.register_function(
|
m->add(
|
||||||
boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::operator[])), "at");
|
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::operator[]))), "at");
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,10 +187,11 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/Assignable.html
|
* http://www.sgi.com/tech/stl/Assignable.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_assignable(Dispatch_Engine &system, const std::string &type)
|
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
add_basic_constructors<ContainerType>(system, type);
|
basic_constructors<ContainerType>(type, m);
|
||||||
add_oper_assign<ContainerType>(system);
|
oper_assign<ContainerType>(m);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,13 +199,16 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/Container.html
|
* http://www.sgi.com/tech/stl/Container.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_assignable<ContainerType>(system, type);
|
assignable_type<ContainerType>(type, m);
|
||||||
|
|
||||||
register_function(system, &ContainerType::size, "size");
|
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
|
||||||
register_function(system, &ContainerType::max_size, "max_size");
|
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::max_size), "max_size");
|
||||||
register_function(system, &ContainerType::empty, "empty");
|
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
|
||||||
|
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,10 +216,12 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/ForwardContainer.html
|
* http://www.sgi.com/tech/stl/ForwardContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr forward_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_input_range<ContainerType>(system, type);
|
input_range_type<ContainerType>(type, m);
|
||||||
bootstrap_container<ContainerType>(system, type);
|
container_type<ContainerType>(type, m);
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,9 +229,10 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/DefaultConstructible.html
|
* http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type)
|
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
system.register_function(build_constructor<Type>(), type);
|
m->add(constructor<Type ()>(), type);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,10 +276,10 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/Sequence.html
|
* http://www.sgi.com/tech/stl/Sequence.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_sequence(Dispatch_Engine &system, const std::string &type)
|
ModulePtr sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_forward_container<ContainerType>(system, type);
|
forward_container_type<ContainerType>(type, m);
|
||||||
bootstrap_default_constructible<ContainerType>(system, type);
|
default_constructible_type<ContainerType>(type, m);
|
||||||
|
|
||||||
std::string insert_name;
|
std::string insert_name;
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||||
@@ -224,8 +289,10 @@ namespace dispatchkit
|
|||||||
insert_name = "insert_at";
|
insert_name = "insert_at";
|
||||||
}
|
}
|
||||||
|
|
||||||
register_function(system, &insert_at<ContainerType>, insert_name);
|
m->add(fun(&insert_at<ContainerType>), insert_name);
|
||||||
register_function(system, &erase_at<ContainerType>, "erase_at");
|
m->add(fun(&erase_at<ContainerType>), "erase_at");
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,14 +300,14 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type)
|
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_sequence<ContainerType>(system, type);
|
sequence_type<ContainerType>(type, m);
|
||||||
|
|
||||||
|
|
||||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||||
|
|
||||||
register_function(system, (backptr(&ContainerType::back)), "back");
|
m->add(fun(backptr(&ContainerType::back)), "back");
|
||||||
|
|
||||||
std::string push_back_name;
|
std::string push_back_name;
|
||||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
|
||||||
@@ -250,8 +317,9 @@ namespace dispatchkit
|
|||||||
push_back_name = "push_back";
|
push_back_name = "push_back";
|
||||||
}
|
}
|
||||||
|
|
||||||
register_function(system, &ContainerType::push_back, push_back_name);
|
m->add(fun(&ContainerType::push_back), push_back_name);
|
||||||
register_function(system, &ContainerType::pop_back, "pop_back");
|
m->add(fun(&ContainerType::pop_back), "pop_back");
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,11 +327,12 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/Vector.html
|
* http://www.sgi.com/tech/stl/Vector.html
|
||||||
*/
|
*/
|
||||||
template<typename VectorType>
|
template<typename VectorType>
|
||||||
void bootstrap_vector(Dispatch_Engine &system, const std::string &type)
|
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
system.register_type<VectorType>(type);
|
m->add(user_type<VectorType>(), type);
|
||||||
bootstrap_random_access_container<VectorType>(system, type);
|
random_access_container_type<VectorType>(type, m);
|
||||||
bootstrap_back_insertion_sequence<VectorType>(system, type);
|
back_insertion_sequence_type<VectorType>(type, m);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,10 +340,11 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/Vector.html
|
* http://www.sgi.com/tech/stl/Vector.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_forward_container<ContainerType>(system, type);
|
forward_container_type<ContainerType>(type, m);
|
||||||
bootstrap_default_constructible<ContainerType>(system, type);
|
default_constructible_type<ContainerType>(type, m);
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,17 +352,17 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/pair.html
|
* http://www.sgi.com/tech/stl/pair.html
|
||||||
*/
|
*/
|
||||||
template<typename PairType>
|
template<typename PairType>
|
||||||
void bootstrap_pair(Dispatch_Engine &system, const std::string &type)
|
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
system.register_type<PairType>(type);
|
m->add(user_type<PairType>(), type);
|
||||||
|
|
||||||
register_member(system, &PairType::first, "first");
|
m->add(fun(&PairType::first), "first");
|
||||||
register_member(system, &PairType::second, "second");
|
m->add(fun(&PairType::second), "second");
|
||||||
|
|
||||||
system.register_function(build_constructor<PairType >(), type);
|
basic_constructors<PairType>(type, m);
|
||||||
system.register_function(build_constructor<PairType, const PairType &>(), type);
|
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||||
system.register_function(build_constructor<PairType, const PairType &>(), "clone");
|
|
||||||
system.register_function(build_constructor<PairType, const typename PairType::first_type &, const typename PairType::second_type &>(), type);
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -301,10 +371,12 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_associative_container<ContainerType>(system, type);
|
associative_container_type<ContainerType>(type, m);
|
||||||
bootstrap_pair<typename ContainerType::value_type>(system, type + "_Pair");
|
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,10 +384,12 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_associative_container<ContainerType>(system, type);
|
associative_container_type<ContainerType>(type, m);
|
||||||
register_function(system, &ContainerType::count, "count");
|
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,14 +397,16 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
|
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_sorted_associative_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator>
|
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator>
|
||||||
(ContainerType::*eq_range)(const typename ContainerType::key_type &);
|
(ContainerType::*eq_range)(const typename ContainerType::key_type &);
|
||||||
|
|
||||||
bootstrap_reversible_container<ContainerType>(system, type);
|
reversible_container_type<ContainerType>(type, m);
|
||||||
bootstrap_associative_container<ContainerType>(system, type);
|
associative_container_type<ContainerType>(type, m);
|
||||||
register_function(system, eq_range(&ContainerType::equal_range), "equal_range");
|
m->add(fun(eq_range(&ContainerType::equal_range)), "equal_range");
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -338,10 +414,12 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
|
* http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
|
||||||
*/
|
*/
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type)
|
ModulePtr unique_sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
bootstrap_sorted_associative_container<ContainerType>(system, type);
|
sorted_associative_container_type<ContainerType>(type, m);
|
||||||
bootstrap_unique_associative_container<ContainerType>(system, type);
|
unique_associative_container_type<ContainerType>(type, m);
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,12 +427,14 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/Map.html
|
* http://www.sgi.com/tech/stl/Map.html
|
||||||
*/
|
*/
|
||||||
template<typename MapType>
|
template<typename MapType>
|
||||||
void bootstrap_map(Dispatch_Engine &system, const std::string &type)
|
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
system.register_type<MapType>(type);
|
m->add(user_type<MapType>(), type);
|
||||||
register_function(system, &MapType::operator[], "[]");
|
m->add(fun(&MapType::operator[]), "[]");
|
||||||
bootstrap_unique_sorted_associative_container<MapType>(system, type);
|
unique_sorted_associative_container_type<MapType>(type, m);
|
||||||
bootstrap_pair_associative_container<MapType>(system, type);
|
pair_associative_container_type<MapType>(type, m);
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,21 +442,35 @@ namespace dispatchkit
|
|||||||
* http://www.sgi.com/tech/stl/basic_string.html
|
* http://www.sgi.com/tech/stl/basic_string.html
|
||||||
*/
|
*/
|
||||||
template<typename String>
|
template<typename String>
|
||||||
void bootstrap_string(Dispatch_Engine &system, const std::string &type)
|
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||||
{
|
{
|
||||||
system.register_type<String>(type);
|
m->add(user_type<String>(), type);
|
||||||
add_oper_add<String>(system);
|
oper_add<String>(m);
|
||||||
add_oper_add_equals<String>(system);
|
oper_add_equals<String>(m);
|
||||||
add_opers_comparison<String>(system);
|
opers_comparison<String>(m);
|
||||||
bootstrap_random_access_container<String>(system, type);
|
random_access_container_type<String>(type, m);
|
||||||
bootstrap_sequence<String>(system, type);
|
sequence_type<String>(type, m);
|
||||||
|
|
||||||
|
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||||
|
std::string push_back_name;
|
||||||
|
if (typeid(typename String::value_type) == typeid(Boxed_Value))
|
||||||
|
{
|
||||||
|
push_back_name = "push_back_ref";
|
||||||
|
} else {
|
||||||
|
push_back_name = "push_back";
|
||||||
|
}
|
||||||
|
m->add(fun(&String::push_back), push_back_name);
|
||||||
|
|
||||||
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
|
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
|
||||||
register_function(system, find_func(&String::find), "find");
|
m->add(fun(find_func(&String::find)), "find");
|
||||||
register_function(system, find_func(&String::rfind), "rfind");
|
m->add(fun(find_func(&String::rfind)), "rfind");
|
||||||
register_function(system, find_func(&String::find_first_of), "find_first_of");
|
m->add(fun(find_func(&String::find_first_of)), "find_first_of");
|
||||||
register_function(system, find_func(&String::find_last_of), "find_last_of");
|
m->add(fun(find_func(&String::find_last_of)), "find_last_of");
|
||||||
register_function(system, find_func(&String::find_first_not_of), "find_first_not_of");
|
m->add(fun(find_func(&String::find_first_not_of)), "find_first_not_of");
|
||||||
register_function(system, find_func(&String::find_last_not_of), "find_last_not_of");
|
m->add(fun(find_func(&String::find_last_not_of)), "find_last_not_of");
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
#include <boost/type_traits/add_const.hpp>
|
#include <boost/type_traits/add_const.hpp>
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Boxed_Value is the main tool of the dispatchkit. It allows
|
* Boxed_Value is the main tool of the dispatchkit. It allows
|
||||||
@@ -97,11 +97,6 @@ namespace dispatchkit
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_false()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type_Info m_type_info;
|
Type_Info m_type_info;
|
||||||
boost::any m_obj;
|
boost::any m_obj;
|
||||||
bool m_is_ref;
|
bool m_is_ref;
|
||||||
@@ -116,26 +111,37 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
struct Object_Cache
|
struct Object_Cache
|
||||||
{
|
{
|
||||||
|
Object_Cache()
|
||||||
|
: m_cullcount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Data> (new Data(
|
return boost::shared_ptr<Data> (new Data(
|
||||||
Get_Type_Info<void>::get(),
|
detail::Get_Type_Info<void>::get(),
|
||||||
boost::any(),
|
boost::any(),
|
||||||
false)
|
false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(boost::shared_ptr<T> obj)
|
boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
|
||||||
|
{
|
||||||
|
return get(*obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Data> data(new Data(
|
boost::shared_ptr<Data> data(new Data(
|
||||||
Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(obj),
|
boost::any(obj),
|
||||||
false,
|
false,
|
||||||
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
||||||
);
|
);
|
||||||
|
|
||||||
std::map<void *, Data >::iterator itr
|
std::map<const void *, Data>::iterator itr
|
||||||
= m_ptrs.find(obj.get());
|
= m_ptrs.find(obj.get());
|
||||||
|
|
||||||
if (itr != m_ptrs.end())
|
if (itr != m_ptrs.end())
|
||||||
@@ -148,19 +154,33 @@ namespace dispatchkit
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
boost::shared_ptr<Data> get(T *t)
|
||||||
|
{
|
||||||
|
return get(boost::ref(*t));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Data> data(new Data(
|
boost::shared_ptr<Data> data(new Data(
|
||||||
Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(obj),
|
boost::any(obj),
|
||||||
true)
|
true)
|
||||||
);
|
);
|
||||||
|
|
||||||
std::map<void *, Data >::iterator itr
|
std::map<const void *, Data >::iterator itr
|
||||||
= m_ptrs.find(obj.get_pointer());
|
= m_ptrs.find(obj.get_pointer());
|
||||||
|
|
||||||
if (itr != m_ptrs.end())
|
// If the ptr is found in the cache and it is the correct type,
|
||||||
|
// return it. It may be the incorrect type when two variables share the
|
||||||
|
// same memory location. Example:
|
||||||
|
// struct test { int x; };
|
||||||
|
// test t;
|
||||||
|
// Both t and t.x share the same memory location, but do not represent
|
||||||
|
// objects of the same type.
|
||||||
|
if (itr != m_ptrs.end()
|
||||||
|
&& itr->second.m_type_info.m_bare_type_info == data->m_type_info.m_bare_type_info)
|
||||||
{
|
{
|
||||||
(*data) = (itr->second);
|
(*data) = (itr->second);
|
||||||
}
|
}
|
||||||
@@ -172,7 +192,7 @@ namespace dispatchkit
|
|||||||
boost::shared_ptr<Data> get(const T& t)
|
boost::shared_ptr<Data> get(const T& t)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Data> data(new Data(
|
boost::shared_ptr<Data> data(new Data(
|
||||||
Get_Type_Info<T>::get(),
|
detail::Get_Type_Info<T>::get(),
|
||||||
boost::any(boost::shared_ptr<T>(new T(t))),
|
boost::any(boost::shared_ptr<T>(new T(t))),
|
||||||
false,
|
false,
|
||||||
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
||||||
@@ -199,13 +219,19 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
void cull()
|
void cull()
|
||||||
{
|
{
|
||||||
std::map<void *, Data >::iterator itr = m_ptrs.begin();
|
++m_cullcount;
|
||||||
|
if (m_cullcount % 10 != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<const void *, Data >::iterator itr = m_ptrs.begin();
|
||||||
|
|
||||||
while (itr != m_ptrs.end())
|
while (itr != m_ptrs.end())
|
||||||
{
|
{
|
||||||
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
|
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
|
||||||
{
|
{
|
||||||
std::map<void *, Data >::iterator todel = itr;
|
std::map<const void *, Data >::iterator todel = itr;
|
||||||
++itr;
|
++itr;
|
||||||
m_ptrs.erase(todel);
|
m_ptrs.erase(todel);
|
||||||
} else {
|
} else {
|
||||||
@@ -214,7 +240,8 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<void *, Data > m_ptrs;
|
std::map<const void *, Data > m_ptrs;
|
||||||
|
int m_cullcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -304,6 +331,8 @@ namespace dispatchkit
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
// Cast_Helper helper classes
|
// Cast_Helper helper classes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -317,8 +346,13 @@ namespace dispatchkit
|
|||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
|
{
|
||||||
|
if (!ob.get_type_info().m_is_const)
|
||||||
{
|
{
|
||||||
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
|
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
|
||||||
|
} else {
|
||||||
|
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||||
}
|
}
|
||||||
@@ -336,8 +370,13 @@ namespace dispatchkit
|
|||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
|
{
|
||||||
|
if (!ob.get_type_info().m_is_const)
|
||||||
{
|
{
|
||||||
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
|
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
|
||||||
|
} else {
|
||||||
|
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||||
}
|
}
|
||||||
@@ -355,8 +394,13 @@ namespace dispatchkit
|
|||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
if (ob.is_ref())
|
if (ob.is_ref())
|
||||||
|
{
|
||||||
|
if (!ob.get_type_info().m_is_const)
|
||||||
{
|
{
|
||||||
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
|
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
|
||||||
|
} else {
|
||||||
|
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
||||||
}
|
}
|
||||||
@@ -415,6 +459,21 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast_Helper for casting to a boost::shared_ptr<> type
|
||||||
|
*/
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper<const boost::shared_ptr<Result> &>
|
||||||
|
{
|
||||||
|
typedef typename boost::shared_ptr<Result> Result_Type;
|
||||||
|
|
||||||
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
|
{
|
||||||
|
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast_Helper for casting to a Boxed_Value type
|
* Cast_Helper for casting to a Boxed_Value type
|
||||||
@@ -422,7 +481,7 @@ namespace dispatchkit
|
|||||||
template<>
|
template<>
|
||||||
struct Cast_Helper<Boxed_Value>
|
struct Cast_Helper<Boxed_Value>
|
||||||
{
|
{
|
||||||
typedef Boxed_Value Result_Type;
|
typedef const Boxed_Value & Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
@@ -436,13 +495,14 @@ namespace dispatchkit
|
|||||||
template<>
|
template<>
|
||||||
struct Cast_Helper<const Boxed_Value &>
|
struct Cast_Helper<const Boxed_Value &>
|
||||||
{
|
{
|
||||||
typedef Boxed_Value Result_Type;
|
typedef const Boxed_Value & Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob)
|
static Result_Type cast(const Boxed_Value &ob)
|
||||||
{
|
{
|
||||||
return ob;
|
return ob;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class that is thrown in the event of a bad_boxed_cast. That is,
|
* class that is thrown in the event of a bad_boxed_cast. That is,
|
||||||
@@ -480,10 +540,10 @@ namespace dispatchkit
|
|||||||
* int &i = boxed_cast<int &>(boxedvalue);
|
* int &i = boxed_cast<int &>(boxedvalue);
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
typename Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
|
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return Cast_Helper<Type>::cast(bv);
|
return detail::Cast_Helper<Type>::cast(bv);
|
||||||
} catch (const boost::bad_any_cast &) {
|
} catch (const boost::bad_any_cast &) {
|
||||||
throw bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
throw bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||||
}
|
}
|
||||||
@@ -619,6 +679,8 @@ namespace dispatchkit
|
|||||||
bool m_isfloat;
|
bool m_isfloat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
||||||
*/
|
*/
|
||||||
@@ -632,6 +694,22 @@ namespace dispatchkit
|
|||||||
return Boxed_POD_Value(ob);
|
return Boxed_POD_Value(ob);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Boxed_Value var(T t)
|
||||||
|
{
|
||||||
|
return Boxed_Value(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the two Boxed_Values share the same internal type
|
||||||
|
*/
|
||||||
|
static bool type_match(Boxed_Value l, Boxed_Value r)
|
||||||
|
{
|
||||||
|
return l.get_type_info() == r.get_type_info();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -23,22 +23,61 @@
|
|||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
#include "proxy_constructors.hpp"
|
#include "proxy_constructors.hpp"
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
class Module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Module &add(const Type_Info &ti, const std::string &name)
|
||||||
|
{
|
||||||
|
m_typeinfos.push_back(std::make_pair(ti, name));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module &add(const Proxy_Function &f, const std::string &name)
|
||||||
|
{
|
||||||
|
m_funcs.push_back(std::make_pair(f, name));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void apply(T &t) const
|
||||||
|
{
|
||||||
|
apply(m_typeinfos.begin(), m_typeinfos.end(), t);
|
||||||
|
apply(m_funcs.begin(), m_funcs.end(), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||||
|
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||||
|
|
||||||
|
template<typename T, typename InItr>
|
||||||
|
void apply(InItr begin, InItr end, T &t) const
|
||||||
|
{
|
||||||
|
while (begin != end)
|
||||||
|
{
|
||||||
|
t.add(begin->first, begin->second);
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<Module> ModulePtr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Proxy_Function implementation that is able to take
|
* A Proxy_Function implementation that is able to take
|
||||||
* a vector of Proxy_Functions and perform a dispatch on them. It is
|
* a vector of Proxy_Functions and perform a dispatch on them. It is
|
||||||
* used specifically in the case of dealing with Function object variables
|
* used specifically in the case of dealing with Function object variables
|
||||||
*/
|
*/
|
||||||
class Dispatch_Function : public Proxy_Function
|
class Dispatch_Function : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dispatch_Function(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &t_funcs)
|
Dispatch_Function(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs)
|
||||||
: m_funcs(t_funcs)
|
: m_funcs(t_funcs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function &) const
|
virtual bool operator==(const Proxy_Function_Base &) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -55,16 +94,21 @@ namespace dispatchkit
|
|||||||
return std::vector<Type_Info>();
|
return std::vector<Type_Info>();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool types_match(const std::vector<Boxed_Value> &types) const
|
virtual int get_arity() const
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > function_vec;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
|
{
|
||||||
|
typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec;
|
||||||
|
|
||||||
function_vec::const_iterator begin = m_funcs.begin();
|
function_vec::const_iterator begin = m_funcs.begin();
|
||||||
function_vec::const_iterator end = m_funcs.end();
|
function_vec::const_iterator end = m_funcs.end();
|
||||||
|
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
if (begin->second->types_match(types))
|
if (begin->second->call_match(vals))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -81,7 +125,24 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > m_funcs;
|
std::vector<std::pair<std::string, Proxy_Function > > m_funcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown in the case that a multi method dispatch fails
|
||||||
|
* because no matching function was found
|
||||||
|
* at runtime due to either an arity_error, a guard_error or a bad_boxed_cast
|
||||||
|
* exception
|
||||||
|
*/
|
||||||
|
struct reserved_word_error : std::runtime_error
|
||||||
|
{
|
||||||
|
reserved_word_error(const std::string &word) throw()
|
||||||
|
: std::runtime_error("Reserved word not allowed in object name: " + word)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~reserved_word_error() throw() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -92,46 +153,47 @@ namespace dispatchkit
|
|||||||
class Dispatch_Engine
|
class Dispatch_Engine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<std::string, dispatchkit::Type_Info> Type_Name_Map;
|
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||||
typedef std::map<std::string, Boxed_Value> Scope;
|
typedef std::map<std::string, Boxed_Value> Scope;
|
||||||
typedef std::deque<Scope> Stack;
|
typedef boost::shared_ptr<std::deque<Scope> > Stack;
|
||||||
|
|
||||||
Dispatch_Engine()
|
Dispatch_Engine()
|
||||||
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
: m_scopes(new Stack::element_type()),
|
||||||
|
m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
||||||
{
|
{
|
||||||
m_scopes.push_back(Scope());
|
m_scopes->push_back(Scope());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new named Proxy_Function to the system
|
* Add a new named Proxy_Function to the system
|
||||||
*/
|
*/
|
||||||
bool register_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &name)
|
bool add(const Proxy_Function &f, const std::string &name)
|
||||||
{
|
{
|
||||||
|
validate_object_name(name);
|
||||||
return add_function(f, name);
|
return add_function(f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a generic, named boost::function() to the system
|
* Add a module's worth of registrations to the system
|
||||||
*/
|
*/
|
||||||
template<typename Function>
|
void add(const ModulePtr &m)
|
||||||
bool register_function(const Function &func, const std::string &name)
|
|
||||||
{
|
{
|
||||||
return add_function(boost::shared_ptr<Proxy_Function>(new Proxy_Function_Impl<Function>(func)), name);
|
m->apply(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value of an object, by name. If the object
|
* Set the value of an object, by name. If the object
|
||||||
* is not available in the current scope it is created
|
* is not available in the current scope it is created
|
||||||
*/
|
*/
|
||||||
template<typename Class>
|
void add(const Boxed_Value &obj, const std::string &name)
|
||||||
void set_object(const std::string &name, const Class &obj)
|
|
||||||
{
|
{
|
||||||
for (int i = m_scopes.size()-1; i >= 0; --i)
|
validate_object_name(name);
|
||||||
|
for (int i = m_scopes->size()-1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
std::map<std::string, Boxed_Value>::const_iterator itr = m_scopes[i].find(name);
|
std::map<std::string, Boxed_Value>::const_iterator itr = (*m_scopes)[i].find(name);
|
||||||
if (itr != m_scopes[i].end())
|
if (itr != (*m_scopes)[i].end())
|
||||||
{
|
{
|
||||||
m_scopes[i][name] = Boxed_Value(obj);
|
(*m_scopes)[i][name] = Boxed_Value(obj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,10 +204,10 @@ namespace dispatchkit
|
|||||||
/**
|
/**
|
||||||
* Adds a named object to the current scope
|
* Adds a named object to the current scope
|
||||||
*/
|
*/
|
||||||
template<typename Class>
|
void add_object(const std::string &name, const Boxed_Value &obj)
|
||||||
void add_object(const std::string &name, const Class &obj)
|
|
||||||
{
|
{
|
||||||
m_scopes.back()[name] = Boxed_Value(obj);
|
validate_object_name(name);
|
||||||
|
m_scopes->back()[name] = Boxed_Value(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,7 +215,7 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
void new_scope()
|
void new_scope()
|
||||||
{
|
{
|
||||||
m_scopes.push_back(Scope());
|
m_scopes->push_back(Scope());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,9 +223,9 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
void pop_scope()
|
void pop_scope()
|
||||||
{
|
{
|
||||||
if (m_scopes.size() > 1)
|
if (m_scopes->size() > 1)
|
||||||
{
|
{
|
||||||
m_scopes.pop_back();
|
m_scopes->pop_back();
|
||||||
} else {
|
} else {
|
||||||
throw std::range_error("Unable to pop global stack");
|
throw std::range_error("Unable to pop global stack");
|
||||||
}
|
}
|
||||||
@@ -182,10 +244,16 @@ namespace dispatchkit
|
|||||||
* \returns the old stack
|
* \returns the old stack
|
||||||
* \param[in] s The new stack
|
* \param[in] s The new stack
|
||||||
*/
|
*/
|
||||||
Stack set_stack(Stack s)
|
Stack set_stack(const Stack &s)
|
||||||
{
|
{
|
||||||
std::swap(s, m_scopes);
|
Stack old = m_scopes;
|
||||||
return s;
|
m_scopes = s;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack new_stack()
|
||||||
|
{
|
||||||
|
return Stack(new Stack::element_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,32 +268,31 @@ namespace dispatchkit
|
|||||||
return m_place_holder;
|
return m_place_holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = m_scopes.size()-1; i >= 0; --i)
|
for (int i = m_scopes->size()-1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
std::map<std::string, Boxed_Value>::const_iterator itr = m_scopes[i].find(name);
|
std::map<std::string, Boxed_Value>::const_iterator itr = (*m_scopes)[i].find(name);
|
||||||
if (itr != m_scopes[i].end())
|
if (itr != (*m_scopes)[i].end())
|
||||||
{
|
{
|
||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> > funcs = get_function_impl(name, false);
|
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs = get_function(name);
|
||||||
|
|
||||||
if (funcs.empty())
|
if (funcs.empty())
|
||||||
{
|
{
|
||||||
throw std::range_error("Object not known: " + name);
|
throw std::range_error("Object not known: " + name);
|
||||||
} else {
|
} else {
|
||||||
return Boxed_Value(boost::shared_ptr<Proxy_Function>(new Dispatch_Function(funcs)));
|
return Boxed_Value(Proxy_Function(new Dispatch_Function(funcs)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new named type
|
* Registers a new named type
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
void add(const Type_Info &ti, const std::string &name)
|
||||||
void register_type(const std::string &name)
|
|
||||||
{
|
{
|
||||||
m_types.insert(std::make_pair(name, Get_Type_Info<Type>::get()));
|
m_types.insert(std::make_pair(name, ti));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,59 +341,57 @@ namespace dispatchkit
|
|||||||
/**
|
/**
|
||||||
* Return a function by name
|
* Return a function by name
|
||||||
*/
|
*/
|
||||||
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> >
|
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >
|
||||||
get_function(const std::string &t_name) const
|
get_function(const std::string &t_name) const
|
||||||
{
|
{
|
||||||
return get_function_impl(t_name, true);
|
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);
|
||||||
|
|
||||||
|
return std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >(range.first, range.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if a function exists
|
||||||
|
*/
|
||||||
|
bool function_exists(const std::string &name) const
|
||||||
|
{
|
||||||
|
return m_functions.find(name) != m_functions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a vector of all registered functions
|
* Get a vector of all registered functions
|
||||||
*/
|
*/
|
||||||
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > get_functions() const
|
std::vector<std::pair<std::string, Proxy_Function > > get_functions() const
|
||||||
{
|
{
|
||||||
return std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >(m_functions.begin(), m_functions.end());
|
return std::vector<std::pair<std::string, Proxy_Function > >(m_functions.begin(), m_functions.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_reserved_word(const std::string &name)
|
||||||
|
{
|
||||||
|
m_reserved_words.insert(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Implementation detail for searching for a function by name.
|
* Throw a reserved_word exception if the name is not allowed
|
||||||
* Looks for all registered global functions and optionally for an object
|
|
||||||
* in scope with the same name
|
|
||||||
*/
|
*/
|
||||||
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> >
|
void validate_object_name(const std::string &name)
|
||||||
get_function_impl(const std::string &t_name, bool include_objects) const
|
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> > funcs;
|
if (m_reserved_words.find(name) != m_reserved_words.end())
|
||||||
|
|
||||||
if (include_objects)
|
|
||||||
{
|
{
|
||||||
try {
|
throw reserved_word_error(name);
|
||||||
funcs.insert(funcs.end(),
|
|
||||||
std::make_pair(
|
|
||||||
t_name,
|
|
||||||
boxed_cast<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type>(get_object(t_name)))
|
|
||||||
);
|
|
||||||
} catch (const bad_boxed_cast &) {
|
|
||||||
} catch (const std::range_error &) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator> range
|
|
||||||
= m_functions.equal_range(t_name);
|
|
||||||
|
|
||||||
funcs.insert(funcs.end(), range.first, range.second);
|
|
||||||
return funcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation detail for adding a function. Returns
|
* Implementation detail for adding a function. Returns
|
||||||
* true if the function was added, false if a function with the
|
* true if the function was added, false if a function with the
|
||||||
* same signature and name already exists.
|
* same signature and name already exists.
|
||||||
*/
|
*/
|
||||||
bool add_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &t_name)
|
bool add_function(const Proxy_Function &f, const std::string &t_name)
|
||||||
{
|
{
|
||||||
std::pair<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator> range
|
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
||||||
= m_functions.equal_range(t_name);
|
= m_functions.equal_range(t_name);
|
||||||
|
|
||||||
while (range.first != range.second)
|
while (range.first != range.second)
|
||||||
@@ -342,11 +407,12 @@ namespace dispatchkit
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::deque<Scope> m_scopes;
|
Stack m_scopes;
|
||||||
|
|
||||||
std::multimap<std::string, boost::shared_ptr<Proxy_Function> > m_functions;
|
std::multimap<std::string, Proxy_Function > m_functions;
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
Boxed_Value m_place_holder;
|
Boxed_Value m_place_holder;
|
||||||
|
std::set<std::string> m_reserved_words;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -354,7 +420,8 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
void dump_object(Boxed_Value o, const Dispatch_Engine &e)
|
void dump_object(Boxed_Value o, const Dispatch_Engine &e)
|
||||||
{
|
{
|
||||||
std::cout << e.get_type_name(o.get_type_info()) << std::endl;
|
Type_Info ti = o.get_type_info();
|
||||||
|
std::cout << (ti.m_is_const?"const ":"") << e.get_type_name(ti) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,13 +429,13 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
void dump_type(const Type_Info &type, const Dispatch_Engine &e)
|
void dump_type(const Type_Info &type, const Dispatch_Engine &e)
|
||||||
{
|
{
|
||||||
std::cout << e.get_type_name(type);
|
std::cout << (type.m_is_const?"const ":"") << e.get_type_name(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump function to stdout
|
* Dump function to stdout
|
||||||
*/
|
*/
|
||||||
void dump_function(const std::pair<const std::string, boost::shared_ptr<Proxy_Function> > &f, const Dispatch_Engine &e)
|
void dump_function(const std::pair<const std::string, Proxy_Function > &f, const Dispatch_Engine &e)
|
||||||
{
|
{
|
||||||
std::vector<Type_Info> params = f.second->get_param_types();
|
std::vector<Type_Info> params = f.second->get_param_types();
|
||||||
std::string annotation = f.second->annotation();
|
std::string annotation = f.second->annotation();
|
||||||
@@ -412,10 +479,10 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > funcs = s.get_functions();
|
std::vector<std::pair<std::string, Proxy_Function > > funcs = s.get_functions();
|
||||||
|
|
||||||
std::cout << "Functions: " << std::endl;
|
std::cout << "Functions: " << std::endl;
|
||||||
for (std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >::const_iterator itr = funcs.begin();
|
for (std::vector<std::pair<std::string, Proxy_Function > >::const_iterator itr = funcs.begin();
|
||||||
itr != funcs.end();
|
itr != funcs.end();
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
@@ -423,6 +490,24 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if the Boxed_Value matches the registered type by name
|
||||||
|
*/
|
||||||
|
bool is_type(const Dispatch_Engine &e, const std::string &user_typename, Boxed_Value r)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return e.get_type(user_typename) == r.get_type_info();
|
||||||
|
} catch (const std::range_error &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string type_name(const Dispatch_Engine &e, Boxed_Value obj)
|
||||||
|
{
|
||||||
|
return e.get_type_name(obj.get_type_info());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -4,13 +4,6 @@
|
|||||||
// and Jason Turner (lefticus@gmail.com)
|
// and Jason Turner (lefticus@gmail.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
|
||||||
|
|
||||||
#define addparam(z,n,text) params.push_back(Boxed_Value(BOOST_PP_CAT(p, n) ));
|
|
||||||
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef BOOST_PP_IS_ITERATING
|
|
||||||
#ifndef __function_call_hpp__
|
#ifndef __function_call_hpp__
|
||||||
#define __function_call_hpp__
|
#define __function_call_hpp__
|
||||||
|
|
||||||
@@ -20,52 +13,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "proxy_functions.hpp"
|
#include "proxy_functions.hpp"
|
||||||
|
#include "function_call_detail.hpp"
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Internal helper class for handling the return
|
|
||||||
* value of a build_function_caller
|
|
||||||
*/
|
|
||||||
template<typename Ret>
|
|
||||||
class Function_Caller_Ret
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Function_Caller_Ret()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Ret call(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &t_funcs,
|
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
|
||||||
{
|
|
||||||
return boxed_cast<Ret>(dispatch(t_funcs, params));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specialization for void return types
|
|
||||||
*/
|
|
||||||
template<>
|
|
||||||
class Function_Caller_Ret<void>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Function_Caller_Ret()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void call(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &t_funcs,
|
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
|
||||||
{
|
|
||||||
dispatch(t_funcs, params);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 9 )
|
|
||||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/function_call.hpp>
|
|
||||||
#include BOOST_PP_ITERATE()
|
|
||||||
|
|
||||||
namespace dispatchkit
|
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Build a function caller that knows how to dispatch on a set of functions
|
* Build a function caller that knows how to dispatch on a set of functions
|
||||||
@@ -77,10 +27,10 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
build_function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs)
|
functor(const std::vector<std::pair<std::string, Proxy_Function > > &funcs)
|
||||||
{
|
{
|
||||||
FunctionType *p;
|
FunctionType *p=0;
|
||||||
return build_function_caller_helper(p, funcs);
|
return detail::build_function_caller_helper(p, funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,7 +38,7 @@ namespace dispatchkit
|
|||||||
* useful in the case that a function is being pass out from scripting back
|
* useful in the case that a function is being pass out from scripting back
|
||||||
* into code
|
* into code
|
||||||
* example:
|
* example:
|
||||||
* void my_function(boost::shared_ptr<Proxy_Function> f)
|
* void my_function(Proxy_Function f)
|
||||||
* {
|
* {
|
||||||
* boost::function<void (int)> local_f =
|
* boost::function<void (int)> local_f =
|
||||||
* build_function_caller(f);
|
* build_function_caller(f);
|
||||||
@@ -98,11 +48,11 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
build_function_caller(boost::shared_ptr<Proxy_Function> func)
|
functor(Proxy_Function func)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > funcs;
|
std::vector<std::pair<std::string, Proxy_Function > > funcs;
|
||||||
funcs.push_back(std::make_pair(std::string(), func));
|
funcs.push_back(std::make_pair(std::string(), func));
|
||||||
return build_function_caller<FunctionType>(funcs);
|
return functor<FunctionType>(funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,58 +61,11 @@ namespace dispatchkit
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
build_function_caller(const Boxed_Value &bv)
|
functor(const Boxed_Value &bv)
|
||||||
{
|
{
|
||||||
return build_function_caller<FunctionType>(boxed_cast<boost::shared_ptr<Proxy_Function> >(bv));
|
return functor<FunctionType>(boxed_cast<Proxy_Function >(bv));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for calling script code as if it were native C++ code
|
|
||||||
* example:
|
|
||||||
* boost::function<int (int, int)> f = build_functor(chai, "func(x, y){x+y}");
|
|
||||||
* \return a boost::function representing the passed in script
|
|
||||||
* \param[in] e ScriptEngine to build the script execution from
|
|
||||||
* \param[in] script Script code to build a function from
|
|
||||||
*/
|
|
||||||
template<typename FunctionType, typename ScriptEngine>
|
|
||||||
boost::function<FunctionType> build_functor(ScriptEngine &e, const std::string &script)
|
|
||||||
{
|
|
||||||
return build_function_caller<FunctionType>(e.evaluate_string(script));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define n BOOST_PP_ITERATION()
|
|
||||||
|
|
||||||
namespace dispatchkit
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* used internally for unwrapping a function call's types
|
|
||||||
*/
|
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
|
||||||
Ret function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs
|
|
||||||
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
|
||||||
{
|
|
||||||
std::vector<Boxed_Value> params;
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT(n, addparam, ~)
|
|
||||||
|
|
||||||
return Function_Caller_Ret<Ret>().call(funcs, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* used internally for unwrapping a function call's types
|
|
||||||
*/
|
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
|
||||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
|
||||||
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs)
|
|
||||||
{
|
|
||||||
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
|
|
||||||
BOOST_PP_ENUM_TRAILING(n, curry, ~));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
98
include/chaiscript/dispatchkit/function_call_detail.hpp
Normal file
98
include/chaiscript/dispatchkit/function_call_detail.hpp
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||||
|
// and Jason Turner (lefticus@gmail.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
|
#define addparam(z,n,text) params.push_back(boost::is_reference<Param ## n>::value?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
|
||||||
|
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BOOST_PP_IS_ITERATING
|
||||||
|
#ifndef __function_call_detail_hpp__
|
||||||
|
#define __function_call_detail_hpp__
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "proxy_functions.hpp"
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Internal helper class for handling the return
|
||||||
|
* value of a build_function_caller
|
||||||
|
*/
|
||||||
|
template<typename Ret>
|
||||||
|
struct Function_Caller_Ret
|
||||||
|
{
|
||||||
|
static Ret call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
|
||||||
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
|
{
|
||||||
|
return boxed_cast<Ret>(dispatch(t_funcs, params));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialization for void return types
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct Function_Caller_Ret<void>
|
||||||
|
{
|
||||||
|
static void call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
|
||||||
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
|
{
|
||||||
|
dispatch(t_funcs, params);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BOOST_PP_ITERATION_LIMITS ( 0, 9 )
|
||||||
|
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/function_call_detail.hpp>
|
||||||
|
#include BOOST_PP_ITERATE()
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define n BOOST_PP_ITERATION()
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* used internally for unwrapping a function call's types
|
||||||
|
*/
|
||||||
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
|
Ret function_caller(const std::vector<std::pair<std::string, Proxy_Function > > &funcs
|
||||||
|
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||||
|
{
|
||||||
|
std::vector<Boxed_Value> params;
|
||||||
|
|
||||||
|
BOOST_PP_REPEAT(n, addparam, ~)
|
||||||
|
|
||||||
|
return Function_Caller_Ret<Ret>::call(funcs, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used internally for unwrapping a function call's types
|
||||||
|
*/
|
||||||
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
|
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
||||||
|
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, Proxy_Function> > &funcs)
|
||||||
|
{
|
||||||
|
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
|
||||||
|
BOOST_PP_ENUM_TRAILING(n, curry, ~));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
100
include/chaiscript/dispatchkit/handle_return.hpp
Normal file
100
include/chaiscript/dispatchkit/handle_return.hpp
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||||
|
// and Jason Turner (lefticus@gmail.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#ifndef __handle_return_hpp__
|
||||||
|
#define __handle_return_hpp__
|
||||||
|
|
||||||
|
#include "boxed_value.hpp"
|
||||||
|
#include "type_info.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
|
*/
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<Ret ()> &f)
|
||||||
|
{
|
||||||
|
return Boxed_Value(f());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<boost::shared_ptr<Ret> &>
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<boost::shared_ptr<Ret> & ()> &f)
|
||||||
|
{
|
||||||
|
return Boxed_Value(f());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<const boost::shared_ptr<Ret> &>
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<const boost::shared_ptr<Ret> & ()> &f)
|
||||||
|
{
|
||||||
|
return Boxed_Value(f());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
|
*/
|
||||||
|
template<typename Ret>
|
||||||
|
struct Handle_Return<Ret &>
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<Ret &()> &f)
|
||||||
|
{
|
||||||
|
return Boxed_Value(boost::ref(f()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct Handle_Return<Boxed_Value>
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<Boxed_Value ()> &f)
|
||||||
|
{
|
||||||
|
return f();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct Handle_Return<Boxed_Value &>
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<Boxed_Value &()> &f)
|
||||||
|
{
|
||||||
|
return f();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used internally for handling a return value from a Proxy_Function call
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
struct Handle_Return<void>
|
||||||
|
{
|
||||||
|
static Boxed_Value call(const boost::function<void ()> &f)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
return Boxed_Value(Boxed_Value::Void_Type());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -19,17 +19,30 @@
|
|||||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_constructors.hpp>
|
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_constructors.hpp>
|
||||||
#include BOOST_PP_ITERATE()
|
#include BOOST_PP_ITERATE()
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
Proxy_Function constructor()
|
||||||
|
{
|
||||||
|
T *f = 0;
|
||||||
|
return (detail::build_constructor_(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define n BOOST_PP_ITERATION()
|
# define n BOOST_PP_ITERATION()
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* A constructor function, used for creating a new object
|
* A constructor function, used for creating a new object
|
||||||
* of a given type with a given set of params
|
* of a given type with a given set of params
|
||||||
*/
|
*/
|
||||||
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
boost::shared_ptr<Class> constructor( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||||
{
|
{
|
||||||
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
|
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
|
||||||
}
|
}
|
||||||
@@ -41,10 +54,11 @@ namespace dispatchkit
|
|||||||
* \todo See if it is possible to make this not be a variadic function
|
* \todo See if it is possible to make this not be a variadic function
|
||||||
*/
|
*/
|
||||||
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
boost::function<boost::shared_ptr<Class> (BOOST_PP_ENUM_PARAMS(n, Param))> build_constructor()
|
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||||
{
|
{
|
||||||
typedef boost::shared_ptr<Class> (*func)(BOOST_PP_ENUM_PARAMS(n, Param));
|
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
|
||||||
return boost::function<boost::shared_ptr<Class> (BOOST_PP_ENUM_PARAMS(n, Param))>(func(&(constructor<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>)));
|
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,98 +4,29 @@
|
|||||||
// and Jason Turner (lefticus@gmail.com)
|
// and Jason Turner (lefticus@gmail.com)
|
||||||
// http://www.chaiscript.com
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
|
||||||
|
|
||||||
#define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info<Param ## n>::get());
|
|
||||||
#define casthelper(z,n,text) ,dispatchkit::boxed_cast< Param ## n >(params[n])
|
|
||||||
#define comparetype(z,n,text) && ((Get_Type_Info<Param ## n>::get() == params[n].get_type_info()))
|
|
||||||
#define trycast(z,n,text) dispatchkit::boxed_cast<Param ## n>(params[n]);
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef BOOST_PP_IS_ITERATING
|
|
||||||
#ifndef __proxy_functions_hpp__
|
#ifndef __proxy_functions_hpp__
|
||||||
#define __proxy_functions_hpp__
|
#define __proxy_functions_hpp__
|
||||||
|
|
||||||
|
|
||||||
#include "boxed_value.hpp"
|
#include "boxed_value.hpp"
|
||||||
#include "type_info.hpp"
|
#include "type_info.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "proxy_functions_detail.hpp"
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<typename Ret>
|
|
||||||
struct Handle_Return
|
|
||||||
{
|
|
||||||
Boxed_Value operator()(const boost::function<Ret ()> &f)
|
|
||||||
{
|
|
||||||
return Boxed_Value(f());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<typename Ret>
|
|
||||||
struct Handle_Return<Ret &>
|
|
||||||
{
|
|
||||||
Boxed_Value operator()(const boost::function<Ret &()> &f)
|
|
||||||
{
|
|
||||||
return Boxed_Value(boost::ref(f()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<>
|
|
||||||
struct Handle_Return<Boxed_Value>
|
|
||||||
{
|
|
||||||
Boxed_Value operator()(const boost::function<Boxed_Value ()> &f)
|
|
||||||
{
|
|
||||||
return f();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<>
|
|
||||||
struct Handle_Return<Boxed_Value &>
|
|
||||||
{
|
|
||||||
Boxed_Value operator()(const boost::function<Boxed_Value &()> &f)
|
|
||||||
{
|
|
||||||
return f();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used internally for handling a return value from a Proxy_Function call
|
|
||||||
*/
|
|
||||||
template<>
|
|
||||||
struct Handle_Return<void>
|
|
||||||
{
|
|
||||||
Boxed_Value operator()(const boost::function<void ()> &f)
|
|
||||||
{
|
|
||||||
f();
|
|
||||||
return Boxed_Value(Boxed_Value::Void_Type());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for building a list of parameters for calling a Proxy_Function
|
* Helper for building a list of parameters for calling a Proxy_Function
|
||||||
* it does automatic conversion to Boxed_Value types via operator<<
|
* it does automatic conversion to Boxed_Value types via operator<<
|
||||||
*
|
*
|
||||||
* example usage:
|
* example usage:
|
||||||
* Boxed_Value retval = dispatch(dispatchengine.get_function("+"),
|
* Boxed_Value retval = dispatch(dispatchengine.get_function("+"),
|
||||||
* dispatchkit::Param_List_Builder() << 5 << 6);
|
* chaiscript::Param_List_Builder() << 5 << 6);
|
||||||
*/
|
*/
|
||||||
struct Param_List_Builder
|
struct Param_List_Builder
|
||||||
{
|
{
|
||||||
@@ -120,30 +51,6 @@ namespace dispatchkit
|
|||||||
std::vector<Boxed_Value> objects;
|
std::vector<Boxed_Value> objects;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when there is a mismatch in number of
|
|
||||||
* parameters during Proxy_Function execution
|
|
||||||
*/
|
|
||||||
struct arity_error : std::range_error
|
|
||||||
{
|
|
||||||
arity_error(int t_got, int t_expected)
|
|
||||||
: std::range_error("Function dispatch arity mismatch"),
|
|
||||||
got(t_got), expected(t_expected)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~arity_error() throw() {}
|
|
||||||
int got;
|
|
||||||
int expected;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
|
||||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions.hpp>
|
|
||||||
#include BOOST_PP_ITERATE()
|
|
||||||
|
|
||||||
namespace dispatchkit
|
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Pure virtual base class for all Proxy_Function implementations
|
* Pure virtual base class for all Proxy_Function implementations
|
||||||
* Proxy_Functions are a type erasure of type safe C++
|
* Proxy_Functions are a type erasure of type safe C++
|
||||||
@@ -152,17 +59,60 @@ namespace dispatchkit
|
|||||||
* Dispatch_Engine only knows how to work with Proxy_Function, no other
|
* Dispatch_Engine only knows how to work with Proxy_Function, no other
|
||||||
* function classes.
|
* function classes.
|
||||||
*/
|
*/
|
||||||
class Proxy_Function
|
class Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Proxy_Function() {}
|
virtual ~Proxy_Function_Base() {}
|
||||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) = 0;
|
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) = 0;
|
||||||
virtual std::vector<Type_Info> get_param_types() const = 0;
|
virtual std::vector<Type_Info> get_param_types() const = 0;
|
||||||
virtual bool operator==(const Proxy_Function &) const = 0;
|
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||||
virtual bool types_match(const std::vector<Boxed_Value> &types) const = 0;
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
|
||||||
|
|
||||||
|
//! Return true if the function is a possible match
|
||||||
|
//! to the passed in values
|
||||||
|
bool filter(const std::vector<Boxed_Value> &vals) const
|
||||||
|
{
|
||||||
|
int arity = get_arity();
|
||||||
|
|
||||||
|
if (arity < 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
} else if (size_t(arity) == vals.size()) {
|
||||||
|
if (arity == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const std::vector<Type_Info> &types = get_param_types();
|
||||||
|
|
||||||
|
if (types.size() < 2)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type_Info &ti = types[1];
|
||||||
|
|
||||||
|
if (!ti.m_bare_type_info || !(vals[0].get_type_info().m_bare_type_info)
|
||||||
|
|| (*ti.m_bare_type_info) == (*user_type<Boxed_Value>().m_bare_type_info)
|
||||||
|
|| (*ti.m_bare_type_info) == (*user_type<Boxed_POD_Value>().m_bare_type_info)
|
||||||
|
|| (*vals[0].get_type_info().m_bare_type_info) == (*ti.m_bare_type_info))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int get_arity() const = 0;
|
||||||
|
|
||||||
virtual std::string annotation() const = 0;
|
virtual std::string annotation() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown if a function's guard fails to execute
|
* Exception thrown if a function's guard fails to execute
|
||||||
*/
|
*/
|
||||||
@@ -181,27 +131,28 @@ namespace dispatchkit
|
|||||||
* A Proxy_Function implementation that is not type safe, the called function
|
* A Proxy_Function implementation that is not type safe, the called function
|
||||||
* is expecting a vector<Boxed_Value> that it works with how it chooses.
|
* is expecting a vector<Boxed_Value> that it works with how it chooses.
|
||||||
*/
|
*/
|
||||||
class Dynamic_Proxy_Function : public Proxy_Function
|
class Dynamic_Proxy_Function : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dynamic_Proxy_Function(
|
Dynamic_Proxy_Function(
|
||||||
const boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
|
const boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
|
||||||
int t_arity=-1,
|
int t_arity=-1,
|
||||||
const std::string &t_description = "",
|
const std::string &t_description = "",
|
||||||
const boost::shared_ptr<Proxy_Function> &t_guard = boost::shared_ptr<Proxy_Function>())
|
const Proxy_Function &t_guard = Proxy_Function())
|
||||||
: m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard)
|
: m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard),
|
||||||
|
m_types(build_param_type_list(t_arity))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function &) const
|
virtual bool operator==(const Proxy_Function_Base &) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool types_match(const std::vector<Boxed_Value> &types) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
{
|
{
|
||||||
return (m_arity < 0 || types.size() == size_t(m_arity))
|
return (m_arity < 0 || vals.size() == size_t(m_arity))
|
||||||
&& test_guard(types);
|
&& test_guard(vals);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Dynamic_Proxy_Function() {}
|
virtual ~Dynamic_Proxy_Function() {}
|
||||||
@@ -223,23 +174,14 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_arity() const
|
||||||
|
{
|
||||||
|
return m_arity;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::vector<Type_Info> get_param_types() const
|
virtual std::vector<Type_Info> get_param_types() const
|
||||||
{
|
{
|
||||||
std::vector<Type_Info> types;
|
return m_types;
|
||||||
|
|
||||||
types.push_back(Get_Type_Info<Boxed_Value>::get());
|
|
||||||
|
|
||||||
if (m_arity >= 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < m_arity; ++i)
|
|
||||||
{
|
|
||||||
types.push_back(Get_Type_Info<Boxed_Value>::get());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
types.push_back(Get_Type_Info<std::vector<Boxed_Value> >::get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return types;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const
|
virtual std::string annotation() const
|
||||||
@@ -264,10 +206,30 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<Type_Info> build_param_type_list(int arity)
|
||||||
|
{
|
||||||
|
std::vector<Type_Info> types;
|
||||||
|
|
||||||
|
types.push_back(detail::Get_Type_Info<Boxed_Value>::get());
|
||||||
|
|
||||||
|
if (arity >= 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < arity; ++i)
|
||||||
|
{
|
||||||
|
types.push_back(detail::Get_Type_Info<Boxed_Value>::get());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
types.push_back(detail::Get_Type_Info<std::vector<Boxed_Value> >::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||||
int m_arity;
|
int m_arity;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
boost::shared_ptr<Proxy_Function> m_guard;
|
Proxy_Function m_guard;
|
||||||
|
std::vector<Type_Info> m_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,26 +246,25 @@ namespace dispatchkit
|
|||||||
* at runtime, when call() is executed.
|
* at runtime, when call() is executed.
|
||||||
* it is used for bind(function, param1, _, param2) style calls
|
* it is used for bind(function, param1, _, param2) style calls
|
||||||
*/
|
*/
|
||||||
class Bound_Function : public Proxy_Function
|
class Bound_Function : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Bound_Function(const boost::shared_ptr<Proxy_Function> &t_f,
|
Bound_Function(const Proxy_Function &t_f,
|
||||||
const std::vector<Boxed_Value> &t_args)
|
const std::vector<Boxed_Value> &t_args)
|
||||||
: m_f(t_f), m_args(t_args)
|
: m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function &) const
|
virtual bool operator==(const Proxy_Function_Base &) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Bound_Function() {}
|
virtual ~Bound_Function() {}
|
||||||
|
|
||||||
virtual bool types_match(const std::vector<Boxed_Value> &types) const
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> params = build_param_list(types);
|
return m_f->call_match(build_param_list(vals));
|
||||||
return m_f->types_match(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms)
|
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms)
|
||||||
@@ -323,7 +284,7 @@ namespace dispatchkit
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (barg != m_args.end()
|
while (barg != m_args.end()
|
||||||
&& !(barg->get_type_info() == Get_Type_Info<Placeholder_Object>::get()))
|
&& !(barg->get_type_info() == detail::Get_Type_Info<Placeholder_Object>::get()))
|
||||||
{
|
{
|
||||||
args.push_back(*barg);
|
args.push_back(*barg);
|
||||||
++barg;
|
++barg;
|
||||||
@@ -336,7 +297,7 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (barg != m_args.end()
|
if (barg != m_args.end()
|
||||||
&& barg->get_type_info() == Get_Type_Info<Placeholder_Object>::get())
|
&& barg->get_type_info() == detail::Get_Type_Info<Placeholder_Object>::get())
|
||||||
{
|
{
|
||||||
++barg;
|
++barg;
|
||||||
}
|
}
|
||||||
@@ -354,14 +315,20 @@ namespace dispatchkit
|
|||||||
return std::vector<Type_Info>();
|
return std::vector<Type_Info>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_arity() const
|
||||||
|
{
|
||||||
|
return m_arity;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const
|
virtual std::string annotation() const
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<Proxy_Function> m_f;
|
Proxy_Function m_f;
|
||||||
std::vector<Boxed_Value> m_args;
|
std::vector<Boxed_Value> m_args;
|
||||||
|
int m_arity;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,17 +337,17 @@ namespace dispatchkit
|
|||||||
* type checking of Boxed_Value parameters, in a type safe manner
|
* type checking of Boxed_Value parameters, in a type safe manner
|
||||||
*/
|
*/
|
||||||
template<typename Func>
|
template<typename Func>
|
||||||
class Proxy_Function_Impl : public Proxy_Function
|
class Proxy_Function_Impl : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Proxy_Function_Impl(const Func &f)
|
Proxy_Function_Impl(const boost::function<Func> &f)
|
||||||
: m_f(f)
|
: m_f(f), m_dummy_func(0), m_types(build_param_type_list(m_dummy_func))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Proxy_Function_Impl() {}
|
virtual ~Proxy_Function_Impl() {}
|
||||||
|
|
||||||
virtual bool operator==(const Proxy_Function &t_func) const
|
virtual bool operator==(const Proxy_Function_Base &t_func) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
dynamic_cast<const Proxy_Function_Impl<Func> &>(t_func);
|
dynamic_cast<const Proxy_Function_Impl<Func> &>(t_func);
|
||||||
@@ -397,12 +364,18 @@ namespace dispatchkit
|
|||||||
|
|
||||||
virtual std::vector<Type_Info> get_param_types() const
|
virtual std::vector<Type_Info> get_param_types() const
|
||||||
{
|
{
|
||||||
return build_param_type_list(m_f);
|
return m_types;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool types_match(const std::vector<Boxed_Value> &types) const
|
virtual int get_arity() const
|
||||||
{
|
{
|
||||||
return compare_types(m_f, types);
|
return m_types.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||||
|
{
|
||||||
|
return compare_types(m_dummy_func, vals);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string annotation() const
|
virtual std::string annotation() const
|
||||||
@@ -411,7 +384,9 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Func m_f;
|
boost::function<Func> m_f;
|
||||||
|
Func *m_dummy_func;
|
||||||
|
std::vector<Type_Info> m_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -435,15 +410,18 @@ namespace dispatchkit
|
|||||||
* each function against the set of parameters, in order, until a matching
|
* each function against the set of parameters, in order, until a matching
|
||||||
* function is found or throw dispatch_error if no matching function is found
|
* function is found or throw dispatch_error if no matching function is found
|
||||||
*/
|
*/
|
||||||
Boxed_Value dispatch(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs,
|
Boxed_Value dispatch(const std::vector<std::pair<std::string, Proxy_Function> > &funcs,
|
||||||
const std::vector<Boxed_Value> &plist)
|
const std::vector<Boxed_Value> &plist)
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >::const_iterator itr = funcs.begin();
|
for (std::vector<std::pair<std::string, Proxy_Function> >::const_iterator itr = funcs.begin();
|
||||||
itr != funcs.end();
|
itr != funcs.end();
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
if (itr->second->filter(plist))
|
||||||
|
{
|
||||||
return (*itr->second)(plist);
|
return (*itr->second)(plist);
|
||||||
|
}
|
||||||
} catch (const bad_boxed_cast &) {
|
} catch (const bad_boxed_cast &) {
|
||||||
//parameter failed to cast, try again
|
//parameter failed to cast, try again
|
||||||
} catch (const arity_error &) {
|
} catch (const arity_error &) {
|
||||||
@@ -457,70 +435,5 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define n BOOST_PP_ITERATION()
|
|
||||||
|
|
||||||
namespace dispatchkit
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Used by Proxy_Function_Impl to return a list of all param types
|
|
||||||
* it contains.
|
|
||||||
*/
|
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
|
||||||
std::vector<Type_Info> build_param_type_list(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &)
|
|
||||||
{
|
|
||||||
std::vector<Type_Info> ti;
|
|
||||||
ti.push_back(Get_Type_Info<Ret>::get());
|
|
||||||
|
|
||||||
BOOST_PP_REPEAT(n, gettypeinfo, ~)
|
|
||||||
|
|
||||||
return ti;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
|
||||||
* The function attempts to unbox each paramter to the expected type.
|
|
||||||
* if any unboxing fails the execution of the function fails and
|
|
||||||
* the bad_boxed_cast is passed up to the caller.
|
|
||||||
*/
|
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
|
||||||
Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
|
||||||
{
|
|
||||||
if (params.size() != n)
|
|
||||||
{
|
|
||||||
throw arity_error(params.size(), n);
|
|
||||||
} else {
|
|
||||||
return Handle_Return<Ret>()(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
|
||||||
* Proxy_Function_Impl object. This function is primarly used to prevent
|
|
||||||
* registration of two functions with the exact same signatures
|
|
||||||
*/
|
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
|
||||||
bool compare_types(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &,
|
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
|
||||||
{
|
|
||||||
if (params.size() != n)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
bool val = true BOOST_PP_REPEAT(n, comparetype, ~);
|
|
||||||
if (val) return true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
BOOST_PP_REPEAT(n, trycast, ~);
|
|
||||||
} catch (const bad_boxed_cast &) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
121
include/chaiscript/dispatchkit/proxy_functions_detail.hpp
Normal file
121
include/chaiscript/dispatchkit/proxy_functions_detail.hpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// This file is distributed under the BSD License.
|
||||||
|
// See "license.txt" for details.
|
||||||
|
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||||
|
// and Jason Turner (lefticus@gmail.com)
|
||||||
|
// http://www.chaiscript.com
|
||||||
|
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
|
#define gettypeinfo(z,n,text) ti.push_back(detail::Get_Type_Info<Param ## n>::get());
|
||||||
|
#define casthelper(z,n,text) ,chaiscript::boxed_cast< Param ## n >(params[n])
|
||||||
|
#define comparetype(z,n,text) && ((detail::Get_Type_Info<Param ## n>::get() == params[n].get_type_info()))
|
||||||
|
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BOOST_PP_IS_ITERATING
|
||||||
|
#ifndef __proxy_functions_detail_hpp__
|
||||||
|
#define __proxy_functions_detail_hpp__
|
||||||
|
|
||||||
|
#include "boxed_value.hpp"
|
||||||
|
#include "type_info.hpp"
|
||||||
|
#include "handle_return.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Exception thrown when there is a mismatch in number of
|
||||||
|
* parameters during Proxy_Function execution
|
||||||
|
*/
|
||||||
|
struct arity_error : std::range_error
|
||||||
|
{
|
||||||
|
arity_error(int t_got, int t_expected)
|
||||||
|
: std::range_error("Function dispatch arity mismatch"),
|
||||||
|
got(t_got), expected(t_expected)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~arity_error() throw() {}
|
||||||
|
int got;
|
||||||
|
int expected;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||||
|
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions_detail.hpp>
|
||||||
|
#include BOOST_PP_ITERATE()
|
||||||
|
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define n BOOST_PP_ITERATION()
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used by Proxy_Function_Impl to return a list of all param types
|
||||||
|
* it contains.
|
||||||
|
*/
|
||||||
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
|
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||||
|
{
|
||||||
|
std::vector<Type_Info> ti;
|
||||||
|
ti.push_back(detail::Get_Type_Info<Ret>::get());
|
||||||
|
|
||||||
|
BOOST_PP_REPEAT(n, gettypeinfo, ~)
|
||||||
|
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||||
|
* The function attempts to unbox each paramter to the expected type.
|
||||||
|
* if any unboxing fails the execution of the function fails and
|
||||||
|
* the bad_boxed_cast is passed up to the caller.
|
||||||
|
*/
|
||||||
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
|
Boxed_Value call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
||||||
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
|
{
|
||||||
|
if (params.size() != n)
|
||||||
|
{
|
||||||
|
throw arity_error(params.size(), n);
|
||||||
|
} else {
|
||||||
|
return Handle_Return<Ret>::call(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||||
|
* Proxy_Function_Impl object. This function is primarly used to prevent
|
||||||
|
* registration of two functions with the exact same signatures
|
||||||
|
*/
|
||||||
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
|
bool compare_types(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
|
||||||
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
|
{
|
||||||
|
if (params.size() != n)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
bool val = true BOOST_PP_REPEAT(n, comparetype, ~);
|
||||||
|
if (val) return true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
BOOST_PP_REPEAT(n, trycast, ~);
|
||||||
|
} catch (const bad_boxed_cast &) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -14,15 +14,23 @@
|
|||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Helper function for register_member function
|
* Helper function for register_member function
|
||||||
*/
|
*/
|
||||||
template<typename T, typename Class>
|
template<typename T, typename Class>
|
||||||
T &get_member(T Class::* m, Class *obj)
|
T &get_member(T Class::* m, Class *obj)
|
||||||
{
|
{
|
||||||
return obj->*m;
|
return (obj->*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Proxy_Function fun_helper(const boost::function<T> &f)
|
||||||
|
{
|
||||||
|
return Proxy_Function(new Proxy_Function_Impl<T>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,9 +39,10 @@ namespace dispatchkit
|
|||||||
* for example, the case of std::pair<>::first and std::pair<>::second
|
* for example, the case of std::pair<>::first and std::pair<>::second
|
||||||
*/
|
*/
|
||||||
template<typename T, typename Class>
|
template<typename T, typename Class>
|
||||||
void register_member(Dispatch_Engine &s, T Class::* m, const std::string &name)
|
Proxy_Function fun_helper(T Class::* m)
|
||||||
{
|
{
|
||||||
s.register_function(boost::function<T (Class *)>(boost::bind(&get_member<T, Class>, m, _1)), name);
|
return fun_helper(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,37 +50,51 @@ namespace dispatchkit
|
|||||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
|
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
|
||||||
#include BOOST_PP_ITERATE()
|
#include BOOST_PP_ITERATE()
|
||||||
|
|
||||||
|
namespace chaiscript
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
Proxy_Function fun(T t)
|
||||||
|
{
|
||||||
|
return detail::fun_helper(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define n BOOST_PP_ITERATION()
|
# define n BOOST_PP_ITERATION()
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Register a global function of n parameters with name
|
* Register a global function of n parameters with name
|
||||||
*/
|
*/
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
void register_function(Dispatch_Engine &s, Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name)
|
Proxy_Function fun_helper(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||||
{
|
{
|
||||||
s.register_function(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
|
return fun_helper(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a class method of n parameters with name
|
* Register a class method of n parameters with name
|
||||||
*/
|
*/
|
||||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name)
|
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||||
{
|
{
|
||||||
s.register_function(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
|
return fun_helper(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a const class method of n parameters with name
|
* Register a const class method of n parameters with name
|
||||||
*/
|
*/
|
||||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||||
void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const std::string &name)
|
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
|
||||||
{
|
{
|
||||||
s.register_function(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
|
return fun_helper(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
#include <boost/type_traits/remove_pointer.hpp>
|
#include <boost/type_traits/remove_pointer.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
namespace dispatchkit
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* compile time deduced information about a type
|
* compile time deduced information about a type
|
||||||
@@ -77,6 +77,8 @@ namespace dispatchkit
|
|||||||
bool m_is_unknown;
|
bool m_is_unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Helper used to create a Type_Info object
|
* Helper used to create a Type_Info object
|
||||||
*/
|
*/
|
||||||
@@ -104,6 +106,18 @@ namespace dispatchkit
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Get_Type_Info<const boost::shared_ptr<T> &>
|
||||||
|
{
|
||||||
|
static Type_Info get()
|
||||||
|
{
|
||||||
|
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
|
||||||
|
boost::is_void<T>::value,
|
||||||
|
&typeid(const boost::shared_ptr<T> &),
|
||||||
|
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Get_Type_Info<boost::reference_wrapper<T> >
|
struct Get_Type_Info<boost::reference_wrapper<T> >
|
||||||
{
|
{
|
||||||
@@ -115,6 +129,22 @@ namespace dispatchkit
|
|||||||
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
|
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Type_Info user_type(T)
|
||||||
|
{
|
||||||
|
return detail::Get_Type_Info<T>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Type_Info user_type()
|
||||||
|
{
|
||||||
|
return detail::Get_Type_Info<T>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -19,13 +19,101 @@ namespace chaiscript
|
|||||||
template <typename Eval_Engine>
|
template <typename Eval_Engine>
|
||||||
class ChaiScript_System {
|
class ChaiScript_System {
|
||||||
Eval_Engine engine;
|
Eval_Engine engine;
|
||||||
|
|
||||||
|
std::set<std::string> loaded_files;
|
||||||
|
|
||||||
ChaiScript_Parser parser;
|
ChaiScript_Parser parser;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the given string in by parsing it and running the results through the evaluator
|
||||||
|
*/
|
||||||
|
Boxed_Value do_eval(const std::string &input, const std::string &filename = "__EVAL__") {
|
||||||
|
//debug_print(tokens);
|
||||||
|
Boxed_Value value;
|
||||||
|
parser.clear_match_stack();
|
||||||
|
|
||||||
|
// Keep a cache of all loaded filenames and use the char * from this cache to pass
|
||||||
|
// to the parser. This is so that the parser does not have the overhead of passing
|
||||||
|
// around and copying strings
|
||||||
|
loaded_files.insert(filename);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (parser.parse(input, loaded_files.find(filename)->c_str())) {
|
||||||
|
//parser.show_match_stack();
|
||||||
|
value = eval_token<Eval_Engine>(engine, parser.ast());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const Return_Value &rv) {
|
||||||
|
value = rv.retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the given boxed string, used during eval() inside of a script
|
||||||
|
*/
|
||||||
|
const Boxed_Value internal_eval(const std::vector<Boxed_Value> &vals) {
|
||||||
|
return do_eval(boxed_cast<std::string>(vals.at(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void use(const std::string &filename)
|
||||||
|
{
|
||||||
|
if (loaded_files.count(filename) == 0)
|
||||||
|
{
|
||||||
|
eval_file(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChaiScript_System() {
|
ChaiScript_System() {
|
||||||
build_eval_system();
|
build_eval_system();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an object to the system: type, function, object
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
ChaiScript_System &add(const T &t, const std::string &name)
|
||||||
|
{
|
||||||
|
engine.add(t, name);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a module object to the system
|
||||||
|
*/
|
||||||
|
ChaiScript_System &add(const ModulePtr &p)
|
||||||
|
{
|
||||||
|
engine.add(p);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for calling script code as if it were native C++ code
|
||||||
|
* example:
|
||||||
|
* boost::function<int (int, int)> f = build_functor(chai, "func(x, y){x+y}");
|
||||||
|
* \return a boost::function representing the passed in script
|
||||||
|
* \param[in] script Script code to build a function from
|
||||||
|
*/
|
||||||
|
template<typename FunctionType>
|
||||||
|
boost::function<FunctionType> functor(const std::string &script)
|
||||||
|
{
|
||||||
|
return chaiscript::functor<FunctionType>(eval(script));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate a string via eval method
|
||||||
|
*/
|
||||||
|
Boxed_Value operator()(const std::string &script)
|
||||||
|
{
|
||||||
|
return do_eval(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current evaluation engine
|
* Returns the current evaluation engine
|
||||||
*/
|
*/
|
||||||
@@ -43,25 +131,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates the given boxed string, used during eval() inside of a script
|
|
||||||
*/
|
|
||||||
const dispatchkit::Boxed_Value eval(const std::vector<dispatchkit::Boxed_Value> &vals) {
|
|
||||||
std::string val;
|
|
||||||
val = dispatchkit::boxed_cast<std::string &>(vals[0]);
|
|
||||||
|
|
||||||
return evaluate_string(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function for loading a file
|
* Helper function for loading a file
|
||||||
*/
|
*/
|
||||||
std::string load_file(const char *filename) {
|
std::string load_file(const std::string &filename) {
|
||||||
std::ifstream infile (filename, std::ios::in | std::ios::ate);
|
std::ifstream infile (filename.c_str(), std::ios::in | std::ios::ate);
|
||||||
|
|
||||||
if (!infile.is_open()) {
|
if (!infile.is_open()) {
|
||||||
std::string fname = filename;
|
throw std::runtime_error("Can not open: " + filename);
|
||||||
throw std::runtime_error("Can not open: " + fname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::streampos size = infile.tellg();
|
std::streampos size = infile.tellg();
|
||||||
@@ -79,48 +156,78 @@ namespace chaiscript
|
|||||||
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||||
*/
|
*/
|
||||||
void build_eval_system() {
|
void build_eval_system() {
|
||||||
dispatchkit::Bootstrap::bootstrap(engine);
|
using namespace bootstrap;
|
||||||
dispatchkit::bootstrap_vector<std::vector<dispatchkit::Boxed_Value> >(engine, "Vector");
|
engine.add_reserved_word("def");
|
||||||
dispatchkit::bootstrap_string<std::string>(engine, "string");
|
engine.add_reserved_word("fun");
|
||||||
dispatchkit::bootstrap_map<std::map<std::string, dispatchkit::Boxed_Value> >(engine, "Map");
|
engine.add_reserved_word("while");
|
||||||
dispatchkit::bootstrap_pair<std::pair<dispatchkit::Boxed_Value, dispatchkit::Boxed_Value > >(engine, "Pair");
|
engine.add_reserved_word("for");
|
||||||
|
engine.add_reserved_word("if");
|
||||||
|
engine.add_reserved_word("else");
|
||||||
|
engine.add_reserved_word("&&");
|
||||||
|
engine.add_reserved_word("||");
|
||||||
|
engine.add_reserved_word(",");
|
||||||
|
engine.add_reserved_word(":=");
|
||||||
|
engine.add_reserved_word("var");
|
||||||
|
engine.add_reserved_word("return");
|
||||||
|
engine.add_reserved_word("break");
|
||||||
|
engine.add_reserved_word("true");
|
||||||
|
engine.add_reserved_word("false");
|
||||||
|
engine.add_reserved_word("_");
|
||||||
|
|
||||||
engine.register_function(boost::shared_ptr<dispatchkit::Proxy_Function>(
|
|
||||||
new dispatchkit::Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::eval, boost::ref(*this), _1), 1)), "eval");
|
|
||||||
|
|
||||||
evaluate_string(chaiscript_prelude);
|
engine.add(Bootstrap::bootstrap());
|
||||||
|
|
||||||
|
engine.add(fun(boost::function<void ()>(boost::bind(&dump_system, boost::ref(engine)))), "dump_system");
|
||||||
|
engine.add(fun(boost::function<void (Boxed_Value)>(boost::bind(&dump_object, _1, boost::ref(engine)))), "dump_object");
|
||||||
|
engine.add(fun(boost::function<bool (Boxed_Value, const std::string &)>(boost::bind(&is_type, boost::ref(engine), _2, _1))),
|
||||||
|
"is_type");
|
||||||
|
|
||||||
|
engine.add(fun(boost::function<std::string (Boxed_Value)>(boost::bind(&chaiscript::type_name, boost::ref(engine), _1))),
|
||||||
|
"type_name");
|
||||||
|
engine.add(fun(boost::function<bool (const std::string &)>(boost::bind(&Eval_Engine::function_exists, boost::ref(engine), _1))),
|
||||||
|
"function_exists");
|
||||||
|
|
||||||
|
engine.add(vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||||
|
engine.add(string_type<std::string>("string"));
|
||||||
|
engine.add(map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||||
|
engine.add(pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||||
|
|
||||||
|
engine.add(fun(boost::function<void (const std::string &)>(boost::bind(&ChaiScript_System<Eval_Engine>::use, this, _1))), "use");
|
||||||
|
|
||||||
|
engine.add(Proxy_Function(
|
||||||
|
new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::internal_eval, boost::ref(*this), _1), 1)), "eval");
|
||||||
|
|
||||||
|
do_eval(chaiscript_prelude, "standard prelude");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
template<typename T>
|
||||||
* Evaluates the given string in by parsing it and running the results through the evaluator
|
T eval(const std::string &input)
|
||||||
*/
|
{
|
||||||
dispatchkit::Boxed_Value evaluate_string(const std::string &input, const char *filename = "__EVAL__") {
|
return boxed_cast<T>(do_eval(input));
|
||||||
//debug_print(tokens);
|
|
||||||
dispatchkit::Boxed_Value value;
|
|
||||||
parser.clear_match_stack();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (parser.parse(input, filename)) {
|
|
||||||
//parser.show_match_stack();
|
|
||||||
value = eval_token<Eval_Engine>(engine, parser.ast());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const Return_Value &rv) {
|
|
||||||
value = rv.retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
Boxed_Value eval(const std::string &input)
|
||||||
|
{
|
||||||
|
return do_eval(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the file specified by filename, evaluates it, and returns the result
|
* Loads the file specified by filename, evaluates it, and returns the result
|
||||||
*/
|
*/
|
||||||
dispatchkit::Boxed_Value evaluate_file(const char *filename) {
|
Boxed_Value eval_file(const std::string &filename) {
|
||||||
return evaluate_string(load_file(filename), filename);
|
return do_eval(load_file(filename), filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the file specified by filename, evaluates it, and returns the as the specified type
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
T eval_file(const std::string &filename) {
|
||||||
|
return boxed_cast<T>(do_eval(load_file(filename), filename));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ChaiScript_System<dispatchkit::Dispatch_Engine> ChaiScript_Engine;
|
typedef ChaiScript_System<Dispatch_Engine> ChaiScript;
|
||||||
}
|
}
|
||||||
#endif /* CHAISCRIPT_ENGINE_HPP_ */
|
#endif /* CHAISCRIPT_ENGINE_HPP_ */
|
||||||
|
|
||||||
|
@@ -15,14 +15,14 @@ namespace chaiscript
|
|||||||
* Helper function that will set up the scope around a function call, including handling the named function parameters
|
* Helper function that will set up the scope around a function call, including handling the named function parameters
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
const dispatchkit::Boxed_Value eval_function (Eval_System &ss, TokenPtr node, const std::vector<std::string> ¶m_names, const std::vector<dispatchkit::Boxed_Value> &vals) {
|
const Boxed_Value eval_function (Eval_System &ss, TokenPtr node, const std::vector<std::string> ¶m_names, const std::vector<Boxed_Value> &vals) {
|
||||||
ss.new_scope();
|
ss.new_scope();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < param_names.size(); ++i) {
|
for (unsigned int i = 0; i < param_names.size(); ++i) {
|
||||||
ss.add_object(param_names[i], vals[i]);
|
ss.add_object(param_names[i], vals[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
retval = eval_token(ss, node);
|
retval = eval_token(ss, node);
|
||||||
@@ -42,8 +42,8 @@ namespace chaiscript
|
|||||||
* Evaluates the top-level file node
|
* Evaluates the top-level file node
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_file(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_file(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < node->children.size(); ++i) {
|
for (i = 0; i < node->children.size(); ++i) {
|
||||||
retval = eval_token(ss, node->children[i]);
|
retval = eval_token(ss, node->children[i]);
|
||||||
@@ -55,13 +55,13 @@ namespace chaiscript
|
|||||||
* Evaluates a variable or function name identifier
|
* Evaluates a variable or function name identifier
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_id(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_id(Eval_System &ss, TokenPtr node) {
|
||||||
|
|
||||||
if (node->text == "true") {
|
if (node->text == "true") {
|
||||||
return dispatchkit::Boxed_Value(true);
|
return Boxed_Value(true);
|
||||||
}
|
}
|
||||||
else if (node->text == "false") {
|
else if (node->text == "false") {
|
||||||
return dispatchkit::Boxed_Value(false);
|
return Boxed_Value(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
@@ -77,68 +77,73 @@ namespace chaiscript
|
|||||||
* Evaluates a floating point number
|
* Evaluates a floating point number
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_float(Eval_System &, TokenPtr node) {
|
Boxed_Value eval_float(Eval_System &, TokenPtr node) {
|
||||||
return dispatchkit::Boxed_Value(double(atof(node->text.c_str())));
|
return Boxed_Value(double(atof(node->text.c_str())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates an integer
|
* Evaluates an integer
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_int(Eval_System &, TokenPtr node) {
|
Boxed_Value eval_int(Eval_System &, TokenPtr node) {
|
||||||
return dispatchkit::Boxed_Value(atoi(node->text.c_str()));
|
return Boxed_Value(atoi(node->text.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a quoted string
|
* Evaluates a quoted string
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_quoted_string(Eval_System &, TokenPtr node) {
|
Boxed_Value eval_quoted_string(Eval_System &, TokenPtr node) {
|
||||||
return dispatchkit::Boxed_Value(node->text);
|
return Boxed_Value(node->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a char group
|
* Evaluates a char group
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_single_quoted_string(Eval_System &, TokenPtr node) {
|
Boxed_Value eval_single_quoted_string(Eval_System &, TokenPtr node) {
|
||||||
return dispatchkit::Boxed_Value(node->text);
|
if (node->text.size() == 1) {
|
||||||
|
return Boxed_Value(char(node->text[0]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Boxed_Value(char((int)node->text[0] * 0xff + (int)node->text[0]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a string of equations in reverse order so that the right-most side has precedence
|
* Evaluates a string of equations in reverse order so that the right-most side has precedence
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_equation(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_equation(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
retval = eval_token(ss, node->children.back());
|
retval = eval_token(ss, node->children.back());
|
||||||
if (node->children.size() > 1) {
|
if (node->children.size() > 1) {
|
||||||
for (i = node->children.size()-3; ((int)i) >= 0; i -= 2) {
|
for (i = node->children.size()-3; ((int)i) >= 0; i -= 2) {
|
||||||
if (node->children[i+1]->text == "=") {
|
if (node->children[i+1]->text == "=") {
|
||||||
dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]);
|
Boxed_Value lhs = eval_token(ss, node->children[i]);
|
||||||
try {
|
try {
|
||||||
if (lhs.is_unknown())
|
if (lhs.is_unknown())
|
||||||
{
|
{
|
||||||
retval = dispatch(ss.get_function("clone"), dispatchkit::Param_List_Builder() << retval);
|
retval = dispatch(ss.get_function("clone"), Param_List_Builder() << retval);
|
||||||
}
|
}
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << lhs;
|
plb << lhs;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
try {
|
try {
|
||||||
retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
|
retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &){
|
catch(const dispatch_error &){
|
||||||
throw Eval_Error("Mismatched types in equation", node->children[i+1]);
|
throw Eval_Error("Mismatched types in equation", node->children[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &){
|
catch(const dispatch_error &){
|
||||||
throw Eval_Error("Can not clone right hand side of equation", node->children[i+1]);
|
throw Eval_Error("Can not clone right hand side of equation", node->children[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->children[i+1]->text == ":=") {
|
else if (node->children[i+1]->text == ":=") {
|
||||||
dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]);
|
Boxed_Value lhs = eval_token(ss, node->children[i]);
|
||||||
if (lhs.is_unknown() || dispatchkit::Bootstrap::type_match(lhs, retval)) {
|
if (lhs.is_unknown() || type_match(lhs, retval)) {
|
||||||
lhs.assign(retval);
|
lhs.assign(retval);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -146,13 +151,13 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << eval_token(ss, node->children[i]);
|
plb << eval_token(ss, node->children[i]);
|
||||||
plb << retval;
|
plb << retval;
|
||||||
try {
|
try {
|
||||||
retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
|
retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &){
|
catch(const dispatch_error &){
|
||||||
throw Eval_Error("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
|
throw Eval_Error("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,8 +170,13 @@ namespace chaiscript
|
|||||||
* Evaluates a variable declaration
|
* Evaluates a variable declaration
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) {
|
||||||
ss.add_object(node->children[0]->text, dispatchkit::Boxed_Value());
|
try {
|
||||||
|
ss.add_object(node->children[0]->text, Boxed_Value());
|
||||||
|
}
|
||||||
|
catch (reserved_word_error &rwe) {
|
||||||
|
throw Eval_Error("Reserved word used as variable '" + node->children[0]->text + "'", node);
|
||||||
|
}
|
||||||
return ss.get_object(node->children[0]->text);
|
return ss.get_object(node->children[0]->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,8 +184,8 @@ namespace chaiscript
|
|||||||
* Evaluates binary boolean operators. Respects short-circuiting rules.
|
* Evaluates binary boolean operators. Respects short-circuiting rules.
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_expression(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_expression(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
@@ -183,9 +193,9 @@ namespace chaiscript
|
|||||||
for (i = 1; i < node->children.size(); i += 2) {
|
for (i = 1; i < node->children.size(); i += 2) {
|
||||||
bool lhs;
|
bool lhs;
|
||||||
try {
|
try {
|
||||||
lhs = dispatchkit::boxed_cast<bool &>(retval);
|
lhs = boxed_cast<bool &>(retval);
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
throw Eval_Error("Condition not boolean", node);
|
throw Eval_Error("Condition not boolean", node);
|
||||||
}
|
}
|
||||||
if (node->children[i]->text == "&&") {
|
if (node->children[i]->text == "&&") {
|
||||||
@@ -193,12 +203,12 @@ namespace chaiscript
|
|||||||
retval = eval_token(ss, node->children[i+1]);
|
retval = eval_token(ss, node->children[i+1]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
retval = dispatchkit::Boxed_Value(false);
|
retval = Boxed_Value(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node->children[i]->text == "||") {
|
else if (node->children[i]->text == "||") {
|
||||||
if (lhs) {
|
if (lhs) {
|
||||||
retval = dispatchkit::Boxed_Value(true);
|
retval = Boxed_Value(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
retval = eval_token(ss, node->children[i+1]);
|
retval = eval_token(ss, node->children[i+1]);
|
||||||
@@ -213,21 +223,21 @@ namespace chaiscript
|
|||||||
* Evaluates comparison, additions, and multiplications and their relatives
|
* Evaluates comparison, additions, and multiplications and their relatives
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_comp_add_mul(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_comp_add_mul(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
if (node->children.size() > 1) {
|
if (node->children.size() > 1) {
|
||||||
for (i = 1; i < node->children.size(); i += 2) {
|
for (i = 1; i < node->children.size(); i += 2) {
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
plb << eval_token(ss, node->children[i + 1]);
|
plb << eval_token(ss, node->children[i + 1]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
retval = dispatch(ss.get_function(node->children[i]->text), plb);
|
retval = dispatch(ss.get_function(node->children[i]->text), plb);
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &){
|
catch(const dispatch_error &){
|
||||||
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
|
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,13 +250,13 @@ namespace chaiscript
|
|||||||
* Evaluates an array lookup
|
* Evaluates an array lookup
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_array_call(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_array_call(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
for (i = 1; i < node->children.size(); ++i) {
|
for (i = 1; i < node->children.size(); ++i) {
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
plb << eval_token(ss, node->children[i]);
|
plb << eval_token(ss, node->children[i]);
|
||||||
try {
|
try {
|
||||||
@@ -255,7 +265,7 @@ namespace chaiscript
|
|||||||
catch(std::out_of_range &) {
|
catch(std::out_of_range &) {
|
||||||
throw Eval_Error("Out of bounds exception", node);
|
throw Eval_Error("Out of bounds exception", node);
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &){
|
catch(const dispatch_error &){
|
||||||
throw Eval_Error("Can not find appropriate array lookup '[]' " + node->children[i]->text, node->children[i]);
|
throw Eval_Error("Can not find appropriate array lookup '[]' " + node->children[i]->text, node->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,13 +277,13 @@ namespace chaiscript
|
|||||||
* Evaluates a unary negation
|
* Evaluates a unary negation
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_negate(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_negate(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
plb << dispatchkit::Boxed_Value(-1.0);
|
plb << Boxed_Value(-1.0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return dispatch(ss.get_function("*"), plb);
|
return dispatch(ss.get_function("*"), plb);
|
||||||
@@ -287,29 +297,29 @@ namespace chaiscript
|
|||||||
* Evaluates a unary boolean not
|
* Evaluates a unary boolean not
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_not(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_not(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
bool cond;
|
bool cond;
|
||||||
try {
|
try {
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
cond = dispatchkit::boxed_cast<bool &>(retval);
|
cond = boxed_cast<bool &>(retval);
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
throw Eval_Error("Boolean not('!') condition not boolean", node->children[0]);
|
throw Eval_Error("Boolean not('!') condition not boolean", node->children[0]);
|
||||||
}
|
}
|
||||||
return dispatchkit::Boxed_Value(!cond);
|
return Boxed_Value(!cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates any unary prefix
|
* Evaluates any unary prefix
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_prefix(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_prefix(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[1]);
|
retval = eval_token(ss, node->children[1]);
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -324,25 +334,25 @@ namespace chaiscript
|
|||||||
* Evaluates (and generates) an inline array initialization
|
* Evaluates (and generates) an inline array initialization
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_inline_array(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_inline_array(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
retval = dispatch(ss.get_function("Vector"), dispatchkit::Param_List_Builder());
|
retval = dispatch(ss.get_function("Vector"), Param_List_Builder());
|
||||||
if (node->children.size() > 0) {
|
if (node->children.size() > 0) {
|
||||||
for (i = 0; i < node->children[0]->children.size(); ++i) {
|
for (i = 0; i < node->children[0]->children.size(); ++i) {
|
||||||
try {
|
try {
|
||||||
dispatchkit::Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
|
Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
|
||||||
dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << tmp);
|
dispatch(ss.get_function("push_back"), Param_List_Builder() << retval << tmp);
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::dispatch_error &) {
|
catch (const dispatch_error &) {
|
||||||
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
|
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::dispatch_error &) {
|
catch (const dispatch_error &) {
|
||||||
throw Eval_Error("Can not find appropriate 'Vector()'", node);
|
throw Eval_Error("Can not find appropriate 'Vector()'", node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,13 +363,13 @@ namespace chaiscript
|
|||||||
* Evaluates (and generates) an inline range initialization
|
* Evaluates (and generates) an inline range initialization
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_inline_range(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_inline_range(Eval_System &ss, TokenPtr node) {
|
||||||
try {
|
try {
|
||||||
return dispatch(ss.get_function("generate_range"), dispatchkit::Param_List_Builder()
|
return dispatch(ss.get_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[0])
|
||||||
<< eval_token(ss, node->children[0]->children[0]->children[1]));
|
<< eval_token(ss, node->children[0]->children[0]->children[1]));
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::dispatch_error &) {
|
catch (const dispatch_error &) {
|
||||||
throw Eval_Error("Unable to generate range vector", node);
|
throw Eval_Error("Unable to generate range vector", node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,24 +378,24 @@ namespace chaiscript
|
|||||||
* Evaluates (and generates) an inline map initialization
|
* Evaluates (and generates) an inline map initialization
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_inline_map(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_inline_map(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
retval = dispatch(ss.get_function("Map"), dispatchkit::Param_List_Builder());
|
retval = dispatch(ss.get_function("Map"), Param_List_Builder());
|
||||||
for (i = 0; i < node->children[0]->children.size(); ++i) {
|
for (i = 0; i < node->children[0]->children.size(); ++i) {
|
||||||
try {
|
try {
|
||||||
dispatchkit::Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
|
Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
|
||||||
dispatchkit::Boxed_Value slot = dispatch(ss.get_function("[]"), dispatchkit::Param_List_Builder() << retval << key);
|
Boxed_Value slot = dispatch(ss.get_function("[]"), Param_List_Builder() << retval << key);
|
||||||
dispatch(ss.get_function("="), dispatchkit::Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
|
dispatch(ss.get_function("="), Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::dispatch_error &) {
|
catch (const dispatch_error &) {
|
||||||
throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]);
|
throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::dispatch_error &) {
|
catch (const dispatch_error &) {
|
||||||
throw Eval_Error("Can not find appropriate 'Map()'", node);
|
throw Eval_Error("Can not find appropriate 'Map()'", node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,21 +406,21 @@ namespace chaiscript
|
|||||||
* Evaluates a function call, starting with its arguments. Handles resetting the scope to the previous one after the call.
|
* Evaluates a function call, starting with its arguments. Handles resetting the scope to the previous one after the call.
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_fun_call(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_fun_call(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack();
|
Dispatch_Engine::Stack prev_stack = ss.get_stack();
|
||||||
dispatchkit::Dispatch_Engine::Stack new_stack;
|
Dispatch_Engine::Stack new_stack = ss.new_stack();
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
new_stack.push_back(dispatchkit::Dispatch_Engine::Scope());
|
new_stack->push_back(Dispatch_Engine::Scope());
|
||||||
|
|
||||||
if ((node->children.size() > 1) && (node->children[1]->identifier == Token_Type::Arg_List)) {
|
if ((node->children.size() > 1) && (node->children[1]->identifier == Token_Type::Arg_List)) {
|
||||||
for (i = 0; i < node->children[1]->children.size(); ++i) {
|
for (i = 0; i < node->children[1]->children.size(); ++i) {
|
||||||
plb << eval_token(ss, node->children[1]->children[i]);
|
plb << eval_token(ss, node->children[1]->children[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatchkit::Boxed_Value fn;
|
Boxed_Value fn;
|
||||||
try {
|
try {
|
||||||
fn = eval_token(ss, node->children[0]);
|
fn = eval_token(ss, node->children[0]);
|
||||||
}
|
}
|
||||||
@@ -420,10 +430,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ss.set_stack(new_stack);
|
ss.set_stack(new_stack);
|
||||||
retval = (*dispatchkit::boxed_cast<boost::shared_ptr<dispatchkit::Proxy_Function> >(fn))(plb);
|
retval = (*boxed_cast<Proxy_Function >(fn))(plb);
|
||||||
ss.set_stack(prev_stack);
|
ss.set_stack(prev_stack);
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &e){
|
catch(const dispatch_error &e){
|
||||||
ss.set_stack(prev_stack);
|
ss.set_stack(prev_stack);
|
||||||
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
|
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
|
||||||
}
|
}
|
||||||
@@ -443,21 +453,21 @@ namespace chaiscript
|
|||||||
* Evaluates a method/attributes invocation
|
* Evaluates a method/attributes invocation
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_dot_access(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_dot_access(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
std::vector<std::pair<std::string, boost::shared_ptr<dispatchkit::Proxy_Function> > > fn;
|
std::vector<std::pair<std::string, Proxy_Function > > fn;
|
||||||
dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack();
|
Dispatch_Engine::Stack prev_stack = ss.get_stack();
|
||||||
dispatchkit::Dispatch_Engine::Stack new_stack;
|
Dispatch_Engine::Stack new_stack = ss.new_stack();
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
new_stack.push_back(dispatchkit::Dispatch_Engine::Scope());
|
new_stack->push_back(Dispatch_Engine::Scope());
|
||||||
|
|
||||||
//todo: Please extract a single way of doing function calls between this and eval_fun_call
|
//todo: Please extract a single way of doing function calls between this and eval_fun_call
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
if (node->children.size() > 1) {
|
if (node->children.size() > 1) {
|
||||||
for (i = 1; i < node->children.size(); ++i) {
|
for (i = 1; i < node->children.size(); ++i) {
|
||||||
dispatchkit::Param_List_Builder plb;
|
Param_List_Builder plb;
|
||||||
plb << retval;
|
plb << retval;
|
||||||
|
|
||||||
if (node->children[i]->children.size() > 1) {
|
if (node->children[i]->children.size() > 1) {
|
||||||
@@ -466,23 +476,32 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fun_name;
|
//std::string fun_name;
|
||||||
|
Boxed_Value fn;
|
||||||
|
try {
|
||||||
if (node->children[i]->identifier == Token_Type::Fun_Call) {
|
if (node->children[i]->identifier == Token_Type::Fun_Call) {
|
||||||
fun_name = node->children[i]->children[0]->text;
|
//fun_name = node->children[i]->children[0]->text;
|
||||||
|
fn = eval_token(ss, node->children[i]->children[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fun_name = node->children[i]->text;
|
//fun_name = node->children[i]->text;
|
||||||
|
fn = eval_token(ss, node->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Eval_Error &ee) {
|
||||||
|
ss.set_stack(prev_stack);
|
||||||
|
throw Eval_Error(ee.reason, node->children[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fn = ss.get_function(fun_name);
|
//fn = ss.get_function(fun_name);
|
||||||
ss.set_stack(new_stack);
|
ss.set_stack(new_stack);
|
||||||
retval = dispatch(fn, plb);
|
//retval = dispatch(fn, plb);
|
||||||
|
retval = (*boxed_cast<Proxy_Function >(fn))(plb);
|
||||||
ss.set_stack(prev_stack);
|
ss.set_stack(prev_stack);
|
||||||
}
|
}
|
||||||
catch(const dispatchkit::dispatch_error &e){
|
catch(const dispatch_error &e){
|
||||||
ss.set_stack(prev_stack);
|
ss.set_stack(prev_stack);
|
||||||
throw Eval_Error(std::string(e.what()) + " with function '" + fun_name + "'", node->children[i]);
|
throw Eval_Error(std::string(e.what()), node->children[i]);
|
||||||
}
|
}
|
||||||
catch(Return_Value &rv) {
|
catch(Return_Value &rv) {
|
||||||
ss.set_stack(prev_stack);
|
ss.set_stack(prev_stack);
|
||||||
@@ -502,16 +521,16 @@ namespace chaiscript
|
|||||||
* Evaluates an if/elseif/else block
|
* Evaluates an if/elseif/else block
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_if(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_if(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
bool cond;
|
bool cond;
|
||||||
try {
|
try {
|
||||||
cond = dispatchkit::boxed_cast<bool &>(retval);
|
cond = boxed_cast<bool &>(retval);
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
throw Eval_Error("If condition not boolean", node->children[0]);
|
throw Eval_Error("If condition not boolean", node->children[0]);
|
||||||
}
|
}
|
||||||
if (cond) {
|
if (cond) {
|
||||||
@@ -525,13 +544,13 @@ namespace chaiscript
|
|||||||
retval = eval_token(ss, node->children[i+1]);
|
retval = eval_token(ss, node->children[i+1]);
|
||||||
cond = true;
|
cond = true;
|
||||||
}
|
}
|
||||||
else if (node->children[i]->text == "elseif") {
|
else if (node->children[i]->text == "else if") {
|
||||||
retval = eval_token(ss, node->children[i+1]);
|
retval = eval_token(ss, node->children[i+1]);
|
||||||
try {
|
try {
|
||||||
cond = dispatchkit::boxed_cast<bool &>(retval);
|
cond = boxed_cast<bool &>(retval);
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
throw Eval_Error("Elseif condition not boolean", node->children[i+1]);
|
throw Eval_Error("'else if' condition not boolean", node->children[i+1]);
|
||||||
}
|
}
|
||||||
if (cond) {
|
if (cond) {
|
||||||
retval = eval_token(ss, node->children[i+2]);
|
retval = eval_token(ss, node->children[i+2]);
|
||||||
@@ -549,25 +568,26 @@ namespace chaiscript
|
|||||||
* Evaluates a while block
|
* Evaluates a while block
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_while(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_while(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
|
||||||
|
|
||||||
retval = eval_token(ss, node->children[0]);
|
|
||||||
bool cond;
|
bool cond;
|
||||||
|
|
||||||
|
ss.new_scope();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cond = dispatchkit::boxed_cast<bool &>(retval);
|
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
|
ss.pop_scope();
|
||||||
throw Eval_Error("While condition not boolean", node->children[0]);
|
throw Eval_Error("While condition not boolean", node->children[0]);
|
||||||
}
|
}
|
||||||
while (cond) {
|
while (cond) {
|
||||||
try {
|
try {
|
||||||
eval_token(ss, node->children[1]);
|
eval_token(ss, node->children[1]);
|
||||||
retval = eval_token(ss, node->children[0]);
|
|
||||||
try {
|
try {
|
||||||
cond = dispatchkit::boxed_cast<bool &>(retval);
|
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
|
ss.pop_scope();
|
||||||
throw Eval_Error("While condition not boolean", node->children[0]);
|
throw Eval_Error("While condition not boolean", node->children[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -575,30 +595,30 @@ namespace chaiscript
|
|||||||
cond = false;
|
cond = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dispatchkit::Boxed_Value();
|
ss.pop_scope();
|
||||||
|
return Boxed_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a for block, including the for's conditions, from left to right
|
* Evaluates a for block, including the for's conditions, from left to right
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_for(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_for(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
|
||||||
|
|
||||||
dispatchkit::Boxed_Value condition;
|
|
||||||
bool cond;
|
bool cond;
|
||||||
|
|
||||||
|
ss.new_scope();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (node->children.size() == 4) {
|
if (node->children.size() == 4) {
|
||||||
eval_token(ss, node->children[0]);
|
eval_token(ss, node->children[0]);
|
||||||
condition = eval_token(ss, node->children[1]);
|
cond = boxed_cast<bool &>(eval_token(ss, node->children[1]));
|
||||||
}
|
}
|
||||||
else if (node->children.size() == 3){
|
else {
|
||||||
condition = eval_token(ss, node->children[0]);
|
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
|
||||||
}
|
}
|
||||||
cond = dispatchkit::boxed_cast<bool &>(condition);
|
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
|
ss.pop_scope();
|
||||||
throw Eval_Error("For condition not boolean", node);
|
throw Eval_Error("For condition not boolean", node);
|
||||||
}
|
}
|
||||||
while (cond) {
|
while (cond) {
|
||||||
@@ -606,37 +626,37 @@ namespace chaiscript
|
|||||||
if (node->children.size() == 4) {
|
if (node->children.size() == 4) {
|
||||||
eval_token(ss, node->children[3]);
|
eval_token(ss, node->children[3]);
|
||||||
eval_token(ss, node->children[2]);
|
eval_token(ss, node->children[2]);
|
||||||
condition = eval_token(ss, node->children[1]);
|
cond = boxed_cast<bool &>(eval_token(ss, node->children[1]));
|
||||||
}
|
}
|
||||||
else if (node->children.size() == 3) {
|
else {
|
||||||
eval_token(ss, node->children[2]);
|
eval_token(ss, node->children[2]);
|
||||||
eval_token(ss, node->children[1]);
|
eval_token(ss, node->children[1]);
|
||||||
condition = eval_token(ss, node->children[0]);
|
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
|
||||||
}
|
}
|
||||||
cond = dispatchkit::boxed_cast<bool &>(condition);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (const dispatchkit::bad_boxed_cast &) {
|
catch (const bad_boxed_cast &) {
|
||||||
|
ss.pop_scope();
|
||||||
throw Eval_Error("For condition not boolean", node);
|
throw Eval_Error("For condition not boolean", node);
|
||||||
}
|
}
|
||||||
catch (Break_Loop &) {
|
catch (Break_Loop &) {
|
||||||
cond = false;
|
cond = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dispatchkit::Boxed_Value();
|
ss.pop_scope();
|
||||||
|
return Boxed_Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates a function definition
|
* Evaluates a function definition
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_def(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_def(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
std::vector<std::string> param_names;
|
std::vector<std::string> param_names;
|
||||||
std::string annotation = node->annotation?node->annotation->text:"";
|
std::string annotation = node->annotation?node->annotation->text:"";
|
||||||
boost::shared_ptr<dispatchkit::Dynamic_Proxy_Function> guard;
|
boost::shared_ptr<Dynamic_Proxy_Function> guard;
|
||||||
size_t numparams = 0;
|
size_t numparams = 0;
|
||||||
std::string function_name = node->children[0]->text;
|
std::string function_name = node->children[0]->text;
|
||||||
TokenPtr guardnode;
|
TokenPtr guardnode;
|
||||||
@@ -661,18 +681,22 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (guardnode) {
|
if (guardnode) {
|
||||||
guard = boost::shared_ptr<dispatchkit::Dynamic_Proxy_Function>
|
guard = boost::shared_ptr<Dynamic_Proxy_Function>
|
||||||
(new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
|
(new Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
|
||||||
boost::ref(ss), guardnode,
|
boost::ref(ss), guardnode,
|
||||||
param_names, _1), numparams));
|
param_names, _1), numparams));
|
||||||
}
|
}
|
||||||
|
|
||||||
ss.register_function(boost::shared_ptr<dispatchkit::Proxy_Function>
|
try {
|
||||||
(new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
|
ss.add(Proxy_Function
|
||||||
|
(new Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
|
||||||
boost::ref(ss), node->children.back(),
|
boost::ref(ss), node->children.back(),
|
||||||
param_names, _1), numparams,
|
param_names, _1), numparams,
|
||||||
annotation, guard)), function_name);
|
annotation, guard)), function_name);
|
||||||
|
}
|
||||||
|
catch (reserved_word_error &rwe) {
|
||||||
|
throw Eval_Error("Reserved word used as function name '" + function_name + "'", node);
|
||||||
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,8 +704,8 @@ namespace chaiscript
|
|||||||
* Evaluates a lambda (anonymous function)
|
* Evaluates a lambda (anonymous function)
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_lambda(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_lambda(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
std::vector<std::string> param_names;
|
std::vector<std::string> param_names;
|
||||||
@@ -699,8 +723,8 @@ namespace chaiscript
|
|||||||
numparams = 0;
|
numparams = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dispatchkit::Boxed_Value(boost::shared_ptr<dispatchkit::Proxy_Function>(
|
return Boxed_Value(Proxy_Function(
|
||||||
new dispatchkit::Dynamic_Proxy_Function(
|
new Dynamic_Proxy_Function(
|
||||||
boost::bind(&eval_function<Eval_System>, boost::ref(ss), node->children.back(), param_names, _1), numparams)));
|
boost::bind(&eval_function<Eval_System>, boost::ref(ss), node->children.back(), param_names, _1), numparams)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,8 +732,8 @@ namespace chaiscript
|
|||||||
* Evaluates a scoped block. Handles resetting the scope after the block has completed.
|
* Evaluates a scoped block. Handles resetting the scope after the block has completed.
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_block(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_block(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
ss.new_scope();
|
ss.new_scope();
|
||||||
@@ -736,13 +760,13 @@ namespace chaiscript
|
|||||||
* Evaluates a return statement
|
* Evaluates a return statement
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_return(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_return(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
Boxed_Value retval;
|
||||||
if (node->children.size() > 0) {
|
if (node->children.size() > 0) {
|
||||||
retval = eval_token(ss, node->children[0]);
|
retval = eval_token(ss, node->children[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
retval = dispatchkit::Boxed_Value();
|
retval = Boxed_Value();
|
||||||
}
|
}
|
||||||
throw Return_Value(retval, node);
|
throw Return_Value(retval, node);
|
||||||
}
|
}
|
||||||
@@ -751,7 +775,7 @@ namespace chaiscript
|
|||||||
* Evaluates a break statement
|
* Evaluates a break statement
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_break(Eval_System &, TokenPtr node) {
|
Boxed_Value eval_break(Eval_System &, TokenPtr node) {
|
||||||
throw Break_Loop(node);
|
throw Break_Loop(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -759,122 +783,121 @@ namespace chaiscript
|
|||||||
* Top-level evaluation dispatch for all AST node types
|
* Top-level evaluation dispatch for all AST node types
|
||||||
*/
|
*/
|
||||||
template <typename Eval_System>
|
template <typename Eval_System>
|
||||||
dispatchkit::Boxed_Value eval_token(Eval_System &ss, TokenPtr node) {
|
Boxed_Value eval_token(Eval_System &ss, TokenPtr node) {
|
||||||
dispatchkit::Boxed_Value retval;
|
|
||||||
|
|
||||||
switch (node->identifier) {
|
switch (node->identifier) {
|
||||||
case (Token_Type::File) :
|
case (Token_Type::File) :
|
||||||
retval = eval_file(ss, node);
|
return eval_file(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Id) :
|
case (Token_Type::Id) :
|
||||||
retval = eval_id(ss, node);
|
return eval_id(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Float) :
|
case (Token_Type::Float) :
|
||||||
retval = eval_float(ss, node);
|
return eval_float(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Int) :
|
case (Token_Type::Int) :
|
||||||
retval = eval_int(ss, node);
|
return eval_int(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Quoted_String) :
|
case (Token_Type::Quoted_String) :
|
||||||
retval = eval_quoted_string(ss, node);
|
return eval_quoted_string(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Single_Quoted_String) :
|
case (Token_Type::Single_Quoted_String) :
|
||||||
retval = eval_single_quoted_string(ss, node);
|
return eval_single_quoted_string(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Equation) :
|
case (Token_Type::Equation) :
|
||||||
retval = eval_equation(ss, node);
|
return eval_equation(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Var_Decl) :
|
case (Token_Type::Var_Decl) :
|
||||||
retval = eval_var_decl(ss, node);
|
return eval_var_decl(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Expression) :
|
case (Token_Type::Expression) :
|
||||||
retval = eval_expression(ss, node);
|
return eval_expression(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Comparison) :
|
case (Token_Type::Comparison) :
|
||||||
case (Token_Type::Additive) :
|
case (Token_Type::Additive) :
|
||||||
case (Token_Type::Multiplicative) :
|
case (Token_Type::Multiplicative) :
|
||||||
retval = eval_comp_add_mul(ss, node);
|
return eval_comp_add_mul(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Array_Call) :
|
case (Token_Type::Array_Call) :
|
||||||
retval = eval_array_call(ss, node);
|
return eval_array_call(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Negate) :
|
case (Token_Type::Negate) :
|
||||||
retval = eval_negate(ss, node);
|
return eval_negate(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Not) :
|
case (Token_Type::Not) :
|
||||||
retval = eval_not(ss, node);
|
return eval_not(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Prefix) :
|
case (Token_Type::Prefix) :
|
||||||
retval = eval_prefix(ss, node);
|
return eval_prefix(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Inline_Array) :
|
case (Token_Type::Inline_Array) :
|
||||||
retval = eval_inline_array(ss, node);
|
return eval_inline_array(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Inline_Range) :
|
case (Token_Type::Inline_Range) :
|
||||||
retval = eval_inline_range(ss, node);
|
return eval_inline_range(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Inline_Map) :
|
case (Token_Type::Inline_Map) :
|
||||||
retval = eval_inline_map(ss, node);
|
return eval_inline_map(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Fun_Call) :
|
case (Token_Type::Fun_Call) :
|
||||||
retval = eval_fun_call(ss, node);
|
return eval_fun_call(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Dot_Access) :
|
case (Token_Type::Dot_Access) :
|
||||||
retval = eval_dot_access(ss, node);
|
return eval_dot_access(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(Token_Type::If) :
|
case(Token_Type::If) :
|
||||||
retval = eval_if(ss, node);
|
return eval_if(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(Token_Type::While) :
|
case(Token_Type::While) :
|
||||||
retval = eval_while(ss, node);
|
return eval_while(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(Token_Type::For) :
|
case(Token_Type::For) :
|
||||||
retval = eval_for(ss, node);
|
return eval_for(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Def) :
|
case (Token_Type::Def) :
|
||||||
retval = eval_def(ss, node);
|
return eval_def(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Lambda) :
|
case (Token_Type::Lambda) :
|
||||||
retval = eval_lambda(ss, node);
|
return eval_lambda(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Block) :
|
case (Token_Type::Block) :
|
||||||
retval = eval_block(ss, node);
|
return eval_block(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Return) :
|
case (Token_Type::Return) :
|
||||||
retval = eval_return(ss, node);
|
return eval_return(ss, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (Token_Type::Break) :
|
case (Token_Type::Break) :
|
||||||
retval = eval_break(ss, node);
|
return eval_break(ss, node);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
default :
|
||||||
|
return Boxed_Value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CHAISCRIPT_EVAL_HPP_ */
|
#endif /* CHAISCRIPT_EVAL_HPP_ */
|
||||||
|
@@ -140,7 +140,7 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
bool Float_() {
|
bool Float_() {
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
if ((input_pos != input_end) && (*input_pos >= '0') && (*input_pos <= '9')) {
|
if ((input_pos != input_end) && (((*input_pos >= '0') && (*input_pos <= '9')) || (*input_pos == '.'))) {
|
||||||
while ((input_pos != input_end) && (*input_pos >= '0') && (*input_pos <= '9')) {
|
while ((input_pos != input_end) && (*input_pos >= '0') && (*input_pos <= '9')) {
|
||||||
++input_pos;
|
++input_pos;
|
||||||
++col;
|
++col;
|
||||||
@@ -178,7 +178,7 @@ namespace chaiscript
|
|||||||
std::string::iterator start = input_pos;
|
std::string::iterator start = input_pos;
|
||||||
int prev_col = col;
|
int prev_col = col;
|
||||||
int prev_line = line;
|
int prev_line = line;
|
||||||
if ((input_pos != input_end) && (*input_pos >= '0') && (*input_pos <= '9')) {
|
if ((input_pos != input_end) && (((*input_pos >= '0') && (*input_pos <= '9')) || (*input_pos == '.')) ) {
|
||||||
if (Float_()) {
|
if (Float_()) {
|
||||||
std::string match(start, input_pos);
|
std::string match(start, input_pos);
|
||||||
TokenPtr t(new Token(match, Token_Type::Float, filename, prev_line, prev_col, line, col));
|
TokenPtr t(new Token(match, Token_Type::Float, filename, prev_line, prev_col, line, col));
|
||||||
@@ -301,7 +301,7 @@ namespace chaiscript
|
|||||||
++col;
|
++col;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw Parse_Error("Unclosed quoted string", File_Position(line, col), filename);
|
throw Eval_Error("Unclosed quoted string", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@@ -343,7 +343,7 @@ namespace chaiscript
|
|||||||
case ('t') : match.push_back('\t'); break;
|
case ('t') : match.push_back('\t'); break;
|
||||||
case ('\'') : match.push_back('\''); break;
|
case ('\'') : match.push_back('\''); break;
|
||||||
case ('\"') : match.push_back('\"'); break;
|
case ('\"') : match.push_back('\"'); break;
|
||||||
default: throw Parse_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
|
default: throw Eval_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -392,7 +392,7 @@ namespace chaiscript
|
|||||||
++col;
|
++col;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw Parse_Error("Unclosed single-quoted string", File_Position(line, col), filename);
|
throw Eval_Error("Unclosed single-quoted string", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@@ -434,7 +434,7 @@ namespace chaiscript
|
|||||||
case ('t') : match.push_back('\t'); break;
|
case ('t') : match.push_back('\t'); break;
|
||||||
case ('\'') : match.push_back('\''); break;
|
case ('\'') : match.push_back('\''); break;
|
||||||
case ('\"') : match.push_back('\"'); break;
|
case ('\"') : match.push_back('\"'); break;
|
||||||
default: throw Parse_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
|
default: throw Eval_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -694,7 +694,7 @@ namespace chaiscript
|
|||||||
if (Char(',')) {
|
if (Char(',')) {
|
||||||
do {
|
do {
|
||||||
if (!Equation()) {
|
if (!Equation()) {
|
||||||
throw Parse_Error("Unexpected value in parameter list", match_stack.back());
|
throw Eval_Error("Unexpected value in parameter list", match_stack.back());
|
||||||
}
|
}
|
||||||
} while (retval && Char(','));
|
} while (retval && Char(','));
|
||||||
}
|
}
|
||||||
@@ -721,7 +721,7 @@ namespace chaiscript
|
|||||||
if (Char(',')) {
|
if (Char(',')) {
|
||||||
do {
|
do {
|
||||||
if (!Map_Pair()) {
|
if (!Map_Pair()) {
|
||||||
throw Parse_Error("Unexpected value in container", match_stack.back());
|
throw Eval_Error("Unexpected value in container", match_stack.back());
|
||||||
}
|
}
|
||||||
} while (retval && Char(','));
|
} while (retval && Char(','));
|
||||||
}
|
}
|
||||||
@@ -746,14 +746,14 @@ namespace chaiscript
|
|||||||
if (Char('(')) {
|
if (Char('(')) {
|
||||||
Arg_List();
|
Arg_List();
|
||||||
if (!Char(')')) {
|
if (!Char(')')) {
|
||||||
throw Parse_Error("Incomplete anonymous function", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete anonymous function", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
|
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete anonymous function", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete anonymous function", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Lambda, prev_stack_top);
|
build_match(Token_Type::Lambda, prev_stack_top);
|
||||||
@@ -784,13 +784,13 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Id(true)) {
|
if (!Id(true)) {
|
||||||
throw Parse_Error("Missing function name in definition", File_Position(line, col), filename);
|
throw Eval_Error("Missing function name in definition", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Char('(')) {
|
if (Char('(')) {
|
||||||
Arg_List();
|
Arg_List();
|
||||||
if (!Char(')')) {
|
if (!Char(')')) {
|
||||||
throw Parse_Error("Incomplete function definition", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete function definition", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,13 +798,13 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (Char(':')) {
|
if (Char(':')) {
|
||||||
if (!Expression()) {
|
if (!Expression()) {
|
||||||
throw Parse_Error("Missing guard expression for function", File_Position(line, col), filename);
|
throw Eval_Error("Missing guard expression for function", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete function definition", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete function definition", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Def, prev_stack_top);
|
build_match(Token_Type::Def, prev_stack_top);
|
||||||
@@ -829,48 +829,51 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Char('(')) {
|
if (!Char('(')) {
|
||||||
throw Parse_Error("Incomplete 'if' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Expression() && Char(')'))) {
|
if (!(Expression() && Char(')'))) {
|
||||||
throw Parse_Error("Incomplete 'if' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
|
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete 'if' block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'if' block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_matches = true;
|
bool has_matches = true;
|
||||||
while (has_matches) {
|
while (has_matches) {
|
||||||
while (Eol());
|
while (Eol());
|
||||||
has_matches = false;
|
has_matches = false;
|
||||||
if (Keyword("elseif", true)) {
|
if (Keyword("else", true)) {
|
||||||
|
if (Keyword("if")) {
|
||||||
|
match_stack.back()->text = "else if";
|
||||||
if (!Char('(')) {
|
if (!Char('(')) {
|
||||||
throw Parse_Error("Incomplete 'elseif' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Expression() && Char(')'))) {
|
if (!(Expression() && Char(')'))) {
|
||||||
throw Parse_Error("Incomplete 'elseif' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
|
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete 'elseif' block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'else if' block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
has_matches = true;
|
has_matches = true;
|
||||||
}
|
}
|
||||||
else if (Keyword("else", true)) {
|
else {
|
||||||
while (Eol());
|
while (Eol());
|
||||||
|
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete 'else' block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'else' block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
has_matches = true;
|
has_matches = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
build_match(Token_Type::If, prev_stack_top);
|
build_match(Token_Type::If, prev_stack_top);
|
||||||
}
|
}
|
||||||
@@ -890,17 +893,17 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Char('(')) {
|
if (!Char('(')) {
|
||||||
throw Parse_Error("Incomplete 'while' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Expression() && Char(')'))) {
|
if (!(Expression() && Char(')'))) {
|
||||||
throw Parse_Error("Incomplete 'while' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
|
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete 'while' block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'while' block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::While, prev_stack_top);
|
build_match(Token_Type::While, prev_stack_top);
|
||||||
@@ -919,7 +922,7 @@ namespace chaiscript
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw Parse_Error("Incomplete conditions in 'for' loop", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete conditions in 'for' loop", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,17 +938,17 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Char('(')) {
|
if (!Char('(')) {
|
||||||
throw Parse_Error("Incomplete 'for' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'for' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(For_Guards() && Char(')'))) {
|
if (!(For_Guards() && Char(')'))) {
|
||||||
throw Parse_Error("Incomplete 'for' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'for' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Eol());
|
while (Eol());
|
||||||
|
|
||||||
if (!Block()) {
|
if (!Block()) {
|
||||||
throw Parse_Error("Incomplete 'for' block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete 'for' block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::For, prev_stack_top);
|
build_match(Token_Type::For, prev_stack_top);
|
||||||
@@ -967,7 +970,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
Statements();
|
Statements();
|
||||||
if (!Char('}')) {
|
if (!Char('}')) {
|
||||||
throw Parse_Error("Incomplete block", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete block", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Block, prev_stack_top);
|
build_match(Token_Type::Block, prev_stack_top);
|
||||||
@@ -1031,7 +1034,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
Arg_List();
|
Arg_List();
|
||||||
if (!Char(')')) {
|
if (!Char(')')) {
|
||||||
throw Parse_Error("Incomplete function call", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete function call", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Fun_Call, prev_stack_top);
|
build_match(Token_Type::Fun_Call, prev_stack_top);
|
||||||
@@ -1040,7 +1043,7 @@ namespace chaiscript
|
|||||||
has_more = true;
|
has_more = true;
|
||||||
|
|
||||||
if (!(Expression() && Char(']'))) {
|
if (!(Expression() && Char(']'))) {
|
||||||
throw Parse_Error("Incomplete array access", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete array access", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Array_Call, prev_stack_top);
|
build_match(Token_Type::Array_Call, prev_stack_top);
|
||||||
@@ -1063,7 +1066,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Id(true)) {
|
if (!Id(true)) {
|
||||||
throw Parse_Error("Incomplete variable declaration", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete variable declaration", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Var_Decl, prev_stack_top);
|
build_match(Token_Type::Var_Decl, prev_stack_top);
|
||||||
@@ -1081,10 +1084,10 @@ namespace chaiscript
|
|||||||
if (Char('(')) {
|
if (Char('(')) {
|
||||||
retval = true;
|
retval = true;
|
||||||
if (!Expression()) {
|
if (!Expression()) {
|
||||||
throw Parse_Error("Incomplete expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
if (!Char(')')) {
|
if (!Char(')')) {
|
||||||
throw Parse_Error("Missing closing parenthesis", File_Position(line, col), filename);
|
throw Eval_Error("Missing closing parenthesis", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
@@ -1102,7 +1105,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
Container_Arg_List();
|
Container_Arg_List();
|
||||||
if (!Char(']')) {
|
if (!Char(']')) {
|
||||||
throw Parse_Error("Missing closing square bracket", File_Position(line, col), filename);
|
throw Eval_Error("Missing closing square bracket", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
if ((prev_stack_top != match_stack.size()) && (match_stack.back()->children.size() > 0)) {
|
if ((prev_stack_top != match_stack.size()) && (match_stack.back()->children.size() > 0)) {
|
||||||
if (match_stack.back()->children[0]->identifier == Token_Type::Value_Range) {
|
if (match_stack.back()->children[0]->identifier == Token_Type::Value_Range) {
|
||||||
@@ -1144,7 +1147,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
while ((input_pos != input_end) && (*input_pos != '`')) {
|
while ((input_pos != input_end) && (*input_pos != '`')) {
|
||||||
if (Eol()) {
|
if (Eol()) {
|
||||||
throw Parse_Error("Carriage return in identifier literal", File_Position(line, col), filename);
|
throw Eval_Error("Carriage return in identifier literal", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
++input_pos;
|
++input_pos;
|
||||||
@@ -1153,10 +1156,10 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (start == input_pos) {
|
if (start == input_pos) {
|
||||||
throw Parse_Error("Missing contents of identifier literal", File_Position(line, col), filename);
|
throw Eval_Error("Missing contents of identifier literal", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
else if (input_pos == input_end) {
|
else if (input_pos == input_end) {
|
||||||
throw Parse_Error("Incomplete identifier literal", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete identifier literal", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
++col;
|
++col;
|
||||||
@@ -1182,7 +1185,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Dot_Access()) {
|
if (!Dot_Access()) {
|
||||||
throw Parse_Error("Incomplete negation expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete negation expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Negate, prev_stack_top);
|
build_match(Token_Type::Negate, prev_stack_top);
|
||||||
@@ -1191,7 +1194,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Dot_Access()) {
|
if (!Dot_Access()) {
|
||||||
throw Parse_Error("Incomplete '!' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete '!' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Not, prev_stack_top);
|
build_match(Token_Type::Not, prev_stack_top);
|
||||||
@@ -1200,7 +1203,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Dot_Access()) {
|
if (!Dot_Access()) {
|
||||||
throw Parse_Error("Incomplete '++' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete '++' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Prefix, prev_stack_top);
|
build_match(Token_Type::Prefix, prev_stack_top);
|
||||||
@@ -1209,7 +1212,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Dot_Access()) {
|
if (!Dot_Access()) {
|
||||||
throw Parse_Error("Incomplete '--' expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete '--' expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Prefix, prev_stack_top);
|
build_match(Token_Type::Prefix, prev_stack_top);
|
||||||
@@ -1244,7 +1247,7 @@ namespace chaiscript
|
|||||||
if (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)) {
|
if (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)) {
|
||||||
do {
|
do {
|
||||||
if (!Additive()) {
|
if (!Additive()) {
|
||||||
throw Parse_Error("Incomplete comparison expression", File_Position(line, col), filename);
|
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)));
|
} while (retval && (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)));
|
||||||
|
|
||||||
@@ -1268,7 +1271,7 @@ namespace chaiscript
|
|||||||
if (Symbol("+", true) || Symbol("-", true)) {
|
if (Symbol("+", true) || Symbol("-", true)) {
|
||||||
do {
|
do {
|
||||||
if (!Multiplicative()) {
|
if (!Multiplicative()) {
|
||||||
throw Parse_Error("Incomplete math expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
} while (retval && (Symbol("+", true) || Symbol("-", true)));
|
} while (retval && (Symbol("+", true) || Symbol("-", true)));
|
||||||
|
|
||||||
@@ -1292,7 +1295,7 @@ namespace chaiscript
|
|||||||
if (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)) {
|
if (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)) {
|
||||||
do {
|
do {
|
||||||
if (!Dot_Access()) {
|
if (!Dot_Access()) {
|
||||||
throw Parse_Error("Incomplete math expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
} while (retval && (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)));
|
} while (retval && (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)));
|
||||||
|
|
||||||
@@ -1316,7 +1319,7 @@ namespace chaiscript
|
|||||||
if (Symbol(".")) {
|
if (Symbol(".")) {
|
||||||
do {
|
do {
|
||||||
if (!Value()) {
|
if (!Value()) {
|
||||||
throw Parse_Error("Incomplete dot notation", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete dot notation", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
} while (retval && Symbol("."));
|
} while (retval && Symbol("."));
|
||||||
|
|
||||||
@@ -1340,7 +1343,7 @@ namespace chaiscript
|
|||||||
if (Symbol("&&", true) || Symbol("||", true)) {
|
if (Symbol("&&", true) || Symbol("||", true)) {
|
||||||
do {
|
do {
|
||||||
if (!Comparison()) {
|
if (!Comparison()) {
|
||||||
throw Parse_Error("Incomplete expression", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
} while (retval && (Symbol("&&", true) || Symbol("||", true)));
|
} while (retval && (Symbol("&&", true) || Symbol("||", true)));
|
||||||
|
|
||||||
@@ -1364,7 +1367,7 @@ namespace chaiscript
|
|||||||
if (Symbol(":")) {
|
if (Symbol(":")) {
|
||||||
do {
|
do {
|
||||||
if (!Expression()) {
|
if (!Expression()) {
|
||||||
throw Parse_Error("Incomplete map pair", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete map pair", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
} while (retval && Symbol(":"));
|
} while (retval && Symbol(":"));
|
||||||
|
|
||||||
@@ -1389,7 +1392,7 @@ namespace chaiscript
|
|||||||
if (Symbol("..")) {
|
if (Symbol("..")) {
|
||||||
retval = true;
|
retval = true;
|
||||||
if (!Expression()) {
|
if (!Expression()) {
|
||||||
throw Parse_Error("Incomplete value range", File_Position(line, col), filename);
|
throw Eval_Error("Incomplete value range", File_Position(line, col), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Value_Range, prev_stack_top);
|
build_match(Token_Type::Value_Range, prev_stack_top);
|
||||||
@@ -1418,7 +1421,7 @@ namespace chaiscript
|
|||||||
retval = true;
|
retval = true;
|
||||||
if (Symbol("=", true) || Symbol(":=", true) || Symbol("+=", true) || Symbol("-=", true) || Symbol("*=", true) || Symbol("/=", true)) {
|
if (Symbol("=", true) || Symbol(":=", true) || Symbol("+=", true) || Symbol("-=", true) || Symbol("*=", true) || Symbol("/=", true)) {
|
||||||
if (!Equation()) {
|
if (!Equation()) {
|
||||||
throw Parse_Error("Incomplete equation", match_stack.back());
|
throw Eval_Error("Incomplete equation", match_stack.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match(Token_Type::Equation, prev_stack_top);
|
build_match(Token_Type::Equation, prev_stack_top);
|
||||||
@@ -1441,7 +1444,7 @@ namespace chaiscript
|
|||||||
has_more = false;
|
has_more = false;
|
||||||
if (Def()) {
|
if (Def()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
|
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1449,7 +1452,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (If()) {
|
else if (If()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
|
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1457,7 +1460,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (While()) {
|
else if (While()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
|
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1465,7 +1468,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (For()) {
|
else if (For()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
|
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1473,7 +1476,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (Return()) {
|
else if (Return()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two expressions missing line separator", match_stack.back());
|
throw Eval_Error("Two expressions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1481,7 +1484,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (Break()) {
|
else if (Break()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two expressions missing line separator", match_stack.back());
|
throw Eval_Error("Two expressions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1489,7 +1492,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (Equation()) {
|
else if (Equation()) {
|
||||||
if (!saw_eol) {
|
if (!saw_eol) {
|
||||||
throw Parse_Error("Two expressions missing line separator", match_stack.back());
|
throw Eval_Error("Two expressions missing line separator", match_stack.back());
|
||||||
}
|
}
|
||||||
has_more = true;
|
has_more = true;
|
||||||
retval = true;
|
retval = true;
|
||||||
@@ -1525,7 +1528,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (Statements()) {
|
if (Statements()) {
|
||||||
if (input_pos != input_end) {
|
if (input_pos != input_end) {
|
||||||
throw Parse_Error("Unparsed input", File_Position(line, col), fname);
|
throw Eval_Error("Unparsed input", File_Position(line, col), fname);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
build_match(Token_Type::File, 0);
|
build_match(Token_Type::File, 0);
|
||||||
|
@@ -12,6 +12,8 @@
|
|||||||
#define CODE_STRING(x, y) #x ", " #y
|
#define CODE_STRING(x, y) #x ", " #y
|
||||||
|
|
||||||
#define chaiscript_prelude CODE_STRING(\
|
#define chaiscript_prelude CODE_STRING(\
|
||||||
|
def new(x) { eval(type_name(x))(); } \
|
||||||
|
def clone(x) : function_exists(type_name(x)) { eval(type_name(x))(x); } \
|
||||||
# to_string for Pair()\n\
|
# to_string for Pair()\n\
|
||||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \
|
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \
|
||||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \
|
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \
|
||||||
@@ -22,7 +24,7 @@ def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \
|
|||||||
}\
|
}\
|
||||||
# Basic to_string function\n\
|
# Basic to_string function\n\
|
||||||
def to_string(x) { \
|
def to_string(x) { \
|
||||||
return internal_to_string(x); \
|
internal_to_string(x); \
|
||||||
}\
|
}\
|
||||||
# Prints to console with no carriage return\n\
|
# Prints to console with no carriage return\n\
|
||||||
def puts(x) { \
|
def puts(x) { \
|
||||||
@@ -41,10 +43,20 @@ def odd(x) { if (x % 2 == 1) { true } else { false } } \
|
|||||||
# Returns true if the value is even\n\
|
# Returns true if the value is even\n\
|
||||||
def even(x) { if (x % 2 == 0) { true } else { false } } \
|
def even(x) { if (x % 2 == 0) { true } else { false } } \
|
||||||
# Pushes the second value onto the container first value while making a clone of the value\n\
|
# Pushes the second value onto the container first value while making a clone of the value\n\
|
||||||
def push_back(container, x) { container.push_back_ref(clone(x)) } \n\
|
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_ref(clone(x)) } \n\
|
||||||
# Inserts the third value at the position of the second value into the container of the first\n\
|
# Inserts the third value at the position of the second value into the container of the first\n\
|
||||||
# while making a clone. \n\
|
# while making a clone. \n\
|
||||||
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
|
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
|
||||||
|
# Returns the reverse of the given container\n\
|
||||||
|
def reverse(container) {\
|
||||||
|
var retval = new(container); \
|
||||||
|
var r = retro(range(container)); \
|
||||||
|
while (!r.empty()) { \
|
||||||
|
retval.push_back(r.front()); \
|
||||||
|
r.pop_front(); \
|
||||||
|
} \
|
||||||
|
retval; \
|
||||||
|
} \
|
||||||
# Performs the second value function over the container first value\n\
|
# Performs the second value function over the container first value\n\
|
||||||
def for_each(container, func) : call_exists(range, container) { \
|
def for_each(container, func) : call_exists(range, container) { \
|
||||||
var range = range(container); \
|
var range = range(container); \
|
||||||
@@ -54,7 +66,7 @@ def for_each(container, func) : call_exists(range, container) { \
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
def back_inserter(container) { \
|
def back_inserter(container) { \
|
||||||
return bind(push_back, container, _); \
|
bind(push_back, container, _); \
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
def map(container, func, inserter) : call_exists(range, container) { \
|
def map(container, func, inserter) : call_exists(range, container) { \
|
||||||
@@ -64,11 +76,11 @@ def map(container, func, inserter) : call_exists(range, container) { \
|
|||||||
range.pop_front(); \
|
range.pop_front(); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
# Performs the second value function over the container first value. Creates a new Vector with the results\n\
|
# Performs the second value function over the container first value. Creates a new container with the results\n\
|
||||||
def map(container, func) { \
|
def map(container, func) { \
|
||||||
var retval = Vector();\
|
var retval = new(container); \
|
||||||
map(container, func, back_inserter(retval));\
|
map(container, func, back_inserter(retval));\
|
||||||
return retval;\
|
retval;\
|
||||||
}\
|
}\
|
||||||
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
|
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
|
||||||
def foldl(container, func, initial) : call_exists(range, container){ \
|
def foldl(container, func, initial) : call_exists(range, container){ \
|
||||||
@@ -84,7 +96,7 @@ def foldl(container, func, initial) : call_exists(range, container){ \
|
|||||||
def sum(container) { foldl(container, `+`, 0.0) } \
|
def sum(container) { foldl(container, `+`, 0.0) } \
|
||||||
# Returns the product of the elements of the given value\n\
|
# Returns the product of the elements of the given value\n\
|
||||||
def product(container) { foldl(container, `*`, 1.0) } \
|
def product(container) { foldl(container, `*`, 1.0) } \
|
||||||
# Returns a new Vector with the elements of the first value concatenated with the elements of the second value\n\
|
# Returns a new container with the elements of the first value concatenated with the elements of the second value\n\
|
||||||
def concat(x, y) : call_exists(clone, x) { \
|
def concat(x, y) : call_exists(clone, x) { \
|
||||||
var retval = x; \
|
var retval = x; \
|
||||||
var len = y.size(); \
|
var len = y.size(); \
|
||||||
@@ -104,11 +116,11 @@ def take(container, num, inserter) : call_exists(range, container) { \
|
|||||||
--i; \
|
--i; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
# Returns a new Vector with the given number of elements taken from the container\n\
|
# Returns a new container with the given number of elements taken from the container\n\
|
||||||
def take(container, num) {\
|
def take(container, num) {\
|
||||||
var retval = Vector(); \
|
var retval = new(container); \
|
||||||
take(container, num, back_inserter(retval)); \
|
take(container, num, back_inserter(retval)); \
|
||||||
return retval; \
|
retval; \
|
||||||
}\
|
}\
|
||||||
def take_while(container, f, inserter) : call_exists(range, container) { \
|
def take_while(container, f, inserter) : call_exists(range, container) { \
|
||||||
var r = range(container); \
|
var r = range(container); \
|
||||||
@@ -117,11 +129,11 @@ def take_while(container, f, inserter) : call_exists(range, container) { \
|
|||||||
r.pop_front(); \
|
r.pop_front(); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
# Returns a new Vector with the given elements match the second value function\n\
|
# Returns a new container with the given elements match the second value function\n\
|
||||||
def take_while(container, f) {\
|
def take_while(container, f) {\
|
||||||
var retval = Vector(); \
|
var retval = new(container); \
|
||||||
take_while(container, f, back_inserter(retval)); \
|
take_while(container, f, back_inserter(retval)); \
|
||||||
return retval;\
|
retval;\
|
||||||
}\
|
}\
|
||||||
def drop(container, num, inserter) : call_exists(range, container) { \
|
def drop(container, num, inserter) : call_exists(range, container) { \
|
||||||
var r = range(container); \
|
var r = range(container); \
|
||||||
@@ -135,11 +147,11 @@ def drop(container, num, inserter) : call_exists(range, container) { \
|
|||||||
r.pop_front(); \
|
r.pop_front(); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
# Returns a new Vector with the given number of elements dropped from the given container \n\
|
# Returns a new container with the given number of elements dropped from the given container \n\
|
||||||
def drop(container, num) {\
|
def drop(container, num) {\
|
||||||
var retval = Vector(); \
|
var retval = new(container); \
|
||||||
drop(container, num, back_inserter(retval)); \
|
drop(container, num, back_inserter(retval)); \
|
||||||
return retval; \
|
retval; \
|
||||||
}\
|
}\
|
||||||
def drop_while(container, f, inserter) : call_exists(range, container) { \
|
def drop_while(container, f, inserter) : call_exists(range, container) { \
|
||||||
var r = range(container); \
|
var r = range(container); \
|
||||||
@@ -151,11 +163,11 @@ def drop_while(container, f, inserter) : call_exists(range, container) { \
|
|||||||
r.pop_front(); \
|
r.pop_front(); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
# Returns a new Vector with the given elements dropped that match the second value function\n\
|
# Returns a new container with the given elements dropped that match the second value function\n\
|
||||||
def drop_while(container, f) {\
|
def drop_while(container, f) {\
|
||||||
var retval = Vector(); \
|
var retval = new(container); \
|
||||||
drop_while(container, f, back_inserter(retval)); \
|
drop_while(container, f, back_inserter(retval)); \
|
||||||
return retval; \
|
retval; \
|
||||||
}\
|
}\
|
||||||
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
|
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
|
||||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \
|
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \
|
||||||
@@ -196,9 +208,9 @@ def filter(container, f, inserter) : call_exists(range, container) { \
|
|||||||
} \
|
} \
|
||||||
# Returns a new Vector which match the second value function\n\
|
# Returns a new Vector which match the second value function\n\
|
||||||
def filter(container, f) { \
|
def filter(container, f) { \
|
||||||
var retval = Vector(); \
|
var retval = new(container); \
|
||||||
filter(container, f, back_inserter(retval));\
|
filter(container, f, back_inserter(retval));\
|
||||||
return retval;\
|
retval;\
|
||||||
}\
|
}\
|
||||||
def generate_range(x, y, inserter) { \
|
def generate_range(x, y, inserter) { \
|
||||||
var i = x; \
|
var i = x; \
|
||||||
@@ -211,7 +223,7 @@ def generate_range(x, y, inserter) { \
|
|||||||
def generate_range(x, y) { \
|
def generate_range(x, y) { \
|
||||||
var retval = Vector(); \
|
var retval = Vector(); \
|
||||||
generate_range(x,y,back_inserter(retval)); \
|
generate_range(x,y,back_inserter(retval)); \
|
||||||
return retval; \
|
retval; \
|
||||||
}\
|
}\
|
||||||
# Returns a new Vector with the first value to the second value as its elements\n\
|
# Returns a new Vector with the first value to the second value as its elements\n\
|
||||||
def collate(x, y) { \
|
def collate(x, y) { \
|
||||||
@@ -230,7 +242,7 @@ def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y)
|
|||||||
def zip_with(f, x, y) { \
|
def zip_with(f, x, y) { \
|
||||||
var retval = Vector(); \
|
var retval = Vector(); \
|
||||||
zip_with(f,x,y,back_inserter(retval)); \
|
zip_with(f,x,y,back_inserter(retval)); \
|
||||||
return retval;\
|
retval;\
|
||||||
}\
|
}\
|
||||||
# Returns a new Vector which joins matching elements of the first and second\n\
|
# Returns a new Vector which joins matching elements of the first and second\n\
|
||||||
def zip(x, y) { \
|
def zip(x, y) { \
|
||||||
@@ -238,28 +250,36 @@ def zip(x, y) { \
|
|||||||
}\
|
}\
|
||||||
# Returns the position of the second value string in the first value string\n\
|
# Returns the position of the second value string in the first value string\n\
|
||||||
def find(str, substr) { \
|
def find(str, substr) { \
|
||||||
return int(find(str, substr, size_t(0))); \
|
int(find(str, substr, size_t(0))); \
|
||||||
} \
|
} \
|
||||||
# Returns the position of last match of the second value string in the first value string\n\
|
# Returns the position of last match of the second value string in the first value string\n\
|
||||||
def rfind(str, substr) { \
|
def rfind(str, substr) { \
|
||||||
return int(rfind(str, substr, size_t(-1))); \
|
int(rfind(str, substr, size_t(-1))); \
|
||||||
} \
|
} \
|
||||||
# Returns the position of the first match of elements in the second value string in the first value string\n\
|
# Returns the position of the first match of elements in the second value string in the first value string\n\
|
||||||
def find_first_of(str, list) { \
|
def find_first_of(str, list) { \
|
||||||
return int(find_first_of(str, list, size_t(0))); \
|
int(find_first_of(str, list, size_t(0))); \
|
||||||
} \
|
} \
|
||||||
# Returns the position of the last match of elements in the second value string in the first value string\n\
|
# Returns the position of the last match of elements in the second value string in the first value string\n\
|
||||||
def find_last_of(str, list) { \
|
def find_last_of(str, list) { \
|
||||||
return int(find_last_of(str, list, size_t(-1))); \
|
int(find_last_of(str, list, size_t(-1))); \
|
||||||
} \
|
} \
|
||||||
# Returns the position of the first non-matching element in the second value string in the first value string\n\
|
# Returns the position of the first non-matching element in the second value string in the first value string\n\
|
||||||
def find_first_not_of(str, list) { \
|
def find_first_not_of(str, list) { \
|
||||||
return int(find_first_not_of(str, list, size_t(0))); \
|
int(find_first_not_of(str, list, size_t(0))); \
|
||||||
} \
|
} \
|
||||||
# Returns the position of the last non-matching element in the second value string in the first value string\n\
|
# Returns the position of the last non-matching element in the second value string in the first value string\n\
|
||||||
def find_last_not_of(str, list) { \
|
def find_last_not_of(str, list) { \
|
||||||
return int(find_last_not_of(str, list, size_t(-1))); \
|
int(find_last_not_of(str, list, size_t(-1))); \
|
||||||
|
} \
|
||||||
|
def ltrim(str) { \
|
||||||
|
drop_while(str, fun(x) { x == ' ' || x == '\t' }); \
|
||||||
|
} \
|
||||||
|
def rtrim(str) { \
|
||||||
|
reverse(drop_while(reverse(str), fun(x) { x == ' ' || x == '\t' })); \
|
||||||
|
} \
|
||||||
|
def trim(str) { \
|
||||||
|
ltrim(rtrim(str)); \
|
||||||
} \
|
} \
|
||||||
)
|
)
|
||||||
|
|
||||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
||||||
|
196
msvc/chai-example/chai-example.vcproj
Normal file
196
msvc/chai-example/chai-example.vcproj
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="chai-example"
|
||||||
|
ProjectGUID="{CE422E94-B360-4588-8C65-6A9BE80798F9}"
|
||||||
|
RootNamespace="chaiexample"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
|
||||||
|
CharacterSet="0"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="C:\Programming\chaiscript\trunk\include"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
|
||||||
|
CharacterSet="0"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\example.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
@@ -8,4 +8,12 @@
|
|||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
AdditionalIncludeDirectories=""C:\Programming\Boost\include\boost-1_38""
|
AdditionalIncludeDirectories=""C:\Programming\Boost\include\boost-1_38""
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
|
||||||
|
/>
|
||||||
</VisualStudioPropertySheet>
|
</VisualStudioPropertySheet>
|
||||||
|
@@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00
|
|||||||
# Visual C++ Express 2008
|
# Visual C++ Express 2008
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chaiscript", "chaiscript.vcproj", "{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chaiscript", "chaiscript.vcproj", "{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chai-example", "..\chai-example\chai-example.vcproj", "{CE422E94-B360-4588-8C65-6A9BE80798F9}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
@@ -13,6 +15,10 @@ Global
|
|||||||
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.Build.0 = Debug|Win32
|
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.ActiveCfg = Release|Win32
|
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.Build.0 = Release|Win32
|
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -122,7 +122,7 @@
|
|||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="3"
|
Optimization="3"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
AdditionalIncludeDirectories=""$(ProjectDir)\..\..\dispatchkit";"$(ProjectDir)\..\..\chaiscript""
|
AdditionalIncludeDirectories=""$(ProjectDir)\..\..\include""
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
@@ -229,6 +229,14 @@
|
|||||||
RelativePath="..\..\include\chaiscript\dispatchkit\function_call.hpp"
|
RelativePath="..\..\include\chaiscript\dispatchkit\function_call.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\chaiscript\dispatchkit\function_call_detail.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\chaiscript\dispatchkit\handle_return.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
|
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
|
||||||
>
|
>
|
||||||
@@ -237,6 +245,10 @@
|
|||||||
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions.hpp"
|
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions_detail.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\chaiscript\dispatchkit\register_function.hpp"
|
RelativePath="..\..\include\chaiscript\dispatchkit\register_function.hpp"
|
||||||
>
|
>
|
||||||
|
@@ -2,7 +2,7 @@ var i = 0
|
|||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
print("i is 0")
|
print("i is 0")
|
||||||
}
|
}
|
||||||
elseif (i == 1) {
|
else if (i == 1) {
|
||||||
print("i is 1")
|
print("i is 1")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -27,9 +27,9 @@ struct System
|
|||||||
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
||||||
|
|
||||||
void add_callback(const std::string &t_name,
|
void add_callback(const std::string &t_name,
|
||||||
boost::shared_ptr<dispatchkit::Proxy_Function> t_func)
|
const chaiscript::Proxy_Function &t_func)
|
||||||
{
|
{
|
||||||
m_callbacks[t_name] = dispatchkit::build_function_caller<std::string (const std::string &)>(t_func);
|
m_callbacks[t_name] = chaiscript::functor<std::string (const std::string &)>(t_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,48 +45,92 @@ struct System
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void take_shared_ptr(const boost::shared_ptr<std::string> &p)
|
||||||
|
{
|
||||||
|
std::cout << *p << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
using namespace chaiscript;
|
||||||
|
|
||||||
|
ChaiScript chai;
|
||||||
chaiscript::ChaiScript_Engine chai;
|
|
||||||
|
|
||||||
//Create a new system object and share it with the chaiscript engine
|
//Create a new system object and share it with the chaiscript engine
|
||||||
System system;
|
System system;
|
||||||
chai.get_eval_engine().add_object("system", boost::ref(system));
|
chai.add(var(&system), "system");
|
||||||
|
|
||||||
//Register the two methods of the System structure.
|
//Register the two methods of the System structure.
|
||||||
dispatchkit::register_function(chai.get_eval_engine(), &System::add_callback, "add_callback");
|
chai.add(fun(&System::add_callback), "add_callback");
|
||||||
dispatchkit::register_function(chai.get_eval_engine(), &System::do_callbacks, "do_callbacks");
|
chai.add(fun(&System::do_callbacks), "do_callbacks");
|
||||||
|
|
||||||
|
chai.add(fun(&take_shared_ptr), "take_shared_ptr");
|
||||||
|
|
||||||
// Let's use chaiscript to add a new lambda callback to our system.
|
// Let's use chaiscript to add a new lambda callback to our system.
|
||||||
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
|
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
|
||||||
// in the "add_callback" function of struct System the chaiscript function is converted into a
|
// in the "add_callback" function of struct System the chaiscript function is converted into a
|
||||||
// boost::function, so it can be handled and called easily and type-safely
|
// boost::function, so it can be handled and called easily and type-safely
|
||||||
chai.evaluate_string("system.add_callback('#1', fun(x) { 'Callback1 ' + x });");
|
chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");
|
||||||
|
|
||||||
// Because we are sharing the "system" object with the chaiscript engine we have equal
|
// Because we are sharing the "system" object with the chaiscript engine we have equal
|
||||||
// access to it both from within chaiscript and from C++ code
|
// access to it both from within chaiscript and from C++ code
|
||||||
system.do_callbacks("TestString");
|
system.do_callbacks("TestString");
|
||||||
chai.evaluate_string("system.do_callbacks(\"TestString\");");
|
chai.eval("system.do_callbacks(\"TestString\");");
|
||||||
|
|
||||||
// The log function is overloaded, therefore we have to give the C++ compiler a hint as to which
|
// The log function is overloaded, therefore we have to give the C++ compiler a hint as to which
|
||||||
// version we want to register. One way to do this is to create a typedef of the function pointer
|
// version we want to register. One way to do this is to create a typedef of the function pointer
|
||||||
// then cast your function to that typedef.
|
// then cast your function to that typedef.
|
||||||
typedef void (*PlainLog)(const std::string &);
|
typedef void (*PlainLog)(const std::string &);
|
||||||
typedef void (*ModuleLog)(const std::string &, const std::string &);
|
typedef void (*ModuleLog)(const std::string &, const std::string &);
|
||||||
dispatchkit::register_function(chai.get_eval_engine(), PlainLog(&log), "log");
|
chai.add(fun(PlainLog(&log)), "log");
|
||||||
dispatchkit::register_function(chai.get_eval_engine(), ModuleLog(&log), "log");
|
chai.add(fun(ModuleLog(&log)), "log");
|
||||||
|
|
||||||
chai.evaluate_string("log('Test Message')");
|
chai.eval("log(\"Test Message\")");
|
||||||
chai.evaluate_string("log('Test Module', 'Test Message');");
|
|
||||||
|
// A shortcut to using eval is just to use the chai operator()
|
||||||
|
chai("log(\"Test Module\", \"Test Message\");");
|
||||||
|
|
||||||
//Finally, it is possible to register any boost::function as a system function, in this
|
//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
|
//way, we can, for instance add a bound member function to the system
|
||||||
chai.get_eval_engine().register_function(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test")), "do_callbacks");
|
chai.add(fun(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test"))), "do_callbacks");
|
||||||
|
|
||||||
//Call bound version of do_callbacks
|
//Call bound version of do_callbacks
|
||||||
chai.evaluate_string("do_callbacks()");
|
chai("do_callbacks()");
|
||||||
|
|
||||||
|
boost::function<void ()> caller = chai.functor<void ()>("fun() { system.do_callbacks(\"From Functor\"); }");
|
||||||
|
caller();
|
||||||
|
|
||||||
|
|
||||||
|
//If we would like a type-safe return value from all call, we can use
|
||||||
|
//the templated version of eval:
|
||||||
|
int i = chai.eval<int>("5+5");
|
||||||
|
|
||||||
|
std::cout << "5+5: " << i << std::endl;
|
||||||
|
|
||||||
|
//Add a new variable
|
||||||
|
chai("var scripti = 15");
|
||||||
|
|
||||||
|
//We can even get a handle to the variables in the system
|
||||||
|
int &scripti = chai.eval<int &>("scripti");
|
||||||
|
|
||||||
|
std::cout << "scripti: " << scripti << std::endl;
|
||||||
|
scripti *= 2;
|
||||||
|
std::cout << "scripti (updated): " << scripti << std::endl;
|
||||||
|
chai("print(\"Scripti from chai: \" + to_string(scripti))");
|
||||||
|
|
||||||
|
//To do: Add examples of handling Boxed_Values directly when needed
|
||||||
|
|
||||||
|
//Creating a functor on the stack and using it immediatly
|
||||||
|
int x = chai.functor<int (int, int)>("fun (x, y) { return x + y; }")(5, 6);
|
||||||
|
|
||||||
|
log("Functor test output", boost::lexical_cast<std::string>(x));
|
||||||
|
|
||||||
|
|
||||||
|
//Ability to create our own container types when needed. std::vector and std::map are
|
||||||
|
//mostly supported currently
|
||||||
|
chai.add(bootstrap::vector_type<std::vector<int> >("IntVector"));
|
||||||
|
|
||||||
|
|
||||||
|
chai("dump_system()");
|
||||||
|
chai("take_shared_ptr(\"Hello World as a shared_ptr\");");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
src/main.cpp
32
src/main.cpp
@@ -17,14 +17,14 @@ void print_help() {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
std::string input;
|
std::string input;
|
||||||
chaiscript::ChaiScript_Engine chai;
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
std::cout << "eval> ";
|
std::cout << "eval> ";
|
||||||
std::getline(std::cin, input);
|
std::getline(std::cin, input);
|
||||||
while (input != "quit") {
|
while (input != "quit") {
|
||||||
|
|
||||||
dispatchkit::Boxed_Value val;
|
chaiscript::Boxed_Value val;
|
||||||
|
|
||||||
if (input == "help") {
|
if (input == "help") {
|
||||||
print_help();
|
print_help();
|
||||||
@@ -32,24 +32,18 @@ int main(int argc, char *argv[]) {
|
|||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
//First, we evaluate it
|
//First, we evaluate it
|
||||||
val = chai.evaluate_string(input);
|
val = chai.eval(input);
|
||||||
|
|
||||||
//Then, we try to print the result of the evaluation to the user
|
//Then, we try to print the result of the evaluation to the user
|
||||||
if (val.get_type_info().m_bare_type_info && *(val.get_type_info().m_bare_type_info) != typeid(void)) {
|
if (val.get_type_info().m_bare_type_info && *(val.get_type_info().m_bare_type_info) != typeid(void)) {
|
||||||
try {
|
try {
|
||||||
dispatchkit::dispatch(chai.get_eval_engine().get_function("print"), dispatchkit::Param_List_Builder() << val);
|
chaiscript::dispatch(chai.get_eval_engine().get_function("print"), chaiscript::Param_List_Builder() << val);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
//If we can't, do nothing
|
//If we can't, do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (chaiscript::Parse_Error &pe) {
|
|
||||||
std::cout << pe.reason << " in " << pe.filename << " at " << pe.position.line << ", " << pe.position.column << std::endl;
|
|
||||||
}
|
|
||||||
catch (chaiscript::Eval_Error &ee) {
|
|
||||||
std::cout << ee.reason << std::endl;
|
|
||||||
}
|
|
||||||
catch (std::exception &e) {
|
catch (std::exception &e) {
|
||||||
std::cout << e.what() << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -63,23 +57,7 @@ int main(int argc, char *argv[]) {
|
|||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
std::string filename(argv[i]);
|
std::string filename(argv[i]);
|
||||||
try {
|
try {
|
||||||
dispatchkit::Boxed_Value val = chai.evaluate_file(argv[i]);
|
chaiscript::Boxed_Value val = chai.eval_file(argv[i]);
|
||||||
}
|
|
||||||
catch (chaiscript::Parse_Error &pe) {
|
|
||||||
if (filename != std::string("__EVAL__")) {
|
|
||||||
std::cout << pe.reason << " in " << pe.filename << " at " << pe.position.line << ", " << pe.position.column << std::endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << pe.reason << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (chaiscript::Eval_Error &ee) {
|
|
||||||
if (filename != std::string("__EVAL__")) {
|
|
||||||
std::cout << ee.reason << " in '" << ee.location->filename << "' at " << ee.location->start.line << ", " << ee.location->start.column << std::endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << ee.reason << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (std::exception &e) {
|
||||||
std::cout << e.what() << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
|
2
unittests/float.chai
Normal file
2
unittests/float.chai
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
print(1.2)
|
||||||
|
print(.5)
|
2
unittests/float.txt
Normal file
2
unittests/float.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
1.2
|
||||||
|
0.5
|
@@ -2,10 +2,10 @@ var i = 3
|
|||||||
if (i == 2) {
|
if (i == 2) {
|
||||||
print("2")
|
print("2")
|
||||||
}
|
}
|
||||||
elseif (i == 4) {
|
else if (i == 4) {
|
||||||
print("4")
|
print("4")
|
||||||
}
|
}
|
||||||
elseif (i == 3) {
|
else if (i == 3) {
|
||||||
print("3")
|
print("3")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ var i = 3
|
|||||||
if (i == 2) {
|
if (i == 2) {
|
||||||
print("2")
|
print("2")
|
||||||
}
|
}
|
||||||
elseif (i == 4) {
|
else if (i == 4) {
|
||||||
print("4")
|
print("4")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
3
unittests/method_lambda.chai
Normal file
3
unittests/method_lambda.chai
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
var addit = fun(x, y) { return x+y }
|
||||||
|
|
||||||
|
print(3.addit(4))
|
1
unittests/method_lambda.txt
Normal file
1
unittests/method_lambda.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
7
|
4
unittests/range.chai
Normal file
4
unittests/range.chai
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
var x = [1, 2, 3, 4]
|
||||||
|
var r = range(x)
|
||||||
|
r.pop_front()
|
||||||
|
print(r.front())
|
1
unittests/range.txt
Normal file
1
unittests/range.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2
|
4
unittests/range_back.chai
Normal file
4
unittests/range_back.chai
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
var x = [1, 2, 3, 4]
|
||||||
|
var r = range(x)
|
||||||
|
r.pop_back()
|
||||||
|
print(r.back())
|
1
unittests/range_back.txt
Normal file
1
unittests/range_back.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3
|
4
unittests/retro.chai
Normal file
4
unittests/retro.chai
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
var x = [1, 2, 3, 4]
|
||||||
|
var r = retro(range(x))
|
||||||
|
r.pop_front()
|
||||||
|
print(r.front())
|
1
unittests/retro.txt
Normal file
1
unittests/retro.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3
|
3
unittests/use.chai
Normal file
3
unittests/use.chai
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
use("unittests/use.inc")
|
||||||
|
|
||||||
|
greet()
|
3
unittests/use.inc
Normal file
3
unittests/use.inc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
def greet {
|
||||||
|
print("hello")
|
||||||
|
}
|
1
unittests/use.txt
Normal file
1
unittests/use.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hello
|
Reference in New Issue
Block a user