Compare commits

..

25 Commits

Author SHA1 Message Date
Jason Turner
669d6e9495 Cleanup comment in example.cpp 2009-07-25 13:48:44 +00:00
Jonathan Turner
9f614bba33 Update ticks in example to proper quotes 2009-07-24 13:31:15 +00:00
Jason Turner
0b789004e9 Make "clone" a chaiscript based operation instead of forcing the user to register a clone method. 2009-07-24 13:17:00 +00:00
Jason Turner
0d3c90a245 Add "type_name" function and port the "new" in prelude to use it instead of clone/clear. 2009-07-24 04:01:28 +00:00
Jonathan Turner
2f591a25a6 Add ltrim, rtrim, and trim 2009-07-23 17:35:39 +00:00
Jonathan Turner
4127a6ed41 Added 'clear'. Added 'push_back' to string. Added char. Added simple reverse 2009-07-23 17:01:07 +00:00
Jason Turner
4e412c0f6a Fix compilation error for G++ 2009-07-23 13:03:57 +00:00
Jason Turner
370121a9ff add example.cpp to build for VC++, fix minor bug in passing of & parameters to functor<>, move bootstrap functions into bootstrap namespace and clean up function names and add "retro" support for reversing of ranges. 2009-07-23 04:35:15 +00:00
Jason Turner
00ac8113c0 Add additional support for boost::shared_ptr as a return type 2009-07-21 02:00:39 +00:00
Jonathan Turner
72b6647718 Add missing return value 2009-07-20 19:53:31 +00:00
Jason Turner
daacbaa9e0 Correct for warnings and errors for the VC++ port. 2009-07-19 03:59:58 +00:00
Jason Turner
a5a1e3ee1b Revamped method for bootstrapping of types, using a new Module class that collects everything related to a type or group of types 2009-07-19 03:04:46 +00:00
Jason Turner
5a5b2929b0 Add additional functor example 2009-07-18 23:41:01 +00:00
Jason Turner
82bd46bb1a More usage cleansups 2009-07-18 23:34:08 +00:00
Jason Turner
4d4c26bf73 Major updates to the C++ API. Please see trunk/src/example.cpp to follow along 2009-07-18 18:05:54 +00:00
Jonathan Turner
ac817ff33a Change 'elseif' to 'else if' to better support C++ expectations 2009-07-17 14:16:27 +00:00
Jason Turner
689143aba5 Fix broken push_back in prelude, to correct for unit tests. 2009-07-16 23:53:13 +00:00
Jason Turner
9b733b2621 Correct g++ compilation error caused by r308, fix for casting to const boost::shared_ptr<> &. 2009-07-16 23:46:19 +00:00
Jason Turner
727dc7b0d6 Add support for boxed_cast<> to const boost::shared_ptr<Type> &, fixing the problem Jon was having 2009-07-16 21:30:01 +00:00
Jonathan Turner
3fc5f8e8e1 Guard push_back to ensure we have the push_back_ref before we call it 2009-07-16 20:32:33 +00:00
Jonathan Turner
aed493322b Clean up exception story so that there is only one exception type and one thing the user needs to catch 2009-07-16 13:24:15 +00:00
Jason Turner
8dbb43f45f Clean up last bug fix with full support for const & (and presumably some support for const *) contained types. 2009-07-15 23:36:10 +00:00
Jason Turner
ec2f81c674 Fix bug that jon discovered that affects attempting to return a reference to an object that shares a memory location with a containing object but has a different type. 2009-07-15 23:12:49 +00:00
Jonathan Turner
724ffdcb20 Oops, resetting CMakeList.txt to the correct one 2009-07-15 14:41:21 +00:00
Jonathan Turner
7c7e437b10 Clean up unnecessary Boxed_Value copies in eval 2009-07-15 14:40:53 +00:00
27 changed files with 1968 additions and 1388 deletions

View File

@@ -20,7 +20,7 @@
#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/function_call.hpp"
namespace chaiscript
{
/**
@@ -83,41 +83,29 @@ namespace chaiscript
};
/**
* Errors generated inside the parser
* Errors generated during parsing or evaluation
*/
struct Parse_Error : public std::runtime_error {
struct Eval_Error : public std::runtime_error {
std::string reason;
File_Position position;
const char *filename;
Parse_Error(const std::string &why, const File_Position &where, const char *fname) :
std::runtime_error("Parse error: \"" + why + "\" in '"
+ std::string(fname) + "' at: (" + boost::lexical_cast<std::string>(where.line+1) + ", " +
boost::lexical_cast<std::string>(where.column) + ")"),
Eval_Error(const std::string &why, const File_Position &where, const char *fname) :
std::runtime_error("Error: \"" + why + "\" " +
(std::string(fname) != "__EVAL__" ? ("in '" + std::string(fname) + "' ") : "during evaluation ") +
+ "at (" + boost::lexical_cast<std::string>(where.line) + ", " +
boost::lexical_cast<std::string>(where.column) + ")"),
reason(why), position(where), filename(fname)
{ }
Parse_Error(const std::string &why, const TokenPtr &where)
: std::runtime_error("Parse error: \"" + why + "\" in '"
+ where->filename + "' line: " + boost::lexical_cast<std::string>(where->start.line+1)),
Eval_Error(const std::string &why, const TokenPtr &where)
: std::runtime_error("Error: \"" + why + "\" " +
(std::string(where->filename) != "__EVAL__" ? ("in '" + std::string(where->filename) + "' ") : "during evaluation ") +
"at (" + boost::lexical_cast<std::string>(where->start.line) + ", " +
boost::lexical_cast<std::string>(where->start.column) + ")"),
reason(why), position(where->start), filename(where->filename) {
}
virtual ~Parse_Error() throw() {}
};
/**
* Errors generated inside the evaluator
*/
struct Eval_Error : public std::runtime_error {
std::string reason;
TokenPtr location;
Eval_Error(const std::string &why, const TokenPtr where)
: std::runtime_error("Eval error: \"" + why + "\" in '"
+ where->filename + "' line: " + boost::lexical_cast<std::string>(where->start.line+1)),
reason(why), location(where) { }
virtual ~Eval_Error() throw() {}
};
@@ -125,10 +113,10 @@ namespace chaiscript
* Special type for returned values
*/
struct Return_Value {
dispatchkit::Boxed_Value retval;
Boxed_Value retval;
TokenPtr location;
Return_Value(const dispatchkit::Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
Return_Value(const Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
};
/**

File diff suppressed because it is too large Load Diff

View File

@@ -5,39 +5,43 @@
// http://www.chaiscript.com
/**
* This file contains utility functions for registration of STL container
* classes. The methodology used is based on the SGI STL concepts.
* http://www.sgi.com/tech/stl/table_of_contents.html
*/
* This file contains utility functions for registration of STL container
* classes. The methodology used is based on the SGI STL concepts.
* http://www.sgi.com/tech/stl/table_of_contents.html
*/
#ifndef __bootstrap_stl_hpp
#ifndef __bootstrap_stl_hpp__
#define __bootstrap_stl_hpp__
#include "dispatchkit.hpp"
#include "register_function.hpp"
namespace dispatchkit
namespace chaiscript
{
/**
* Input_Range, based on the D concept of ranges.
* \todo Update the Range code to base its capabilities on
* the type_traits of the iterator passed in
*/
template<typename Container>
struct Input_Range
namespace bootstrap
{
/**
* Bidir_Range, based on the D concept of ranges.
* \todo Update the Range code to base its capabilities on
* the user_typetraits of the iterator passed in
*/
template<typename Container>
struct Bidir_Range
{
Input_Range(Container &c)
typedef typename std::iterator_traits<typename Container::iterator>::reference reference_type;
Bidir_Range(Container &c)
: m_begin(c.begin()), m_end(c.end())
{
}
Input_Range(typename Container::iterator itr)
Bidir_Range(typename Container::iterator itr)
: m_begin(itr), m_end(itr)
{
}
Input_Range(const std::pair<typename Container::iterator, typename Container::iterator> &t_p)
Bidir_Range(const std::pair<typename Container::iterator, typename Container::iterator> &t_p)
: m_begin(t_p.first), m_end(t_p.second)
{
}
@@ -56,7 +60,16 @@ namespace dispatchkit
++m_begin;
}
typename std::iterator_traits<typename Container::iterator>::reference front() const
void pop_back()
{
if (empty())
{
throw std::range_error("Range empty");
}
--m_end;
}
reference_type front() const
{
if (empty())
{
@@ -65,120 +78,172 @@ namespace dispatchkit
return *m_begin;
}
reference_type back() const
{
if (empty())
{
throw std::range_error("Range empty");
}
typename Container::iterator pos = m_end;
--pos;
return *(pos);
}
typename Container::iterator m_begin;
typename Container::iterator m_end;
};
/**
* Add Input_Range support for the given ContainerType
*/
template<typename ContainerType>
void bootstrap_input_range(Dispatch_Engine &system, const std::string &type)
template<typename Range>
struct Retro
{
system.register_type<Input_Range<ContainerType> >(type+"_Range");
system.register_type<typename ContainerType::iterator>(type+"_Iterator");
Retro(const Range &r)
: m_r(r)
{}
system.register_function(build_constructor<Input_Range<ContainerType>, ContainerType &>(), "range");
system.register_function(build_constructor<Input_Range<ContainerType>,
typename ContainerType::iterator>(), "range");
bool empty() { return m_r.empty(); }
void pop_front() { m_r.pop_back(); }
void pop_back() { m_r.pop_front(); }
typename Range::reference_type front() { return m_r.back(); }
typename Range::reference_type back() { return m_r.front(); }
private:
Range m_r;
};
/**
* Add Bidir_Range support for the given ContainerType
*/
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<Bidir_Range<ContainerType> >(), type + "_Range");
m->add(user_type<Retro<Bidir_Range<ContainerType> > >(), type + "_Retro_Range");
m->add(user_type<typename ContainerType::iterator>(), type+"_Iterator");
copy_constructor<Bidir_Range<ContainerType> >(type + "_Range", m);
copy_constructor<Retro<Bidir_Range<ContainerType> > >(type + "_Retro_Range", m);
m->add(constructor<Bidir_Range<ContainerType> (ContainerType &)>(), "range");
m->add(constructor<Bidir_Range<ContainerType> (typename ContainerType::iterator)>(), "range");
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator> ItrPair;
system.register_function(build_constructor<Input_Range<ContainerType>,
const ItrPair &>(), "range");
system.register_type<ItrPair>(type+"_Iterator_Pair");
m->add(constructor<Bidir_Range<ContainerType> (const ItrPair &)>(), "range");
m->add(user_type<ItrPair>(), type+"_Iterator_Pair");
m->add(fun(&Bidir_Range<ContainerType>::empty), "empty");
m->add(fun(&Bidir_Range<ContainerType>::pop_front), "pop_front");
m->add(fun(&Bidir_Range<ContainerType>::front), "front");
m->add(fun(&Bidir_Range<ContainerType>::pop_back), "pop_back");
m->add(fun(&Bidir_Range<ContainerType>::back), "back");
m->add(fun(&Retro<Bidir_Range<ContainerType> >::empty), "empty");
m->add(fun(&Retro<Bidir_Range<ContainerType> >::pop_front), "pop_front");
m->add(fun(&Retro<Bidir_Range<ContainerType> >::front), "front");
m->add(fun(&Retro<Bidir_Range<ContainerType> >::pop_back), "pop_back");
m->add(fun(&Retro<Bidir_Range<ContainerType> >::back), "back");
m->add(constructor<Retro<Bidir_Range<ContainerType> > (const Bidir_Range<ContainerType> &)>(), "retro");
register_function(system, &Input_Range<ContainerType>::empty, "empty");
register_function(system, &Input_Range<ContainerType>::pop_front, "pop_front");
register_function(system, &Input_Range<ContainerType>::front, "front");
system.register_function(build_constructor<Input_Range<ContainerType>, const Input_Range<ContainerType> &>(), "clone");
return m;
}
/**
* Add reversible_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ReversibleContainer.html
*/
template<typename ContainerType>
void bootstrap_reversible_container(Dispatch_Engine &/*system*/, const std::string &/*type*/)
{
}
/**
* Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType>
void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type)
{
bootstrap_reversible_container<ContainerType>(system, type);
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
/**
* Add reversible_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ReversibleContainer.html
*/
template<typename ContainerType>
ModulePtr reversible_container_type(const std::string &, ModulePtr m = ModulePtr(new Module()))
{
return m;
}
//In the interest of runtime safety for the system, we prefer the at() method for [] access,
//to throw an exception in an out of bounds condition.
system.register_function(
boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::at)), "[]");
system.register_function(
boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::operator[])), "at");
/**
* Add random_access_container concept to the given ContainerType
* http://www.sgi.com/tech/stl/RandomAccessContainer.html
*/
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
reversible_container_type<ContainerType>(type, m);
typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t);
}
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
//to throw an exception in an out of bounds condition.
m->add(
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::at))), "[]");
m->add(
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>(indexoper(&ContainerType::operator[]))), "at");
/**
* Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType>
void bootstrap_assignable(Dispatch_Engine &system, const std::string &type)
{
add_basic_constructors<ContainerType>(system, type);
add_oper_assign<ContainerType>(system);
}
return m;
}
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
void bootstrap_container(Dispatch_Engine &system, const std::string &type)
{
bootstrap_assignable<ContainerType>(system, type);
/**
* Add assignable concept to the given ContainerType
* http://www.sgi.com/tech/stl/Assignable.html
*/
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
basic_constructors<ContainerType>(type, m);
oper_assign<ContainerType>(m);
return m;
}
register_function(system, &ContainerType::size, "size");
register_function(system, &ContainerType::max_size, "max_size");
register_function(system, &ContainerType::empty, "empty");
}
/**
* Add container concept to the given ContainerType
* http://www.sgi.com/tech/stl/Container.html
*/
template<typename ContainerType>
ModulePtr container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
assignable_type<ContainerType>(type, m);
/**
* Add forward container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ForwardContainer.html
*/
template<typename ContainerType>
void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type)
{
bootstrap_input_range<ContainerType>(system, type);
bootstrap_container<ContainerType>(system, type);
}
m->add(fun(&ContainerType::size), "size");
m->add(fun(&ContainerType::max_size), "max_size");
m->add(fun(&ContainerType::empty), "empty");
m->add(fun(&ContainerType::clear), "clear");
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type>
void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type)
{
system.register_function(build_constructor<Type>(), type);
}
return m;
}
/**
* Algorithm for inserting at a specific position into a container
*/
template<typename Type>
/**
* Add forward container concept to the given ContainerType
* http://www.sgi.com/tech/stl/ForwardContainer.html
*/
template<typename ContainerType>
ModulePtr forward_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
input_range_type<ContainerType>(type, m);
container_type<ContainerType>(type, m);
return m;
}
/**
* Add default constructable concept to the given Type
* http://www.sgi.com/tech/stl/DefaultConstructible.html
*/
template<typename Type>
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(constructor<Type ()>(), type);
return m;
}
/**
* Algorithm for inserting at a specific position into a container
*/
template<typename Type>
void insert_at(Type &container, int pos, const typename Type::value_type &v)
{
typename Type::iterator itr = container.begin();
typename Type::iterator end = container.end();
if (pos < 0 || std::distance(itr, end) < pos)
{
throw std::range_error("Cannot insert past end of range");
@@ -188,15 +253,15 @@ namespace dispatchkit
container.insert(itr, v);
}
/**
* Algorithm for erasing a specific position from a container
*/
template<typename Type>
/**
* Algorithm for erasing a specific position from a container
*/
template<typename Type>
void erase_at(Type &container, int pos)
{
typename Type::iterator itr = container.begin();
typename Type::iterator end = container.end();
if (pos < 0 || std::distance(itr, end) < (pos-1))
{
throw std::range_error("Cannot erase past end of range");
@@ -206,178 +271,207 @@ namespace dispatchkit
container.erase(itr);
}
/**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
void bootstrap_sequence(Dispatch_Engine &system, const std::string &type)
{
bootstrap_forward_container<ContainerType>(system, type);
bootstrap_default_constructible<ContainerType>(system, type);
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
/**
* Add sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/Sequence.html
*/
template<typename ContainerType>
ModulePtr sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
insert_name = "insert_ref_at";
} else {
insert_name = "insert_at";
forward_container_type<ContainerType>(type, m);
default_constructible_type<ContainerType>(type, m);
std::string insert_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
insert_name = "insert_ref_at";
} else {
insert_name = "insert_at";
}
m->add(fun(&insert_at<ContainerType>), insert_name);
m->add(fun(&erase_at<ContainerType>), "erase_at");
return m;
}
register_function(system, &insert_at<ContainerType>, insert_name);
register_function(system, &erase_at<ContainerType>, "erase_at");
}
/**
* Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type)
{
bootstrap_sequence<ContainerType>(system, type);
typedef typename ContainerType::reference (ContainerType::*backptr)();
register_function(system, (backptr(&ContainerType::back)), "back");
std::string push_back_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
/**
* Add back insertion sequence concept to the given ContainerType
* http://www.sgi.com/tech/stl/BackInsertionSequence.html
*/
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
sequence_type<ContainerType>(type, m);
typedef typename ContainerType::reference (ContainerType::*backptr)();
m->add(fun(backptr(&ContainerType::back)), "back");
std::string push_back_name;
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
m->add(fun(&ContainerType::push_back), push_back_name);
m->add(fun(&ContainerType::pop_back), "pop_back");
return m;
}
register_function(system, &ContainerType::push_back, push_back_name);
register_function(system, &ContainerType::pop_back, "pop_back");
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
void bootstrap_vector(Dispatch_Engine &system, const std::string &type)
{
system.register_type<VectorType>(type);
bootstrap_random_access_container<VectorType>(system, type);
bootstrap_back_insertion_sequence<VectorType>(system, type);
}
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename ContainerType>
void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type)
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename VectorType>
ModulePtr vector_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_forward_container<ContainerType>(system, type);
bootstrap_default_constructible<ContainerType>(system, type);
m->add(user_type<VectorType>(), type);
random_access_container_type<VectorType>(type, m);
back_insertion_sequence_type<VectorType>(type, m);
return m;
}
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType>
void bootstrap_pair(Dispatch_Engine &system, const std::string &type)
/**
* Create a vector type with associated concepts
* http://www.sgi.com/tech/stl/Vector.html
*/
template<typename ContainerType>
ModulePtr associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
system.register_type<PairType>(type);
register_member(system, &PairType::first, "first");
register_member(system, &PairType::second, "second");
system.register_function(build_constructor<PairType >(), type);
system.register_function(build_constructor<PairType, const PairType &>(), type);
system.register_function(build_constructor<PairType, const PairType &>(), "clone");
system.register_function(build_constructor<PairType, const typename PairType::first_type &, const typename PairType::second_type &>(), type);
}
/**
* Add pair associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
*/
template<typename ContainerType>
void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type)
{
bootstrap_associative_container<ContainerType>(system, type);
bootstrap_pair<typename ContainerType::value_type>(system, type + "_Pair");
forward_container_type<ContainerType>(type, m);
default_constructible_type<ContainerType>(type, m);
return m;
}
/**
* Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType>
void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type)
/**
* bootstrap a given PairType
* http://www.sgi.com/tech/stl/pair.html
*/
template<typename PairType>
ModulePtr pair_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
bootstrap_associative_container<ContainerType>(system, type);
register_function(system, &ContainerType::count, "count");
m->add(user_type<PairType>(), type);
m->add(fun(&PairType::first), "first");
m->add(fun(&PairType::second), "second");
basic_constructors<PairType>(type, m);
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
return m;
}
/**
* Add sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
*/
template<typename ContainerType>
void bootstrap_sorted_associative_container(Dispatch_Engine &system, const std::string &type)
/**
* Add pair associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/PairAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
associative_container_type<ContainerType>(type, m);
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
return m;
}
/**
* Add unique associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
associative_container_type<ContainerType>(type, m);
m->add(fun(&ContainerType::count), "count");
return m;
}
/**
* Add sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
typedef std::pair<typename ContainerType::iterator, typename ContainerType::iterator>
(ContainerType::*eq_range)(const typename ContainerType::key_type &);
(ContainerType::*eq_range)(const typename ContainerType::key_type &);
bootstrap_reversible_container<ContainerType>(system, type);
bootstrap_associative_container<ContainerType>(system, type);
register_function(system, eq_range(&ContainerType::equal_range), "equal_range");
}
reversible_container_type<ContainerType>(type, m);
associative_container_type<ContainerType>(type, m);
m->add(fun(eq_range(&ContainerType::equal_range)), "equal_range");
/**
* Add unique sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
*/
template<typename ContainerType>
void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type)
{
bootstrap_sorted_associative_container<ContainerType>(system, type);
bootstrap_unique_associative_container<ContainerType>(system, type);
return m;
}
/**
* Add a MapType container
* http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType>
void bootstrap_map(Dispatch_Engine &system, const std::string &type)
/**
* Add unique sorted associative container concept to the given ContainerType
* http://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
*/
template<typename ContainerType>
ModulePtr unique_sorted_associative_container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
system.register_type<MapType>(type);
register_function(system, &MapType::operator[], "[]");
bootstrap_unique_sorted_associative_container<MapType>(system, type);
bootstrap_pair_associative_container<MapType>(system, type);
sorted_associative_container_type<ContainerType>(type, m);
unique_associative_container_type<ContainerType>(type, m);
return m;
}
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String>
void bootstrap_string(Dispatch_Engine &system, const std::string &type)
/**
* Add a MapType container
* http://www.sgi.com/tech/stl/Map.html
*/
template<typename MapType>
ModulePtr map_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
system.register_type<String>(type);
add_oper_add<String>(system);
add_oper_add_equals<String>(system);
add_opers_comparison<String>(system);
bootstrap_random_access_container<String>(system, type);
bootstrap_sequence<String>(system, type);
m->add(user_type<MapType>(), type);
m->add(fun(&MapType::operator[]), "[]");
unique_sorted_associative_container_type<MapType>(type, m);
pair_associative_container_type<MapType>(type, m);
return m;
}
/**
* Add a String container
* http://www.sgi.com/tech/stl/basic_string.html
*/
template<typename String>
ModulePtr string_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
{
m->add(user_type<String>(), type);
oper_add<String>(m);
oper_add_equals<String>(m);
opers_comparison<String>(m);
random_access_container_type<String>(type, m);
sequence_type<String>(type, m);
//Special case: add push_back to string (which doesn't support other back_insertion operations
std::string push_back_name;
if (typeid(typename String::value_type) == typeid(Boxed_Value))
{
push_back_name = "push_back_ref";
} else {
push_back_name = "push_back";
}
m->add(fun(&String::push_back), push_back_name);
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
register_function(system, find_func(&String::find), "find");
register_function(system, find_func(&String::rfind), "rfind");
register_function(system, find_func(&String::find_first_of), "find_first_of");
register_function(system, find_func(&String::find_last_of), "find_last_of");
register_function(system, find_func(&String::find_first_not_of), "find_first_not_of");
register_function(system, find_func(&String::find_last_not_of), "find_last_not_of");
m->add(fun(find_func(&String::find)), "find");
m->add(fun(find_func(&String::rfind)), "rfind");
m->add(fun(find_func(&String::find_first_of)), "find_first_of");
m->add(fun(find_func(&String::find_last_of)), "find_last_of");
m->add(fun(find_func(&String::find_first_not_of)), "find_first_not_of");
m->add(fun(find_func(&String::find_last_not_of)), "find_last_not_of");
return m;
}
}
}
#endif

View File

@@ -17,7 +17,7 @@
#include <boost/cstdint.hpp>
#include <boost/type_traits/add_const.hpp>
namespace dispatchkit
namespace chaiscript
{
/**
* Boxed_Value is the main tool of the dispatchkit. It allows
@@ -126,7 +126,13 @@ namespace dispatchkit
}
template<typename T>
boost::shared_ptr<Data> get(boost::shared_ptr<T> obj)
boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
{
return get(*obj);
}
template<typename T>
boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
{
boost::shared_ptr<Data> data(new Data(
Get_Type_Info<T>::get(),
@@ -135,7 +141,7 @@ namespace dispatchkit
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
);
std::map<void *, Data >::iterator itr
std::map<const void *, Data>::iterator itr
= m_ptrs.find(obj.get());
if (itr != m_ptrs.end())
@@ -148,6 +154,12 @@ namespace dispatchkit
return data;
}
template<typename T>
boost::shared_ptr<Data> get(T *t)
{
return get(boost::ref(*t));
}
template<typename T>
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
{
@@ -157,10 +169,18 @@ namespace dispatchkit
true)
);
std::map<void *, Data >::iterator itr
std::map<const void *, Data >::iterator itr
= m_ptrs.find(obj.get_pointer());
if (itr != m_ptrs.end())
// If the ptr is found in the cache and it is the correct type,
// return it. It may be the incorrect type when two variables share the
// same memory location. Example:
// struct test { int x; };
// test t;
// Both t and t.x share the same memory location, but do not represent
// objects of the same type.
if (itr != m_ptrs.end()
&& itr->second.m_type_info.m_bare_type_info == data->m_type_info.m_bare_type_info)
{
(*data) = (itr->second);
}
@@ -199,13 +219,13 @@ namespace dispatchkit
*/
void cull()
{
std::map<void *, Data >::iterator itr = m_ptrs.begin();
std::map<const void *, Data >::iterator itr = m_ptrs.begin();
while (itr != m_ptrs.end())
{
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
{
std::map<void *, Data >::iterator todel = itr;
std::map<const void *, Data >::iterator todel = itr;
++itr;
m_ptrs.erase(todel);
} else {
@@ -214,7 +234,7 @@ namespace dispatchkit
}
}
std::map<void *, Data > m_ptrs;
std::map<const void *, Data > m_ptrs;
};
public:
@@ -318,7 +338,12 @@ namespace dispatchkit
{
if (ob.is_ref())
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
if (!ob.get_type_info().m_is_const)
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
} else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
}
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
}
@@ -337,7 +362,12 @@ namespace dispatchkit
{
if (ob.is_ref())
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
if (!ob.get_type_info().m_is_const)
{
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
} else {
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
}
} else {
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
}
@@ -356,7 +386,12 @@ namespace dispatchkit
{
if (ob.is_ref())
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
if (!ob.get_type_info().m_is_const)
{
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
} else {
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
}
} else {
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
}
@@ -415,6 +450,21 @@ namespace dispatchkit
}
};
/**
* Cast_Helper for casting to a boost::shared_ptr<> type
*/
template<typename Result>
struct Cast_Helper<const boost::shared_ptr<Result> &>
{
typedef typename boost::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
}
};
/**
* Cast_Helper for casting to a Boxed_Value type
@@ -632,6 +682,21 @@ namespace dispatchkit
return Boxed_POD_Value(ob);
}
};
template<typename T>
Boxed_Value var(T t)
{
return Boxed_Value(t);
}
/**
* Return true if the two Boxed_Value's share the same internal type
*/
static bool type_match(Boxed_Value l, Boxed_Value r)
{
return l.get_type_info() == r.get_type_info();
}
}
#endif

View File

@@ -23,22 +23,61 @@
#include "proxy_functions.hpp"
#include "proxy_constructors.hpp"
namespace dispatchkit
namespace chaiscript
{
class Module
{
public:
Module &add(const Type_Info &ti, const std::string &name)
{
m_typeinfos.push_back(std::make_pair(ti, name));
return *this;
}
Module &add(const Proxy_Function &f, const std::string &name)
{
m_funcs.push_back(std::make_pair(f, name));
return *this;
}
template<typename T>
void apply(T &t) const
{
apply(m_typeinfos.begin(), m_typeinfos.end(), t);
apply(m_funcs.begin(), m_funcs.end(), t);
}
private:
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
template<typename T, typename InItr>
void apply(InItr begin, InItr end, T &t) const
{
while (begin != end)
{
t.add(begin->first, begin->second);
++begin;
}
}
};
typedef boost::shared_ptr<Module> ModulePtr;
/**
* A Proxy_Function implementation that is able to take
* a vector of Proxy_Functions and perform a dispatch on them. It is
* used specifically in the case of dealing with Function object variables
*/
class Dispatch_Function : public Proxy_Function
class Dispatch_Function : public Proxy_Function_Base
{
public:
Dispatch_Function(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &t_funcs)
Dispatch_Function(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs)
: m_funcs(t_funcs)
{
}
virtual bool operator==(const Proxy_Function &) const
virtual bool operator==(const Proxy_Function_Base &) const
{
return false;
}
@@ -57,7 +96,7 @@ namespace dispatchkit
virtual bool types_match(const std::vector<Boxed_Value> &types) const
{
typedef std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > function_vec;
typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec;
function_vec::const_iterator begin = m_funcs.begin();
function_vec::const_iterator end = m_funcs.end();
@@ -81,7 +120,7 @@ namespace dispatchkit
}
private:
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > m_funcs;
std::vector<std::pair<std::string, Proxy_Function > > m_funcs;
};
@@ -92,7 +131,7 @@ namespace dispatchkit
class Dispatch_Engine
{
public:
typedef std::map<std::string, dispatchkit::Type_Info> Type_Name_Map;
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
typedef std::map<std::string, Boxed_Value> Scope;
typedef std::deque<Scope> Stack;
@@ -105,48 +144,45 @@ namespace dispatchkit
/**
* Add a new named Proxy_Function to the system
*/
bool register_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &name)
bool add(const Proxy_Function &f, const std::string &name)
{
return add_function(f, name);
}
/**
* Add a generic, named boost::function() to the system
* Add a module's worth of registrations to the system
*/
template<typename Function>
bool register_function(const Function &func, const std::string &name)
{
return add_function(boost::shared_ptr<Proxy_Function>(new Proxy_Function_Impl<Function>(func)), name);
}
void add(const ModulePtr &m)
{
m->apply(*this);
}
/**
* Set the value of an object, by name. If the object
* is not available in the current scope it is created
*/
template<typename Class>
void set_object(const std::string &name, const Class &obj)
void add(const Boxed_Value &obj, const std::string &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);
if (itr != m_scopes[i].end())
{
std::map<std::string, Boxed_Value>::const_iterator itr = m_scopes[i].find(name);
if (itr != m_scopes[i].end())
{
m_scopes[i][name] = Boxed_Value(obj);
return;
}
m_scopes[i][name] = Boxed_Value(obj);
return;
}
add_object(name, obj);
}
add_object(name, obj);
}
/**
* Adds a named object to the current scope
*/
template<typename Class>
void add_object(const std::string &name, const Class &obj)
{
m_scopes.back()[name] = Boxed_Value(obj);
}
void add_object(const std::string &name, const Boxed_Value &obj)
{
m_scopes.back()[name] = Boxed_Value(obj);
}
/**
* Adds a new scope to the stack
@@ -209,24 +245,23 @@ namespace dispatchkit
}
}
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> > funcs = get_function_impl(name, false);
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs = get_function_impl(name, false);
if (funcs.empty())
{
throw std::range_error("Object not known: " + name);
} else {
return Boxed_Value(boost::shared_ptr<Proxy_Function>(new Dispatch_Function(funcs)));
return Boxed_Value(Proxy_Function(new Dispatch_Function(funcs)));
}
}
/**
* Registers a new named type
*/
template<typename Type>
void register_type(const std::string &name)
{
m_types.insert(std::make_pair(name, Get_Type_Info<Type>::get()));
}
void add(const Type_Info &ti, const std::string &name)
{
m_types.insert(std::make_pair(name, ti));
}
/**
* Returns the type info for a named type
@@ -274,7 +309,7 @@ namespace dispatchkit
/**
* Return a function by name
*/
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> >
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >
get_function(const std::string &t_name) const
{
return get_function_impl(t_name, true);
@@ -283,9 +318,9 @@ namespace dispatchkit
/**
* Get a vector of all registered functions
*/
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > get_functions() const
std::vector<std::pair<std::string, Proxy_Function > > get_functions() const
{
return std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >(m_functions.begin(), m_functions.end());
return std::vector<std::pair<std::string, Proxy_Function > >(m_functions.begin(), m_functions.end());
}
private:
@@ -294,10 +329,10 @@ namespace dispatchkit
* Looks for all registered global functions and optionally for an object
* in scope with the same name
*/
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> >
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >
get_function_impl(const std::string &t_name, bool include_objects) const
{
std::vector<std::pair<std::string, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type> > funcs;
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs;
if (include_objects)
{
@@ -305,14 +340,14 @@ namespace dispatchkit
funcs.insert(funcs.end(),
std::make_pair(
t_name,
boxed_cast<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::mapped_type>(get_object(t_name)))
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, boost::shared_ptr<Proxy_Function> >::const_iterator, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator> range
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
= m_functions.equal_range(t_name);
funcs.insert(funcs.end(), range.first, range.second);
@@ -324,9 +359,9 @@ namespace dispatchkit
* true if the function was added, false if a function with the
* same signature and name already exists.
*/
bool add_function(const boost::shared_ptr<Proxy_Function> &f, const std::string &t_name)
bool add_function(const Proxy_Function &f, const std::string &t_name)
{
std::pair<std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator, std::multimap<std::string, boost::shared_ptr<Proxy_Function> >::const_iterator> range
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
= m_functions.equal_range(t_name);
while (range.first != range.second)
@@ -344,7 +379,7 @@ namespace dispatchkit
std::deque<Scope> m_scopes;
std::multimap<std::string, boost::shared_ptr<Proxy_Function> > m_functions;
std::multimap<std::string, Proxy_Function > m_functions;
Type_Name_Map m_types;
Boxed_Value m_place_holder;
};
@@ -354,7 +389,8 @@ namespace dispatchkit
*/
void dump_object(Boxed_Value o, const Dispatch_Engine &e)
{
std::cout << e.get_type_name(o.get_type_info()) << std::endl;
Type_Info ti = o.get_type_info();
std::cout << (ti.m_is_const?"const ":"") << e.get_type_name(ti) << std::endl;
}
/**
@@ -362,13 +398,13 @@ namespace dispatchkit
*/
void dump_type(const Type_Info &type, const Dispatch_Engine &e)
{
std::cout << e.get_type_name(type);
std::cout << (type.m_is_const?"const ":"") << e.get_type_name(type);
}
/**
* Dump function to stdout
*/
void dump_function(const std::pair<const std::string, boost::shared_ptr<Proxy_Function> > &f, const Dispatch_Engine &e)
void dump_function(const std::pair<const std::string, Proxy_Function > &f, const Dispatch_Engine &e)
{
std::vector<Type_Info> params = f.second->get_param_types();
std::string annotation = f.second->annotation();
@@ -412,10 +448,10 @@ namespace dispatchkit
}
std::cout << std::endl;
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > funcs = s.get_functions();
std::vector<std::pair<std::string, Proxy_Function > > funcs = s.get_functions();
std::cout << "Functions: " << std::endl;
for (std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >::const_iterator itr = funcs.begin();
for (std::vector<std::pair<std::string, Proxy_Function > >::const_iterator itr = funcs.begin();
itr != funcs.end();
++itr)
{
@@ -423,6 +459,24 @@ namespace dispatchkit
}
std::cout << std::endl;
}
/**
* return true if the Boxed_Value matches the registered type by name
*/
bool is_type(const Dispatch_Engine &e, const std::string &user_typename, Boxed_Value r)
{
try {
return e.get_type(user_typename) == r.get_type_info();
} catch (const std::range_error &) {
return false;
}
}
std::string type_name(const Dispatch_Engine &e, Boxed_Value obj)
{
return e.get_type_name(obj.get_type_info());
}
}
#endif

View File

@@ -6,7 +6,7 @@
#include <boost/preprocessor.hpp>
#define addparam(z,n,text) params.push_back(Boxed_Value(BOOST_PP_CAT(p, n) ));
#define addparam(z,n,text) params.push_back(boost::is_reference<Param ## n>::value?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
@@ -21,7 +21,7 @@
#include <vector>
#include "proxy_functions.hpp"
namespace dispatchkit
namespace chaiscript
{
/**
* Internal helper class for handling the return
@@ -35,7 +35,7 @@ namespace dispatchkit
{
}
Ret call(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &t_funcs,
Ret call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params)
{
return boxed_cast<Ret>(dispatch(t_funcs, params));
@@ -53,7 +53,7 @@ namespace dispatchkit
{
}
void call(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &t_funcs,
void call(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs,
const std::vector<Boxed_Value> &params)
{
dispatch(t_funcs, params);
@@ -65,7 +65,7 @@ namespace dispatchkit
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/function_call.hpp>
#include BOOST_PP_ITERATE()
namespace dispatchkit
namespace chaiscript
{
/**
* Build a function caller that knows how to dispatch on a set of functions
@@ -77,9 +77,9 @@ namespace dispatchkit
*/
template<typename FunctionType>
boost::function<FunctionType>
build_function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs)
functor(const std::vector<std::pair<std::string, Proxy_Function > > &funcs)
{
FunctionType *p;
FunctionType *p=0;
return build_function_caller_helper(p, funcs);
}
@@ -88,7 +88,7 @@ namespace dispatchkit
* useful in the case that a function is being pass out from scripting back
* into code
* example:
* void my_function(boost::shared_ptr<Proxy_Function> f)
* void my_function(Proxy_Function f)
* {
* boost::function<void (int)> local_f =
* build_function_caller(f);
@@ -98,11 +98,11 @@ namespace dispatchkit
*/
template<typename FunctionType>
boost::function<FunctionType>
build_function_caller(boost::shared_ptr<Proxy_Function> func)
functor(Proxy_Function func)
{
std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > funcs;
std::vector<std::pair<std::string, Proxy_Function > > funcs;
funcs.push_back(std::make_pair(std::string(), func));
return build_function_caller<FunctionType>(funcs);
return functor<FunctionType>(funcs);
}
/**
@@ -111,37 +111,24 @@ namespace dispatchkit
*/
template<typename FunctionType>
boost::function<FunctionType>
build_function_caller(const Boxed_Value &bv)
functor(const Boxed_Value &bv)
{
return build_function_caller<FunctionType>(boxed_cast<boost::shared_ptr<Proxy_Function> >(bv));
return functor<FunctionType>(boxed_cast<Proxy_Function >(bv));
}
/**
* Helper for calling script code as if it were native C++ code
* example:
* boost::function<int (int, int)> f = build_functor(chai, "func(x, y){x+y}");
* \return a boost::function representing the passed in script
* \param[in] e ScriptEngine to build the script execution from
* \param[in] script Script code to build a function from
*/
template<typename FunctionType, typename ScriptEngine>
boost::function<FunctionType> build_functor(ScriptEngine &e, const std::string &script)
{
return build_function_caller<FunctionType>(e.evaluate_string(script));
}
}
# endif
#else
# define n BOOST_PP_ITERATION()
namespace dispatchkit
namespace chaiscript
{
/**
* used internally for unwrapping a function call's types
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
Ret function_caller(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs
Ret function_caller(const std::vector<std::pair<std::string, Proxy_Function > > &funcs
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
std::vector<Boxed_Value> params;
@@ -156,7 +143,7 @@ namespace dispatchkit
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs)
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, Proxy_Function> > &funcs)
{
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
BOOST_PP_ENUM_TRAILING(n, curry, ~));

View File

@@ -19,17 +19,28 @@
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_constructors.hpp>
#include BOOST_PP_ITERATE()
# endif
namespace chaiscript
{
template<typename T>
Proxy_Function constructor()
{
T *f = 0;
return (build_constructor_(f));
}
}
#else
# define n BOOST_PP_ITERATION()
namespace dispatchkit
namespace chaiscript
{
/**
* A constructor function, used for creating a new object
* of a given type with a given set of params
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::shared_ptr<Class> constructor( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
{
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
}
@@ -41,10 +52,10 @@ namespace dispatchkit
* \todo See if it is possible to make this not be a variadic function
*/
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
boost::function<boost::shared_ptr<Class> (BOOST_PP_ENUM_PARAMS(n, Param))> build_constructor()
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
typedef boost::shared_ptr<Class> (*func)(BOOST_PP_ENUM_PARAMS(n, Param));
return boost::function<boost::shared_ptr<Class> (BOOST_PP_ENUM_PARAMS(n, Param))>(func(&(constructor<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>)));
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
}
}

View File

@@ -7,9 +7,9 @@
#include <boost/preprocessor.hpp>
#define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info<Param ## n>::get());
#define casthelper(z,n,text) ,dispatchkit::boxed_cast< Param ## n >(params[n])
#define casthelper(z,n,text) ,chaiscript::boxed_cast< Param ## n >(params[n])
#define comparetype(z,n,text) && ((Get_Type_Info<Param ## n>::get() == params[n].get_type_info()))
#define trycast(z,n,text) dispatchkit::boxed_cast<Param ## n>(params[n]);
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
#ifndef BOOST_PP_IS_ITERATING
@@ -26,7 +26,7 @@
#include <stdexcept>
#include <vector>
namespace dispatchkit
namespace chaiscript
{
/**
* Used internally for handling a return value from a Proxy_Function call
@@ -40,6 +40,24 @@ namespace dispatchkit
}
};
template<typename Ret>
struct Handle_Return<boost::shared_ptr<Ret> &>
{
Boxed_Value operator()(const boost::function<boost::shared_ptr<Ret> & ()> &f)
{
return Boxed_Value(f());
}
};
template<typename Ret>
struct Handle_Return<const boost::shared_ptr<Ret> &>
{
Boxed_Value operator()(const boost::function<const boost::shared_ptr<Ret> & ()> &f)
{
return Boxed_Value(f());
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
@@ -95,7 +113,7 @@ namespace dispatchkit
*
* example usage:
* Boxed_Value retval = dispatch(dispatchengine.get_function("+"),
* dispatchkit::Param_List_Builder() << 5 << 6);
* chaiscript::Param_List_Builder() << 5 << 6);
*/
struct Param_List_Builder
{
@@ -142,7 +160,7 @@ namespace dispatchkit
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions.hpp>
#include BOOST_PP_ITERATE()
namespace dispatchkit
namespace chaiscript
{
/**
* Pure virtual base class for all Proxy_Function implementations
@@ -152,17 +170,19 @@ namespace dispatchkit
* Dispatch_Engine only knows how to work with Proxy_Function, no other
* function classes.
*/
class Proxy_Function
class Proxy_Function_Base
{
public:
virtual ~Proxy_Function() {}
virtual ~Proxy_Function_Base() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) = 0;
virtual std::vector<Type_Info> get_param_types() const = 0;
virtual bool operator==(const Proxy_Function &) const = 0;
virtual bool operator==(const Proxy_Function_Base &) const = 0;
virtual bool types_match(const std::vector<Boxed_Value> &types) const = 0;
virtual std::string annotation() const = 0;
};
typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function;
/**
* Exception thrown if a function's guard fails to execute
*/
@@ -181,19 +201,19 @@ namespace dispatchkit
* A Proxy_Function implementation that is not type safe, the called function
* is expecting a vector<Boxed_Value> that it works with how it chooses.
*/
class Dynamic_Proxy_Function : public Proxy_Function
class Dynamic_Proxy_Function : public Proxy_Function_Base
{
public:
Dynamic_Proxy_Function(
const boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
int t_arity=-1,
const std::string &t_description = "",
const boost::shared_ptr<Proxy_Function> &t_guard = boost::shared_ptr<Proxy_Function>())
const Proxy_Function &t_guard = Proxy_Function())
: m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard)
{
}
virtual bool operator==(const Proxy_Function &) const
virtual bool operator==(const Proxy_Function_Base &) const
{
return false;
}
@@ -267,7 +287,7 @@ namespace dispatchkit
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
int m_arity;
std::string m_description;
boost::shared_ptr<Proxy_Function> m_guard;
Proxy_Function m_guard;
};
/**
@@ -284,16 +304,16 @@ namespace dispatchkit
* at runtime, when call() is executed.
* it is used for bind(function, param1, _, param2) style calls
*/
class Bound_Function : public Proxy_Function
class Bound_Function : public Proxy_Function_Base
{
public:
Bound_Function(const boost::shared_ptr<Proxy_Function> &t_f,
Bound_Function(const Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args)
: m_f(t_f), m_args(t_args)
{
}
virtual bool operator==(const Proxy_Function &) const
virtual bool operator==(const Proxy_Function_Base &) const
{
return false;
}
@@ -360,7 +380,7 @@ namespace dispatchkit
}
private:
boost::shared_ptr<Proxy_Function> m_f;
Proxy_Function m_f;
std::vector<Boxed_Value> m_args;
};
@@ -370,17 +390,17 @@ namespace dispatchkit
* type checking of Boxed_Value parameters, in a type safe manner
*/
template<typename Func>
class Proxy_Function_Impl : public Proxy_Function
class Proxy_Function_Impl : public Proxy_Function_Base
{
public:
Proxy_Function_Impl(const Func &f)
Proxy_Function_Impl(const boost::function<Func> &f)
: m_f(f)
{
}
virtual ~Proxy_Function_Impl() {}
virtual bool operator==(const Proxy_Function &t_func) const
virtual bool operator==(const Proxy_Function_Base &t_func) const
{
try {
dynamic_cast<const Proxy_Function_Impl<Func> &>(t_func);
@@ -397,12 +417,14 @@ namespace dispatchkit
virtual std::vector<Type_Info> get_param_types() const
{
return build_param_type_list(m_f);
Func *f = 0;
return build_param_type_list(f);
}
virtual bool types_match(const std::vector<Boxed_Value> &types) const
{
return compare_types(m_f, types);
Func *f = 0;
return compare_types(f, types);
}
virtual std::string annotation() const
@@ -411,7 +433,7 @@ namespace dispatchkit
}
private:
Func m_f;
boost::function<Func> m_f;
};
/**
@@ -435,10 +457,10 @@ namespace dispatchkit
* each function against the set of parameters, in order, until a matching
* function is found or throw dispatch_error if no matching function is found
*/
Boxed_Value dispatch(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs,
Boxed_Value dispatch(const std::vector<std::pair<std::string, Proxy_Function> > &funcs,
const std::vector<Boxed_Value> &plist)
{
for (std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > >::const_iterator itr = funcs.begin();
for (std::vector<std::pair<std::string, Proxy_Function> >::const_iterator itr = funcs.begin();
itr != funcs.end();
++itr)
{
@@ -461,14 +483,14 @@ namespace dispatchkit
#else
# define n BOOST_PP_ITERATION()
namespace dispatchkit
namespace chaiscript
{
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
std::vector<Type_Info> build_param_type_list(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &)
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
std::vector<Type_Info> ti;
ti.push_back(Get_Type_Info<Ret>::get());
@@ -502,7 +524,7 @@ namespace dispatchkit
* registration of two functions with the exact same signatures
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
bool compare_types(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &,
bool compare_types(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
const std::vector<Boxed_Value> &params)
{
if (params.size() != n)

View File

@@ -14,15 +14,22 @@
#include <boost/function.hpp>
#include <boost/bind.hpp>
namespace dispatchkit
namespace chaiscript
{
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
/**
* Helper function for register_member function
*/
template<typename T, typename Class>
T &get_member(T Class::* m, Class *obj)
{
return obj->*m;
return (obj->*m);
}
/**
@@ -31,10 +38,11 @@ namespace dispatchkit
* for example, the case of std::pair<>::first and std::pair<>::second
*/
template<typename T, typename Class>
void register_member(Dispatch_Engine &s, T Class::* m, const std::string &name)
Proxy_Function fun(T Class::* m)
{
s.register_function(boost::function<T (Class *)>(boost::bind(&get_member<T, Class>, m, _1)), name);
return fun(boost::function<T& (Class *)>(boost::bind(&get_member<T, Class>, m, _1)));
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
@@ -45,33 +53,33 @@ namespace dispatchkit
#else
# define n BOOST_PP_ITERATION()
namespace dispatchkit
namespace chaiscript
{
/**
* Register a global function of n parameters with name
*/
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
void register_function(Dispatch_Engine &s, Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name)
Proxy_Function fun(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
s.register_function(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
return fun(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
}
/**
* Register a class method of n parameters with name
*/
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name)
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
{
s.register_function(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
return fun(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
}
/**
* Register a const class method of n parameters with name
*/
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const std::string &name)
Proxy_Function fun(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
{
s.register_function(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f), name);
return fun(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
}
}

View File

@@ -16,7 +16,7 @@
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/ref.hpp>
namespace dispatchkit
namespace chaiscript
{
/**
* compile time deduced information about a type
@@ -115,6 +115,22 @@ namespace dispatchkit
&typeid(typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type));
}
};
template<typename T>
Type_Info user_type(T)
{
return Get_Type_Info<T>::get();
}
template<typename T>
Type_Info user_type()
{
return Get_Type_Info<T>::get();
}
}
#endif

View File

@@ -21,11 +21,82 @@ namespace chaiscript
Eval_Engine engine;
ChaiScript_Parser parser;
/**
* Evaluates the given string in by parsing it and running the results through the evaluator
*/
Boxed_Value do_eval(const std::string &input, const char *filename = "__EVAL__") {
//debug_print(tokens);
Boxed_Value value;
parser.clear_match_stack();
try {
if (parser.parse(input, filename)) {
//parser.show_match_stack();
value = eval_token<Eval_Engine>(engine, parser.ast());
}
}
catch (const Return_Value &rv) {
value = rv.retval;
}
return value;
}
/**
* Evaluates the given boxed string, used during eval() inside of a script
*/
const Boxed_Value internal_eval(const std::vector<Boxed_Value> &vals) {
return do_eval(boxed_cast<std::string>(vals.at(0)));
}
public:
ChaiScript_System() {
build_eval_system();
}
/**
* Adds an object to the system: type, function, object
*/
template<typename T>
ChaiScript_System &add(const T &t, const std::string &name)
{
engine.add(t, name);
return *this;
}
/**
* Adds a module object to the system
*/
ChaiScript_System &add(const ModulePtr &p)
{
engine.add(p);
return *this;
}
/**
* Helper for calling script code as if it were native C++ code
* example:
* boost::function<int (int, int)> f = build_functor(chai, "func(x, y){x+y}");
* \return a boost::function representing the passed in script
* \param[in] script Script code to build a function from
*/
template<typename FunctionType>
boost::function<FunctionType> functor(const std::string &script)
{
return chaiscript::functor<FunctionType>(eval(script));
}
/**
* Evaluate a string via eval method
*/
Boxed_Value operator()(const std::string &script)
{
return do_eval(script);
}
/**
* Returns the current evaluation engine
*/
@@ -43,16 +114,6 @@ namespace chaiscript
}
}
/**
* Evaluates the given boxed string, used during eval() inside of a script
*/
const dispatchkit::Boxed_Value eval(const std::vector<dispatchkit::Boxed_Value> &vals) {
std::string val;
val = dispatchkit::boxed_cast<std::string &>(vals[0]);
return evaluate_string(val);
}
/**
* Helper function for loading a file
*/
@@ -79,48 +140,56 @@ namespace chaiscript
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
*/
void build_eval_system() {
dispatchkit::Bootstrap::bootstrap(engine);
dispatchkit::bootstrap_vector<std::vector<dispatchkit::Boxed_Value> >(engine, "Vector");
dispatchkit::bootstrap_string<std::string>(engine, "string");
dispatchkit::bootstrap_map<std::map<std::string, dispatchkit::Boxed_Value> >(engine, "Map");
dispatchkit::bootstrap_pair<std::pair<dispatchkit::Boxed_Value, dispatchkit::Boxed_Value > >(engine, "Pair");
using namespace bootstrap;
engine.add(Bootstrap::bootstrap());
engine.register_function(boost::shared_ptr<dispatchkit::Proxy_Function>(
new dispatchkit::Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::eval, boost::ref(*this), _1), 1)), "eval");
engine.add(fun(boost::function<void ()>(boost::bind(&dump_system, boost::ref(engine)))), "dump_system");
engine.add(fun(boost::function<void (Boxed_Value)>(boost::bind(&dump_object, _1, boost::ref(engine)))), "dump_object");
engine.add(fun(boost::function<bool (Boxed_Value, const std::string &)>(boost::bind(&is_type, boost::ref(engine), _2, _1))),
"is_type");
evaluate_string(chaiscript_prelude);
engine.add(fun(boost::function<std::string (Boxed_Value)>(boost::bind(&chaiscript::type_name, boost::ref(engine), _1))),
"type_name");
engine.add(vector_type<std::vector<Boxed_Value> >("Vector"));
engine.add(string_type<std::string>("string"));
engine.add(map_type<std::map<std::string, Boxed_Value> >("Map"));
engine.add(pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
engine.add(Proxy_Function(
new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::internal_eval, boost::ref(*this), _1), 1)), "eval");
do_eval(chaiscript_prelude, "standard prelude");
}
/**
* Evaluates the given string in by parsing it and running the results through the evaluator
*/
dispatchkit::Boxed_Value evaluate_string(const std::string &input, const char *filename = "__EVAL__") {
//debug_print(tokens);
dispatchkit::Boxed_Value value;
parser.clear_match_stack();
template<typename T>
T eval(const std::string &input)
{
return boxed_cast<T>(do_eval(input));
}
try {
if (parser.parse(input, filename)) {
//parser.show_match_stack();
value = eval_token<Eval_Engine>(engine, parser.ast());
}
}
catch (const Return_Value &rv) {
value = rv.retval;
}
return value;
Boxed_Value eval(const std::string &input)
{
return do_eval(input);
}
/**
* Loads the file specified by filename, evaluates it, and returns the result
*/
dispatchkit::Boxed_Value evaluate_file(const char *filename) {
return evaluate_string(load_file(filename), filename);
Boxed_Value eval_file(const char *filename) {
return do_eval(load_file(filename), filename);
}
/**
* Loads the file specified by filename, evaluates it, and returns the as the specified type
*/
template<typename T>
T eval_file(const char *filename) {
return boxed_cast<T>(do_eval(load_file(filename), filename));
}
};
typedef ChaiScript_System<dispatchkit::Dispatch_Engine> ChaiScript_Engine;
typedef ChaiScript_System<Dispatch_Engine> ChaiScript;
}
#endif /* CHAISCRIPT_ENGINE_HPP_ */

View File

@@ -15,14 +15,14 @@ namespace chaiscript
* Helper function that will set up the scope around a function call, including handling the named function parameters
*/
template <typename Eval_System>
const dispatchkit::Boxed_Value eval_function (Eval_System &ss, TokenPtr node, const std::vector<std::string> &param_names, const std::vector<dispatchkit::Boxed_Value> &vals) {
const Boxed_Value eval_function (Eval_System &ss, TokenPtr node, const std::vector<std::string> &param_names, const std::vector<Boxed_Value> &vals) {
ss.new_scope();
for (unsigned int i = 0; i < param_names.size(); ++i) {
ss.add_object(param_names[i], vals[i]);
}
dispatchkit::Boxed_Value retval;
Boxed_Value retval;
try {
retval = eval_token(ss, node);
@@ -42,8 +42,8 @@ namespace chaiscript
* Evaluates the top-level file node
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_file(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_file(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
for (i = 0; i < node->children.size(); ++i) {
retval = eval_token(ss, node->children[i]);
@@ -55,13 +55,13 @@ namespace chaiscript
* Evaluates a variable or function name identifier
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_id(Eval_System &ss, TokenPtr node) {
Boxed_Value eval_id(Eval_System &ss, TokenPtr node) {
if (node->text == "true") {
return dispatchkit::Boxed_Value(true);
return Boxed_Value(true);
}
else if (node->text == "false") {
return dispatchkit::Boxed_Value(false);
return Boxed_Value(false);
}
else {
try {
@@ -77,68 +77,73 @@ namespace chaiscript
* Evaluates a floating point number
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_float(Eval_System &, TokenPtr node) {
return dispatchkit::Boxed_Value(double(atof(node->text.c_str())));
Boxed_Value eval_float(Eval_System &, TokenPtr node) {
return Boxed_Value(double(atof(node->text.c_str())));
}
/**
* Evaluates an integer
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_int(Eval_System &, TokenPtr node) {
return dispatchkit::Boxed_Value(atoi(node->text.c_str()));
Boxed_Value eval_int(Eval_System &, TokenPtr node) {
return Boxed_Value(atoi(node->text.c_str()));
}
/**
* Evaluates a quoted string
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_quoted_string(Eval_System &, TokenPtr node) {
return dispatchkit::Boxed_Value(node->text);
Boxed_Value eval_quoted_string(Eval_System &, TokenPtr node) {
return Boxed_Value(node->text);
}
/**
* Evaluates a char group
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_single_quoted_string(Eval_System &, TokenPtr node) {
return dispatchkit::Boxed_Value(node->text);
Boxed_Value eval_single_quoted_string(Eval_System &, TokenPtr node) {
if (node->text.size() == 1) {
return Boxed_Value(char(node->text[0]));
}
else {
return Boxed_Value(char((int)node->text[0] * 0xff + (int)node->text[0]));
}
}
/**
* Evaluates a string of equations in reverse order so that the right-most side has precedence
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_equation(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_equation(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
retval = eval_token(ss, node->children.back());
if (node->children.size() > 1) {
for (i = node->children.size()-3; ((int)i) >= 0; i -= 2) {
if (node->children[i+1]->text == "=") {
dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]);
Boxed_Value lhs = eval_token(ss, node->children[i]);
try {
if (lhs.is_unknown())
{
retval = dispatch(ss.get_function("clone"), dispatchkit::Param_List_Builder() << retval);
retval = dispatch(ss.get_function("clone"), Param_List_Builder() << retval);
}
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << lhs;
plb << retval;
try {
retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
}
catch(const dispatchkit::dispatch_error &){
catch(const dispatch_error &){
throw Eval_Error("Mismatched types in equation", node->children[i+1]);
}
}
catch(const dispatchkit::dispatch_error &){
catch(const dispatch_error &){
throw Eval_Error("Can not clone right hand side of equation", node->children[i+1]);
}
}
else if (node->children[i+1]->text == ":=") {
dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]);
if (lhs.is_unknown() || dispatchkit::Bootstrap::type_match(lhs, retval)) {
Boxed_Value lhs = eval_token(ss, node->children[i]);
if (lhs.is_unknown() || type_match(lhs, retval)) {
lhs.assign(retval);
}
else {
@@ -146,13 +151,13 @@ namespace chaiscript
}
}
else {
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << eval_token(ss, node->children[i]);
plb << retval;
try {
retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
}
catch(const dispatchkit::dispatch_error &){
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
}
}
@@ -165,8 +170,8 @@ namespace chaiscript
* Evaluates a variable declaration
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) {
ss.add_object(node->children[0]->text, dispatchkit::Boxed_Value());
Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) {
ss.add_object(node->children[0]->text, Boxed_Value());
return ss.get_object(node->children[0]->text);
}
@@ -174,8 +179,8 @@ namespace chaiscript
* Evaluates binary boolean operators. Respects short-circuiting rules.
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_expression(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_expression(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
retval = eval_token(ss, node->children[0]);
@@ -183,9 +188,9 @@ namespace chaiscript
for (i = 1; i < node->children.size(); i += 2) {
bool lhs;
try {
lhs = dispatchkit::boxed_cast<bool &>(retval);
lhs = boxed_cast<bool &>(retval);
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("Condition not boolean", node);
}
if (node->children[i]->text == "&&") {
@@ -193,12 +198,12 @@ namespace chaiscript
retval = eval_token(ss, node->children[i+1]);
}
else {
retval = dispatchkit::Boxed_Value(false);
retval = Boxed_Value(false);
}
}
else if (node->children[i]->text == "||") {
if (lhs) {
retval = dispatchkit::Boxed_Value(true);
retval = Boxed_Value(true);
}
else {
retval = eval_token(ss, node->children[i+1]);
@@ -213,21 +218,21 @@ namespace chaiscript
* Evaluates comparison, additions, and multiplications and their relatives
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_comp_add_mul(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_comp_add_mul(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
retval = eval_token(ss, node->children[0]);
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); i += 2) {
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i + 1]);
try {
retval = dispatch(ss.get_function(node->children[i]->text), plb);
}
catch(const dispatchkit::dispatch_error &){
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
}
}
@@ -240,13 +245,13 @@ namespace chaiscript
* Evaluates an array lookup
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_array_call(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_array_call(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
retval = eval_token(ss, node->children[0]);
for (i = 1; i < node->children.size(); ++i) {
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << retval;
plb << eval_token(ss, node->children[i]);
try {
@@ -255,7 +260,7 @@ namespace chaiscript
catch(std::out_of_range &) {
throw Eval_Error("Out of bounds exception", node);
}
catch(const dispatchkit::dispatch_error &){
catch(const dispatch_error &){
throw Eval_Error("Can not find appropriate array lookup '[]' " + node->children[i]->text, node->children[i]);
}
}
@@ -267,13 +272,13 @@ namespace chaiscript
* Evaluates a unary negation
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_negate(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_negate(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
retval = eval_token(ss, node->children[0]);
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << retval;
plb << dispatchkit::Boxed_Value(-1.0);
plb << Boxed_Value(-1.0);
try {
return dispatch(ss.get_function("*"), plb);
@@ -287,29 +292,29 @@ namespace chaiscript
* Evaluates a unary boolean not
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_not(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_not(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
bool cond;
try {
retval = eval_token(ss, node->children[0]);
cond = dispatchkit::boxed_cast<bool &>(retval);
cond = boxed_cast<bool &>(retval);
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("Boolean not('!') condition not boolean", node->children[0]);
}
return dispatchkit::Boxed_Value(!cond);
return Boxed_Value(!cond);
}
/**
* Evaluates any unary prefix
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_prefix(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_prefix(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
retval = eval_token(ss, node->children[1]);
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << retval;
try {
@@ -324,25 +329,25 @@ namespace chaiscript
* Evaluates (and generates) an inline array initialization
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_inline_array(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_inline_array(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
try {
retval = dispatch(ss.get_function("Vector"), dispatchkit::Param_List_Builder());
retval = dispatch(ss.get_function("Vector"), Param_List_Builder());
if (node->children.size() > 0) {
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
dispatchkit::Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << tmp);
Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
dispatch(ss.get_function("push_back"), Param_List_Builder() << retval << tmp);
}
catch (const dispatchkit::dispatch_error &) {
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
}
}
}
}
catch (const dispatchkit::dispatch_error &) {
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'Vector()'", node);
}
@@ -353,13 +358,13 @@ namespace chaiscript
* Evaluates (and generates) an inline range initialization
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_inline_range(Eval_System &ss, TokenPtr node) {
Boxed_Value eval_inline_range(Eval_System &ss, TokenPtr node) {
try {
return dispatch(ss.get_function("generate_range"), dispatchkit::Param_List_Builder()
return dispatch(ss.get_function("generate_range"), Param_List_Builder()
<< eval_token(ss, node->children[0]->children[0]->children[0])
<< eval_token(ss, node->children[0]->children[0]->children[1]));
}
catch (const dispatchkit::dispatch_error &) {
catch (const dispatch_error &) {
throw Eval_Error("Unable to generate range vector", node);
}
}
@@ -368,24 +373,24 @@ namespace chaiscript
* Evaluates (and generates) an inline map initialization
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_inline_map(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_inline_map(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
try {
retval = dispatch(ss.get_function("Map"), dispatchkit::Param_List_Builder());
retval = dispatch(ss.get_function("Map"), Param_List_Builder());
for (i = 0; i < node->children[0]->children.size(); ++i) {
try {
dispatchkit::Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
dispatchkit::Boxed_Value slot = dispatch(ss.get_function("[]"), dispatchkit::Param_List_Builder() << retval << key);
dispatch(ss.get_function("="), dispatchkit::Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
Boxed_Value slot = dispatch(ss.get_function("[]"), Param_List_Builder() << retval << key);
dispatch(ss.get_function("="), Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
}
catch (const dispatchkit::dispatch_error &) {
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]);
}
}
}
catch (const dispatchkit::dispatch_error &) {
catch (const dispatch_error &) {
throw Eval_Error("Can not find appropriate 'Map()'", node);
}
@@ -396,21 +401,21 @@ namespace chaiscript
* Evaluates a function call, starting with its arguments. Handles resetting the scope to the previous one after the call.
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_fun_call(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
dispatchkit::Param_List_Builder plb;
dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack();
dispatchkit::Dispatch_Engine::Stack new_stack;
Boxed_Value eval_fun_call(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
Param_List_Builder plb;
Dispatch_Engine::Stack prev_stack = ss.get_stack();
Dispatch_Engine::Stack new_stack;
unsigned int i;
new_stack.push_back(dispatchkit::Dispatch_Engine::Scope());
new_stack.push_back(Dispatch_Engine::Scope());
if ((node->children.size() > 1) && (node->children[1]->identifier == Token_Type::Arg_List)) {
for (i = 0; i < node->children[1]->children.size(); ++i) {
plb << eval_token(ss, node->children[1]->children[i]);
}
}
dispatchkit::Boxed_Value fn;
Boxed_Value fn;
try {
fn = eval_token(ss, node->children[0]);
}
@@ -420,10 +425,10 @@ namespace chaiscript
}
try {
ss.set_stack(new_stack);
retval = (*dispatchkit::boxed_cast<boost::shared_ptr<dispatchkit::Proxy_Function> >(fn))(plb);
retval = (*boxed_cast<Proxy_Function >(fn))(plb);
ss.set_stack(prev_stack);
}
catch(const dispatchkit::dispatch_error &e){
catch(const dispatch_error &e){
ss.set_stack(prev_stack);
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
}
@@ -443,21 +448,21 @@ namespace chaiscript
* Evaluates a method/attributes invocation
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_dot_access(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
std::vector<std::pair<std::string, boost::shared_ptr<dispatchkit::Proxy_Function> > > fn;
dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack();
dispatchkit::Dispatch_Engine::Stack new_stack;
Boxed_Value eval_dot_access(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
std::vector<std::pair<std::string, Proxy_Function > > fn;
Dispatch_Engine::Stack prev_stack = ss.get_stack();
Dispatch_Engine::Stack new_stack;
unsigned int i, j;
new_stack.push_back(dispatchkit::Dispatch_Engine::Scope());
new_stack.push_back(Dispatch_Engine::Scope());
//todo: Please extract a single way of doing function calls between this and eval_fun_call
retval = eval_token(ss, node->children[0]);
if (node->children.size() > 1) {
for (i = 1; i < node->children.size(); ++i) {
dispatchkit::Param_List_Builder plb;
Param_List_Builder plb;
plb << retval;
if (node->children[i]->children.size() > 1) {
@@ -480,7 +485,7 @@ namespace chaiscript
retval = dispatch(fn, plb);
ss.set_stack(prev_stack);
}
catch(const dispatchkit::dispatch_error &e){
catch(const dispatch_error &e){
ss.set_stack(prev_stack);
throw Eval_Error(std::string(e.what()) + " with function '" + fun_name + "'", node->children[i]);
}
@@ -502,16 +507,16 @@ namespace chaiscript
* Evaluates an if/elseif/else block
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_if(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_if(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
retval = eval_token(ss, node->children[0]);
bool cond;
try {
cond = dispatchkit::boxed_cast<bool &>(retval);
cond = boxed_cast<bool &>(retval);
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("If condition not boolean", node->children[0]);
}
if (cond) {
@@ -525,13 +530,13 @@ namespace chaiscript
retval = eval_token(ss, node->children[i+1]);
cond = true;
}
else if (node->children[i]->text == "elseif") {
else if (node->children[i]->text == "else if") {
retval = eval_token(ss, node->children[i+1]);
try {
cond = dispatchkit::boxed_cast<bool &>(retval);
cond = boxed_cast<bool &>(retval);
}
catch (const dispatchkit::bad_boxed_cast &) {
throw Eval_Error("Elseif condition not boolean", 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]);
@@ -549,25 +554,21 @@ namespace chaiscript
* Evaluates a while block
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_while(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
retval = eval_token(ss, node->children[0]);
Boxed_Value eval_while(Eval_System &ss, TokenPtr node) {
bool cond;
try {
cond = dispatchkit::boxed_cast<bool &>(retval);
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("While condition not boolean", node->children[0]);
}
while (cond) {
try {
eval_token(ss, node->children[1]);
retval = eval_token(ss, node->children[0]);
try {
cond = dispatchkit::boxed_cast<bool &>(retval);
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("While condition not boolean", node->children[0]);
}
}
@@ -575,30 +576,26 @@ namespace chaiscript
cond = false;
}
}
return dispatchkit::Boxed_Value();
return Boxed_Value();
}
/**
* Evaluates a for block, including the for's conditions, from left to right
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_for(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
dispatchkit::Boxed_Value condition;
Boxed_Value eval_for(Eval_System &ss, TokenPtr node) {
bool cond;
try {
if (node->children.size() == 4) {
eval_token(ss, node->children[0]);
condition = eval_token(ss, node->children[1]);
cond = boxed_cast<bool &>(eval_token(ss, node->children[1]));
}
else if (node->children.size() == 3){
condition = eval_token(ss, node->children[0]);
else {
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
}
cond = dispatchkit::boxed_cast<bool &>(condition);
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("For condition not boolean", node);
}
while (cond) {
@@ -606,37 +603,35 @@ namespace chaiscript
if (node->children.size() == 4) {
eval_token(ss, node->children[3]);
eval_token(ss, node->children[2]);
condition = eval_token(ss, node->children[1]);
cond = boxed_cast<bool &>(eval_token(ss, node->children[1]));
}
else if (node->children.size() == 3) {
else {
eval_token(ss, node->children[2]);
eval_token(ss, node->children[1]);
condition = eval_token(ss, node->children[0]);
cond = boxed_cast<bool &>(eval_token(ss, node->children[0]));
}
cond = dispatchkit::boxed_cast<bool &>(condition);
}
catch (const dispatchkit::bad_boxed_cast &) {
catch (const bad_boxed_cast &) {
throw Eval_Error("For condition not boolean", node);
}
catch (Break_Loop &) {
cond = false;
}
}
return dispatchkit::Boxed_Value();
return Boxed_Value();
}
/**
* Evaluates a function definition
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_def(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_def(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
std::vector<std::string> param_names;
std::string annotation = node->annotation?node->annotation->text:"";
boost::shared_ptr<dispatchkit::Dynamic_Proxy_Function> guard;
boost::shared_ptr<Dynamic_Proxy_Function> guard;
size_t numparams = 0;
std::string function_name = node->children[0]->text;
TokenPtr guardnode;
@@ -661,14 +656,14 @@ namespace chaiscript
}
if (guardnode) {
guard = boost::shared_ptr<dispatchkit::Dynamic_Proxy_Function>
(new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
guard = boost::shared_ptr<Dynamic_Proxy_Function>
(new Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
boost::ref(ss), guardnode,
param_names, _1), numparams));
}
ss.register_function(boost::shared_ptr<dispatchkit::Proxy_Function>
(new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
ss.add(Proxy_Function
(new Dynamic_Proxy_Function(boost::bind(&eval_function<Eval_System>,
boost::ref(ss), node->children.back(),
param_names, _1), numparams,
annotation, guard)), function_name);
@@ -680,8 +675,8 @@ namespace chaiscript
* Evaluates a lambda (anonymous function)
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_lambda(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_lambda(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
std::vector<std::string> param_names;
@@ -699,8 +694,8 @@ namespace chaiscript
numparams = 0;
}
return dispatchkit::Boxed_Value(boost::shared_ptr<dispatchkit::Proxy_Function>(
new dispatchkit::Dynamic_Proxy_Function(
return Boxed_Value(Proxy_Function(
new Dynamic_Proxy_Function(
boost::bind(&eval_function<Eval_System>, boost::ref(ss), node->children.back(), param_names, _1), numparams)));
}
@@ -708,8 +703,8 @@ namespace chaiscript
* Evaluates a scoped block. Handles resetting the scope after the block has completed.
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_block(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_block(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
unsigned int i;
ss.new_scope();
@@ -736,13 +731,13 @@ namespace chaiscript
* Evaluates a return statement
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_return(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_return(Eval_System &ss, TokenPtr node) {
Boxed_Value retval;
if (node->children.size() > 0) {
retval = eval_token(ss, node->children[0]);
}
else {
retval = dispatchkit::Boxed_Value();
retval = Boxed_Value();
}
throw Return_Value(retval, node);
}
@@ -751,7 +746,7 @@ namespace chaiscript
* Evaluates a break statement
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_break(Eval_System &, TokenPtr node) {
Boxed_Value eval_break(Eval_System &, TokenPtr node) {
throw Break_Loop(node);
}
@@ -759,122 +754,121 @@ namespace chaiscript
* Top-level evaluation dispatch for all AST node types
*/
template <typename Eval_System>
dispatchkit::Boxed_Value eval_token(Eval_System &ss, TokenPtr node) {
dispatchkit::Boxed_Value retval;
Boxed_Value eval_token(Eval_System &ss, TokenPtr node) {
switch (node->identifier) {
case (Token_Type::File) :
retval = eval_file(ss, node);
return eval_file(ss, node);
break;
case (Token_Type::Id) :
retval = eval_id(ss, node);
return eval_id(ss, node);
break;
case (Token_Type::Float) :
retval = eval_float(ss, node);
return eval_float(ss, node);
break;
case (Token_Type::Int) :
retval = eval_int(ss, node);
return eval_int(ss, node);
break;
case (Token_Type::Quoted_String) :
retval = eval_quoted_string(ss, node);
return eval_quoted_string(ss, node);
break;
case (Token_Type::Single_Quoted_String) :
retval = eval_single_quoted_string(ss, node);
return eval_single_quoted_string(ss, node);
break;
case (Token_Type::Equation) :
retval = eval_equation(ss, node);
return eval_equation(ss, node);
break;
case (Token_Type::Var_Decl) :
retval = eval_var_decl(ss, node);
return eval_var_decl(ss, node);
break;
case (Token_Type::Expression) :
retval = eval_expression(ss, node);
return eval_expression(ss, node);
break;
case (Token_Type::Comparison) :
case (Token_Type::Additive) :
case (Token_Type::Multiplicative) :
retval = eval_comp_add_mul(ss, node);
return eval_comp_add_mul(ss, node);
break;
case (Token_Type::Array_Call) :
retval = eval_array_call(ss, node);
return eval_array_call(ss, node);
break;
case (Token_Type::Negate) :
retval = eval_negate(ss, node);
return eval_negate(ss, node);
break;
case (Token_Type::Not) :
retval = eval_not(ss, node);
return eval_not(ss, node);
break;
case (Token_Type::Prefix) :
retval = eval_prefix(ss, node);
return eval_prefix(ss, node);
break;
case (Token_Type::Inline_Array) :
retval = eval_inline_array(ss, node);
return eval_inline_array(ss, node);
break;
case (Token_Type::Inline_Range) :
retval = eval_inline_range(ss, node);
return eval_inline_range(ss, node);
break;
case (Token_Type::Inline_Map) :
retval = eval_inline_map(ss, node);
return eval_inline_map(ss, node);
break;
case (Token_Type::Fun_Call) :
retval = eval_fun_call(ss, node);
return eval_fun_call(ss, node);
break;
case (Token_Type::Dot_Access) :
retval = eval_dot_access(ss, node);
return eval_dot_access(ss, node);
break;
case(Token_Type::If) :
retval = eval_if(ss, node);
return eval_if(ss, node);
break;
case(Token_Type::While) :
retval = eval_while(ss, node);
return eval_while(ss, node);
break;
case(Token_Type::For) :
retval = eval_for(ss, node);
return eval_for(ss, node);
break;
case (Token_Type::Def) :
retval = eval_def(ss, node);
return eval_def(ss, node);
break;
case (Token_Type::Lambda) :
retval = eval_lambda(ss, node);
return eval_lambda(ss, node);
break;
case (Token_Type::Block) :
retval = eval_block(ss, node);
return eval_block(ss, node);
break;
case (Token_Type::Return) :
retval = eval_return(ss, node);
return eval_return(ss, node);
break;
case (Token_Type::Break) :
retval = eval_break(ss, node);
return eval_break(ss, node);
break;
}
return retval;
default :
return Boxed_Value();
}
}
}
#endif /* CHAISCRIPT_EVAL_HPP_ */

View File

@@ -301,7 +301,7 @@ namespace chaiscript
++col;
}
else {
throw Parse_Error("Unclosed quoted string", File_Position(line, col), filename);
throw Eval_Error("Unclosed quoted string", File_Position(line, col), filename);
}
}
return retval;
@@ -343,7 +343,7 @@ namespace chaiscript
case ('t') : match.push_back('\t'); break;
case ('\'') : match.push_back('\''); break;
case ('\"') : match.push_back('\"'); break;
default: throw Parse_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
default: throw Eval_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
}
}
else {
@@ -392,7 +392,7 @@ namespace chaiscript
++col;
}
else {
throw Parse_Error("Unclosed single-quoted string", File_Position(line, col), filename);
throw Eval_Error("Unclosed single-quoted string", File_Position(line, col), filename);
}
}
return retval;
@@ -434,7 +434,7 @@ namespace chaiscript
case ('t') : match.push_back('\t'); break;
case ('\'') : match.push_back('\''); break;
case ('\"') : match.push_back('\"'); break;
default: throw Parse_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
default: throw Eval_Error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), filename);
}
}
else {
@@ -694,7 +694,7 @@ namespace chaiscript
if (Char(',')) {
do {
if (!Equation()) {
throw Parse_Error("Unexpected value in parameter list", match_stack.back());
throw Eval_Error("Unexpected value in parameter list", match_stack.back());
}
} while (retval && Char(','));
}
@@ -721,7 +721,7 @@ namespace chaiscript
if (Char(',')) {
do {
if (!Map_Pair()) {
throw Parse_Error("Unexpected value in container", match_stack.back());
throw Eval_Error("Unexpected value in container", match_stack.back());
}
} while (retval && Char(','));
}
@@ -746,14 +746,14 @@ namespace chaiscript
if (Char('(')) {
Arg_List();
if (!Char(')')) {
throw Parse_Error("Incomplete anonymous function", File_Position(line, col), filename);
throw Eval_Error("Incomplete anonymous function", File_Position(line, col), filename);
}
}
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete anonymous function", File_Position(line, col), filename);
throw Eval_Error("Incomplete anonymous function", File_Position(line, col), filename);
}
build_match(Token_Type::Lambda, prev_stack_top);
@@ -784,13 +784,13 @@ namespace chaiscript
retval = true;
if (!Id(true)) {
throw Parse_Error("Missing function name in definition", File_Position(line, col), filename);
throw Eval_Error("Missing function name in definition", File_Position(line, col), filename);
}
if (Char('(')) {
Arg_List();
if (!Char(')')) {
throw Parse_Error("Incomplete function definition", File_Position(line, col), filename);
throw Eval_Error("Incomplete function definition", File_Position(line, col), filename);
}
}
@@ -798,13 +798,13 @@ namespace chaiscript
if (Char(':')) {
if (!Expression()) {
throw Parse_Error("Missing guard expression for function", File_Position(line, col), filename);
throw Eval_Error("Missing guard expression for function", File_Position(line, col), filename);
}
}
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete function definition", File_Position(line, col), filename);
throw Eval_Error("Incomplete function definition", File_Position(line, col), filename);
}
build_match(Token_Type::Def, prev_stack_top);
@@ -829,46 +829,49 @@ namespace chaiscript
retval = true;
if (!Char('(')) {
throw Parse_Error("Incomplete 'if' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
throw Parse_Error("Incomplete 'if' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
}
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete 'if' block", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'if' block", File_Position(line, col), filename);
}
bool has_matches = true;
while (has_matches) {
while (Eol());
has_matches = false;
if (Keyword("elseif", true)) {
if (!Char('(')) {
throw Parse_Error("Incomplete 'elseif' expression", File_Position(line, col), filename);
}
if (Keyword("else", true)) {
if (Keyword("if")) {
match_stack.back()->text = "else if";
if (!Char('(')) {
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
throw Parse_Error("Incomplete 'elseif' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
}
while (Eol());
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete 'elseif' block", File_Position(line, col), filename);
if (!Block()) {
throw Eval_Error("Incomplete 'else if' block", File_Position(line, col), filename);
}
has_matches = true;
}
has_matches = true;
}
else if (Keyword("else", true)) {
while (Eol());
else {
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete 'else' block", File_Position(line, col), filename);
if (!Block()) {
throw Eval_Error("Incomplete 'else' block", File_Position(line, col), filename);
}
has_matches = true;
}
has_matches = true;
}
}
@@ -890,17 +893,17 @@ namespace chaiscript
retval = true;
if (!Char('(')) {
throw Parse_Error("Incomplete 'while' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
}
if (!(Expression() && Char(')'))) {
throw Parse_Error("Incomplete 'while' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
}
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete 'while' block", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'while' block", File_Position(line, col), filename);
}
build_match(Token_Type::While, prev_stack_top);
@@ -919,7 +922,7 @@ namespace chaiscript
return true;
}
else {
throw Parse_Error("Incomplete conditions in 'for' loop", File_Position(line, col), filename);
throw Eval_Error("Incomplete conditions in 'for' loop", File_Position(line, col), filename);
}
}
@@ -935,17 +938,17 @@ namespace chaiscript
retval = true;
if (!Char('(')) {
throw Parse_Error("Incomplete 'for' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'for' expression", File_Position(line, col), filename);
}
if (!(For_Guards() && Char(')'))) {
throw Parse_Error("Incomplete 'for' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'for' expression", File_Position(line, col), filename);
}
while (Eol());
if (!Block()) {
throw Parse_Error("Incomplete 'for' block", File_Position(line, col), filename);
throw Eval_Error("Incomplete 'for' block", File_Position(line, col), filename);
}
build_match(Token_Type::For, prev_stack_top);
@@ -967,7 +970,7 @@ namespace chaiscript
Statements();
if (!Char('}')) {
throw Parse_Error("Incomplete block", File_Position(line, col), filename);
throw Eval_Error("Incomplete block", File_Position(line, col), filename);
}
build_match(Token_Type::Block, prev_stack_top);
@@ -1031,7 +1034,7 @@ namespace chaiscript
Arg_List();
if (!Char(')')) {
throw Parse_Error("Incomplete function call", File_Position(line, col), filename);
throw Eval_Error("Incomplete function call", File_Position(line, col), filename);
}
build_match(Token_Type::Fun_Call, prev_stack_top);
@@ -1040,7 +1043,7 @@ namespace chaiscript
has_more = true;
if (!(Expression() && Char(']'))) {
throw Parse_Error("Incomplete array access", File_Position(line, col), filename);
throw Eval_Error("Incomplete array access", File_Position(line, col), filename);
}
build_match(Token_Type::Array_Call, prev_stack_top);
@@ -1063,7 +1066,7 @@ namespace chaiscript
retval = true;
if (!Id(true)) {
throw Parse_Error("Incomplete variable declaration", File_Position(line, col), filename);
throw Eval_Error("Incomplete variable declaration", File_Position(line, col), filename);
}
build_match(Token_Type::Var_Decl, prev_stack_top);
@@ -1081,10 +1084,10 @@ namespace chaiscript
if (Char('(')) {
retval = true;
if (!Expression()) {
throw Parse_Error("Incomplete expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
}
if (!Char(')')) {
throw Parse_Error("Missing closing parenthesis", File_Position(line, col), filename);
throw Eval_Error("Missing closing parenthesis", File_Position(line, col), filename);
}
}
return retval;
@@ -1102,7 +1105,7 @@ namespace chaiscript
retval = true;
Container_Arg_List();
if (!Char(']')) {
throw Parse_Error("Missing closing square bracket", File_Position(line, col), filename);
throw Eval_Error("Missing closing square bracket", File_Position(line, col), filename);
}
if ((prev_stack_top != match_stack.size()) && (match_stack.back()->children.size() > 0)) {
if (match_stack.back()->children[0]->identifier == Token_Type::Value_Range) {
@@ -1144,7 +1147,7 @@ namespace chaiscript
while ((input_pos != input_end) && (*input_pos != '`')) {
if (Eol()) {
throw Parse_Error("Carriage return in identifier literal", File_Position(line, col), filename);
throw Eval_Error("Carriage return in identifier literal", File_Position(line, col), filename);
}
else {
++input_pos;
@@ -1153,10 +1156,10 @@ namespace chaiscript
}
if (start == input_pos) {
throw Parse_Error("Missing contents of identifier literal", File_Position(line, col), filename);
throw Eval_Error("Missing contents of identifier literal", File_Position(line, col), filename);
}
else if (input_pos == input_end) {
throw Parse_Error("Incomplete identifier literal", File_Position(line, col), filename);
throw Eval_Error("Incomplete identifier literal", File_Position(line, col), filename);
}
++col;
@@ -1182,7 +1185,7 @@ namespace chaiscript
retval = true;
if (!Dot_Access()) {
throw Parse_Error("Incomplete negation expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete negation expression", File_Position(line, col), filename);
}
build_match(Token_Type::Negate, prev_stack_top);
@@ -1191,7 +1194,7 @@ namespace chaiscript
retval = true;
if (!Dot_Access()) {
throw Parse_Error("Incomplete '!' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete '!' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Not, prev_stack_top);
@@ -1200,7 +1203,7 @@ namespace chaiscript
retval = true;
if (!Dot_Access()) {
throw Parse_Error("Incomplete '++' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete '++' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Prefix, prev_stack_top);
@@ -1209,7 +1212,7 @@ namespace chaiscript
retval = true;
if (!Dot_Access()) {
throw Parse_Error("Incomplete '--' expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete '--' expression", File_Position(line, col), filename);
}
build_match(Token_Type::Prefix, prev_stack_top);
@@ -1244,7 +1247,7 @@ namespace chaiscript
if (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)) {
do {
if (!Additive()) {
throw Parse_Error("Incomplete comparison expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete comparison expression", File_Position(line, col), filename);
}
} while (retval && (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)));
@@ -1268,7 +1271,7 @@ namespace chaiscript
if (Symbol("+", true) || Symbol("-", true)) {
do {
if (!Multiplicative()) {
throw Parse_Error("Incomplete math expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("+", true) || Symbol("-", true)));
@@ -1292,7 +1295,7 @@ namespace chaiscript
if (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)) {
do {
if (!Dot_Access()) {
throw Parse_Error("Incomplete math expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)));
@@ -1316,7 +1319,7 @@ namespace chaiscript
if (Symbol(".")) {
do {
if (!Value()) {
throw Parse_Error("Incomplete dot notation", File_Position(line, col), filename);
throw Eval_Error("Incomplete dot notation", File_Position(line, col), filename);
}
} while (retval && Symbol("."));
@@ -1340,7 +1343,7 @@ namespace chaiscript
if (Symbol("&&", true) || Symbol("||", true)) {
do {
if (!Comparison()) {
throw Parse_Error("Incomplete expression", File_Position(line, col), filename);
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("&&", true) || Symbol("||", true)));
@@ -1364,7 +1367,7 @@ namespace chaiscript
if (Symbol(":")) {
do {
if (!Expression()) {
throw Parse_Error("Incomplete map pair", File_Position(line, col), filename);
throw Eval_Error("Incomplete map pair", File_Position(line, col), filename);
}
} while (retval && Symbol(":"));
@@ -1389,7 +1392,7 @@ namespace chaiscript
if (Symbol("..")) {
retval = true;
if (!Expression()) {
throw Parse_Error("Incomplete value range", File_Position(line, col), filename);
throw Eval_Error("Incomplete value range", File_Position(line, col), filename);
}
build_match(Token_Type::Value_Range, prev_stack_top);
@@ -1418,7 +1421,7 @@ namespace chaiscript
retval = true;
if (Symbol("=", true) || Symbol(":=", true) || Symbol("+=", true) || Symbol("-=", true) || Symbol("*=", true) || Symbol("/=", true)) {
if (!Equation()) {
throw Parse_Error("Incomplete equation", match_stack.back());
throw Eval_Error("Incomplete equation", match_stack.back());
}
build_match(Token_Type::Equation, prev_stack_top);
@@ -1441,7 +1444,7 @@ namespace chaiscript
has_more = false;
if (Def()) {
if (!saw_eol) {
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1449,7 +1452,7 @@ namespace chaiscript
}
else if (If()) {
if (!saw_eol) {
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1457,7 +1460,7 @@ namespace chaiscript
}
else if (While()) {
if (!saw_eol) {
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1465,7 +1468,7 @@ namespace chaiscript
}
else if (For()) {
if (!saw_eol) {
throw Parse_Error("Two function definitions missing line separator", match_stack.back());
throw Eval_Error("Two function definitions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1473,7 +1476,7 @@ namespace chaiscript
}
else if (Return()) {
if (!saw_eol) {
throw Parse_Error("Two expressions missing line separator", match_stack.back());
throw Eval_Error("Two expressions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1481,7 +1484,7 @@ namespace chaiscript
}
else if (Break()) {
if (!saw_eol) {
throw Parse_Error("Two expressions missing line separator", match_stack.back());
throw Eval_Error("Two expressions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1489,7 +1492,7 @@ namespace chaiscript
}
else if (Equation()) {
if (!saw_eol) {
throw Parse_Error("Two expressions missing line separator", match_stack.back());
throw Eval_Error("Two expressions missing line separator", match_stack.back());
}
has_more = true;
retval = true;
@@ -1525,7 +1528,7 @@ namespace chaiscript
if (Statements()) {
if (input_pos != input_end) {
throw Parse_Error("Unparsed input", File_Position(line, col), fname);
throw Eval_Error("Unparsed input", File_Position(line, col), fname);
}
else {
build_match(Token_Type::File, 0);

View File

@@ -12,6 +12,8 @@
#define CODE_STRING(x, y) #x ", " #y
#define chaiscript_prelude CODE_STRING(\
def new(x) { eval(type_name(x))(); } \
def clone(x) { eval(type_name(x))(x); } \
# to_string for Pair()\n\
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \
@@ -22,7 +24,7 @@ def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \
}\
# Basic to_string function\n\
def to_string(x) { \
return internal_to_string(x); \
internal_to_string(x); \
}\
# Prints to console with no carriage return\n\
def puts(x) { \
@@ -41,10 +43,20 @@ def odd(x) { if (x % 2 == 1) { true } else { false } } \
# Returns true if the value is even\n\
def even(x) { if (x % 2 == 0) { true } else { false } } \
# Pushes the second value onto the container first value while making a clone of the value\n\
def push_back(container, x) { container.push_back_ref(clone(x)) } \n\
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_ref(clone(x)) } \n\
# Inserts the third value at the position of the second value into the container of the first\n\
# while making a clone. \n\
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
# Returns the reverse of the given container\n\
def reverse(container) {\
var retval = new(container); \
var r = retro(range(container)); \
while (!r.empty()) { \
retval.push_back(r.front()); \
r.pop_front(); \
} \
retval; \
} \
# Performs the second value function over the container first value\n\
def for_each(container, func) : call_exists(range, container) { \
var range = range(container); \
@@ -54,7 +66,7 @@ def for_each(container, func) : call_exists(range, container) { \
} \
} \
def back_inserter(container) { \
return bind(push_back, container, _); \
bind(push_back, container, _); \
}\
\
def map(container, func, inserter) : call_exists(range, container) { \
@@ -64,11 +76,11 @@ def map(container, func, inserter) : call_exists(range, container) { \
range.pop_front(); \
} \
} \
# Performs the second value function over the container first value. Creates a new Vector with the results\n\
# Performs the second value function over the container first value. Creates a new container with the results\n\
def map(container, func) { \
var retval = Vector();\
var retval = new(container); \
map(container, func, back_inserter(retval));\
return retval;\
retval;\
}\
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
def foldl(container, func, initial) : call_exists(range, container){ \
@@ -84,7 +96,7 @@ def foldl(container, func, initial) : call_exists(range, container){ \
def sum(container) { foldl(container, `+`, 0.0) } \
# Returns the product of the elements of the given value\n\
def product(container) { foldl(container, `*`, 1.0) } \
# Returns a new Vector with the elements of the first value concatenated with the elements of the second value\n\
# Returns a new container with the elements of the first value concatenated with the elements of the second value\n\
def concat(x, y) : call_exists(clone, x) { \
var retval = x; \
var len = y.size(); \
@@ -104,11 +116,11 @@ def take(container, num, inserter) : call_exists(range, container) { \
--i; \
} \
} \
# Returns a new Vector with the given number of elements taken from the container\n\
# Returns a new container with the given number of elements taken from the container\n\
def take(container, num) {\
var retval = Vector(); \
var retval = new(container); \
take(container, num, back_inserter(retval)); \
return retval; \
retval; \
}\
def take_while(container, f, inserter) : call_exists(range, container) { \
var r = range(container); \
@@ -117,11 +129,11 @@ def take_while(container, f, inserter) : call_exists(range, container) { \
r.pop_front(); \
} \
} \
# Returns a new Vector with the given elements match the second value function\n\
# Returns a new container with the given elements match the second value function\n\
def take_while(container, f) {\
var retval = Vector(); \
var retval = new(container); \
take_while(container, f, back_inserter(retval)); \
return retval;\
retval;\
}\
def drop(container, num, inserter) : call_exists(range, container) { \
var r = range(container); \
@@ -135,11 +147,11 @@ def drop(container, num, inserter) : call_exists(range, container) { \
r.pop_front(); \
} \
} \
# Returns a new Vector with the given number of elements dropped from the given container \n\
# Returns a new container with the given number of elements dropped from the given container \n\
def drop(container, num) {\
var retval = Vector(); \
var retval = new(container); \
drop(container, num, back_inserter(retval)); \
return retval; \
retval; \
}\
def drop_while(container, f, inserter) : call_exists(range, container) { \
var r = range(container); \
@@ -151,11 +163,11 @@ def drop_while(container, f, inserter) : call_exists(range, container) { \
r.pop_front(); \
} \
} \
# Returns a new Vector with the given elements dropped that match the second value function\n\
# Returns a new container with the given elements dropped that match the second value function\n\
def drop_while(container, f) {\
var retval = Vector(); \
var retval = new(container); \
drop_while(container, f, back_inserter(retval)); \
return retval; \
retval; \
}\
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \
@@ -196,9 +208,9 @@ def filter(container, f, inserter) : call_exists(range, container) { \
} \
# Returns a new Vector which match the second value function\n\
def filter(container, f) { \
var retval = Vector(); \
var retval = new(container); \
filter(container, f, back_inserter(retval));\
return retval;\
retval;\
}\
def generate_range(x, y, inserter) { \
var i = x; \
@@ -211,7 +223,7 @@ def generate_range(x, y, inserter) { \
def generate_range(x, y) { \
var retval = Vector(); \
generate_range(x,y,back_inserter(retval)); \
return retval; \
retval; \
}\
# Returns a new Vector with the first value to the second value as its elements\n\
def collate(x, y) { \
@@ -230,7 +242,7 @@ def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y)
def zip_with(f, x, y) { \
var retval = Vector(); \
zip_with(f,x,y,back_inserter(retval)); \
return retval;\
retval;\
}\
# Returns a new Vector which joins matching elements of the first and second\n\
def zip(x, y) { \
@@ -238,28 +250,36 @@ def zip(x, y) { \
}\
# Returns the position of the second value string in the first value string\n\
def find(str, substr) { \
return int(find(str, substr, size_t(0))); \
int(find(str, substr, size_t(0))); \
} \
# Returns the position of last match of the second value string in the first value string\n\
def rfind(str, substr) { \
return int(rfind(str, substr, size_t(-1))); \
int(rfind(str, substr, size_t(-1))); \
} \
# Returns the position of the first match of elements in the second value string in the first value string\n\
def find_first_of(str, list) { \
return int(find_first_of(str, list, size_t(0))); \
int(find_first_of(str, list, size_t(0))); \
} \
# Returns the position of the last match of elements in the second value string in the first value string\n\
def find_last_of(str, list) { \
return int(find_last_of(str, list, size_t(-1))); \
int(find_last_of(str, list, size_t(-1))); \
} \
# Returns the position of the first non-matching element in the second value string in the first value string\n\
def find_first_not_of(str, list) { \
return int(find_first_not_of(str, list, size_t(0))); \
int(find_first_not_of(str, list, size_t(0))); \
} \
# Returns the position of the last non-matching element in the second value string in the first value string\n\
def find_last_not_of(str, list) { \
return int(find_last_not_of(str, list, size_t(-1))); \
int(find_last_not_of(str, list, size_t(-1))); \
} \
def ltrim(str) { \
drop_while(str, fun(x) { x == ' ' || x == '\t' }); \
} \
def rtrim(str) { \
reverse(drop_while(reverse(str), fun(x) { x == ' ' || x == '\t' })); \
} \
def trim(str) { \
ltrim(rtrim(str)); \
} \
)
#endif /* CHAISCRIPT_PRELUDE_HPP_ */

View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="chai-example"
ProjectGUID="{CE422E94-B360-4588-8C65-6A9BE80798F9}"
RootNamespace="chaiexample"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="C:\Programming\chaiscript\trunk\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\chaiscript\Boost.vsprops"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\example.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -8,4 +8,12 @@
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;C:\Programming\Boost\include\boost-1_38&quot;"
/>
<Tool
Name="VCLibrarianTool"
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
/>
<Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories="C:\Programming\Boost\lib"
/>
</VisualStudioPropertySheet>

View File

@@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chaiscript", "chaiscript.vcproj", "{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chai-example", "..\chai-example\chai-example.vcproj", "{CE422E94-B360-4588-8C65-6A9BE80798F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -13,6 +15,10 @@ Global
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Debug|Win32.Build.0 = Debug|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.ActiveCfg = Release|Win32
{46FD9DC7-2DA9-4C17-ADE4-E3A18C46E87B}.Release|Win32.Build.0 = Release|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.ActiveCfg = Debug|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Debug|Win32.Build.0 = Debug|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.ActiveCfg = Release|Win32
{CE422E94-B360-4588-8C65-6A9BE80798F9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -27,9 +27,9 @@ struct System
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
void add_callback(const std::string &t_name,
boost::shared_ptr<dispatchkit::Proxy_Function> t_func)
const chaiscript::Proxy_Function &t_func)
{
m_callbacks[t_name] = dispatchkit::build_function_caller<std::string (const std::string &)>(t_func);
m_callbacks[t_name] = chaiscript::functor<std::string (const std::string &)>(t_func);
}
@@ -47,46 +47,81 @@ struct System
int main(int argc, char *argv[]) {
using namespace chaiscript;
chaiscript::ChaiScript_Engine chai;
ChaiScript chai;
//Create a new system object and share it with the chaiscript engine
System system;
chai.get_eval_engine().add_object("system", boost::ref(system));
chai.add(var(&system), "system");
//Register the two methods of the System structure.
dispatchkit::register_function(chai.get_eval_engine(), &System::add_callback, "add_callback");
dispatchkit::register_function(chai.get_eval_engine(), &System::do_callbacks, "do_callbacks");
chai.add(fun(&System::add_callback), "add_callback");
chai.add(fun(&System::do_callbacks), "do_callbacks");
// Let's use chaiscript to add a new lambda callback to our system.
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
// in the "add_callback" function of struct System the chaiscript function is converted into a
// boost::function, so it can be handled and called easily and type-safely
chai.evaluate_string("system.add_callback('#1', fun(x) { 'Callback1 ' + x });");
chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");
// Because we are sharing the "system" object with the chaiscript engine we have equal
// access to it both from within chaiscript and from C++ code
system.do_callbacks("TestString");
chai.evaluate_string("system.do_callbacks(\"TestString\");");
chai.eval("system.do_callbacks(\"TestString\");");
// The log function is overloaded, therefore we have to give the C++ compiler a hint as to which
// version we want to register. One way to do this is to create a typedef of the function pointer
// then cast your function to that typedef.
typedef void (*PlainLog)(const std::string &);
typedef void (*ModuleLog)(const std::string &, const std::string &);
dispatchkit::register_function(chai.get_eval_engine(), PlainLog(&log), "log");
dispatchkit::register_function(chai.get_eval_engine(), ModuleLog(&log), "log");
chai.add(fun(PlainLog(&log)), "log");
chai.add(fun(ModuleLog(&log)), "log");
chai.evaluate_string("log('Test Message')");
chai.evaluate_string("log('Test Module', 'Test Message');");
chai.eval("log(\"Test Message\")");
// A shortcut to using eval is just to use the chai operator()
chai("log(\"Test Module\", \"Test Message\");");
//Finally, it is possible to register any boost::function as a system function, in this
//way, we can, for instance add a bound member function to the system
chai.get_eval_engine().register_function(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test")), "do_callbacks");
chai.add(fun(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test"))), "do_callbacks");
//Call bound version of do_callbacks
chai.evaluate_string("do_callbacks()");
chai("do_callbacks()");
boost::function<void ()> caller = chai.functor<void ()>("fun() { system.do_callbacks(\"From Functor\"); }");
caller();
//If we would like a type-safe return value from all call, we can use
//the templated version of eval:
int i = chai.eval<int>("5+5");
std::cout << "5+5: " << i << std::endl;
//Add a new variable
chai("var scripti = 15");
//We can even get a handle to the variables in the system
int &scripti = chai.eval<int &>("scripti");
std::cout << "scripti: " << scripti << std::endl;
scripti *= 2;
std::cout << "scripti (updated): " << scripti << std::endl;
chai("print(\"Scripti from chai: \" + to_string(scripti))");
//To do: Add examples of handling Boxed_Values directly when needed
//Creating a functor on the stack and using it immediatly
int x = chai.functor<int (int, int)>("fun (x, y) { return x + y; }")(5, 6);
log("Functor test output", boost::lexical_cast<std::string>(x));
//Ability to create our own container types when needed. std::vector and std::map are
//mostly supported currently
chai.add(bootstrap::vector_type<std::vector<int> >("IntVector"));
}

View File

@@ -17,14 +17,14 @@ void print_help() {
int main(int argc, char *argv[]) {
std::string input;
chaiscript::ChaiScript_Engine chai;
chaiscript::ChaiScript chai;
if (argc < 2) {
std::cout << "eval> ";
std::getline(std::cin, input);
while (input != "quit") {
dispatchkit::Boxed_Value val;
chaiscript::Boxed_Value val;
if (input == "help") {
print_help();
@@ -32,24 +32,18 @@ int main(int argc, char *argv[]) {
else {
try {
//First, we evaluate it
val = chai.evaluate_string(input);
val = chai.eval(input);
//Then, we try to print the result of the evaluation to the user
if (val.get_type_info().m_bare_type_info && *(val.get_type_info().m_bare_type_info) != typeid(void)) {
try {
dispatchkit::dispatch(chai.get_eval_engine().get_function("print"), dispatchkit::Param_List_Builder() << val);
chaiscript::dispatch(chai.get_eval_engine().get_function("print"), chaiscript::Param_List_Builder() << val);
}
catch (...) {
//If we can't, do nothing
}
}
}
catch (chaiscript::Parse_Error &pe) {
std::cout << pe.reason << " in " << pe.filename << " at " << pe.position.line << ", " << pe.position.column << std::endl;
}
catch (chaiscript::Eval_Error &ee) {
std::cout << ee.reason << std::endl;
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
@@ -63,23 +57,7 @@ int main(int argc, char *argv[]) {
for (int i = 1; i < argc; ++i) {
std::string filename(argv[i]);
try {
dispatchkit::Boxed_Value val = chai.evaluate_file(argv[i]);
}
catch (chaiscript::Parse_Error &pe) {
if (filename != std::string("__EVAL__")) {
std::cout << pe.reason << " in " << pe.filename << " at " << pe.position.line << ", " << pe.position.column << std::endl;
}
else {
std::cout << pe.reason << std::endl;
}
}
catch (chaiscript::Eval_Error &ee) {
if (filename != std::string("__EVAL__")) {
std::cout << ee.reason << " in '" << ee.location->filename << "' at " << ee.location->start.line << ", " << ee.location->start.column << std::endl;
}
else {
std::cout << ee.reason << std::endl;
}
chaiscript::Boxed_Value val = chai.eval_file(argv[i]);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;

View File

@@ -2,10 +2,10 @@ var i = 3
if (i == 2) {
print("2")
}
elseif (i == 4) {
else if (i == 4) {
print("4")
}
elseif (i == 3) {
else if (i == 3) {
print("3")
}

View File

@@ -2,7 +2,7 @@ var i = 3
if (i == 2) {
print("2")
}
elseif (i == 4) {
else if (i == 4) {
print("4")
}
else {

4
unittests/range.chai Normal file
View File

@@ -0,0 +1,4 @@
var x = [1, 2, 3, 4]
var r = range(x)
r.pop_front()
print(r.front())

1
unittests/range.txt Normal file
View File

@@ -0,0 +1 @@
2

View File

@@ -0,0 +1,4 @@
var x = [1, 2, 3, 4]
var r = range(x)
r.pop_back()
print(r.back())

1
unittests/range_back.txt Normal file
View File

@@ -0,0 +1 @@
3

4
unittests/retro.chai Normal file
View File

@@ -0,0 +1,4 @@
var x = [1, 2, 3, 4]
var r = retro(range(x))
r.pop_front()
print(r.front())

1
unittests/retro.txt Normal file
View File

@@ -0,0 +1 @@
3