Compare commits
14 Commits
Release-1.
...
v1.3.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3a951cea99 | ||
![]() |
8620f4eaf9 | ||
![]() |
59ecf32f9b | ||
![]() |
541e453098 | ||
![]() |
0b780593a6 | ||
![]() |
2e7c5f413e | ||
![]() |
7e5b7cbd7a | ||
![]() |
c539e0b458 | ||
![]() |
1f011f3d5b | ||
![]() |
a136236179 | ||
![]() |
8840f06053 | ||
![]() |
00e4de774f | ||
![]() |
bc3a17b3b7 | ||
![]() |
4a57efde25 |
@@ -87,7 +87,8 @@ namespace chaiscript
|
||||
*/
|
||||
struct Eval_Error : public std::runtime_error {
|
||||
std::string reason;
|
||||
File_Position position;
|
||||
File_Position start_position;
|
||||
File_Position end_position;
|
||||
const char *filename;
|
||||
|
||||
Eval_Error(const std::string &why, const File_Position &where, const char *fname) :
|
||||
@@ -95,7 +96,7 @@ namespace chaiscript
|
||||
(std::string(fname) != "__EVAL__" ? ("in '" + std::string(fname) + "' ") : "during evaluation ") +
|
||||
+ "at (" + boost::lexical_cast<std::string>(where.line) + ", " +
|
||||
boost::lexical_cast<std::string>(where.column) + ")"),
|
||||
reason(why), position(where), filename(fname)
|
||||
reason(why), start_position(where), end_position(where), filename(fname)
|
||||
{ }
|
||||
|
||||
Eval_Error(const std::string &why, const TokenPtr &where)
|
||||
@@ -103,7 +104,7 @@ namespace chaiscript
|
||||
(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), position(where->start), filename(where->filename) {
|
||||
reason(why), start_position(where->start), end_position(where->end), filename(where->filename) {
|
||||
}
|
||||
|
||||
virtual ~Eval_Error() throw() {}
|
||||
|
@@ -203,10 +203,10 @@ namespace chaiscript
|
||||
{
|
||||
assignable_type<ContainerType>(type, m);
|
||||
|
||||
m->add(fun(&ContainerType::size), "size");
|
||||
m->add(fun(&ContainerType::max_size), "max_size");
|
||||
m->add(fun(&ContainerType::empty), "empty");
|
||||
m->add(fun(&ContainerType::clear), "clear");
|
||||
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
|
||||
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::max_size), "max_size");
|
||||
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
|
||||
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -387,7 +387,7 @@ namespace chaiscript
|
||||
ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
associative_container_type<ContainerType>(type, m);
|
||||
m->add(fun(&ContainerType::count), "count");
|
||||
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -129,6 +129,23 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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() {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Main class for the dispatchkit. Handles management
|
||||
* of the object stack, functions and registered types.
|
||||
@@ -152,6 +169,7 @@ namespace chaiscript
|
||||
*/
|
||||
bool add(const Proxy_Function &f, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
return add_function(f, name);
|
||||
}
|
||||
|
||||
@@ -169,6 +187,7 @@ namespace chaiscript
|
||||
*/
|
||||
void add(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
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);
|
||||
@@ -187,6 +206,7 @@ namespace chaiscript
|
||||
*/
|
||||
void add_object(const std::string &name, const Boxed_Value &obj)
|
||||
{
|
||||
validate_object_name(name);
|
||||
m_scopes->back()[name] = Boxed_Value(obj);
|
||||
}
|
||||
|
||||
@@ -257,7 +277,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, 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())
|
||||
{
|
||||
@@ -321,10 +341,21 @@ namespace chaiscript
|
||||
/**
|
||||
* Return a function by name
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, 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
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,35 +366,22 @@ namespace chaiscript
|
||||
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:
|
||||
/**
|
||||
* Implementation detail for searching for a function by name.
|
||||
* Looks for all registered global functions and optionally for an object
|
||||
* in scope with the same name
|
||||
* Throw a reserved_word exception if the name is not allowed
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >
|
||||
get_function_impl(const std::string &t_name, bool include_objects) const
|
||||
void validate_object_name(const std::string &name)
|
||||
{
|
||||
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs;
|
||||
|
||||
if (include_objects)
|
||||
if (m_reserved_words.find(name) != m_reserved_words.end())
|
||||
{
|
||||
try {
|
||||
funcs.insert(funcs.end(),
|
||||
std::make_pair(
|
||||
t_name,
|
||||
boxed_cast<std::multimap<std::string, Proxy_Function >::mapped_type>(get_object(t_name)))
|
||||
);
|
||||
} catch (const bad_boxed_cast &) {
|
||||
} catch (const std::range_error &) {
|
||||
}
|
||||
throw reserved_word_error(name);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
funcs.insert(funcs.end(), range.first, range.second);
|
||||
return funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,6 +412,7 @@ namespace chaiscript
|
||||
std::multimap<std::string, Proxy_Function > m_functions;
|
||||
Type_Name_Map m_types;
|
||||
Boxed_Value m_place_holder;
|
||||
std::set<std::string> m_reserved_words;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -30,7 +30,7 @@ namespace chaiscript
|
||||
functor(const std::vector<std::pair<std::string, Proxy_Function > > &funcs)
|
||||
{
|
||||
FunctionType *p=0;
|
||||
return build_function_caller_helper(p, funcs);
|
||||
return detail::build_function_caller_helper(p, funcs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -30,7 +30,7 @@ namespace chaiscript
|
||||
* value of a build_function_caller
|
||||
*/
|
||||
template<typename Ret>
|
||||
class Function_Caller_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)
|
||||
|
@@ -16,12 +16,6 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
template<typename T>
|
||||
Proxy_Function fun(const boost::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
@@ -32,57 +26,76 @@ namespace chaiscript
|
||||
{
|
||||
return (obj->*m);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Proxy_Function fun_helper(const boost::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically create a get_member helper function for an object
|
||||
* to allow for runtime dispatched access to public data members
|
||||
* for example, the case of std::pair<>::first and std::pair<>::second
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
Proxy_Function fun_helper(T Class::* m)
|
||||
{
|
||||
return fun_helper(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically create a get_member helper function for an object
|
||||
* to allow for runtime dispatched access to public data members
|
||||
* for example, the case of std::pair<>::first and std::pair<>::second
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
Proxy_Function fun(T Class::* m)
|
||||
{
|
||||
return fun(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
template<typename T>
|
||||
Proxy_Function fun(T t)
|
||||
{
|
||||
return detail::fun_helper(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
/**
|
||||
* Register a global function of n parameters with name
|
||||
*/
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Register a global function of n parameters with name
|
||||
*/
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun_helper(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)>
|
||||
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
/**
|
||||
* 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)>
|
||||
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
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
|
||||
*/
|
||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
|
||||
{
|
||||
return fun(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
/**
|
||||
* 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)>
|
||||
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
|
||||
{
|
||||
return fun_helper(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -106,6 +106,18 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
struct Get_Type_Info<boost::reference_wrapper<T> >
|
||||
{
|
||||
|
@@ -19,18 +19,27 @@ namespace chaiscript
|
||||
template <typename Eval_Engine>
|
||||
class ChaiScript_System {
|
||||
Eval_Engine engine;
|
||||
|
||||
std::set<std::string> loaded_files;
|
||||
|
||||
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 char *filename = "__EVAL__") {
|
||||
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, filename)) {
|
||||
if (parser.parse(input, loaded_files.find(filename)->c_str())) {
|
||||
//parser.show_match_stack();
|
||||
value = eval_token<Eval_Engine>(engine, parser.ast());
|
||||
}
|
||||
@@ -49,6 +58,14 @@ namespace chaiscript
|
||||
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:
|
||||
ChaiScript_System() {
|
||||
@@ -117,12 +134,11 @@ namespace chaiscript
|
||||
/**
|
||||
* Helper function for loading a file
|
||||
*/
|
||||
std::string load_file(const char *filename) {
|
||||
std::ifstream infile (filename, std::ios::in | std::ios::ate);
|
||||
std::string load_file(const std::string &filename) {
|
||||
std::ifstream infile (filename.c_str(), std::ios::in | std::ios::ate);
|
||||
|
||||
if (!infile.is_open()) {
|
||||
std::string fname = filename;
|
||||
throw std::runtime_error("Can not open: " + fname);
|
||||
throw std::runtime_error("Can not open: " + filename);
|
||||
}
|
||||
|
||||
std::streampos size = infile.tellg();
|
||||
@@ -141,6 +157,24 @@ namespace chaiscript
|
||||
*/
|
||||
void build_eval_system() {
|
||||
using namespace bootstrap;
|
||||
engine.add_reserved_word("def");
|
||||
engine.add_reserved_word("fun");
|
||||
engine.add_reserved_word("while");
|
||||
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.add(Bootstrap::bootstrap());
|
||||
|
||||
engine.add(fun(boost::function<void ()>(boost::bind(&dump_system, boost::ref(engine)))), "dump_system");
|
||||
@@ -150,12 +184,16 @@ namespace chaiscript
|
||||
|
||||
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");
|
||||
|
||||
@@ -176,7 +214,7 @@ namespace chaiscript
|
||||
/**
|
||||
* Loads the file specified by filename, evaluates it, and returns the result
|
||||
*/
|
||||
Boxed_Value eval_file(const char *filename) {
|
||||
Boxed_Value eval_file(const std::string &filename) {
|
||||
return do_eval(load_file(filename), filename);
|
||||
}
|
||||
|
||||
@@ -184,7 +222,7 @@ namespace chaiscript
|
||||
* Loads the file specified by filename, evaluates it, and returns the as the specified type
|
||||
*/
|
||||
template<typename T>
|
||||
T eval_file(const char *filename) {
|
||||
T eval_file(const std::string &filename) {
|
||||
return boxed_cast<T>(do_eval(load_file(filename), filename));
|
||||
}
|
||||
};
|
||||
|
@@ -171,7 +171,12 @@ namespace chaiscript
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) {
|
||||
ss.add_object(node->children[0]->text, 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);
|
||||
}
|
||||
|
||||
@@ -471,23 +476,32 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::string fun_name;
|
||||
if (node->children[i]->identifier == Token_Type::Fun_Call) {
|
||||
fun_name = node->children[i]->children[0]->text;
|
||||
}
|
||||
else {
|
||||
fun_name = node->children[i]->text;
|
||||
}
|
||||
|
||||
//std::string fun_name;
|
||||
Boxed_Value fn;
|
||||
try {
|
||||
fn = ss.get_function(fun_name);
|
||||
if (node->children[i]->identifier == Token_Type::Fun_Call) {
|
||||
//fun_name = node->children[i]->children[0]->text;
|
||||
fn = eval_token(ss, node->children[i]->children[0]);
|
||||
}
|
||||
else {
|
||||
//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 {
|
||||
//fn = ss.get_function(fun_name);
|
||||
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);
|
||||
}
|
||||
catch(const dispatch_error &e){
|
||||
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) {
|
||||
ss.set_stack(prev_stack);
|
||||
@@ -556,10 +570,14 @@ namespace chaiscript
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_while(Eval_System &ss, TokenPtr node) {
|
||||
bool cond;
|
||||
|
||||
ss.new_scope();
|
||||
|
||||
try {
|
||||
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
ss.pop_scope();
|
||||
throw Eval_Error("While condition not boolean", node->children[0]);
|
||||
}
|
||||
while (cond) {
|
||||
@@ -569,6 +587,7 @@ namespace chaiscript
|
||||
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
ss.pop_scope();
|
||||
throw Eval_Error("While condition not boolean", node->children[0]);
|
||||
}
|
||||
}
|
||||
@@ -576,6 +595,7 @@ namespace chaiscript
|
||||
cond = false;
|
||||
}
|
||||
}
|
||||
ss.pop_scope();
|
||||
return Boxed_Value();
|
||||
}
|
||||
|
||||
@@ -586,6 +606,8 @@ namespace chaiscript
|
||||
Boxed_Value eval_for(Eval_System &ss, TokenPtr node) {
|
||||
bool cond;
|
||||
|
||||
ss.new_scope();
|
||||
|
||||
try {
|
||||
if (node->children.size() == 4) {
|
||||
eval_token(ss, node->children[0]);
|
||||
@@ -596,6 +618,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
ss.pop_scope();
|
||||
throw Eval_Error("For condition not boolean", node);
|
||||
}
|
||||
while (cond) {
|
||||
@@ -612,12 +635,14 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
ss.pop_scope();
|
||||
throw Eval_Error("For condition not boolean", node);
|
||||
}
|
||||
catch (Break_Loop &) {
|
||||
cond = false;
|
||||
}
|
||||
}
|
||||
ss.pop_scope();
|
||||
return Boxed_Value();
|
||||
}
|
||||
|
||||
@@ -662,12 +687,16 @@ namespace chaiscript
|
||||
param_names, _1), numparams));
|
||||
}
|
||||
|
||||
ss.add(Proxy_Function
|
||||
(new Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
|
||||
try {
|
||||
ss.add(Proxy_Function
|
||||
(new Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
|
||||
boost::ref(ss), node->children.back(),
|
||||
param_names, _1), numparams,
|
||||
annotation, guard)), function_name);
|
||||
|
||||
}
|
||||
catch (reserved_word_error &rwe) {
|
||||
throw Eval_Error("Reserved word used as function name '" + function_name + "'", node);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@@ -140,7 +140,7 @@ namespace chaiscript
|
||||
*/
|
||||
bool Float_() {
|
||||
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')) {
|
||||
++input_pos;
|
||||
++col;
|
||||
@@ -178,7 +178,7 @@ namespace chaiscript
|
||||
std::string::iterator start = input_pos;
|
||||
int prev_col = col;
|
||||
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_()) {
|
||||
std::string match(start, input_pos);
|
||||
TokenPtr t(new Token(match, Token_Type::Float, filename, prev_line, prev_col, line, col));
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
#define chaiscript_prelude CODE_STRING(\
|
||||
def new(x) { eval(type_name(x))(); } \
|
||||
def clone(x) { eval(type_name(x))(x); } \
|
||||
def clone(x) : function_exists(type_name(x)) { eval(type_name(x))(x); } \
|
||||
# to_string for Pair()\n\
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \
|
||||
|
@@ -122,7 +122,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\..\..\dispatchkit";"$(ProjectDir)\..\..\chaiscript""
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)\..\..\include""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
@@ -229,6 +229,14 @@
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\function_call.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\function_call_detail.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\handle_return.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
|
||||
>
|
||||
@@ -237,6 +245,10 @@
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_functions_detail.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\register_function.hpp"
|
||||
>
|
||||
|
@@ -45,6 +45,10 @@ struct System
|
||||
}
|
||||
};
|
||||
|
||||
void take_shared_ptr(const boost::shared_ptr<std::string> &p)
|
||||
{
|
||||
std::cout << *p << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
using namespace chaiscript;
|
||||
@@ -59,6 +63,8 @@ int main(int argc, char *argv[]) {
|
||||
chai.add(fun(&System::add_callback), "add_callback");
|
||||
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.
|
||||
// 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
|
||||
@@ -123,5 +129,8 @@ int main(int argc, char *argv[]) {
|
||||
//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\");");
|
||||
}
|
||||
|
||||
|
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
|
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
|
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