Compare commits

..

14 Commits

Author SHA1 Message Date
Jason Turner
3a951cea99 Extend the reserved object name registration to include some missing values such as break and return and such 2009-08-26 02:21:41 +00:00
Jonathan Turner
8620f4eaf9 Fix for issue 23, makes for and while loops live in their own deeper scope 2009-08-26 02:02:41 +00:00
Jonathan Turner
59ecf32f9b Add Eval_Error end extents and reserved word errors 2009-08-25 01:10:28 +00:00
Jason Turner
541e453098 check in of reserved word handling 2009-08-25 00:36:02 +00:00
Jason Turner
0b780593a6 Make for better error messages when a clone fails 2009-08-22 13:55:06 +00:00
Jason Turner
2e7c5f413e Cleanup get_function implementation 2009-08-21 22:51:12 +00:00
Jonathan Turner
7e5b7cbd7a Switch get_function to default to not doing object lookup. Correct method eval to maintain method lambda syntax. Add unit test for method lambda 2009-08-21 20:05:05 +00:00
Jonathan Turner
c539e0b458 Add unittest for 'use' feature 2009-08-21 18:26:34 +00:00
Jason Turner
1f011f3d5b Add "use" function for loading chai files from inside of ChaiScript and fix potential memory bug with filename const char * pointers being passed around 2009-08-21 03:33:57 +00:00
Jason Turner
a136236179 Fix dispatch for const boost::shared_ptr<> & parameters for functions, add a test to example.cpp and fix some issues with building example.cpp 2009-08-20 21:35:56 +00:00
Jonathan Turner
8840f06053 Allow floating point numbers without a zero before the decimal point 2009-08-20 14:50:13 +00:00
Jason Turner
00e4de774f Move "fun_helper" into detail namespace 2009-08-09 19:12:01 +00:00
Jason Turner
bc3a17b3b7 Port VC++ fix from last rev back to Linux 2009-08-09 18:42:32 +00:00
Jason Turner
4a57efde25 Correct bug with bootstrapping of Map type on windows. Also, make it easier to specify the type of a function being added at the time it is being added. 2009-08-09 16:49:14 +00:00
20 changed files with 255 additions and 107 deletions

View File

@@ -87,7 +87,8 @@ namespace chaiscript
*/ */
struct Eval_Error : public std::runtime_error { struct Eval_Error : public std::runtime_error {
std::string reason; std::string reason;
File_Position position; File_Position start_position;
File_Position end_position;
const char *filename; const char *filename;
Eval_Error(const std::string &why, const File_Position &where, const char *fname) : 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 ") + (std::string(fname) != "__EVAL__" ? ("in '" + std::string(fname) + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(where.line) + ", " + + "at (" + boost::lexical_cast<std::string>(where.line) + ", " +
boost::lexical_cast<std::string>(where.column) + ")"), 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) 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 ") + (std::string(where->filename) != "__EVAL__" ? ("in '" + std::string(where->filename) + "' ") : "during evaluation ") +
"at (" + boost::lexical_cast<std::string>(where->start.line) + ", " + "at (" + boost::lexical_cast<std::string>(where->start.line) + ", " +
boost::lexical_cast<std::string>(where->start.column) + ")"), 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() {} virtual ~Eval_Error() throw() {}

View File

@@ -203,10 +203,10 @@ namespace chaiscript
{ {
assignable_type<ContainerType>(type, m); assignable_type<ContainerType>(type, m);
m->add(fun(&ContainerType::size), "size"); m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
m->add(fun(&ContainerType::max_size), "max_size"); m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::max_size), "max_size");
m->add(fun(&ContainerType::empty), "empty"); m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun(&ContainerType::clear), "clear"); m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
return m; return m;
} }
@@ -387,7 +387,7 @@ namespace chaiscript
ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module())) ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{ {
associative_container_type<ContainerType>(type, m); 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; return m;
} }

View File

@@ -127,7 +127,24 @@ namespace chaiscript
private: private:
std::vector<std::pair<std::string, 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() {}
};
/** /**
* Main class for the dispatchkit. Handles management * Main class for the dispatchkit. Handles management
@@ -152,6 +169,7 @@ namespace chaiscript
*/ */
bool add(const 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);
} }
@@ -169,6 +187,7 @@ namespace chaiscript
*/ */
void add(const Boxed_Value &obj, const std::string &name) void add(const Boxed_Value &obj, const std::string &name)
{ {
validate_object_name(name);
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);
@@ -187,6 +206,7 @@ namespace chaiscript
*/ */
void add_object(const std::string &name, const Boxed_Value &obj) void add_object(const std::string &name, const Boxed_Value &obj)
{ {
validate_object_name(name);
m_scopes->back()[name] = Boxed_Value(obj); 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()) if (funcs.empty())
{ {
@@ -321,12 +341,23 @@ namespace chaiscript
/** /**
* Return a function by name * 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 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
*/ */
@@ -335,35 +366,22 @@ namespace chaiscript
return std::vector<std::pair<std::string, 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, 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, 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, Proxy_Function >::mapped_type>(get_object(t_name)))
);
} catch (const bad_boxed_cast &) {
} catch (const std::range_error &) {
}
} }
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; 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;
}; };
/** /**

View File

@@ -30,7 +30,7 @@ namespace chaiscript
functor(const std::vector<std::pair<std::string, Proxy_Function > > &funcs) functor(const std::vector<std::pair<std::string, Proxy_Function > > &funcs)
{ {
FunctionType *p=0; FunctionType *p=0;
return build_function_caller_helper(p, funcs); return detail::build_function_caller_helper(p, funcs);
} }
/** /**

View File

@@ -30,7 +30,7 @@ namespace chaiscript
* value of a build_function_caller * value of a build_function_caller
*/ */
template<typename Ret> 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, static Ret call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params)

View File

@@ -16,12 +16,6 @@
namespace chaiscript namespace chaiscript
{ {
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
namespace detail namespace detail
{ {
/** /**
@@ -32,57 +26,76 @@ namespace chaiscript
{ {
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));
}
/**
* 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_ITERATION_LIMITS ( 0, 10 )
#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 chaiscript namespace chaiscript
{ {
/** 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)> * Register a global function of n parameters with name
Proxy_Function fun(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param))) */
{ template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
return fun(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f)); 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 * 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)>
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))) Proxy_Function fun_helper(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)); 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)>
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const) Proxy_Function fun_helper(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)); return fun_helper(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
} }
}
} }
#endif #endif

View File

@@ -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> template<typename T>
struct Get_Type_Info<boost::reference_wrapper<T> > struct Get_Type_Info<boost::reference_wrapper<T> >
{ {

View File

@@ -19,18 +19,27 @@ 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 * 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); //debug_print(tokens);
Boxed_Value value; Boxed_Value value;
parser.clear_match_stack(); 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 { try {
if (parser.parse(input, filename)) { if (parser.parse(input, loaded_files.find(filename)->c_str())) {
//parser.show_match_stack(); //parser.show_match_stack();
value = eval_token<Eval_Engine>(engine, parser.ast()); value = eval_token<Eval_Engine>(engine, parser.ast());
} }
@@ -49,6 +58,14 @@ namespace chaiscript
return do_eval(boxed_cast<std::string>(vals.at(0))); 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() {
@@ -117,12 +134,11 @@ namespace chaiscript
/** /**
* 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();
@@ -141,6 +157,24 @@ namespace chaiscript
*/ */
void build_eval_system() { void build_eval_system() {
using namespace bootstrap; 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(Bootstrap::bootstrap());
engine.add(fun(boost::function<void ()>(boost::bind(&dump_system, boost::ref(engine)))), "dump_system"); 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))), engine.add(fun(boost::function<std::string (Boxed_Value)>(boost::bind(&chaiscript::type_name, boost::ref(engine), _1))),
"type_name"); "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(vector_type<std::vector<Boxed_Value> >("Vector"));
engine.add(string_type<std::string>("string")); engine.add(string_type<std::string>("string"));
engine.add(map_type<std::map<std::string, Boxed_Value> >("Map")); engine.add(map_type<std::map<std::string, Boxed_Value> >("Map"));
engine.add(pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair")); 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( engine.add(Proxy_Function(
new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::internal_eval, boost::ref(*this), _1), 1)), "eval"); 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 * 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); 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 * Loads the file specified by filename, evaluates it, and returns the as the specified type
*/ */
template<typename T> 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)); return boxed_cast<T>(do_eval(load_file(filename), filename));
} }
}; };

View File

@@ -171,7 +171,12 @@ namespace chaiscript
*/ */
template <typename Eval_System> template <typename Eval_System>
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, 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);
} }
@@ -471,23 +476,32 @@ namespace chaiscript
} }
} }
std::string fun_name; //std::string fun_name;
if (node->children[i]->identifier == Token_Type::Fun_Call) { Boxed_Value fn;
fun_name = node->children[i]->children[0]->text;
}
else {
fun_name = node->children[i]->text;
}
try { 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); 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 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);
@@ -556,10 +570,14 @@ namespace chaiscript
template <typename Eval_System> template <typename Eval_System>
Boxed_Value eval_while(Eval_System &ss, TokenPtr node) { Boxed_Value eval_while(Eval_System &ss, TokenPtr node) {
bool cond; bool cond;
ss.new_scope();
try { try {
cond = boxed_cast<bool &>(eval_token(ss, node->children[0])); cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
} }
catch (const 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) {
@@ -569,6 +587,7 @@ namespace chaiscript
cond = boxed_cast<bool &>(eval_token(ss, node->children[0])); cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
} }
catch (const 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]);
} }
} }
@@ -576,6 +595,7 @@ namespace chaiscript
cond = false; cond = false;
} }
} }
ss.pop_scope();
return Boxed_Value(); return Boxed_Value();
} }
@@ -586,6 +606,8 @@ namespace chaiscript
Boxed_Value eval_for(Eval_System &ss, TokenPtr node) { Boxed_Value eval_for(Eval_System &ss, TokenPtr node) {
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]);
@@ -596,6 +618,7 @@ namespace chaiscript
} }
} }
catch (const 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) {
@@ -612,12 +635,14 @@ namespace chaiscript
} }
} }
catch (const 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;
} }
} }
ss.pop_scope();
return Boxed_Value(); return Boxed_Value();
} }
@@ -662,12 +687,16 @@ namespace chaiscript
param_names, _1), numparams)); param_names, _1), numparams));
} }
ss.add(Proxy_Function try {
(new 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;
} }

View File

@@ -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));

View File

@@ -13,7 +13,7 @@
#define chaiscript_prelude CODE_STRING(\ #define chaiscript_prelude CODE_STRING(\
def new(x) { eval(type_name(x))(); } \ 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\ # 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() + ">"; \

View File

@@ -122,7 +122,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="3" Optimization="3"
EnableIntrinsicFunctions="true" EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\dispatchkit&quot;;&quot;$(ProjectDir)\..\..\chaiscript&quot;" AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\include&quot;"
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"
> >

View File

@@ -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[]) { int main(int argc, char *argv[]) {
using namespace chaiscript; 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::add_callback), "add_callback");
chai.add(fun(&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
@@ -123,5 +129,8 @@ int main(int argc, char *argv[]) {
//mostly supported currently //mostly supported currently
chai.add(bootstrap::vector_type<std::vector<int> >("IntVector")); 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
View File

@@ -0,0 +1,2 @@
print(1.2)
print(.5)

2
unittests/float.txt Normal file
View File

@@ -0,0 +1,2 @@
1.2
0.5

View File

@@ -0,0 +1,3 @@
var addit = fun(x, y) { return x+y }
print(3.addit(4))

View File

@@ -0,0 +1 @@
7

3
unittests/use.chai Normal file
View File

@@ -0,0 +1,3 @@
use("unittests/use.inc")
greet()

3
unittests/use.inc Normal file
View File

@@ -0,0 +1,3 @@
def greet {
print("hello")
}

1
unittests/use.txt Normal file
View File

@@ -0,0 +1 @@
hello