Compare commits

...

17 Commits

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

View File

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

View File

@@ -158,7 +158,7 @@ namespace chaiscript
template<typename ContainerType>
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<void (ContainerType::*)()>(&ContainerType::clear), "clear");
@@ -319,7 +319,8 @@ namespace chaiscript
template<typename ContainerType>
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;
}
@@ -412,13 +413,16 @@ namespace chaiscript
}
m->add(fun(&String::push_back), push_back_name);
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
m->add(fun(static_cast<find_func>(&String::find)), "find");
m->add(fun(static_cast<find_func>(&String::rfind)), "rfind");
m->add(fun(static_cast<find_func>(&String::find_first_of)), "find_first_of");
m->add(fun(static_cast<find_func>(&String::find_last_of)), "find_last_of");
m->add(fun(static_cast<find_func>(&String::find_first_not_of)), "find_first_not_of");
m->add(fun(static_cast<find_func>(&String::find_last_not_of)), "find_last_not_of");
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
typedef boost::function<int (const String *, const String &, int)> find_func;
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find))), "find");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::rfind))), "rfind");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_of))), "find_first_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_of))), "find_last_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_not_of))), "find_first_not_of");
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_not_of))), "find_last_not_of");
return m;
}

View File

@@ -17,6 +17,7 @@
#include <boost/bind.hpp>
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
#include <limits>
namespace chaiscript
{
@@ -264,6 +265,11 @@ namespace chaiscript
{
}
void swap(Boxed_Value &rhs)
{
std::swap(m_data, rhs.m_data);
}
/**
* Return a reference to the static global Object_Cache
*/
@@ -293,7 +299,8 @@ namespace chaiscript
*/
Boxed_Value &operator=(const Boxed_Value &rhs)
{
m_data = rhs.m_data;
Boxed_Value temp(rhs);
swap(temp);
return *this;
}
@@ -315,6 +322,11 @@ namespace chaiscript
return m_data->m_type_info.is_const();
}
bool is_type(const Type_Info &ti) const
{
return m_data->m_type_info.bare_equal(ti);
}
bool is_null() const
{
if (m_data->m_is_null)
@@ -335,6 +347,12 @@ namespace chaiscript
return m_data->m_is_ref;
}
bool is_pointer() const
{
return !is_ref();
}
private:
boost::shared_ptr<Data> m_data;
};
@@ -700,7 +718,7 @@ namespace chaiscript
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i + r.i);
return smart_size(i + r.i);
}
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
@@ -710,7 +728,7 @@ namespace chaiscript
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i - r.i);
return smart_size(i - r.i);
}
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
@@ -750,7 +768,7 @@ namespace chaiscript
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i / r.i);
return smart_size(i / r.i);
}
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
@@ -760,7 +778,7 @@ namespace chaiscript
{
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");
@@ -771,7 +789,7 @@ namespace chaiscript
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i * r.i);
return smart_size(i * r.i);
}
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
@@ -782,7 +800,7 @@ namespace chaiscript
{
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");
@@ -792,12 +810,23 @@ namespace chaiscript
{
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");
}
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;
@@ -874,7 +903,14 @@ namespace chaiscript
{
return l.get_type_info() == r.get_type_info();
}
}
namespace std
{
template<> void swap(chaiscript::Boxed_Value &lhs, chaiscript::Boxed_Value &rhs)
{
lhs.swap(rhs);
}
}
#endif

View File

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

View File

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

View File

@@ -13,6 +13,7 @@
#include "type_info.hpp"
#include <string>
#include <boost/function.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <stdexcept>
#include <vector>
#include "proxy_functions_detail.hpp"
@@ -442,11 +443,10 @@ namespace chaiscript
if (bv.is_const())
{
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 {
Class *o = boxed_cast<Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
// return Boxed_Value( boost::ref(o->*m_attr) );
}
} else {
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() {}
};
@@ -527,7 +532,7 @@ namespace chaiscript
++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_void() const { return m_is_void; }
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
{

View File

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

View File

@@ -42,13 +42,16 @@ namespace chaiscript
*/
template <typename Eval_System>
Boxed_Value eval_file(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
unsigned int i;
for (i = 0; i < node->children.size(); ++i) {
retval = eval_token(ss, node->children[i]);
}
const unsigned int size = node->children.size();
for (unsigned int i = 0; i < size; ++i) {
const Boxed_Value &retval = eval_token(ss, node->children[i]);
if (i + 1 == size)
{
return retval;
}
}
return Boxed_Value();
}
template <typename Eval_System>
void cache_const(Eval_System &/*ss*/, const TokenPtr &node, const Boxed_Value &value) {
@@ -173,16 +176,14 @@ namespace chaiscript
try {
if (lhs.is_undef())
{
retval = ss.call_function("clone", Param_List_Builder() << retval);
retval = ss.call_function("clone", retval);
}
Param_List_Builder plb;
plb << lhs;
plb << retval;
try {
retval = ss.call_function(node->children[i+1]->text, plb);
retval = ss.call_function(node->children[i+1]->text, lhs, retval);
}
catch(const dispatch_error &){
throw Eval_Error("Mismatched types in equation", node->children[i+1]);
throw Eval_Error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."), node->children[i+1]);
}
}
catch(const dispatch_error &){
@@ -199,11 +200,8 @@ namespace chaiscript
}
}
else {
Param_List_Builder plb;
plb << eval_token(ss, node->children[i]);
plb << retval;
try {
retval = ss.call_function(node->children[i+1]->text, plb);
retval = ss.call_function(node->children[i+1]->text, eval_token(ss, node->children[i]), retval);
}
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
@@ -251,12 +249,12 @@ namespace chaiscript
Boxed_Value eval_logical(Eval_System &ss, const TokenPtr &node) {
unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
Boxed_Value retval(eval_token(ss, node->children[0]));
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); i += 2) {
bool lhs;
try {
lhs = boxed_cast<bool >(retval);
lhs = boxed_cast<bool>(retval);
}
catch (const bad_boxed_cast &) {
throw Eval_Error("Condition not boolean", node);
@@ -290,20 +288,14 @@ namespace chaiscript
unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); i += 2) {
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i + 1]);
try {
retval = ss.call_function(node->children[i]->text, plb);
retval = ss.call_function(node->children[i]->text, retval, eval_token(ss, node->children[i + 1]));
}
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
}
}
}
return retval;
}
@@ -317,11 +309,8 @@ namespace chaiscript
Boxed_Value retval = eval_token(ss, node->children[0]);
for (i = 1; i < node->children.size(); ++i) {
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i]);
try {
retval = ss.call_function("[]", plb);
retval = ss.call_function("[]", retval, eval_token(ss, node->children[i]));
}
catch(std::out_of_range &) {
throw Eval_Error("Out of bounds exception", node);
@@ -339,11 +328,8 @@ namespace chaiscript
*/
template <typename Eval_System>
Boxed_Value eval_prefix(Eval_System &ss, const TokenPtr &node) {
Param_List_Builder plb;
plb << eval_token(ss, node->children[1]);
try {
return ss.call_function(node->children[0]->text, plb);
return ss.call_function(node->children[0]->text, eval_token(ss, node->children[1]));
}
catch(std::exception &){
throw Eval_Error("Can not find appropriate unary '" + node->children[0]->text + "'", node->children[0]);
@@ -358,18 +344,15 @@ namespace chaiscript
unsigned int i;
try {
Boxed_Value retval = ss.call_function("Vector", Param_List_Builder());
if (node->children.size() > 0) {
Boxed_Value retval = ss.call_function("Vector");
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
ss.call_function("push_back", Param_List_Builder() << retval << tmp);
ss.call_function("push_back", retval, eval_token(ss, node->children[0]->children[i]));
}
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
}
}
}
return retval;
}
@@ -385,9 +368,9 @@ namespace chaiscript
template <typename Eval_System>
Boxed_Value eval_inline_range(Eval_System &ss, const TokenPtr &node) {
try {
return ss.call_function("generate_range", Param_List_Builder()
<< eval_token(ss, node->children[0]->children[0]->children[0])
<< eval_token(ss, node->children[0]->children[0]->children[1]));
return ss.call_function("generate_range",
eval_token(ss, node->children[0]->children[0]->children[0]),
eval_token(ss, node->children[0]->children[0]->children[1]));
}
catch (const dispatch_error &) {
throw Eval_Error("Unable to generate range vector", node);
@@ -402,12 +385,12 @@ namespace chaiscript
unsigned int i;
try {
Boxed_Value retval = ss.call_function("Map", Param_List_Builder());
Boxed_Value retval = ss.call_function("Map");
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
Boxed_Value slot = ss.call_function("[]", Param_List_Builder() << retval << key);
ss.call_function("=", Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
Boxed_Value slot
= ss.call_function("[]", retval, eval_token(ss, node->children[0]->children[i]->children[0]));
ss.call_function("=", slot, eval_token(ss, node->children[0]->children[i]->children[1]));
}
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]);
@@ -441,7 +424,7 @@ namespace chaiscript
try {
ss.set_stack(new_stack);
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
const Boxed_Value &retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
ss.set_stack(prev_stack);
return retval;
}
@@ -483,8 +466,7 @@ namespace chaiscript
Boxed_Value fn = eval_token(ss, node->children[0]);
try {
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb);
return retval;
return (*boxed_cast<Const_Proxy_Function >(fn))(plb);
}
catch(const dispatch_error &e){
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
@@ -513,7 +495,7 @@ namespace chaiscript
//todo: Please extract a single way of doing function calls between this and eval_fun_call
Boxed_Value retval = eval_token(ss, node->children[0]);
Boxed_Value retval(eval_token(ss, node->children[0]));
if (node->children.size() > 1) {
for (i = 2; i < node->children.size(); i+=2) {
Param_List_Builder plb;
@@ -570,7 +552,6 @@ namespace chaiscript
template <typename Eval_System>
Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
retval = Boxed_Value();
ss.new_scope();
try {
@@ -683,6 +664,7 @@ namespace chaiscript
ss.pop_scope();
throw;
}
if (node->children.back()->identifier == Token_Type::Finally) {
retval = eval_token(ss, node->children.back()->children[0]);
}
@@ -699,35 +681,32 @@ namespace chaiscript
Boxed_Value eval_if(Eval_System &ss, const TokenPtr &node) {
unsigned int i;
Boxed_Value retval = eval_token(ss, node->children[0]);
bool cond;
try {
cond = boxed_cast<bool>(retval);
cond = boxed_cast<bool>(eval_token(ss, node->children[0]));
}
catch (const bad_boxed_cast &) {
throw Eval_Error("If condition not boolean", node->children[0]);
}
if (cond) {
retval = eval_token(ss, node->children[1]);
return eval_token(ss, node->children[1]);
}
else {
if (node->children.size() > 2) {
i = 2;
while ((!cond) && (i < node->children.size())) {
if (node->children[i]->text == "else") {
retval = eval_token(ss, node->children[i+1]);
cond = true;
return eval_token(ss, node->children[i+1]);
}
else if (node->children[i]->text == "else if") {
retval = eval_token(ss, node->children[i+1]);
try {
cond = boxed_cast<bool>(retval);
cond = boxed_cast<bool>(eval_token(ss, node->children[i+1]));
}
catch (const bad_boxed_cast &) {
throw Eval_Error("'else if' condition not boolean", node->children[i+1]);
}
if (cond) {
retval = eval_token(ss, node->children[i+2]);
return eval_token(ss, node->children[i+2]);
}
}
i = i + 3;
@@ -735,7 +714,7 @@ namespace chaiscript
}
}
return retval;
return Boxed_Value(false);
}
/**
@@ -980,17 +959,22 @@ namespace chaiscript
*/
template <typename Eval_System>
Boxed_Value eval_block(Eval_System &ss, const TokenPtr &node) {
Boxed_Value retval;
unsigned int i;
unsigned int num_children = node->children.size();
ss.new_scope();
for (i = 0; i < node->children.size(); ++i) {
for (i = 0; i < num_children; ++i) {
try {
retval = eval_token(ss, node->children[i]);
}
catch (const chaiscript::Return_Value &rv) {
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*/) {
ss.pop_scope();
retval = rv.retval;
throw;
}
catch (...) {
@@ -998,9 +982,9 @@ namespace chaiscript
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())) {
while (input_pos != input_end) {
if (Eol_()) {
if (Symbol_("\r\n") || Char_('\n')) {
++line;
col = 1;
break;
}
else {
@@ -1584,7 +1586,6 @@ namespace chaiscript
if (Operator_Helper(precedence)) {
do {
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",
File_Position(line, col), filename);
}

View File

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

View File

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

View File

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

View File

@@ -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;
print(i.is_undef());
print(i.is_var_undef());
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