Compare commits

..

16 Commits

Author SHA1 Message Date
Jason Turner
4457df9ff5 Fix NO_THREADS related issues 2009-12-06 05:12:02 +00:00
Jason Turner
e601de9d18 Reduce use of Param_List_Builder by providing call_function implementations for 0,1,2 arity 2009-12-06 01:31:58 +00:00
Jason Turner
37b2ac2056 Implement proper swap for Boxed_Value 2009-12-05 19:30:09 +00:00
Jason Turner
645cdddd70 Small but measurable eval performance increase (in optimized builds) by managing the number of Boxed_Values copies and assignments 2009-12-05 18:54:55 +00:00
Jonathan Turner
ac8462fb67 Fix up some broken sample files 2009-12-02 14:29:42 +00:00
Jason Turner
636c55493c Smartly size the integer returned from a Boxed_POD_Value operation to return an "int" if the resulting value is small enough 2009-12-01 03:52:57 +00:00
Jason Turner
e2a2c14c0d Eliminate use of size_t in stl related wrappings 2009-12-01 02:56:02 +00:00
Jonathan Turner
c418644a5b Fix for single-line comments stopping at semicolon. 2009-11-27 22:52:55 +00:00
Jason Turner
fbf8f53e04 Add Type_Info type and add *_type objects at time of type registration. 2009-11-21 22:47:44 +00:00
Jason Turner
a0c6366479 Added introspecition/classification of types 2009-11-21 06:39:35 +00:00
Jason Turner
15ffbd200a Fixed unittests broken by last checkin 2009-11-21 06:39:11 +00:00
Jason Turner
1c6b2725b3 Provide some hints for dispatches with lhs (first param) that is const 2009-11-21 06:02:17 +00:00
Jason Turner
95c124ca35 Support better tracking of loaded modules for saving and setting of state 2009-11-21 05:28:00 +00:00
Jason Turner
1bd73884b2 Add documentation to the set_state get_state functions 2009-11-18 05:05:40 +00:00
Jason Turner
d3e4af433e Add support for saving/restoring of chaiscript engine state. 2009-11-18 04:43:08 +00:00
Jason Turner
9f65303370 Handle case of const & return values (should probably be investigated a bit more) 2009-11-18 04:42:43 +00:00
20 changed files with 344 additions and 144 deletions

View File

@@ -528,8 +528,28 @@ namespace chaiscript
m->add(fun(&Dynamic_Object::get_attr), "get_attr"); m->add(fun(&Dynamic_Object::get_attr), "get_attr");
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }"); m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
m->add(fun(&Boxed_Value::is_undef), "is_undef"); m->add(fun(&Boxed_Value::is_undef), "is_var_undef");
m->add(fun(&Boxed_Value::is_null), "is_null"); m->add(fun(&Boxed_Value::is_null), "is_var_null");
m->add(fun(&Boxed_Value::is_const), "is_var_const");
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
operators::equal<Type_Info>(m);
m->add(fun(&Type_Info::is_const), "is_type_const");
m->add(fun(&Type_Info::is_reference), "is_type_reference");
m->add(fun(&Type_Info::is_void), "is_type_void");
m->add(fun(&Type_Info::is_undef), "is_type_undef");
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
m->add(fun(&Type_Info::name), "cpp_name");
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
m->add(fun(&Type_Info::bare_equal), "bare_equal");
basic_constructors<bool>("bool", m); basic_constructors<bool>("bool", m);
operators::assign<bool>(m); operators::assign<bool>(m);

View File

@@ -158,7 +158,7 @@ namespace chaiscript
template<typename ContainerType> template<typename ContainerType>
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{ {
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size"); m->add(fun(boost::function<int (const ContainerType *)>(&ContainerType::size)), "size");
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty"); m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear"); m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
@@ -319,7 +319,8 @@ namespace chaiscript
template<typename ContainerType> template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{ {
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count"); // m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count)), "count");
return m; return m;
} }
@@ -412,13 +413,16 @@ namespace chaiscript
} }
m->add(fun(&String::push_back), push_back_name); 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_ptr)(const String &, typename String::size_type) const;
m->add(fun(static_cast<find_func>(&String::find)), "find");
m->add(fun(static_cast<find_func>(&String::rfind)), "rfind"); typedef boost::function<int (const String *, const String &, int)> find_func;
m->add(fun(static_cast<find_func>(&String::find_first_of)), "find_first_of");
m->add(fun(static_cast<find_func>(&String::find_last_of)), "find_last_of"); m->add(fun(find_func(static_cast<find_func_ptr>(&String::find))), "find");
m->add(fun(static_cast<find_func>(&String::find_first_not_of)), "find_first_not_of"); m->add(fun(find_func(static_cast<find_func_ptr>(&String::rfind))), "rfind");
m->add(fun(static_cast<find_func>(&String::find_last_not_of)), "find_last_not_of"); m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_of))), "find_first_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_of))), "find_last_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_not_of))), "find_first_not_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_not_of))), "find_last_not_of");
return m; return m;
} }

View File

@@ -264,6 +264,11 @@ namespace chaiscript
{ {
} }
void swap(Boxed_Value &rhs)
{
std::swap(m_data, rhs.m_data);
}
/** /**
* Return a reference to the static global Object_Cache * Return a reference to the static global Object_Cache
*/ */
@@ -293,7 +298,8 @@ namespace chaiscript
*/ */
Boxed_Value &operator=(const Boxed_Value &rhs) Boxed_Value &operator=(const Boxed_Value &rhs)
{ {
m_data = rhs.m_data; Boxed_Value temp(rhs);
swap(temp);
return *this; return *this;
} }
@@ -315,6 +321,11 @@ namespace chaiscript
return m_data->m_type_info.is_const(); return m_data->m_type_info.is_const();
} }
bool is_type(const Type_Info &ti) const
{
return m_data->m_type_info.bare_equal(ti);
}
bool is_null() const bool is_null() const
{ {
if (m_data->m_is_null) if (m_data->m_is_null)
@@ -335,6 +346,12 @@ namespace chaiscript
return m_data->m_is_ref; return m_data->m_is_ref;
} }
bool is_pointer() const
{
return !is_ref();
}
private: private:
boost::shared_ptr<Data> m_data; boost::shared_ptr<Data> m_data;
}; };
@@ -700,7 +717,7 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i + r.i); return smart_size(i + r.i);
} }
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i)); return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
@@ -710,7 +727,7 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i - r.i); return smart_size(i - r.i);
} }
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i)); return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
@@ -750,7 +767,7 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i / r.i); return smart_size(i / r.i);
} }
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i)); return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
@@ -760,7 +777,7 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i << r.i); return smart_size(i << r.i);
} }
throw bad_boxed_cast("<< only valid for integer types"); throw bad_boxed_cast("<< only valid for integer types");
@@ -771,7 +788,7 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i * r.i); return smart_size(i * r.i);
} }
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i)); return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
@@ -782,7 +799,7 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i % r.i); return smart_size(i % r.i);
} }
throw bad_boxed_cast("% only valid for integer types"); throw bad_boxed_cast("% only valid for integer types");
@@ -792,12 +809,23 @@ namespace chaiscript
{ {
if (!m_isfloat && !r.m_isfloat) if (!m_isfloat && !r.m_isfloat)
{ {
return Boxed_Value(i >> r.i); return smart_size(i >> r.i);
} }
throw bad_boxed_cast(">> only valid for integer types"); throw bad_boxed_cast(">> only valid for integer types");
} }
Boxed_Value smart_size(boost::int64_t i) const
{
if (i < std::numeric_limits<int>::min()
|| i > std::numeric_limits<int>::max())
{
return Boxed_Value(i);
} else {
return Boxed_Value(static_cast<int>(i));
}
}
double d; double d;
@@ -874,7 +902,14 @@ namespace chaiscript
{ {
return l.get_type_info() == r.get_type_info(); return l.get_type_info() == r.get_type_info();
} }
}
namespace std
{
template<> void swap(chaiscript::Boxed_Value &lhs, chaiscript::Boxed_Value &rhs)
{
lhs.swap(rhs);
}
} }
#endif #endif

View File

@@ -43,6 +43,7 @@ namespace chaiscript
return *this; return *this;
} }
//Add a bit of chaiscript to eval during module implementation //Add a bit of chaiscript to eval during module implementation
Module &eval(const std::string &str) Module &eval(const std::string &str)
{ {
@@ -50,6 +51,11 @@ namespace chaiscript
return *this; return *this;
} }
Module &add(const boost::shared_ptr<Module> &m)
{
m->apply(*this, *this);
return *m;
}
template<typename Eval, typename Engine> template<typename Eval, typename Engine>
void apply(Eval &t_eval, Engine &t_engine) const void apply(Eval &t_eval, Engine &t_engine) const
@@ -192,6 +198,14 @@ namespace chaiscript
typedef boost::tuples::tuple<std::map<std::string, Boxed_Value>, std::deque<Scope>, bool> StackData; typedef boost::tuples::tuple<std::map<std::string, Boxed_Value>, std::deque<Scope>, bool> StackData;
typedef boost::shared_ptr<StackData> Stack; typedef boost::shared_ptr<StackData> Stack;
struct State
{
std::multimap<std::string, Proxy_Function> m_functions;
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
};
Dispatch_Engine() Dispatch_Engine()
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object())) : m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
{ {
@@ -268,7 +282,7 @@ namespace chaiscript
boost::unique_lock<boost::shared_mutex> l(m_global_object_mutex); boost::unique_lock<boost::shared_mutex> l(m_global_object_mutex);
#endif #endif
m_global_objects[name] = obj; m_state.m_global_objects[name] = obj;
} }
/** /**
@@ -334,7 +348,7 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex); boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
get_function_cache() = m_functions; get_function_cache() = m_state.m_functions;
} }
/** /**
@@ -377,8 +391,8 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_global_object_mutex); boost::shared_lock<boost::shared_mutex> l(m_global_object_mutex);
#endif #endif
itr = m_global_objects.find(name); itr = m_state.m_global_objects.find(name);
if (itr != m_global_objects.end()) if (itr != m_state.m_global_objects.end())
{ {
cache[name] = itr->second; cache[name] = itr->second;
return itr->second; return itr->second;
@@ -403,11 +417,13 @@ namespace chaiscript
*/ */
void add(const Type_Info &ti, const std::string &name) void add(const Type_Info &ti, const std::string &name)
{ {
add_global_const(const_var(ti), name + "_type");
#ifndef CHAISCRIPT_NO_THREADS #ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex); boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
m_types.insert(std::make_pair(name, ti)); m_state.m_types.insert(std::make_pair(name, ti));
} }
/** /**
@@ -419,9 +435,9 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex); boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
Type_Name_Map::const_iterator itr = m_types.find(name); Type_Name_Map::const_iterator itr = m_state.m_types.find(name);
if (itr != m_types.end()) if (itr != m_state.m_types.end())
{ {
return itr->second; return itr->second;
} }
@@ -440,8 +456,8 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex); boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
for (Type_Name_Map::const_iterator itr = m_types.begin(); for (Type_Name_Map::const_iterator itr = m_state.m_types.begin();
itr != m_types.end(); itr != m_state.m_types.end();
++itr) ++itr)
{ {
if (itr->second.bare_equal(ti)) if (itr->second.bare_equal(ti))
@@ -462,7 +478,7 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex); boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
return std::vector<std::pair<std::string, Type_Info> >(m_types.begin(), m_types.end()); return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
} }
/** /**
@@ -501,7 +517,7 @@ namespace chaiscript
boost::unique_lock<boost::shared_mutex> l(m_mutex); boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
m_reserved_words.insert(name); m_state.m_reserved_words.insert(name);
} }
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const
@@ -510,7 +526,27 @@ namespace chaiscript
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
= functions.equal_range(t_name); = functions.equal_range(t_name);
return dispatch(range.first, range.second, params); return dispatch(range.first, range.second, params);
}
Boxed_Value call_function(const std::string &t_name) const
{
return call_function(t_name, std::vector<Boxed_Value>());
}
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1) const
{
std::vector<Boxed_Value> params;
params.push_back(p1);
return call_function(t_name, params);
}
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1, const Boxed_Value &p2) const
{
std::vector<Boxed_Value> params;
params.push_back(p1);
params.push_back(p2);
return call_function(t_name, params);
} }
/** /**
@@ -616,6 +652,26 @@ namespace chaiscript
return get_type_name(obj.get_type_info()); return get_type_name(obj.get_type_info());
} }
State get_state()
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
#endif
return m_state;
}
void set_state(const State &t_state)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
#endif
m_state = t_state;
}
private: private:
/** /**
@@ -642,7 +698,7 @@ namespace chaiscript
boost::shared_lock<boost::shared_mutex> l(m_mutex); boost::shared_lock<boost::shared_mutex> l(m_mutex);
#endif #endif
if (m_reserved_words.find(name) != m_reserved_words.end()) if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
{ {
throw reserved_word_error(name); throw reserved_word_error(name);
} }
@@ -660,7 +716,7 @@ namespace chaiscript
#endif #endif
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, 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_state.m_functions.equal_range(t_name);
while (range.first != range.second) while (range.first != range.second)
{ {
@@ -671,7 +727,7 @@ namespace chaiscript
++range.first; ++range.first;
} }
m_functions.insert(std::make_pair(t_name, f)); m_state.m_functions.insert(std::make_pair(t_name, f));
get_function_cache().insert(std::make_pair(t_name, f)); get_function_cache().insert(std::make_pair(t_name, f));
return true; return true;
@@ -698,13 +754,9 @@ namespace chaiscript
chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder; chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder;
std::multimap<std::string, Proxy_Function> m_functions; State m_state;
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
Boxed_Value m_place_holder; Boxed_Value m_place_holder;
std::set<std::string> m_reserved_words;
}; };
} }

View File

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

View File

@@ -13,6 +13,7 @@
#include "type_info.hpp" #include "type_info.hpp"
#include <string> #include <string>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "proxy_functions_detail.hpp" #include "proxy_functions_detail.hpp"
@@ -442,11 +443,10 @@ namespace chaiscript
if (bv.is_const()) if (bv.is_const())
{ {
const Class *o = boxed_cast<const Class *>(bv); const Class *o = boxed_cast<const Class *>(bv);
return Handle_Return<typename boost::add_const<typename boost::add_reference<T>::type>::type>::handle(o->*m_attr); return Handle_Return<const typename boost::add_reference<T>::type>::handle(o->*m_attr);
} else { } else {
Class *o = boxed_cast<Class *>(bv); Class *o = boxed_cast<Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr); return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
// return Boxed_Value( boost::ref(o->*m_attr) );
} }
} else { } else {
throw arity_error(params.size(), 1); throw arity_error(params.size(), 1);
@@ -497,6 +497,11 @@ namespace chaiscript
{ {
} }
dispatch_error(bool is_const) throw()
: std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":""))
{
}
virtual ~dispatch_error() throw() {} virtual ~dispatch_error() throw() {}
}; };
@@ -527,7 +532,7 @@ namespace chaiscript
++begin; ++begin;
} }
throw dispatch_error(); throw dispatch_error(plist.empty()?false:plist[0].is_const());
} }
/** /**

View File

@@ -87,6 +87,17 @@ namespace chaiscript
bool is_reference() const { return m_is_reference; } bool is_reference() const { return m_is_reference; }
bool is_void() const { return m_is_void; } bool is_void() const { return m_is_void; }
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; } bool is_undef() const { return m_is_undef || m_bare_type_info == 0; }
bool is_pointer() const { return m_is_pointer; }
std::string name() const
{
if (m_type_info)
{
return m_type_info->name();
} else {
return "";
}
}
std::string bare_name() const std::string bare_name() const
{ {

View File

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

View File

@@ -42,12 +42,15 @@ namespace chaiscript
*/ */
template <typename Eval_System> template <typename Eval_System>
Boxed_Value eval_file(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_file(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval; const unsigned int size = node->children.size();
unsigned int i; for (unsigned int i = 0; i < size; ++i) {
for (i = 0; i < node->children.size(); ++i) { const Boxed_Value &retval = eval_token(ss, node->children[i]);
retval = eval_token(ss, node->children[i]); if (i + 1 == size)
{
return retval;
}
} }
return retval; return Boxed_Value();
} }
template <typename Eval_System> template <typename Eval_System>
@@ -173,16 +176,14 @@ namespace chaiscript
try { try {
if (lhs.is_undef()) if (lhs.is_undef())
{ {
retval = ss.call_function("clone", Param_List_Builder() << retval); retval = ss.call_function("clone", retval);
} }
Param_List_Builder plb;
plb << lhs;
plb << retval;
try { try {
retval = ss.call_function(node->children[i+1]->text, plb); retval = ss.call_function(node->children[i+1]->text, lhs, retval);
} }
catch(const dispatch_error &){ catch(const dispatch_error &){
throw Eval_Error("Mismatched types in equation", node->children[i+1]); throw Eval_Error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."), node->children[i+1]);
} }
} }
catch(const dispatch_error &){ catch(const dispatch_error &){
@@ -199,11 +200,8 @@ namespace chaiscript
} }
} }
else { else {
Param_List_Builder plb;
plb << eval_token(ss, node->children[i]);
plb << retval;
try { try {
retval = ss.call_function(node->children[i+1]->text, plb); retval = ss.call_function(node->children[i+1]->text, eval_token(ss, node->children[i]), retval);
} }
catch(const dispatch_error &){ 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]);
@@ -251,12 +249,12 @@ namespace chaiscript
Boxed_Value eval_logical(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_logical(Eval_System &ss, const TokenPtr &node) {
unsigned int i; unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]); Boxed_Value retval(eval_token(ss, node->children[0]));
if (node->children.size() > 1) { if (node->children.size() > 1) {
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 = boxed_cast<bool >(retval); lhs = boxed_cast<bool>(retval);
} }
catch (const bad_boxed_cast &) { catch (const bad_boxed_cast &) {
throw Eval_Error("Condition not boolean", node); throw Eval_Error("Condition not boolean", node);
@@ -290,18 +288,12 @@ namespace chaiscript
unsigned int i; unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]); Boxed_Value retval = eval_token(ss, node->children[0]);
if (node->children.size() > 1) { for (i = 1; i < node->children.size(); i += 2) {
for (i = 1; i < node->children.size(); i += 2) { try {
Param_List_Builder plb; retval = ss.call_function(node->children[i]->text, retval, eval_token(ss, node->children[i + 1]));
plb << retval; }
plb << eval_token(ss, node->children[i + 1]); catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
try {
retval = ss.call_function(node->children[i]->text, plb);
}
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
}
} }
} }
@@ -317,11 +309,8 @@ namespace chaiscript
Boxed_Value retval = eval_token(ss, node->children[0]); Boxed_Value retval = eval_token(ss, node->children[0]);
for (i = 1; i < node->children.size(); ++i) { for (i = 1; i < node->children.size(); ++i) {
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i]);
try { try {
retval = ss.call_function("[]", plb); retval = ss.call_function("[]", retval, eval_token(ss, node->children[i]));
} }
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);
@@ -339,11 +328,8 @@ namespace chaiscript
*/ */
template <typename Eval_System> template <typename Eval_System>
Boxed_Value eval_prefix(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_prefix(Eval_System &ss, const TokenPtr &node) {
Param_List_Builder plb;
plb << eval_token(ss, node->children[1]);
try { try {
return ss.call_function(node->children[0]->text, plb); return ss.call_function(node->children[0]->text, eval_token(ss, node->children[1]));
} }
catch(std::exception &){ catch(std::exception &){
throw Eval_Error("Can not find appropriate unary '" + node->children[0]->text + "'", node->children[0]); throw Eval_Error("Can not find appropriate unary '" + node->children[0]->text + "'", node->children[0]);
@@ -358,16 +344,13 @@ namespace chaiscript
unsigned int i; unsigned int i;
try { try {
Boxed_Value retval = ss.call_function("Vector", Param_List_Builder()); Boxed_Value retval = ss.call_function("Vector");
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 { ss.call_function("push_back", retval, eval_token(ss, node->children[0]->children[i]));
Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]); }
ss.call_function("push_back", Param_List_Builder() << retval << tmp); catch (const dispatch_error &) {
} throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
}
} }
} }
@@ -385,9 +368,9 @@ namespace chaiscript
template <typename Eval_System> template <typename Eval_System>
Boxed_Value eval_inline_range(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_inline_range(Eval_System &ss, const TokenPtr &node) {
try { try {
return ss.call_function("generate_range", Param_List_Builder() return ss.call_function("generate_range",
<< eval_token(ss, node->children[0]->children[0]->children[0]) eval_token(ss, node->children[0]->children[0]->children[0]),
<< eval_token(ss, node->children[0]->children[0]->children[1])); eval_token(ss, node->children[0]->children[0]->children[1]));
} }
catch (const dispatch_error &) { catch (const dispatch_error &) {
throw Eval_Error("Unable to generate range vector", node); throw Eval_Error("Unable to generate range vector", node);
@@ -402,12 +385,12 @@ namespace chaiscript
unsigned int i; unsigned int i;
try { try {
Boxed_Value retval = ss.call_function("Map", Param_List_Builder()); Boxed_Value retval = ss.call_function("Map");
for (i = 0; i < node->children[0]->children.size(); ++i) { for (i = 0; i < node->children[0]->children.size(); ++i) {
try { try {
Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]); Boxed_Value slot
Boxed_Value slot = ss.call_function("[]", Param_List_Builder() << retval << key); = ss.call_function("[]", retval, eval_token(ss, node->children[0]->children[i]->children[0]));
ss.call_function("=", Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1])); ss.call_function("=", slot, eval_token(ss, node->children[0]->children[i]->children[1]));
} }
catch (const 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]);
@@ -441,7 +424,7 @@ namespace chaiscript
try { try {
ss.set_stack(new_stack); ss.set_stack(new_stack);
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb); const Boxed_Value &retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
return retval; return retval;
} }
@@ -483,8 +466,7 @@ namespace chaiscript
Boxed_Value fn = eval_token(ss, node->children[0]); Boxed_Value fn = eval_token(ss, node->children[0]);
try { try {
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb); return (*boxed_cast<Const_Proxy_Function >(fn))(plb);
return retval;
} }
catch(const dispatch_error &e){ catch(const dispatch_error &e){
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]);
@@ -513,7 +495,7 @@ namespace chaiscript
//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
Boxed_Value retval = eval_token(ss, node->children[0]); Boxed_Value retval(eval_token(ss, node->children[0]));
if (node->children.size() > 1) { if (node->children.size() > 1) {
for (i = 2; i < node->children.size(); i+=2) { for (i = 2; i < node->children.size(); i+=2) {
Param_List_Builder plb; Param_List_Builder plb;
@@ -570,7 +552,6 @@ namespace chaiscript
template <typename Eval_System> template <typename Eval_System>
Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval; Boxed_Value retval;
retval = Boxed_Value();
ss.new_scope(); ss.new_scope();
try { try {
@@ -683,6 +664,7 @@ namespace chaiscript
ss.pop_scope(); ss.pop_scope();
throw; throw;
} }
if (node->children.back()->identifier == Token_Type::Finally) { if (node->children.back()->identifier == Token_Type::Finally) {
retval = eval_token(ss, node->children.back()->children[0]); retval = eval_token(ss, node->children.back()->children[0]);
} }
@@ -699,35 +681,32 @@ namespace chaiscript
Boxed_Value eval_if(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_if(Eval_System &ss, const TokenPtr &node) {
unsigned int i; unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
bool cond; bool cond;
try { try {
cond = boxed_cast<bool>(retval); cond = boxed_cast<bool>(eval_token(ss, node->children[0]));
} }
catch (const 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) {
retval = eval_token(ss, node->children[1]); return eval_token(ss, node->children[1]);
} }
else { else {
if (node->children.size() > 2) { if (node->children.size() > 2) {
i = 2; i = 2;
while ((!cond) && (i < node->children.size())) { while ((!cond) && (i < node->children.size())) {
if (node->children[i]->text == "else") { if (node->children[i]->text == "else") {
retval = eval_token(ss, node->children[i+1]); return eval_token(ss, node->children[i+1]);
cond = true;
} }
else if (node->children[i]->text == "else if") { else if (node->children[i]->text == "else if") {
retval = eval_token(ss, node->children[i+1]);
try { try {
cond = boxed_cast<bool>(retval); cond = boxed_cast<bool>(eval_token(ss, node->children[i+1]));
} }
catch (const bad_boxed_cast &) { catch (const bad_boxed_cast &) {
throw Eval_Error("'else if' 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]); return eval_token(ss, node->children[i+2]);
} }
} }
i = i + 3; i = i + 3;
@@ -735,7 +714,7 @@ namespace chaiscript
} }
} }
return retval; return Boxed_Value(false);
} }
/** /**
@@ -980,17 +959,22 @@ namespace chaiscript
*/ */
template <typename Eval_System> template <typename Eval_System>
Boxed_Value eval_block(Eval_System &ss, const TokenPtr &node) { Boxed_Value eval_block(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
unsigned int i; unsigned int i;
unsigned int num_children = node->children.size();
ss.new_scope(); ss.new_scope();
for (i = 0; i < node->children.size(); ++i) { for (i = 0; i < num_children; ++i) {
try { try {
retval = eval_token(ss, node->children[i]); const Boxed_Value &retval = eval_token(ss, node->children[i]);
if (i + 1 == num_children)
{
ss.pop_scope();
return retval;
}
} }
catch (const chaiscript::Return_Value &rv) { catch (const chaiscript::Return_Value &rv) {
ss.pop_scope(); ss.pop_scope();
retval = rv.retval;
throw; throw;
} }
catch (...) { catch (...) {
@@ -998,9 +982,9 @@ namespace chaiscript
throw; throw;
} }
} }
ss.pop_scope();
return retval; ss.pop_scope();
return Boxed_Value();
} }
/** /**

View File

@@ -171,7 +171,9 @@ namespace chaiscript
} }
else if (Symbol_(singleline_comment.c_str())) { else if (Symbol_(singleline_comment.c_str())) {
while (input_pos != input_end) { while (input_pos != input_end) {
if (Eol_()) { if (Symbol_("\r\n") || Char_('\n')) {
++line;
col = 1;
break; break;
} }
else { else {
@@ -1584,7 +1586,6 @@ namespace chaiscript
if (Operator_Helper(precedence)) { if (Operator_Helper(precedence)) {
do { do {
if (!Operator(precedence+1)) { if (!Operator(precedence+1)) {
std::cout << std::string(input_pos, input_end);
throw Eval_Error("Incomplete " + std::string(token_type_to_string(operators[precedence])) + " expression", throw Eval_Error("Incomplete " + std::string(token_type_to_string(operators[precedence])) + " expression",
File_Position(line, col), filename); File_Position(line, col), filename);
} }

View File

@@ -282,27 +282,27 @@ def zip(x, y) { \n\
}\n\ }\n\
# 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 string::find(substr) : is_type(substr, "string") { \n\ def string::find(substr) : is_type(substr, "string") { \n\
int(find(this, substr, size_t(0))); \n\ int(find(this, substr, 0)); \n\
} \n\ } \n\
# 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 string::rfind(substr) : is_type(substr, "string") { \n\ def string::rfind(substr) : is_type(substr, "string") { \n\
int(rfind(this, substr, size_t(-1))); \n\ int(rfind(this, substr, -1)); \n\
} \n\ } \n\
# 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 string::find_first_of(list) : is_type(list, "string") { \n\ def string::find_first_of(list) : is_type(list, "string") { \n\
int(find_first_of(this, list, size_t(0))); \n\ int(find_first_of(this, list, 0)); \n\
} \n\ } \n\
# 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 string::find_last_of(list) : is_type(list, "string") { \n\ def string::find_last_of(list) : is_type(list, "string") { \n\
int(find_last_of(this, list, size_t(-1))); \n\ int(find_last_of(this, list, -1)); \n\
} \n\ } \n\
# 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 string::find_first_not_of(list) : is_type(list, "string") { \n\ def string::find_first_not_of(list) : is_type(list, "string") { \n\
int(find_first_not_of(this, list, size_t(0))); \n\ int(find_first_not_of(this, list, 0)); \n\
} \n\ } \n\
# 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 string::find_last_not_of(list) : is_type(list, "string") { \n\ def string::find_last_not_of(list) : is_type(list, "string") { \n\
int(find_last_not_of(this, list, size_t(-1))); \n\ int(find_last_not_of(this, list, -1)); \n\
} \n\ } \n\
def string::ltrim() { \n\ def string::ltrim() { \n\
drop_while(this, fun(x) { x == ' ' || x == '\t' }); \n\ drop_while(this, fun(x) { x == ' ' || x == '\t' }); \n\

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

10
unittests/type_info.chai Normal file
View File

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

9
unittests/type_info.txt Normal file
View File

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