Compare commits
54 Commits
Release-2.
...
v2.3.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0c0df2c982 | ||
![]() |
4457df9ff5 | ||
![]() |
e601de9d18 | ||
![]() |
37b2ac2056 | ||
![]() |
645cdddd70 | ||
![]() |
ac8462fb67 | ||
![]() |
636c55493c | ||
![]() |
e2a2c14c0d | ||
![]() |
c418644a5b | ||
![]() |
fbf8f53e04 | ||
![]() |
a0c6366479 | ||
![]() |
15ffbd200a | ||
![]() |
1c6b2725b3 | ||
![]() |
95c124ca35 | ||
![]() |
1bd73884b2 | ||
![]() |
d3e4af433e | ||
![]() |
9f65303370 | ||
![]() |
391eaa9e11 | ||
![]() |
ed11f48847 | ||
![]() |
9dddb49850 | ||
![]() |
cca477dae6 | ||
![]() |
07352a16a3 | ||
![]() |
e14931f389 | ||
![]() |
f4a680a582 | ||
![]() |
e6c6223c5b | ||
![]() |
cbc61d898c | ||
![]() |
3a37ceedb7 | ||
![]() |
1bc968e788 | ||
![]() |
fe5a935abd | ||
![]() |
4e5c972e66 | ||
![]() |
d946cb7e9d | ||
![]() |
18bfead387 | ||
![]() |
4c015d7e44 | ||
![]() |
1122f2c818 | ||
![]() |
d2d752ecd4 | ||
![]() |
a18c701866 | ||
![]() |
9871604a48 | ||
![]() |
b1d12fdc91 | ||
![]() |
24e717d532 | ||
![]() |
1568fedebd | ||
![]() |
c88578d537 | ||
![]() |
9827345213 | ||
![]() |
c51d14fb13 | ||
![]() |
480761c1f7 | ||
![]() |
12e909d9aa | ||
![]() |
b1e892487f | ||
![]() |
720eabcb16 | ||
![]() |
1fde71f3f4 | ||
![]() |
90f8b77171 | ||
![]() |
315d7521a7 | ||
![]() |
ff177b5eaf | ||
![]() |
46fd7e9a58 | ||
![]() |
edd274ccce | ||
![]() |
a5b2ec3006 |
@@ -29,125 +29,6 @@
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
typedef ModulePtr (*Create_Module_Func)();
|
||||
|
||||
/**
|
||||
* Types of AST nodes available to the parser and eval
|
||||
*/
|
||||
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Expression, Comparison, Additive, Multiplicative, Negate, Not, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl }; };
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* Helper lookup to get the name of each node type
|
||||
*/
|
||||
const char *token_type_to_string(int tokentype) {
|
||||
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Expression", "Comparison", "Additive", "Multiplicative", "Negate", "Not", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl"};
|
||||
|
||||
return token_types[tokentype];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience type for file positions
|
||||
*/
|
||||
struct File_Position {
|
||||
int line;
|
||||
int column;
|
||||
|
||||
File_Position(int file_line, int file_column)
|
||||
: line(file_line), column(file_column) { }
|
||||
|
||||
File_Position() : line(0), column(0) { }
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<struct Token> TokenPtr;
|
||||
|
||||
/**
|
||||
* The struct that doubles as both a parser token and an AST node
|
||||
*/
|
||||
struct Token {
|
||||
std::string text;
|
||||
int identifier;
|
||||
const char *filename;
|
||||
File_Position start, end;
|
||||
bool is_cached;
|
||||
Boxed_Value cached_value;
|
||||
|
||||
std::vector<TokenPtr> children;
|
||||
TokenPtr annotation;
|
||||
|
||||
Token(const std::string &token_text, int id, const char *fname) :
|
||||
text(token_text), identifier(id), filename(fname), is_cached(false) { }
|
||||
|
||||
Token(const std::string &token_text, int id, const char *fname, int start_line, int start_col, int end_line, int end_col) :
|
||||
text(token_text), identifier(id), filename(fname), is_cached(false) {
|
||||
|
||||
start.line = start_line;
|
||||
start.column = start_col;
|
||||
end.line = end_line;
|
||||
end.column = end_col;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors generated during parsing or evaluation
|
||||
*/
|
||||
struct Eval_Error : public std::runtime_error {
|
||||
std::string reason;
|
||||
File_Position start_position;
|
||||
File_Position end_position;
|
||||
const char *filename;
|
||||
|
||||
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), start_position(where), end_position(where), filename(fname)
|
||||
{ }
|
||||
|
||||
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), start_position(where->start), end_position(where->end), filename(where->filename) {
|
||||
}
|
||||
|
||||
virtual ~Eval_Error() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type for returned values
|
||||
*/
|
||||
struct Return_Value {
|
||||
Boxed_Value retval;
|
||||
TokenPtr location;
|
||||
|
||||
Return_Value(const Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type indicating a call to 'break'
|
||||
*/
|
||||
struct Break_Loop {
|
||||
TokenPtr location;
|
||||
|
||||
Break_Loop(const TokenPtr where) : location(where) { }
|
||||
};
|
||||
}
|
||||
|
||||
#include "language/chaiscript_eval.hpp"
|
||||
#include "language/chaiscript_engine.hpp"
|
||||
|
||||
|
65
include/chaiscript/dispatchkit/bind_first.hpp
Normal file
65
include/chaiscript/dispatchkit/bind_first.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
|
||||
#define param(z,n,text) BOOST_PP_CAT(text, BOOST_PP_INC(n))
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef __bind_first_hpp__
|
||||
#define __bind_first_hpp__
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 8 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/bind_first.hpp>
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
# define m BOOST_PP_INC(n)
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
||||
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
|
||||
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
|
||||
{
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
|
||||
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const, const O &o)
|
||||
{
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
|
||||
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
|
||||
{
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
|
||||
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)
|
||||
{
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -10,6 +10,7 @@
|
||||
#include "dispatchkit.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "operators.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -17,129 +18,6 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Set of helper functions for common operators
|
||||
*/
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret add(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 + p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret subtract(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 - p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret divide(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 / p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret multiply(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 * p2;
|
||||
}
|
||||
|
||||
template<typename Ret, typename P1, typename P2>
|
||||
Ret modulus(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 % p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 &assign(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 = p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 == p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool not_equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 != p2;
|
||||
}
|
||||
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool less_than(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 < p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool greater_than(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 > p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool less_than_equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 <= p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
bool greater_than_equals(P1 p1, P2 p2)
|
||||
{
|
||||
return p1 >= p2;
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 ×equal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 *= p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 ÷sequal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 /= p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 &addsequal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 += p2);
|
||||
}
|
||||
|
||||
template<typename P1, typename P2>
|
||||
P1 &subtractsequal(P1 &p1, const P2 &p2)
|
||||
{
|
||||
return (p1 -= p2);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixincrement(P1 &p1)
|
||||
{
|
||||
return (++p1);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixdecrement(P1 &p1)
|
||||
{
|
||||
return (--p1);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixnegate(P1 &p1)
|
||||
{
|
||||
return (p1);
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &prefixnot(P1 &p1)
|
||||
{
|
||||
return (p1);
|
||||
}
|
||||
|
||||
/* Special helpers for generating generic "POD" type operators
|
||||
* The POD operators are needed for general support of C++ POD
|
||||
@@ -150,6 +28,7 @@ namespace chaiscript
|
||||
template<typename P1>
|
||||
P1 &assign_pod(P1 &p1, Boxed_POD_Value v)
|
||||
{
|
||||
|
||||
if (v.m_isfloat)
|
||||
{
|
||||
return (p1 = P1(v.d));
|
||||
@@ -170,7 +49,63 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 ×equal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
P1 &assign_bitwise_and_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.m_isfloat)
|
||||
{
|
||||
return p1 &= P1(r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("&= only valid for integer types");
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_xor_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.m_isfloat)
|
||||
{
|
||||
return p1 ^= P1(r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("^= only valid for integer types");
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_bitwise_or_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.m_isfloat)
|
||||
{
|
||||
return p1 |= P1(r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("&= only valid for integer types");
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_difference_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
return p1 -= P1(r.d);
|
||||
} else {
|
||||
return p1 -= P1(r.i);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_left_shift_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.m_isfloat)
|
||||
{
|
||||
return p1 <<= P1(r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("<<= only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_product_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
@@ -181,7 +116,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 ÷sequal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
P1 &assign_quotient_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
@@ -192,7 +127,31 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
P1 &assign_remainder_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.m_isfloat)
|
||||
{
|
||||
return p1 %= P1(r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("%= only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_right_shift_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (!r.m_isfloat)
|
||||
{
|
||||
return p1 >>= P1(r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast(">>= only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
template<typename P1>
|
||||
P1 &assign_sum_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
@@ -202,223 +161,66 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename P1>
|
||||
P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r)
|
||||
{
|
||||
if (r.m_isfloat)
|
||||
{
|
||||
return p1 -= P1(r.d);
|
||||
} else {
|
||||
return p1 -= P1(r.i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::equals<const T&, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "+" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_add(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::add<T, const T&, const T&>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "+=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_add_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::addsequal<T, T>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "-" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_subtract(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::subtract<T, const T&, const T&>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "/" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_divide(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::divide<T, const T&, const T&>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "*" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_multiply(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::multiply<T, const T&, const T&>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "!=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_not_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::not_equals<const T&, const T&>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user defined assignment operator for T = U
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
ModulePtr oper_assign_overload(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign<T,U>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add canonical form of "=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_assign(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign<T,T>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add assignment operator for T = POD.
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign_pod<T>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add canonical form of "<" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_less_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of ">" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of "<=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_less_than_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::less_than_equals<const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical form of ">=" for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_greater_than_equals(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::greater_than_equals<const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add user defined comparison operators for T and R.
|
||||
* Examples: T < R, T == R, etc.
|
||||
*/
|
||||
template<typename T, typename R>
|
||||
ModulePtr opers_comparison_overload(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::equals<const T&, const R&>), "==");
|
||||
m->add(fun(&detail::not_equals<const T&, const R&>), "!=");
|
||||
m->add(fun(&detail::less_than<const T&, const R&>), "<");
|
||||
m->add(fun(&detail::greater_than<const T&, const R&>), ">");
|
||||
m->add(fun(&detail::less_than_equals<const T&, const R&>), "<=");
|
||||
m->add(fun(&detail::greater_than_equals<const T&, const R&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical forms of all comparison operators for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr opers_comparison(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
opers_comparison_overload<T, T>(m);
|
||||
operators::equal<T>(m);
|
||||
operators::greater_than<T>(m);
|
||||
operators::greater_than_equal<T>(m);
|
||||
operators::less_than<T>(m);
|
||||
operators::less_than_equal<T>(m);
|
||||
operators::not_equal<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all arithmetic operators that return a type of Ret, taking
|
||||
* a lhs of T and a rhs of R, when possible.
|
||||
* examples: Ret = T + R;
|
||||
* ++T
|
||||
* T *= R;
|
||||
*/
|
||||
template<typename Ret, typename T, typename R>
|
||||
ModulePtr opers_arithmetic_overload(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::add<Ret, T, R>), "+");
|
||||
m->add(fun(&detail::subtract<Ret, T, R>), "-");
|
||||
m->add(fun(&detail::divide<Ret, T, R>), "/");
|
||||
m->add(fun(&detail::multiply<Ret, T, R>), "*");
|
||||
m->add(fun(&detail::timesequal<T, R>), "*=");
|
||||
m->add(fun(&detail::dividesequal<T, R>), "/=");
|
||||
m->add(fun(&detail::subtractsequal<T, R>), "-=");
|
||||
m->add(fun(&detail::addsequal<T, R>), "+=");
|
||||
m->add(fun(&detail::prefixincrement<T>), "++");
|
||||
m->add(fun(&detail::prefixdecrement<T>), "--");
|
||||
m->add(fun(&detail::prefixnegate<T>), "-");
|
||||
m->add(fun(&detail::prefixnot<T>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add arithmetic assign operators for POD types:
|
||||
* example: POD *= T, POD /= T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr opers_arithmetic_modify_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr opers_integer_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::timesequal_pod<T>), "*=");
|
||||
m->add(fun(&detail::dividesequal_pod<T>), "/=");
|
||||
m->add(fun(&detail::subtractsequal_pod<T>), "-=");
|
||||
m->add(fun(&detail::addsequal_pod<T>), "+=");
|
||||
operators::assign_bitwise_and<T>(m);
|
||||
operators::assign_xor<T>(m);
|
||||
operators::assign_bitwise_or<T>(m);
|
||||
operators::assign_difference<T>(m);
|
||||
operators::assign_left_shift<T>(m);
|
||||
operators::assign_product<T>(m);
|
||||
operators::assign_quotient<T>(m);
|
||||
operators::assign_remainder<T>(m);
|
||||
operators::assign_right_shift<T>(m);
|
||||
operators::assign_sum<T>(m);
|
||||
|
||||
operators::prefix_decrement<T>(m);
|
||||
operators::prefix_increment<T>(m);
|
||||
operators::addition<T>(m);
|
||||
operators::unary_plus<T>(m);
|
||||
operators::subtraction<T>(m);
|
||||
operators::unary_minus<T>(m);
|
||||
operators::bitwise_and<T>(m);
|
||||
operators::bitwise_compliment<T>(m);
|
||||
operators::bitwise_xor<T>(m);
|
||||
operators::bitwise_or<T>(m);
|
||||
operators::division<T>(m);
|
||||
operators::left_shift<T>(m);
|
||||
operators::multiplication<T>(m);
|
||||
operators::remainder<T>(m);
|
||||
operators::right_shift<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr opers_float_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
operators::assign_difference<T>(m);
|
||||
operators::assign_product<T>(m);
|
||||
operators::assign_quotient<T>(m);
|
||||
operators::assign_sum<T>(m);
|
||||
|
||||
operators::addition<T>(m);
|
||||
operators::unary_plus<T>(m);
|
||||
operators::subtraction<T>(m);
|
||||
operators::unary_minus<T>(m);
|
||||
operators::division<T>(m);
|
||||
operators::multiplication<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -464,16 +266,6 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add canonical forms of all arithmetic operators for type T
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr opers_arithmetic(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
opers_arithmetic_overload<T, T, T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* to_string function for internal use. Uses ostream operator<<
|
||||
*/
|
||||
@@ -494,6 +286,17 @@ namespace chaiscript
|
||||
return boost::lexical_cast<Input>(i);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add assignment operator for T = POD.
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr oper_assign_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::assign_pod<T>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
@@ -503,16 +306,52 @@ namespace chaiscript
|
||||
{
|
||||
m->add(user_type<T>(), name);
|
||||
basic_constructors<T>(name, m);
|
||||
oper_assign<T>(m);
|
||||
operators::assign<T>(m);
|
||||
oper_assign_pod<T>(m);
|
||||
construct_pod<T>(name, m);
|
||||
opers_arithmetic<T>(m);
|
||||
opers_arithmetic_modify_pod<T>(m);
|
||||
|
||||
m->add(fun(&detail::assign_sum_pod<T>), "+=");
|
||||
m->add(fun(&detail::assign_difference_pod<T>), "-=");
|
||||
m->add(fun(&detail::assign_product_pod<T>), "*=");
|
||||
m->add(fun(&detail::assign_quotient_pod<T>), "/=");
|
||||
|
||||
m->add(fun(&to_string<T>), "to_string");
|
||||
m->add(fun(&parse_string<T>), "to_" + name);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_integer_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
bootstrap_pod_type<T>(name, m);
|
||||
|
||||
m->add(fun(&detail::assign_bitwise_and_pod<T>), "&=");
|
||||
m->add(fun(&detail::assign_xor_pod<T>), "^=");
|
||||
m->add(fun(&detail::assign_bitwise_or_pod<T>), "|=");
|
||||
m->add(fun(&detail::assign_left_shift_pod<T>), "<<=");
|
||||
m->add(fun(&detail::assign_remainder_pod<T>), "%=");
|
||||
m->add(fun(&detail::assign_right_shift_pod<T>), ">>=");
|
||||
|
||||
opers_integer_arithmetic<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
*/
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_float_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
bootstrap_pod_type<T>(name, m);
|
||||
opers_float_arithmetic<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* "clone" function for a shared_ptr type. This is used in the case
|
||||
* where you do not want to make a deep copy of an object during cloning
|
||||
@@ -546,7 +385,7 @@ namespace chaiscript
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<typename boost::add_const<Type>::type> &rhs)
|
||||
{
|
||||
if (lhs.is_unknown()
|
||||
if (lhs.is_undef()
|
||||
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
|
||||
{
|
||||
lhs.assign(Boxed_Value(rhs));
|
||||
@@ -568,7 +407,7 @@ namespace chaiscript
|
||||
*/
|
||||
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs)
|
||||
{
|
||||
if (lhs.is_unknown())
|
||||
if (lhs.is_undef())
|
||||
{
|
||||
return (lhs.assign(rhs));
|
||||
} else {
|
||||
@@ -586,28 +425,21 @@ namespace chaiscript
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all comparison operators for POD types
|
||||
*/
|
||||
static void opers_comparison_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::equals<Boxed_POD_Value, Boxed_POD_Value>), "==");
|
||||
m->add(fun(&detail::not_equals<Boxed_POD_Value, Boxed_POD_Value>), "!=");
|
||||
m->add(fun(&detail::less_than<Boxed_POD_Value, Boxed_POD_Value>), "<");
|
||||
m->add(fun(&detail::greater_than<Boxed_POD_Value, Boxed_POD_Value>), ">");
|
||||
m->add(fun(&detail::less_than_equals<Boxed_POD_Value, Boxed_POD_Value>), "<=");
|
||||
m->add(fun(&detail::greater_than_equals<Boxed_POD_Value, Boxed_POD_Value>), ">=");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all arithmetic operators for PODs
|
||||
*/
|
||||
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&detail::add<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
|
||||
m->add(fun(&detail::subtract<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
|
||||
m->add(fun(&detail::divide<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
|
||||
m->add(fun(&detail::multiply<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
|
||||
m->add(fun(&operators::addition<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "+");
|
||||
m->add(fun(&operators::subtraction<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "-");
|
||||
m->add(fun(&operators::bitwise_and<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "&");
|
||||
m->add(fun(&operators::bitwise_xor<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "^");
|
||||
m->add(fun(&operators::bitwise_or<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "|");
|
||||
m->add(fun(&operators::division<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "/");
|
||||
m->add(fun(&operators::left_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "<<");
|
||||
m->add(fun(&operators::multiplication<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "*");
|
||||
m->add(fun(&operators::remainder<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), "%");
|
||||
m->add(fun(&operators::right_shift<Boxed_Value, Boxed_POD_Value, Boxed_POD_Value>), ">>");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -696,10 +528,31 @@ namespace chaiscript
|
||||
m->add(fun(&Dynamic_Object::get_attr), "get_attr");
|
||||
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
|
||||
|
||||
m->add(fun(&Boxed_Value::is_undef), "is_var_undef");
|
||||
m->add(fun(&Boxed_Value::is_null), "is_var_null");
|
||||
m->add(fun(&Boxed_Value::is_const), "is_var_const");
|
||||
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
||||
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
||||
m->add(fun(&Boxed_Value::is_type), "is_type");
|
||||
|
||||
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
||||
m->add(user_type<Type_Info>(), "Type_Info");
|
||||
|
||||
|
||||
operators::equal<Type_Info>(m);
|
||||
|
||||
m->add(fun(&Type_Info::is_const), "is_type_const");
|
||||
m->add(fun(&Type_Info::is_reference), "is_type_reference");
|
||||
m->add(fun(&Type_Info::is_void), "is_type_void");
|
||||
m->add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||
m->add(fun(&Type_Info::name), "cpp_name");
|
||||
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
|
||||
|
||||
basic_constructors<bool>("bool", m);
|
||||
oper_assign<std::string>(m);
|
||||
oper_assign<bool>(m);
|
||||
operators::assign<bool>(m);
|
||||
|
||||
m->add(fun(&to_string<const std::string &>), "internal_to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "internal_to_string");
|
||||
@@ -707,16 +560,17 @@ namespace chaiscript
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
m->add(fun(&what), "what");
|
||||
|
||||
bootstrap_pod_type<double>("double", m);
|
||||
bootstrap_pod_type<int>("int", m);
|
||||
bootstrap_pod_type<size_t>("size_t", m);
|
||||
bootstrap_pod_type<char>("char", m);
|
||||
bootstrap_pod_type<boost::int64_t>("int64_t", m);
|
||||
bootstrap_float_type<double>("double", m);
|
||||
bootstrap_integer_type<int>("int", m);
|
||||
bootstrap_integer_type<size_t>("size_t", m);
|
||||
bootstrap_integer_type<char>("char", m);
|
||||
bootstrap_integer_type<boost::int64_t>("int64_t", m);
|
||||
|
||||
opers_comparison_pod(m);
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
opers_comparison<Boxed_POD_Value>(m);
|
||||
opers_arithmetic_pod(m);
|
||||
|
||||
m->add(fun(&detail::modulus<int, int, int>), "%");
|
||||
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
@@ -122,24 +122,13 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
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,
|
||||
@@ -158,7 +147,7 @@ namespace chaiscript
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
basic_constructors<ContainerType>(type, m);
|
||||
oper_assign<ContainerType>(m);
|
||||
operators::assign<ContainerType>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -167,30 +156,15 @@ namespace chaiscript
|
||||
* http://www.sgi.com/tech/stl/Container.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
assignable_type<ContainerType>(type, m);
|
||||
|
||||
m->add(fun<size_t (ContainerType::*)() const>(&ContainerType::size), "size");
|
||||
m->add(fun(boost::function<int (const ContainerType *)>(&ContainerType::size)), "size");
|
||||
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
|
||||
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -243,11 +217,8 @@ namespace chaiscript
|
||||
* http://www.sgi.com/tech/stl/Sequence.html
|
||||
*/
|
||||
template<typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
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))
|
||||
{
|
||||
@@ -267,11 +238,8 @@ namespace chaiscript
|
||||
* 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()))
|
||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
sequence_type<ContainerType>(type, m);
|
||||
|
||||
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
@@ -297,8 +265,6 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
sequence_type<ContainerType>(type, m);
|
||||
|
||||
typedef typename ContainerType::reference (ContainerType::*frontptr)();
|
||||
|
||||
m->add(fun(static_cast<frontptr>(&ContainerType::front)), "front");
|
||||
@@ -315,44 +281,6 @@ namespace chaiscript
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* hopefully working List type
|
||||
* http://www.sgi.com/tech/stl/List.html
|
||||
*/
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<ListType>(), type);
|
||||
front_insertion_sequence_type<ListType>(type, m);
|
||||
back_insertion_sequence_type<ListType>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
m->add(user_type<VectorType>(), type);
|
||||
random_access_container_type<VectorType>(type, m);
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
forward_container_type<ContainerType>(type, m);
|
||||
default_constructible_type<ContainerType>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* bootstrap a given PairType
|
||||
* http://www.sgi.com/tech/stl/pair.html
|
||||
@@ -379,7 +307,6 @@ namespace chaiscript
|
||||
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;
|
||||
@@ -390,39 +317,10 @@ namespace chaiscript
|
||||
* 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()))
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
associative_container_type<ContainerType>(type, m);
|
||||
m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&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 &);
|
||||
|
||||
reversible_container_type<ContainerType>(type, m);
|
||||
associative_container_type<ContainerType>(type, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
sorted_associative_container_type<ContainerType>(type, m);
|
||||
unique_associative_container_type<ContainerType>(type, m);
|
||||
// m->add(fun<size_t (ContainerType::*)(const typename ContainerType::key_type &) const>(&ContainerType::count), "count");
|
||||
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count)), "count");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -436,12 +334,57 @@ namespace chaiscript
|
||||
{
|
||||
m->add(user_type<MapType>(), type);
|
||||
m->add(fun(&MapType::operator[]), "[]");
|
||||
unique_sorted_associative_container_type<MapType>(type, m);
|
||||
|
||||
container_type<MapType>(type, m);
|
||||
assignable_type<MapType>(type, m);
|
||||
unique_associative_container_type<MapType>(type, m);
|
||||
pair_associative_container_type<MapType>(type, m);
|
||||
input_range_type<MapType>(type, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* hopefully working List type
|
||||
* http://www.sgi.com/tech/stl/List.html
|
||||
*/
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<ListType>(), type);
|
||||
|
||||
front_insertion_sequence_type<ListType>(type, m);
|
||||
back_insertion_sequence_type<ListType>(type, m);
|
||||
sequence_type<ListType>(type, m);
|
||||
container_type<ListType>(type, m);
|
||||
default_constructible_type<ListType>(type, m);
|
||||
assignable_type<ListType>(type, m);
|
||||
input_range_type<ListType>(type, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
m->add(user_type<VectorType>(), type);
|
||||
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
sequence_type<VectorType>(type, m);
|
||||
random_access_container_type<VectorType>(type, m);
|
||||
container_type<VectorType>(type, m);
|
||||
default_constructible_type<VectorType>(type, m);
|
||||
assignable_type<VectorType>(type, m);
|
||||
input_range_type<VectorType>(type, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a String container
|
||||
* http://www.sgi.com/tech/stl/basic_string.html
|
||||
@@ -450,11 +393,15 @@ namespace chaiscript
|
||||
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);
|
||||
operators::addition<String>(m);
|
||||
operators::assign_sum<String>(m);
|
||||
opers_comparison<String>(m);
|
||||
random_access_container_type<String>(type, m);
|
||||
sequence_type<String>(type, m);
|
||||
default_constructible_type<String>(type, m);
|
||||
container_type<String>(type, m);
|
||||
assignable_type<String>(type, m);
|
||||
input_range_type<String>(type, m);
|
||||
|
||||
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||
std::string push_back_name;
|
||||
@@ -466,13 +413,16 @@ namespace chaiscript
|
||||
}
|
||||
m->add(fun(&String::push_back), push_back_name);
|
||||
|
||||
typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const;
|
||||
m->add(fun(static_cast<find_func>(&String::find)), "find");
|
||||
m->add(fun(static_cast<find_func>(&String::rfind)), "rfind");
|
||||
m->add(fun(static_cast<find_func>(&String::find_first_of)), "find_first_of");
|
||||
m->add(fun(static_cast<find_func>(&String::find_last_of)), "find_last_of");
|
||||
m->add(fun(static_cast<find_func>(&String::find_first_not_of)), "find_first_not_of");
|
||||
m->add(fun(static_cast<find_func>(&String::find_last_not_of)), "find_last_not_of");
|
||||
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
|
||||
|
||||
typedef boost::function<int (const String *, const String &, int)> find_func;
|
||||
|
||||
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find))), "find");
|
||||
m->add(fun(find_func(static_cast<find_func_ptr>(&String::rfind))), "rfind");
|
||||
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_of))), "find_first_of");
|
||||
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_of))), "find_last_of");
|
||||
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_first_not_of))), "find_first_not_of");
|
||||
m->add(fun(find_func(static_cast<find_func_ptr>(&String::find_last_not_of))), "find_last_not_of");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -42,49 +43,27 @@ namespace chaiscript
|
||||
*/
|
||||
struct Data
|
||||
{
|
||||
/**
|
||||
* used to provide type-erased access to the internal boost::shared_ptr
|
||||
* reference count information
|
||||
*/
|
||||
struct Shared_Ptr_Proxy
|
||||
{
|
||||
virtual ~Shared_Ptr_Proxy()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool unique(boost::any *) = 0;
|
||||
virtual long use_count(boost::any *) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Typed implementation of the Shared_Ptr_Proxy
|
||||
*/
|
||||
template<typename T>
|
||||
struct Shared_Ptr_Proxy_Impl : Shared_Ptr_Proxy
|
||||
{
|
||||
virtual ~Shared_Ptr_Proxy_Impl()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool unique(boost::any *a)
|
||||
static bool unique(boost::any *a)
|
||||
{
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
|
||||
return ptr->unique();
|
||||
}
|
||||
|
||||
virtual long use_count(boost::any *a)
|
||||
template<typename T>
|
||||
static bool is_null(boost::any *a)
|
||||
{
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(a);
|
||||
return ptr->use_count();
|
||||
return ptr->get() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
Data(const Type_Info &ti,
|
||||
const boost::any &to,
|
||||
bool tr,
|
||||
const boost::shared_ptr<Shared_Ptr_Proxy> &t_proxy = boost::shared_ptr<Shared_Ptr_Proxy>())
|
||||
const boost::function<bool (boost::any*)> &t_unique = boost::function<bool (boost::any*)>(),
|
||||
const boost::function<bool (boost::any*)> &t_is_null = boost::function<bool (boost::any*)>())
|
||||
: m_type_info(ti), m_obj(to),
|
||||
m_is_ref(tr), m_ptr_proxy(t_proxy)
|
||||
m_is_ref(tr), m_unique(t_unique), m_is_null(t_is_null)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -93,7 +72,8 @@ namespace chaiscript
|
||||
m_type_info = rhs.m_type_info;
|
||||
m_obj = rhs.m_obj;
|
||||
m_is_ref = rhs.m_is_ref;
|
||||
m_ptr_proxy = rhs.m_ptr_proxy;
|
||||
m_unique = rhs.m_unique;
|
||||
m_is_null = rhs.m_is_null;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -101,7 +81,8 @@ namespace chaiscript
|
||||
Type_Info m_type_info;
|
||||
boost::any m_obj;
|
||||
bool m_is_ref;
|
||||
boost::shared_ptr<Shared_Ptr_Proxy> m_ptr_proxy;
|
||||
boost::function<bool (boost::any*)> m_unique;
|
||||
boost::function<bool (boost::any*)> m_is_null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -141,7 +122,8 @@ namespace chaiscript
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(obj),
|
||||
false,
|
||||
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
||||
&Data::unique<T>,
|
||||
&Data::is_null<T>)
|
||||
);
|
||||
|
||||
std::map<std::pair<const void *, bool>, Data>::iterator itr
|
||||
@@ -200,7 +182,8 @@ namespace chaiscript
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(boost::shared_ptr<T>(new T(t))),
|
||||
false,
|
||||
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
|
||||
&Data::unique<T>,
|
||||
&Data::is_null<T>)
|
||||
);
|
||||
|
||||
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj);
|
||||
@@ -226,7 +209,7 @@ namespace chaiscript
|
||||
{
|
||||
|
||||
++m_cullcount;
|
||||
if (force || m_cullcount % 10 != 0)
|
||||
if (force || m_cullcount % 20 != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -236,7 +219,7 @@ namespace chaiscript
|
||||
|
||||
while (itr != m_ptrs.end())
|
||||
{
|
||||
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
|
||||
if (itr->second.m_unique(&itr->second.m_obj))
|
||||
{
|
||||
std::map<std::pair<const void *, bool>, Data >::iterator todel = itr;
|
||||
++itr;
|
||||
@@ -247,7 +230,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::pair<const void *, bool>, Data > m_ptrs;
|
||||
std::map<std::pair<const void *, bool>, Data> m_ptrs;
|
||||
int m_cullcount;
|
||||
};
|
||||
|
||||
@@ -282,6 +265,11 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
void swap(Boxed_Value &rhs)
|
||||
{
|
||||
std::swap(m_data, rhs.m_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to the static global Object_Cache
|
||||
*/
|
||||
@@ -311,7 +299,8 @@ namespace chaiscript
|
||||
*/
|
||||
Boxed_Value &operator=(const Boxed_Value &rhs)
|
||||
{
|
||||
m_data = rhs.m_data;
|
||||
Boxed_Value temp(rhs);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -323,9 +312,29 @@ namespace chaiscript
|
||||
/**
|
||||
* return true if the object is uninitialized
|
||||
*/
|
||||
bool is_unknown() const
|
||||
bool is_undef() const
|
||||
{
|
||||
return m_data->m_type_info.is_unknown();
|
||||
return m_data->m_type_info.is_undef();
|
||||
}
|
||||
|
||||
bool is_const() const
|
||||
{
|
||||
return m_data->m_type_info.is_const();
|
||||
}
|
||||
|
||||
bool is_type(const Type_Info &ti) const
|
||||
{
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (m_data->m_is_null)
|
||||
{
|
||||
return m_data->m_is_null(&m_data->m_obj);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boost::any get() const
|
||||
@@ -338,6 +347,12 @@ namespace chaiscript
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
|
||||
bool is_pointer() const
|
||||
{
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
boost::shared_ptr<Data> m_data;
|
||||
};
|
||||
@@ -624,7 +639,7 @@ namespace chaiscript
|
||||
Boxed_POD_Value(const Boxed_Value &v)
|
||||
: d(0), i(0), m_isfloat(false)
|
||||
{
|
||||
if (v.get_type_info().is_unknown())
|
||||
if (v.get_type_info().is_undef())
|
||||
{
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
@@ -703,42 +718,117 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i + r.i);
|
||||
return smart_size(i + r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator*(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i * r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator/(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i / r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator-(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i - r.i);
|
||||
return smart_size(i - r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator&(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i & r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("& only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator^(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i ^ r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("^ only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator|(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return Boxed_Value(i | r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("| only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator/(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i / r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
Boxed_Value operator<<(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i << r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("<< only valid for integer types");
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value operator*(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i * r.i);
|
||||
}
|
||||
|
||||
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
|
||||
}
|
||||
|
||||
|
||||
Boxed_Value operator%(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i % r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast("% only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value operator>>(const Boxed_POD_Value &r) const
|
||||
{
|
||||
if (!m_isfloat && !r.m_isfloat)
|
||||
{
|
||||
return smart_size(i >> r.i);
|
||||
}
|
||||
|
||||
throw bad_boxed_cast(">> only valid for integer types");
|
||||
}
|
||||
|
||||
Boxed_Value smart_size(boost::int64_t i) const
|
||||
{
|
||||
if (i < std::numeric_limits<int>::min()
|
||||
|| i > std::numeric_limits<int>::max())
|
||||
{
|
||||
return Boxed_Value(i);
|
||||
} else {
|
||||
return Boxed_Value(static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double d;
|
||||
boost::int64_t i;
|
||||
|
||||
@@ -755,6 +845,20 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_POD_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return Boxed_POD_Value(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_POD_Value &>
|
||||
{
|
||||
typedef Boxed_POD_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return Boxed_POD_Value(ob);
|
||||
@@ -799,7 +903,14 @@ namespace chaiscript
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<> void swap(chaiscript::Boxed_Value &lhs, chaiscript::Boxed_Value &rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "type_info.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "../chaiscript_threading.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -42,6 +43,7 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//Add a bit of chaiscript to eval during module implementation
|
||||
Module &eval(const std::string &str)
|
||||
{
|
||||
@@ -49,6 +51,11 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const boost::shared_ptr<Module> &m)
|
||||
{
|
||||
m->apply(*this, *this);
|
||||
return *m;
|
||||
}
|
||||
|
||||
template<typename Eval, typename Engine>
|
||||
void apply(Eval &t_eval, Engine &t_engine) const
|
||||
@@ -165,6 +172,19 @@ namespace chaiscript
|
||||
virtual ~reserved_word_error() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that a non-const object was added as a shared object
|
||||
*/
|
||||
struct global_non_const : std::runtime_error
|
||||
{
|
||||
global_non_const() throw()
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() throw() {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Main class for the dispatchkit. Handles management
|
||||
@@ -178,6 +198,14 @@ namespace chaiscript
|
||||
typedef boost::tuples::tuple<std::map<std::string, Boxed_Value>, std::deque<Scope>, bool> StackData;
|
||||
typedef boost::shared_ptr<StackData> Stack;
|
||||
|
||||
struct State
|
||||
{
|
||||
std::multimap<std::string, Proxy_Function> m_functions;
|
||||
std::map<std::string, Boxed_Value> m_global_objects;
|
||||
Type_Name_Map m_types;
|
||||
std::set<std::string> m_reserved_words;
|
||||
};
|
||||
|
||||
Dispatch_Engine()
|
||||
: m_place_holder(boost::shared_ptr<Placeholder_Object>(new Placeholder_Object()))
|
||||
{
|
||||
@@ -237,19 +265,24 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new shared object, between all the threads
|
||||
* Adds a new global shared object, between all the threads
|
||||
*/
|
||||
void add_shared_object(const Boxed_Value &obj, const std::string &name)
|
||||
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
if (!obj.is_const())
|
||||
{
|
||||
throw global_non_const();
|
||||
}
|
||||
|
||||
stack.get<0>().erase(name);
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_shared_object_mutex);
|
||||
boost::unique_lock<boost::shared_mutex> l(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
m_shared_objects[name] = obj;
|
||||
m_state.m_global_objects[name] = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +348,7 @@ namespace chaiscript
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
get_function_cache() = m_functions;
|
||||
get_function_cache() = m_state.m_functions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,23 +377,22 @@ namespace chaiscript
|
||||
// Is it in the stack?
|
||||
for (int i = stack.get<1>().size()-1; i >= 0; --i)
|
||||
{
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = (stack.get<1>())[i].find(name);
|
||||
if (itr != (stack.get<1>())[i].end())
|
||||
std::map<std::string, Boxed_Value>::const_iterator stackitr = (stack.get<1>())[i].find(name);
|
||||
if (stackitr != (stack.get<1>())[i].end())
|
||||
{
|
||||
cache[name] = itr->second;
|
||||
return itr->second;
|
||||
cache[name] = stackitr->second;
|
||||
return stackitr->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Are we in the 0th stack and should check the shared objects?
|
||||
if (stack.get<2>())
|
||||
// Is the value we are looking for a global?
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_shared_object_mutex);
|
||||
boost::shared_lock<boost::shared_mutex> l(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
itr = m_shared_objects.find(name);
|
||||
if (itr != m_shared_objects.end())
|
||||
itr = m_state.m_global_objects.find(name);
|
||||
if (itr != m_state.m_global_objects.end())
|
||||
{
|
||||
cache[name] = itr->second;
|
||||
return itr->second;
|
||||
@@ -385,11 +417,13 @@ namespace chaiscript
|
||||
*/
|
||||
void add(const Type_Info &ti, const std::string &name)
|
||||
{
|
||||
add_global_const(const_var(ti), name + "_type");
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
m_types.insert(std::make_pair(name, ti));
|
||||
m_state.m_types.insert(std::make_pair(name, ti));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,9 +435,9 @@ namespace chaiscript
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
Type_Name_Map::const_iterator itr = m_types.find(name);
|
||||
Type_Name_Map::const_iterator itr = m_state.m_types.find(name);
|
||||
|
||||
if (itr != m_types.end())
|
||||
if (itr != m_state.m_types.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
@@ -422,8 +456,8 @@ namespace chaiscript
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
for (Type_Name_Map::const_iterator itr = m_types.begin();
|
||||
itr != m_types.end();
|
||||
for (Type_Name_Map::const_iterator itr = m_state.m_types.begin();
|
||||
itr != m_state.m_types.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->second.bare_equal(ti))
|
||||
@@ -444,7 +478,7 @@ namespace chaiscript
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
return std::vector<std::pair<std::string, Type_Info> >(m_types.begin(), m_types.end());
|
||||
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -483,7 +517,7 @@ namespace chaiscript
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
m_reserved_words.insert(name);
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
@@ -495,6 +529,26 @@ namespace chaiscript
|
||||
return dispatch(range.first, range.second, params);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name) const
|
||||
{
|
||||
return call_function(t_name, std::vector<Boxed_Value>());
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1) const
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
params.push_back(p1);
|
||||
return call_function(t_name, params);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1, const Boxed_Value &p2) const
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
params.push_back(p1);
|
||||
params.push_back(p2);
|
||||
return call_function(t_name, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object info to stdout
|
||||
*/
|
||||
@@ -574,13 +628,23 @@ namespace chaiscript
|
||||
/**
|
||||
* return true if the Boxed_Value matches the registered type by name
|
||||
*/
|
||||
bool is_type(const std::string &user_typename, Boxed_Value r) const
|
||||
bool is_type(Boxed_Value r, const std::string &user_typename) const
|
||||
{
|
||||
try {
|
||||
return get_type(user_typename) == r.get_type_info();
|
||||
} catch (const std::range_error &) {
|
||||
return false;
|
||||
if (get_type(user_typename).bare_equal(r.get_type_info()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} catch (const std::range_error &) {
|
||||
}
|
||||
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(r);
|
||||
return d.get_type_name() == user_typename;
|
||||
} catch (const std::bad_cast &) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string type_name(Boxed_Value obj) const
|
||||
@@ -588,6 +652,26 @@ namespace chaiscript
|
||||
return get_type_name(obj.get_type_info());
|
||||
}
|
||||
|
||||
State get_state()
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void set_state(const State &t_state)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
boost::unique_lock<boost::shared_mutex> l2(m_global_object_mutex);
|
||||
#endif
|
||||
|
||||
m_state = t_state;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -614,7 +698,7 @@ namespace chaiscript
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
if (m_reserved_words.find(name) != m_reserved_words.end())
|
||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
||||
{
|
||||
throw reserved_word_error(name);
|
||||
}
|
||||
@@ -632,7 +716,7 @@ namespace chaiscript
|
||||
#endif
|
||||
|
||||
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
||||
= m_functions.equal_range(t_name);
|
||||
= m_state.m_functions.equal_range(t_name);
|
||||
|
||||
while (range.first != range.second)
|
||||
{
|
||||
@@ -643,7 +727,7 @@ namespace chaiscript
|
||||
++range.first;
|
||||
}
|
||||
|
||||
m_functions.insert(std::make_pair(t_name, f));
|
||||
m_state.m_functions.insert(std::make_pair(t_name, f));
|
||||
get_function_cache().insert(std::make_pair(t_name, f));
|
||||
|
||||
return true;
|
||||
@@ -651,7 +735,7 @@ namespace chaiscript
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
mutable boost::shared_mutex m_mutex;
|
||||
mutable boost::shared_mutex m_shared_object_mutex;
|
||||
mutable boost::shared_mutex m_global_object_mutex;
|
||||
#endif
|
||||
|
||||
struct Stack_Holder
|
||||
@@ -670,13 +754,9 @@ namespace chaiscript
|
||||
chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
|
||||
std::multimap<std::string, Proxy_Function> m_functions;
|
||||
std::map<std::string, Boxed_Value> m_shared_objects;
|
||||
State m_state;
|
||||
|
||||
Type_Name_Map m_types;
|
||||
Boxed_Value m_place_holder;
|
||||
|
||||
std::set<std::string> m_reserved_words;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -47,6 +47,16 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret &>
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
@@ -57,6 +67,11 @@ namespace chaiscript
|
||||
{
|
||||
return Boxed_Value(boost::ref(r));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -83,6 +98,19 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
template<>
|
||||
struct Handle_Return<const Boxed_Value &>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used internally for handling a return value from a Proxy_Function call
|
||||
*/
|
||||
|
442
include/chaiscript/dispatchkit/operators.hpp
Normal file
442
include/chaiscript/dispatchkit/operators.hpp
Normal file
@@ -0,0 +1,442 @@
|
||||
#ifndef __CHAISCRIPT_OPERATORS_HPP__
|
||||
#define __CHAISCRIPT_OPERATORS_HPP__
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace operators
|
||||
{
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign(L l, R r)
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_bitwise_and(L l, R r)
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_xor(L l, R r)
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_bitwise_or(L l, R r)
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_difference(L l, R r)
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_left_shift(L l, R r)
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_product(L l, R r)
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_quotient(L l, R r)
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_remainder(L l, R r)
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_right_shift(L l, R r)
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_sum(L l, R r)
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret prefix_decrement(L l)
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret prefix_increment(L l)
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret equal(L l, R r)
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret greater_than(L l, R r)
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret greater_than_equal(L l, R r)
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret less_than(L l, R r)
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret less_than_equal(L l, R r)
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret logical_compliment(L l)
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret not_equal(L l, R r)
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret addition(L l, R r)
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_plus(L l)
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret subtraction(L l, R r)
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_minus(L l)
|
||||
{
|
||||
return (-l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_and(L l, R r)
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret bitwise_compliment(L l)
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_xor(L l, R r)
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_or(L l, R r)
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret division(L l, R r)
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret left_shift(L l, R r)
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret multiplication(L l, R r)
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret remainder(L l, R r)
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret right_shift(L l, R r)
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign<T &, T &, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&prefix_decrement<T &, T &>), "--");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&prefix_increment<T &, T &>), "++");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&equal<bool, const T&, const T&>), "==");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&less_than<bool, const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&logical_compliment<bool, const T &>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(¬_equal<bool, const T &, const T &>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&addition<T, const T &, const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&unary_plus<T, const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&subtraction<T, const T &, const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&unary_minus<T, const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_compliment<T, const T &>), "~");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&division<T, const T &, const T &>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&multiplication<T, const T &, const T &>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&remainder<T, const T &, const T &>), "%");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -13,6 +13,7 @@
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include "proxy_functions_detail.hpp"
|
||||
@@ -92,7 +93,8 @@ namespace chaiscript
|
||||
|
||||
const Type_Info &ti = types[1];
|
||||
|
||||
if (ti.is_unknown() || vals[0].get_type_info().is_unknown()
|
||||
|
||||
if (ti.is_undef() || vals[0].get_type_info().is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
|| ti.bare_equal(user_type<Boxed_POD_Value>())
|
||||
|| ti.bare_equal(vals[0].get_type_info()))
|
||||
@@ -359,7 +361,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl(const boost::function<Func> &f)
|
||||
: Proxy_Function_Base(build_param_type_list((Func *)(0))),
|
||||
: Proxy_Function_Base(build_param_type_list(static_cast<Func *>(0))),
|
||||
m_f(f), m_dummy_func(0)
|
||||
{
|
||||
}
|
||||
@@ -407,6 +409,81 @@ namespace chaiscript
|
||||
Func *m_dummy_func;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute getter Proxy_Function implementation
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
class Attribute_Access : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &t_func) const
|
||||
{
|
||||
try {
|
||||
const Attribute_Access<T, Class> &aa
|
||||
= dynamic_cast<const Attribute_Access<T, Class> &>(t_func);
|
||||
return m_attr == aa.m_attr;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
const Boxed_Value &bv = params[0];
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv);
|
||||
return Handle_Return<const typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv);
|
||||
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
}
|
||||
} else {
|
||||
throw arity_error(params.size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||
}
|
||||
|
||||
virtual std::string annotation() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> param_types()
|
||||
{
|
||||
std::vector<Type_Info> v;
|
||||
v.push_back(user_type<T>());
|
||||
v.push_back(user_type<Class>());
|
||||
return v;
|
||||
}
|
||||
T Class::* m_attr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that a multi method dispatch fails
|
||||
* because no matching function was found
|
||||
@@ -420,6 +497,11 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
dispatch_error(bool is_const) throw()
|
||||
: std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":""))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dispatch_error() throw() {}
|
||||
};
|
||||
|
||||
@@ -450,7 +532,7 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
|
||||
throw dispatch_error();
|
||||
throw dispatch_error(plist.empty()?false:plist[0].is_const());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -4,99 +4,74 @@
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef __register_function_hpp__
|
||||
#define __register_function_hpp__
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "bind_first.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function_types/components.hpp>
|
||||
#include <boost/function_types/function_type.hpp>
|
||||
#include <boost/function_types/is_member_object_pointer.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Helper function for register_member function
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
T &get_member(T Class::* m, Class *obj)
|
||||
template<bool Object>
|
||||
struct Fun_Helper
|
||||
{
|
||||
return (obj->*m);
|
||||
template<typename T>
|
||||
static Proxy_Function go(T t)
|
||||
{
|
||||
return Proxy_Function(
|
||||
new Proxy_Function_Impl<
|
||||
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
|
||||
boost::function<
|
||||
typename boost::function_types::function_type<boost::function_types::components<T> >::type
|
||||
>(t)));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Fun_Helper<true>
|
||||
{
|
||||
template<typename T, typename Class>
|
||||
static Proxy_Function go(T Class::* m)
|
||||
{
|
||||
return Proxy_Function(new Attribute_Access<T, Class>(m));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Proxy_Function fun_helper(const boost::function<T> &f)
|
||||
Proxy_Function fun(const boost::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically create a get_member helper function for an object
|
||||
* to allow for runtime dispatched access to public data members
|
||||
* for example, the case of std::pair<>::first and std::pair<>::second
|
||||
*/
|
||||
template<typename T, typename Class>
|
||||
Proxy_Function fun_helper(T Class::* m)
|
||||
{
|
||||
return fun_helper(boost::function<T& (Class *)>(boost::bind(&detail::get_member<T, Class>, m, _1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
template<typename T>
|
||||
Proxy_Function fun(T t)
|
||||
{
|
||||
return detail::fun_helper(t);
|
||||
return detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value>::go(t);
|
||||
}
|
||||
|
||||
template<typename T, typename Q>
|
||||
Proxy_Function fun(T t, const Q &q)
|
||||
{
|
||||
return fun(bind_first(t, q));
|
||||
}
|
||||
|
||||
template<typename T, typename Q, typename R>
|
||||
Proxy_Function fun(T t, const Q &q, const R &r)
|
||||
{
|
||||
return fun(bind_first(bind_first(t, q), r));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Register a global function of n parameters with name
|
||||
*/
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun_helper(boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a class method of n parameters with name
|
||||
*/
|
||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return fun_helper(boost::function<Ret (Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a const class method of n parameters with name
|
||||
*/
|
||||
template<typename Ret, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Proxy_Function fun_helper(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param))const)
|
||||
{
|
||||
return fun_helper(boost::function<Ret (const Class* BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param))>(f));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -29,14 +29,14 @@ namespace chaiscript
|
||||
: m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
||||
m_is_void(t_is_void),
|
||||
m_type_info(t_ti), m_bare_type_info(t_bareti),
|
||||
m_is_unknown(false)
|
||||
m_is_undef(false)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info()
|
||||
: m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||
m_is_void(false), m_type_info(0), m_bare_type_info(0),
|
||||
m_is_unknown(true)
|
||||
m_is_undef(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace chaiscript
|
||||
m_is_pointer(ti.m_is_pointer),
|
||||
m_is_void(ti.m_is_void), m_type_info(ti.m_type_info),
|
||||
m_bare_type_info(ti.m_bare_type_info),
|
||||
m_is_unknown(ti.m_is_unknown)
|
||||
m_is_undef(ti.m_is_undef)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace chaiscript
|
||||
m_is_void = ti.m_is_void;
|
||||
m_type_info = ti.m_type_info;
|
||||
m_bare_type_info = ti.m_bare_type_info;
|
||||
m_is_unknown = ti.m_is_unknown;
|
||||
m_is_undef = ti.m_is_undef;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,18 @@ namespace chaiscript
|
||||
bool is_const() const { return m_is_const; }
|
||||
bool is_reference() const { return m_is_reference; }
|
||||
bool is_void() const { return m_is_void; }
|
||||
bool is_unknown() const { return m_is_unknown || m_bare_type_info == 0; }
|
||||
bool is_undef() const { return m_is_undef || m_bare_type_info == 0; }
|
||||
bool is_pointer() const { return m_is_pointer; }
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
if (m_type_info)
|
||||
{
|
||||
return m_type_info->name();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bare_name() const
|
||||
{
|
||||
@@ -105,7 +116,7 @@ namespace chaiscript
|
||||
bool m_is_void;
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
bool m_is_unknown;
|
||||
bool m_is_undef;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
|
137
include/chaiscript/language/chaiscript_common.hpp
Normal file
137
include/chaiscript/language/chaiscript_common.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org)
|
||||
// and Jason Turner (lefticus@gmail.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef _CHAISCRIPT_COMMON_HPP
|
||||
#define _CHAISCRIPT_COMMON_HPP
|
||||
|
||||
|
||||
#ifdef BOOST_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
typedef ModulePtr (*Create_Module_Func)();
|
||||
|
||||
/**
|
||||
* Types of AST nodes available to the parser and eval
|
||||
*/
|
||||
class Token_Type { public: enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Inplace_Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Comparison, Additive, Multiplicative, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or}; };
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* Helper lookup to get the name of each node type
|
||||
*/
|
||||
const char *token_type_to_string(int tokentype) {
|
||||
const char *token_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Inplace_Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Comparison", "Additive", "Multiplicative", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or"};
|
||||
|
||||
return token_types[tokentype];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience type for file positions
|
||||
*/
|
||||
struct File_Position {
|
||||
int line;
|
||||
int column;
|
||||
|
||||
File_Position(int file_line, int file_column)
|
||||
: line(file_line), column(file_column) { }
|
||||
|
||||
File_Position() : line(0), column(0) { }
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<struct Token> TokenPtr;
|
||||
|
||||
/**
|
||||
* The struct that doubles as both a parser token and an AST node
|
||||
*/
|
||||
struct Token {
|
||||
std::string text;
|
||||
int identifier;
|
||||
const char *filename;
|
||||
File_Position start, end;
|
||||
bool is_cached;
|
||||
Boxed_Value cached_value;
|
||||
|
||||
std::vector<TokenPtr> children;
|
||||
TokenPtr annotation;
|
||||
|
||||
Token(const std::string &token_text, int id, const char *fname) :
|
||||
text(token_text), identifier(id), filename(fname), is_cached(false) { }
|
||||
|
||||
Token(const std::string &token_text, int id, const char *fname, int start_line, int start_col, int end_line, int end_col) :
|
||||
text(token_text), identifier(id), filename(fname), is_cached(false) {
|
||||
|
||||
start.line = start_line;
|
||||
start.column = start_col;
|
||||
end.line = end_line;
|
||||
end.column = end_col;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors generated during parsing or evaluation
|
||||
*/
|
||||
struct Eval_Error : public std::runtime_error {
|
||||
std::string reason;
|
||||
File_Position start_position;
|
||||
File_Position end_position;
|
||||
const char *filename;
|
||||
|
||||
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), start_position(where), end_position(where), filename(fname)
|
||||
{ }
|
||||
|
||||
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), start_position(where->start), end_position(where->end), filename(where->filename) {
|
||||
}
|
||||
|
||||
virtual ~Eval_Error() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type for returned values
|
||||
*/
|
||||
struct Return_Value {
|
||||
Boxed_Value retval;
|
||||
TokenPtr location;
|
||||
|
||||
Return_Value(const Boxed_Value &return_value, const TokenPtr where) : retval(return_value), location(where) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type indicating a call to 'break'
|
||||
*/
|
||||
struct Break_Loop {
|
||||
TokenPtr location;
|
||||
|
||||
Break_Loop(const TokenPtr where) : location(where) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CHAISCRIPT_COMMON_HPP */
|
||||
|
@@ -10,6 +10,8 @@
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
|
||||
#include <chaiscript/language/chaiscript_common.hpp>
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
@@ -18,8 +20,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "chaiscript_prelude.hpp"
|
||||
#include "chaiscript_parser.hpp"
|
||||
#include <chaiscript/language/chaiscript_prelude.hpp>
|
||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -49,6 +51,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
|
||||
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
@@ -73,17 +78,14 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
ModulePtr get()
|
||||
{
|
||||
return m_func.m_symbol();
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
#else
|
||||
|
||||
@@ -183,17 +185,14 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
ModulePtr get()
|
||||
{
|
||||
return m_func.m_symbol();
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
|
||||
#else
|
||||
@@ -224,6 +223,7 @@ namespace chaiscript
|
||||
|
||||
std::set<std::string> loaded_files;
|
||||
std::map<std::string, Loadable_Module_Ptr> loaded_modules;
|
||||
std::set<std::string> active_loaded_modules;
|
||||
|
||||
Eval_Engine engine;
|
||||
|
||||
@@ -295,8 +295,8 @@ namespace chaiscript
|
||||
/**
|
||||
* 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)), "__EVAL__", true);
|
||||
const Boxed_Value internal_eval(const std::string &e) {
|
||||
return do_eval(e, "__EVAL__", true);
|
||||
}
|
||||
|
||||
void use(const std::string &filename)
|
||||
@@ -328,12 +328,53 @@ namespace chaiscript
|
||||
/**
|
||||
* Adds a shared object, that can be used by all threads, to the system
|
||||
*/
|
||||
ChaiScript_System &add_shared_object(const Boxed_Value &bv, const std::string &name)
|
||||
ChaiScript_System &add_global_const(const Boxed_Value &bv, const std::string &name)
|
||||
{
|
||||
engine.add_shared_object(bv, name);
|
||||
engine.add_global_const(bv, name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
struct State
|
||||
{
|
||||
std::set<std::string> loaded_files;
|
||||
typename Eval_Engine::State engine_state;
|
||||
std::set<std::string> active_loaded_modules;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a state object that represents the current
|
||||
* set of loaded files, the set of global variables and
|
||||
* the set of initialized functions
|
||||
*/
|
||||
State get_state()
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
|
||||
boost::shared_lock<boost::shared_mutex> l2(mutex);
|
||||
#endif
|
||||
|
||||
State s;
|
||||
s.loaded_files = loaded_files;
|
||||
s.engine_state = engine.get_state();
|
||||
s.active_loaded_modules = active_loaded_modules;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the state from a saved State object.
|
||||
*/
|
||||
void set_state(const State &t_state)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::lock_guard<boost::recursive_mutex> l(use_mutex);
|
||||
boost::shared_lock<boost::shared_mutex> l2(mutex);
|
||||
#endif
|
||||
|
||||
loaded_files = t_state.loaded_files;
|
||||
active_loaded_modules = t_state.active_loaded_modules;
|
||||
engine.set_state(t_state.engine_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to the system: type, function, object
|
||||
*/
|
||||
@@ -397,7 +438,11 @@ namespace chaiscript
|
||||
{
|
||||
Loadable_Module_Ptr lm(new Loadable_Module(t_module_name, t_filename));
|
||||
loaded_modules[t_module_name] = lm;
|
||||
add(lm->get());
|
||||
active_loaded_modules.insert(t_module_name);
|
||||
add(lm->m_moduleptr);
|
||||
} else if (active_loaded_modules.count(t_module_name) == 0) {
|
||||
active_loaded_modules.insert(t_module_name);
|
||||
add(loaded_modules[t_module_name]->m_moduleptr);
|
||||
} else {
|
||||
engine.sync_cache();
|
||||
}
|
||||
@@ -486,42 +531,31 @@ namespace chaiscript
|
||||
engine.add_reserved_word("false");
|
||||
engine.add_reserved_word("_");
|
||||
|
||||
|
||||
add(Bootstrap::bootstrap());
|
||||
|
||||
engine.add(fun(boost::function<void ()>(boost::bind(&Eval_Engine::dump_system, boost::ref(engine)))), "dump_system");
|
||||
engine.add(fun(boost::function<void (Boxed_Value)>(boost::bind(&Eval_Engine::dump_object, boost::ref(engine), _1))), "dump_object");
|
||||
engine.add(fun(boost::function<bool (Boxed_Value, const std::string &)>(boost::bind(&Eval_Engine::is_type, boost::ref(engine), _2, _1))),
|
||||
"is_type");
|
||||
engine.add(fun(&Eval_Engine::dump_system, boost::ref(engine)), "dump_system");
|
||||
engine.add(fun(&Eval_Engine::dump_object, boost::ref(engine)), "dump_object");
|
||||
engine.add(fun(&Eval_Engine::is_type, boost::ref(engine)), "is_type");
|
||||
engine.add(fun(&Eval_Engine::type_name, boost::ref(engine)), "type_name");
|
||||
engine.add(fun(&Eval_Engine::function_exists, boost::ref(engine)), "function_exists");
|
||||
|
||||
engine.add(fun(boost::function<std::string (Boxed_Value)>(boost::bind(&Eval_Engine::type_name, boost::ref(engine), _1))),
|
||||
"type_name");
|
||||
engine.add(fun(boost::function<bool (const std::string &)>(boost::bind(&Eval_Engine::function_exists, boost::ref(engine), _1))),
|
||||
"function_exists");
|
||||
engine.add(fun(&Eval_Engine::get_type_name, boost::ref(engine)), "name");
|
||||
|
||||
|
||||
engine.add(fun(boost::function<void (const std::string &)>(
|
||||
boost::bind(static_cast<void (ChaiScript_System<Eval_Engine>::*)(const std::string&)>(
|
||||
&ChaiScript_System<Eval_Engine>::load_module), boost::ref(*this), _1))),
|
||||
"load_module");
|
||||
typedef void (ChaiScript_System<Eval_Engine>::*load_mod_1)(const std::string&);
|
||||
typedef void (ChaiScript_System<Eval_Engine>::*load_mod_2)(const std::string&, const std::string&);
|
||||
|
||||
engine.add(fun(static_cast<load_mod_1>(&ChaiScript_System<Eval_Engine>::load_module), this), "load_module");
|
||||
engine.add(fun(static_cast<load_mod_2>(&ChaiScript_System<Eval_Engine>::load_module), this), "load_module");
|
||||
|
||||
engine.add(fun(boost::function<void (const std::string &, const std::string &)>(
|
||||
boost::bind(static_cast<void (ChaiScript_System<Eval_Engine>::*)(const std::string&, const std::string&)>(
|
||||
&ChaiScript_System<Eval_Engine>::load_module), boost::ref(*this), _1, _2))),
|
||||
"load_module");
|
||||
|
||||
add(vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
add(string_type<std::string>("string"));
|
||||
add(map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
add(pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
|
||||
engine.add(fun(boost::function<void (const std::string &)>(boost::bind(&ChaiScript_System<Eval_Engine>::use, this, _1))), "use");
|
||||
|
||||
engine.add(Proxy_Function(
|
||||
new Dynamic_Proxy_Function(boost::bind(&ChaiScript_System<Eval_Engine>::internal_eval, boost::ref(*this), _1), 1)), "eval");
|
||||
|
||||
|
||||
|
||||
engine.add(fun(&ChaiScript_System<Eval_Engine>::use, this), "use");
|
||||
engine.add(fun(&ChaiScript_System<Eval_Engine>::internal_eval, this), "eval");
|
||||
|
||||
|
||||
do_eval(chaiscript_prelude, "standard prelude");
|
||||
|
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <chaiscript/language/chaiscript_common.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
/**
|
||||
@@ -40,13 +42,16 @@ namespace chaiscript
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_file(Eval_System &ss, const TokenPtr &node) {
|
||||
Boxed_Value retval;
|
||||
unsigned int i;
|
||||
for (i = 0; i < node->children.size(); ++i) {
|
||||
retval = eval_token(ss, node->children[i]);
|
||||
}
|
||||
const unsigned int size = node->children.size();
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
const Boxed_Value &retval = eval_token(ss, node->children[i]);
|
||||
if (i + 1 == size)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
return Boxed_Value();
|
||||
}
|
||||
|
||||
template <typename Eval_System>
|
||||
void cache_const(Eval_System &/*ss*/, const TokenPtr &node, const Boxed_Value &value) {
|
||||
@@ -150,22 +155,8 @@ namespace chaiscript
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_single_quoted_string(Eval_System &ss, const TokenPtr &node) {
|
||||
/*
|
||||
if (node->text.size() == 1) {
|
||||
//return Boxed_Value(char(node->text[0]));
|
||||
return const_var(char(node->text[0]));
|
||||
}
|
||||
else {
|
||||
//return Boxed_Value(char((int)node->text[0] * 0xff + (int)node->text[0]));
|
||||
return const_var(char((int)node->text[0] * 0xff + (int)node->text[0]));
|
||||
}
|
||||
*/
|
||||
|
||||
if (!node->is_cached) {
|
||||
cache_const(ss, node,
|
||||
node->text.size() == 1 ?
|
||||
const_var(char(node->text[0])) :
|
||||
const_var(char((int)node->text[0] * 0xff + (int)node->text[0])));
|
||||
cache_const(ss, node, const_var(char(node->text[0])));
|
||||
}
|
||||
return node->cached_value;
|
||||
}
|
||||
@@ -175,26 +166,24 @@ namespace chaiscript
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_equation(Eval_System &ss, const TokenPtr &node) {
|
||||
unsigned int i;
|
||||
int i;
|
||||
Boxed_Value retval = eval_token(ss, node->children.back());
|
||||
if (node->children.size() > 1) {
|
||||
for (i = node->children.size()-3; ((int)i) >= 0; i -= 2) {
|
||||
for (i = node->children.size()-3; i >= 0; i -= 2) {
|
||||
if (node->children[i+1]->text == "=") {
|
||||
Boxed_Value lhs = eval_token(ss, node->children[i]);
|
||||
|
||||
try {
|
||||
if (lhs.is_unknown())
|
||||
if (lhs.is_undef())
|
||||
{
|
||||
retval = ss.call_function("clone", Param_List_Builder() << retval);
|
||||
retval = ss.call_function("clone", retval);
|
||||
}
|
||||
Param_List_Builder plb;
|
||||
plb << lhs;
|
||||
plb << retval;
|
||||
|
||||
try {
|
||||
retval = ss.call_function(node->children[i+1]->text, plb);
|
||||
retval = ss.call_function(node->children[i+1]->text, lhs, retval);
|
||||
}
|
||||
catch(const dispatch_error &){
|
||||
throw Eval_Error("Mismatched types in equation", node->children[i+1]);
|
||||
throw Eval_Error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."), node->children[i+1]);
|
||||
}
|
||||
}
|
||||
catch(const dispatch_error &){
|
||||
@@ -203,7 +192,7 @@ namespace chaiscript
|
||||
}
|
||||
else if (node->children[i+1]->text == ":=") {
|
||||
Boxed_Value lhs = eval_token(ss, node->children[i]);
|
||||
if (lhs.is_unknown() || type_match(lhs, retval)) {
|
||||
if (lhs.is_undef() || type_match(lhs, retval)) {
|
||||
lhs.assign(retval);
|
||||
}
|
||||
else {
|
||||
@@ -211,11 +200,8 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
else {
|
||||
Param_List_Builder plb;
|
||||
plb << eval_token(ss, node->children[i]);
|
||||
plb << retval;
|
||||
try {
|
||||
retval = ss.call_function(node->children[i+1]->text, plb);
|
||||
retval = ss.call_function(node->children[i+1]->text, eval_token(ss, node->children[i]), retval);
|
||||
}
|
||||
catch(const dispatch_error &){
|
||||
throw Eval_Error("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
|
||||
@@ -260,15 +246,15 @@ namespace chaiscript
|
||||
* Evaluates binary boolean operators. Respects short-circuiting rules.
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_expression(Eval_System &ss, const TokenPtr &node) {
|
||||
Boxed_Value eval_logical(Eval_System &ss, const TokenPtr &node) {
|
||||
unsigned int i;
|
||||
|
||||
Boxed_Value retval = eval_token(ss, node->children[0]);
|
||||
Boxed_Value retval(eval_token(ss, node->children[0]));
|
||||
if (node->children.size() > 1) {
|
||||
for (i = 1; i < node->children.size(); i += 2) {
|
||||
bool lhs;
|
||||
try {
|
||||
lhs = boxed_cast<bool &>(retval);
|
||||
lhs = boxed_cast<bool>(retval);
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
throw Eval_Error("Condition not boolean", node);
|
||||
@@ -302,20 +288,14 @@ namespace chaiscript
|
||||
unsigned int i;
|
||||
|
||||
Boxed_Value retval = eval_token(ss, node->children[0]);
|
||||
if (node->children.size() > 1) {
|
||||
for (i = 1; i < node->children.size(); i += 2) {
|
||||
Param_List_Builder plb;
|
||||
plb << retval;
|
||||
plb << eval_token(ss, node->children[i + 1]);
|
||||
|
||||
try {
|
||||
retval = ss.call_function(node->children[i]->text, plb);
|
||||
retval = ss.call_function(node->children[i]->text, retval, eval_token(ss, node->children[i + 1]));
|
||||
}
|
||||
catch(const dispatch_error &){
|
||||
throw Eval_Error("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -329,11 +309,8 @@ namespace chaiscript
|
||||
|
||||
Boxed_Value retval = eval_token(ss, node->children[0]);
|
||||
for (i = 1; i < node->children.size(); ++i) {
|
||||
Param_List_Builder plb;
|
||||
plb << retval;
|
||||
plb << eval_token(ss, node->children[i]);
|
||||
try {
|
||||
retval = ss.call_function("[]", plb);
|
||||
retval = ss.call_function("[]", retval, eval_token(ss, node->children[i]));
|
||||
}
|
||||
catch(std::out_of_range &) {
|
||||
throw Eval_Error("Out of bounds exception", node);
|
||||
@@ -346,50 +323,16 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a unary negation
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_negate(Eval_System &ss, const TokenPtr &node) {
|
||||
Boxed_Value retval = eval_token(ss, node->children[0]);
|
||||
Param_List_Builder plb;
|
||||
plb << retval;
|
||||
plb << Boxed_Value(-1.0);
|
||||
|
||||
try {
|
||||
return ss.call_function("*", plb);
|
||||
}
|
||||
catch(std::exception &){
|
||||
throw Eval_Error("Can not find appropriate negation", node->children[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a unary boolean not
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_not(Eval_System &ss, const TokenPtr &node) {
|
||||
try {
|
||||
return Boxed_Value(!boxed_cast<bool>(eval_token(ss, node->children[0])));
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
throw Eval_Error("Boolean not('!') condition not boolean", node->children[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates any unary prefix
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_prefix(Eval_System &ss, const TokenPtr &node) {
|
||||
Param_List_Builder plb;
|
||||
plb << eval_token(ss, node->children[1]);
|
||||
|
||||
try {
|
||||
return ss.call_function(node->children[0]->text, plb);
|
||||
return ss.call_function(node->children[0]->text, eval_token(ss, node->children[1]));
|
||||
}
|
||||
catch(std::exception &){
|
||||
throw Eval_Error("Can not find appropriate prefix", node->children[0]);
|
||||
throw Eval_Error("Can not find appropriate unary '" + node->children[0]->text + "'", node->children[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,18 +344,15 @@ namespace chaiscript
|
||||
unsigned int i;
|
||||
|
||||
try {
|
||||
Boxed_Value retval = ss.call_function("Vector", Param_List_Builder());
|
||||
if (node->children.size() > 0) {
|
||||
Boxed_Value retval = ss.call_function("Vector");
|
||||
for (i = 0; i < node->children[0]->children.size(); ++i) {
|
||||
try {
|
||||
Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]);
|
||||
ss.call_function("push_back", Param_List_Builder() << retval << tmp);
|
||||
ss.call_function("push_back", retval, eval_token(ss, node->children[0]->children[i]));
|
||||
}
|
||||
catch (const dispatch_error &) {
|
||||
throw Eval_Error("Can not find appropriate 'push_back'", node->children[0]->children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -428,9 +368,9 @@ namespace chaiscript
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_inline_range(Eval_System &ss, const TokenPtr &node) {
|
||||
try {
|
||||
return ss.call_function("generate_range", Param_List_Builder()
|
||||
<< eval_token(ss, node->children[0]->children[0]->children[0])
|
||||
<< eval_token(ss, node->children[0]->children[0]->children[1]));
|
||||
return ss.call_function("generate_range",
|
||||
eval_token(ss, node->children[0]->children[0]->children[0]),
|
||||
eval_token(ss, node->children[0]->children[0]->children[1]));
|
||||
}
|
||||
catch (const dispatch_error &) {
|
||||
throw Eval_Error("Unable to generate range vector", node);
|
||||
@@ -445,12 +385,12 @@ namespace chaiscript
|
||||
unsigned int i;
|
||||
|
||||
try {
|
||||
Boxed_Value retval = ss.call_function("Map", Param_List_Builder());
|
||||
Boxed_Value retval = ss.call_function("Map");
|
||||
for (i = 0; i < node->children[0]->children.size(); ++i) {
|
||||
try {
|
||||
Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]);
|
||||
Boxed_Value slot = ss.call_function("[]", Param_List_Builder() << retval << key);
|
||||
ss.call_function("=", Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1]));
|
||||
Boxed_Value slot
|
||||
= ss.call_function("[]", retval, eval_token(ss, node->children[0]->children[i]->children[0]));
|
||||
ss.call_function("=", slot, eval_token(ss, node->children[0]->children[i]->children[1]));
|
||||
}
|
||||
catch (const dispatch_error &) {
|
||||
throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]);
|
||||
@@ -484,7 +424,7 @@ namespace chaiscript
|
||||
|
||||
try {
|
||||
ss.set_stack(new_stack);
|
||||
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
|
||||
const Boxed_Value &retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
|
||||
ss.set_stack(prev_stack);
|
||||
return retval;
|
||||
}
|
||||
@@ -526,8 +466,7 @@ namespace chaiscript
|
||||
Boxed_Value fn = eval_token(ss, node->children[0]);
|
||||
|
||||
try {
|
||||
Boxed_Value retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb);
|
||||
return retval;
|
||||
return (*boxed_cast<Const_Proxy_Function >(fn))(plb);
|
||||
}
|
||||
catch(const dispatch_error &e){
|
||||
throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]);
|
||||
@@ -550,16 +489,15 @@ namespace chaiscript
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_dot_access(Eval_System &ss, const TokenPtr &node) {
|
||||
std::vector<std::pair<std::string, Proxy_Function > > fn;
|
||||
Dispatch_Engine::Stack prev_stack = ss.get_stack();
|
||||
Dispatch_Engine::Stack new_stack = ss.new_stack();
|
||||
unsigned int i, j;
|
||||
|
||||
//todo: Please extract a single way of doing function calls between this and eval_fun_call
|
||||
|
||||
Boxed_Value retval = eval_token(ss, node->children[0]);
|
||||
Boxed_Value retval(eval_token(ss, node->children[0]));
|
||||
if (node->children.size() > 1) {
|
||||
for (i = 1; i < node->children.size(); ++i) {
|
||||
for (i = 2; i < node->children.size(); i+=2) {
|
||||
Param_List_Builder plb;
|
||||
plb << retval;
|
||||
|
||||
@@ -586,9 +524,7 @@ namespace chaiscript
|
||||
throw Eval_Error(ee.reason, node->children[i]);
|
||||
}
|
||||
try {
|
||||
//fn = ss.get_function(fun_name);
|
||||
ss.set_stack(new_stack);
|
||||
//retval = dispatch(fn, plb);
|
||||
retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb);
|
||||
ss.set_stack(prev_stack);
|
||||
}
|
||||
@@ -616,7 +552,6 @@ namespace chaiscript
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_try(Eval_System &ss, const TokenPtr &node) {
|
||||
Boxed_Value retval;
|
||||
retval = Boxed_Value();
|
||||
|
||||
ss.new_scope();
|
||||
try {
|
||||
@@ -729,6 +664,7 @@ namespace chaiscript
|
||||
ss.pop_scope();
|
||||
throw;
|
||||
}
|
||||
|
||||
if (node->children.back()->identifier == Token_Type::Finally) {
|
||||
retval = eval_token(ss, node->children.back()->children[0]);
|
||||
}
|
||||
@@ -745,35 +681,32 @@ namespace chaiscript
|
||||
Boxed_Value eval_if(Eval_System &ss, const TokenPtr &node) {
|
||||
unsigned int i;
|
||||
|
||||
Boxed_Value retval = eval_token(ss, node->children[0]);
|
||||
bool cond;
|
||||
try {
|
||||
cond = boxed_cast<bool>(retval);
|
||||
cond = boxed_cast<bool>(eval_token(ss, node->children[0]));
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
throw Eval_Error("If condition not boolean", node->children[0]);
|
||||
}
|
||||
if (cond) {
|
||||
retval = eval_token(ss, node->children[1]);
|
||||
return eval_token(ss, node->children[1]);
|
||||
}
|
||||
else {
|
||||
if (node->children.size() > 2) {
|
||||
i = 2;
|
||||
while ((!cond) && (i < node->children.size())) {
|
||||
if (node->children[i]->text == "else") {
|
||||
retval = eval_token(ss, node->children[i+1]);
|
||||
cond = true;
|
||||
return eval_token(ss, node->children[i+1]);
|
||||
}
|
||||
else if (node->children[i]->text == "else if") {
|
||||
retval = eval_token(ss, node->children[i+1]);
|
||||
try {
|
||||
cond = boxed_cast<bool>(retval);
|
||||
cond = boxed_cast<bool>(eval_token(ss, node->children[i+1]));
|
||||
}
|
||||
catch (const bad_boxed_cast &) {
|
||||
throw Eval_Error("'else if' condition not boolean", node->children[i+1]);
|
||||
}
|
||||
if (cond) {
|
||||
retval = eval_token(ss, node->children[i+2]);
|
||||
return eval_token(ss, node->children[i+2]);
|
||||
}
|
||||
}
|
||||
i = i + 3;
|
||||
@@ -781,7 +714,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
return Boxed_Value(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1026,17 +959,22 @@ namespace chaiscript
|
||||
*/
|
||||
template <typename Eval_System>
|
||||
Boxed_Value eval_block(Eval_System &ss, const TokenPtr &node) {
|
||||
Boxed_Value retval;
|
||||
unsigned int i;
|
||||
unsigned int num_children = node->children.size();
|
||||
|
||||
ss.new_scope();
|
||||
for (i = 0; i < node->children.size(); ++i) {
|
||||
for (i = 0; i < num_children; ++i) {
|
||||
try {
|
||||
retval = eval_token(ss, node->children[i]);
|
||||
}
|
||||
catch (const chaiscript::Return_Value &rv) {
|
||||
const Boxed_Value &retval = eval_token(ss, node->children[i]);
|
||||
|
||||
if (i + 1 == num_children)
|
||||
{
|
||||
ss.pop_scope();
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::Return_Value &/*rv*/) {
|
||||
ss.pop_scope();
|
||||
retval = rv.retval;
|
||||
throw;
|
||||
}
|
||||
catch (...) {
|
||||
@@ -1044,9 +982,9 @@ namespace chaiscript
|
||||
throw;
|
||||
}
|
||||
}
|
||||
ss.pop_scope();
|
||||
|
||||
return retval;
|
||||
ss.pop_scope();
|
||||
return Boxed_Value();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1108,13 +1046,19 @@ namespace chaiscript
|
||||
return eval_var_decl(ss, node);
|
||||
break;
|
||||
|
||||
case (Token_Type::Expression) :
|
||||
return eval_expression(ss, node);
|
||||
case (Token_Type::Logical_And) :
|
||||
case (Token_Type::Logical_Or) :
|
||||
return eval_logical(ss, node);
|
||||
break;
|
||||
|
||||
case (Token_Type::Bitwise_And) :
|
||||
case (Token_Type::Bitwise_Xor) :
|
||||
case (Token_Type::Bitwise_Or) :
|
||||
case (Token_Type::Comparison) :
|
||||
case (Token_Type::Equality) :
|
||||
case (Token_Type::Additive) :
|
||||
case (Token_Type::Multiplicative) :
|
||||
case (Token_Type::Shift) :
|
||||
return eval_comp_add_mul(ss, node);
|
||||
break;
|
||||
|
||||
@@ -1122,14 +1066,6 @@ namespace chaiscript
|
||||
return eval_array_call(ss, node);
|
||||
break;
|
||||
|
||||
case (Token_Type::Negate) :
|
||||
return eval_negate(ss, node);
|
||||
break;
|
||||
|
||||
case (Token_Type::Not) :
|
||||
return eval_not(ss, node);
|
||||
break;
|
||||
|
||||
case (Token_Type::Prefix) :
|
||||
return eval_prefix(ss, node);
|
||||
break;
|
||||
|
@@ -7,10 +7,14 @@
|
||||
#ifndef CHAISCRIPT_PARSER_HPP_
|
||||
#define CHAISCRIPT_PARSER_HPP_
|
||||
|
||||
#include <boost/assign/std/vector.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "chaiscript_prelude.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -23,13 +27,79 @@ namespace chaiscript
|
||||
const char *filename;
|
||||
std::vector<TokenPtr> match_stack;
|
||||
|
||||
std::vector<std::vector<std::string> > operator_matches;
|
||||
std::vector<Token_Type::Type> operators;
|
||||
|
||||
public:
|
||||
ChaiScript_Parser() {
|
||||
multiline_comment_begin = "/*";
|
||||
multiline_comment_end = "*/";
|
||||
singleline_comment = "//";
|
||||
|
||||
setup_operators();
|
||||
}
|
||||
|
||||
ChaiScript_Parser(const ChaiScript_Parser &); // explicitly unimplemented copy constructor
|
||||
ChaiScript_Parser &operator=(const ChaiScript_Parser &); // explicitly unimplemented assignment operator
|
||||
|
||||
void setup_operators() {
|
||||
using namespace boost::assign;
|
||||
|
||||
operators.push_back(Token_Type::Logical_Or);
|
||||
std::vector<std::string> logical_or;
|
||||
logical_or += "||";
|
||||
operator_matches.push_back(logical_or);
|
||||
|
||||
operators.push_back(Token_Type::Logical_And);
|
||||
std::vector<std::string> logical_and;
|
||||
logical_and += "&&";
|
||||
operator_matches.push_back(logical_and);
|
||||
|
||||
operators.push_back(Token_Type::Bitwise_Or);
|
||||
std::vector<std::string> bitwise_or;
|
||||
bitwise_or += "|";
|
||||
operator_matches.push_back(bitwise_or);
|
||||
|
||||
operators.push_back(Token_Type::Bitwise_Xor);
|
||||
std::vector<std::string> bitwise_xor;
|
||||
bitwise_xor += "^";
|
||||
operator_matches.push_back(bitwise_xor);
|
||||
|
||||
operators.push_back(Token_Type::Bitwise_And);
|
||||
std::vector<std::string> bitwise_and;
|
||||
bitwise_and += "&";
|
||||
operator_matches.push_back(bitwise_and);
|
||||
|
||||
operators.push_back(Token_Type::Equality);
|
||||
std::vector<std::string> equality;
|
||||
equality += "==", "!=";
|
||||
operator_matches.push_back(equality);
|
||||
|
||||
operators.push_back(Token_Type::Comparison);
|
||||
std::vector<std::string> comparison;
|
||||
comparison += "<", "<=", ">", ">=";
|
||||
operator_matches.push_back(comparison);
|
||||
|
||||
operators.push_back(Token_Type::Shift);
|
||||
std::vector<std::string> shift;
|
||||
shift += "<<", ">>";
|
||||
operator_matches.push_back(shift);
|
||||
|
||||
operators.push_back(Token_Type::Additive);
|
||||
std::vector<std::string> additive;
|
||||
additive += "+", "-";
|
||||
operator_matches.push_back(additive);
|
||||
|
||||
operators.push_back(Token_Type::Multiplicative);
|
||||
std::vector<std::string> multiplicative;
|
||||
multiplicative += "*", "/", "%";
|
||||
operator_matches.push_back(multiplicative);
|
||||
|
||||
operators.push_back(Token_Type::Dot_Access);
|
||||
std::vector<std::string> dot_access;
|
||||
dot_access += ".";
|
||||
operator_matches.push_back(dot_access);
|
||||
}
|
||||
/**
|
||||
* Prints the parsed tokens as a tree
|
||||
*/
|
||||
@@ -68,7 +138,7 @@ namespace chaiscript
|
||||
*/
|
||||
void build_match(Token_Type::Type match_type, int match_start) {
|
||||
//so we want to take everything to the right of this and make them children
|
||||
if (match_start != (int)match_stack.size()) {
|
||||
if (match_start != int(match_stack.size())) {
|
||||
TokenPtr t(new Token("", match_type, filename, match_stack[match_start]->start.line, match_stack[match_start]->start.column, line, col));
|
||||
t->children.assign(match_stack.begin() + (match_start), match_stack.end());
|
||||
match_stack.erase(match_stack.begin() + (match_start), match_stack.end());
|
||||
@@ -101,7 +171,9 @@ namespace chaiscript
|
||||
}
|
||||
else if (Symbol_(singleline_comment.c_str())) {
|
||||
while (input_pos != input_end) {
|
||||
if (Eol_()) {
|
||||
if (Symbol_("\r\n") || Char_('\n')) {
|
||||
++line;
|
||||
col = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
@@ -140,6 +212,8 @@ namespace chaiscript
|
||||
*/
|
||||
bool Float_() {
|
||||
bool retval = false;
|
||||
std::string::iterator start = input_pos;
|
||||
|
||||
if ((input_pos != input_end) && (((*input_pos >= '0') && (*input_pos <= '9')) || (*input_pos == '.'))) {
|
||||
while ((input_pos != input_end) && (*input_pos >= '0') && (*input_pos <= '9')) {
|
||||
++input_pos;
|
||||
@@ -161,10 +235,47 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a floating point value from input, without skipping initial whitespace
|
||||
*/
|
||||
bool Hex_() {
|
||||
bool retval = false;
|
||||
if ((input_pos != input_end) && (*input_pos == '0')) {
|
||||
++input_pos;
|
||||
++col;
|
||||
|
||||
if ((input_pos != input_end) && ((*input_pos == 'x') || (*input_pos == 'X'))) {
|
||||
++input_pos;
|
||||
++col;
|
||||
if ((input_pos != input_end) && (((*input_pos >= '0') && (*input_pos <= '9')) ||
|
||||
((*input_pos >= 'a') && (*input_pos <= 'f')) ||
|
||||
((*input_pos >= 'A') && (*input_pos <= 'F')))) {
|
||||
retval = true;
|
||||
while ((input_pos != input_end) && (((*input_pos >= '0') && (*input_pos <= '9')) ||
|
||||
((*input_pos >= 'a') && (*input_pos <= 'f')) ||
|
||||
((*input_pos >= 'A') && (*input_pos <= 'F')))) {
|
||||
++input_pos;
|
||||
++col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
--input_pos;
|
||||
--col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
--input_pos;
|
||||
--col;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads a number from the input, detecting if it's an integer or floating point
|
||||
*/
|
||||
@@ -172,13 +283,25 @@ namespace chaiscript
|
||||
SkipWS();
|
||||
|
||||
if (!capture) {
|
||||
return Float_();
|
||||
return Hex_() || Float_();
|
||||
}
|
||||
else {
|
||||
std::string::iterator start = input_pos;
|
||||
int prev_col = col;
|
||||
int prev_line = line;
|
||||
if ((input_pos != input_end) && (((*input_pos >= '0') && (*input_pos <= '9')) || (*input_pos == '.')) ) {
|
||||
if (Hex_()) {
|
||||
std::string match(start, input_pos);
|
||||
std::stringstream ss(match);
|
||||
int temp_int;
|
||||
ss >> std::hex >> temp_int;
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << temp_int;
|
||||
TokenPtr t(new Token(out_int.str(), Token_Type::Int, filename, prev_line, prev_col, line, col));
|
||||
match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
if (Float_()) {
|
||||
std::string match(start, input_pos);
|
||||
TokenPtr t(new Token(match, Token_Type::Float, filename, prev_line, prev_col, line, col));
|
||||
@@ -187,8 +310,20 @@ namespace chaiscript
|
||||
}
|
||||
else {
|
||||
std::string match(start, input_pos);
|
||||
if ((match.size() > 0) && (match[0] == '0')) {
|
||||
std::stringstream ss(match);
|
||||
int temp_int;
|
||||
ss >> std::oct >> temp_int;
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << temp_int;
|
||||
TokenPtr t(new Token(out_int.str(), Token_Type::Int, filename, prev_line, prev_col, line, col));
|
||||
match_stack.push_back(t);
|
||||
}
|
||||
else {
|
||||
TokenPtr t(new Token(match, Token_Type::Int, filename, prev_line, prev_col, line, col));
|
||||
match_stack.push_back(t);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -211,7 +346,32 @@ namespace chaiscript
|
||||
++col;
|
||||
}
|
||||
}
|
||||
else if ((input_pos != input_end) && (*input_pos == '`')) {
|
||||
retval = true;
|
||||
++col;
|
||||
++input_pos;
|
||||
std::string::iterator start = input_pos;
|
||||
|
||||
while ((input_pos != input_end) && (*input_pos != '`')) {
|
||||
if (Eol()) {
|
||||
throw Eval_Error("Carriage return in identifier literal", File_Position(line, col), filename);
|
||||
}
|
||||
else {
|
||||
++input_pos;
|
||||
++col;
|
||||
}
|
||||
}
|
||||
|
||||
if (start == input_pos) {
|
||||
throw Eval_Error("Missing contents of identifier literal", File_Position(line, col), filename);
|
||||
}
|
||||
else if (input_pos == input_end) {
|
||||
throw Eval_Error("Incomplete identifier literal", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
++col;
|
||||
++input_pos;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -229,11 +389,20 @@ namespace chaiscript
|
||||
int prev_col = col;
|
||||
int prev_line = line;
|
||||
if (Id_()) {
|
||||
if (*start == '`') {
|
||||
//Id Literal
|
||||
std::string match(start+1, input_pos-1);
|
||||
TokenPtr t(new Token(match, Token_Type::Id, filename, prev_line, prev_col, line, col));
|
||||
match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
std::string match(start, input_pos);
|
||||
TokenPtr t(new Token(match, Token_Type::Id, filename, prev_line, prev_col, line, col));
|
||||
match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
@@ -696,7 +865,8 @@ namespace chaiscript
|
||||
bool retval = Symbol_(s);
|
||||
if (retval) {
|
||||
//todo: fix this. Hacky workaround for preventing substring matches
|
||||
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '=') || (*input_pos == '.'))) {
|
||||
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/')
|
||||
|| (*input_pos == '|') || (*input_pos == '&') || (*input_pos == '^') || (*input_pos == '=') || (*input_pos == '.') || (*input_pos == '<') || (*input_pos == '>'))) {
|
||||
input_pos = start;
|
||||
col = prev_col;
|
||||
line = prev_line;
|
||||
@@ -714,7 +884,8 @@ namespace chaiscript
|
||||
int prev_line = line;
|
||||
if (Symbol_(s)) {
|
||||
//todo: fix this. Hacky workaround for preventing substring matches
|
||||
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/') || (*input_pos == '=') || (*input_pos == '.'))) {
|
||||
if ((input_pos != input_end) && (disallow_prevention == false) && ((*input_pos == '+') || (*input_pos == '-') || (*input_pos == '*') || (*input_pos == '/')
|
||||
|| (*input_pos == '|') || (*input_pos == '&') || (*input_pos == '^') || (*input_pos == '=') || (*input_pos == '.') || (*input_pos == '<') || (*input_pos == '>'))) {
|
||||
input_pos = start;
|
||||
col = prev_col;
|
||||
line = prev_line;
|
||||
@@ -905,7 +1076,7 @@ namespace chaiscript
|
||||
while (Eol());
|
||||
|
||||
if (Char(':')) {
|
||||
if (!Expression()) {
|
||||
if (!Operator()) {
|
||||
throw Eval_Error("Missing guard expression for function", File_Position(line, col), filename);
|
||||
}
|
||||
}
|
||||
@@ -935,16 +1106,6 @@ namespace chaiscript
|
||||
*/
|
||||
bool Try() {
|
||||
bool retval = false;
|
||||
bool is_annotated = false;
|
||||
|
||||
TokenPtr annotation;
|
||||
|
||||
if (Annotation()) {
|
||||
while (Eol_());
|
||||
annotation = match_stack.back();
|
||||
match_stack.pop_back();
|
||||
is_annotated = true;
|
||||
}
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
@@ -968,7 +1129,7 @@ namespace chaiscript
|
||||
throw Eval_Error("Incomplete 'catch' expression", File_Position(line, col), filename);
|
||||
}
|
||||
if (Char(':')) {
|
||||
if (!Expression()) {
|
||||
if (!Operator()) {
|
||||
throw Eval_Error("Missing guard expression for catch", File_Position(line, col), filename);
|
||||
}
|
||||
}
|
||||
@@ -1016,7 +1177,7 @@ namespace chaiscript
|
||||
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
if (!(Expression() && Char(')'))) {
|
||||
if (!(Operator() && Char(')'))) {
|
||||
throw Eval_Error("Incomplete 'if' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
@@ -1037,7 +1198,7 @@ namespace chaiscript
|
||||
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
if (!(Expression() && Char(')'))) {
|
||||
if (!(Operator() && Char(')'))) {
|
||||
throw Eval_Error("Incomplete 'else if' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
@@ -1080,7 +1241,7 @@ namespace chaiscript
|
||||
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
if (!(Expression() && Char(')'))) {
|
||||
if (!(Operator() && Char(')'))) {
|
||||
throw Eval_Error("Incomplete 'while' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
@@ -1102,7 +1263,7 @@ namespace chaiscript
|
||||
bool For_Guards() {
|
||||
Equation();
|
||||
|
||||
if (Char(';') && Expression() && Char(';') && Equation()) {
|
||||
if (Char(';') && Operator() && Char(';') && Equation()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -1174,7 +1335,7 @@ namespace chaiscript
|
||||
if (Keyword("return")) {
|
||||
retval = true;
|
||||
|
||||
Expression();
|
||||
Operator();
|
||||
build_match(Token_Type::Return, prev_stack_top);
|
||||
}
|
||||
|
||||
@@ -1206,7 +1367,7 @@ namespace chaiscript
|
||||
std::string::iterator prev_pos = input_pos;
|
||||
|
||||
unsigned int prev_stack_top = match_stack.size();
|
||||
if (Id(true) || Id_Literal()) {
|
||||
if (Id(true)) {
|
||||
retval = true;
|
||||
bool has_more = true;
|
||||
|
||||
@@ -1226,7 +1387,7 @@ namespace chaiscript
|
||||
else if (Char('[')) {
|
||||
has_more = true;
|
||||
|
||||
if (!(Expression() && Char(']'))) {
|
||||
if (!(Operator() && Char(']'))) {
|
||||
throw Eval_Error("Incomplete array access", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
@@ -1283,7 +1444,7 @@ namespace chaiscript
|
||||
|
||||
if (Char('(')) {
|
||||
retval = true;
|
||||
if (!Expression()) {
|
||||
if (!Operator()) {
|
||||
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
|
||||
}
|
||||
if (!Char(')')) {
|
||||
@@ -1326,53 +1487,6 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an identifier literal of the special form `<name>` from input
|
||||
*/
|
||||
bool Id_Literal() {
|
||||
bool retval = false;
|
||||
|
||||
SkipWS();
|
||||
|
||||
if ((input_pos != input_end) && (*input_pos == '`')) {
|
||||
retval = true;
|
||||
|
||||
int prev_col = col;
|
||||
int prev_line = line;
|
||||
|
||||
++col;
|
||||
++input_pos;
|
||||
|
||||
std::string::iterator start = input_pos;
|
||||
|
||||
while ((input_pos != input_end) && (*input_pos != '`')) {
|
||||
if (Eol()) {
|
||||
throw Eval_Error("Carriage return in identifier literal", File_Position(line, col), filename);
|
||||
}
|
||||
else {
|
||||
++input_pos;
|
||||
++col;
|
||||
}
|
||||
}
|
||||
|
||||
if (start == input_pos) {
|
||||
throw Eval_Error("Missing contents of identifier literal", File_Position(line, col), filename);
|
||||
}
|
||||
else if (input_pos == input_end) {
|
||||
throw Eval_Error("Incomplete identifier literal", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
++col;
|
||||
std::string match(start, input_pos);
|
||||
TokenPtr t(new Token(match, Token_Type::Id, filename, prev_line, prev_col, line, col));
|
||||
match_stack.push_back(t);
|
||||
++input_pos;
|
||||
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a unary prefixed expression from input
|
||||
*/
|
||||
@@ -1384,7 +1498,7 @@ namespace chaiscript
|
||||
if (Symbol("++", true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Dot_Access()) {
|
||||
if (!Operator(operators.size()-1)) {
|
||||
throw Eval_Error("Incomplete '++' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
@@ -1393,29 +1507,47 @@ namespace chaiscript
|
||||
else if (Symbol("--", true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Dot_Access()) {
|
||||
if (!Operator(operators.size()-1)) {
|
||||
throw Eval_Error("Incomplete '--' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
build_match(Token_Type::Prefix, prev_stack_top);
|
||||
}
|
||||
else if (Char('-')) {
|
||||
else if (Char('-', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Dot_Access()) {
|
||||
throw Eval_Error("Incomplete negation expression", File_Position(line, col), filename);
|
||||
if (!Operator(operators.size()-1)) {
|
||||
throw Eval_Error("Incomplete unary '-' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
build_match(Token_Type::Negate, prev_stack_top);
|
||||
build_match(Token_Type::Prefix, prev_stack_top);
|
||||
}
|
||||
else if (Char('!')) {
|
||||
else if (Char('+', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Dot_Access()) {
|
||||
if (!Operator(operators.size()-1)) {
|
||||
throw Eval_Error("Incomplete unary '+' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
build_match(Token_Type::Prefix, prev_stack_top);
|
||||
}
|
||||
else if (Char('!', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(operators.size()-1)) {
|
||||
throw Eval_Error("Incomplete '!' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
build_match(Token_Type::Not, prev_stack_top);
|
||||
build_match(Token_Type::Prefix, prev_stack_top);
|
||||
}
|
||||
else if (Char('~', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(operators.size()-1)) {
|
||||
throw Eval_Error("Incomplete '~' expression", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
build_match(Token_Type::Prefix, prev_stack_top);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -1434,121 +1566,37 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string of binary comparisons from input
|
||||
*/
|
||||
bool Comparison() {
|
||||
bool Operator_Helper(int precedence) {
|
||||
for (unsigned int i = 0; i < operator_matches[precedence].size(); ++i) {
|
||||
if (Symbol(operator_matches[precedence][i].c_str(), true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Operator(unsigned int precedence = 0) {
|
||||
bool retval = false;
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Additive()) {
|
||||
if (precedence < operators.size()) {
|
||||
if (Operator(precedence+1)) {
|
||||
retval = true;
|
||||
if (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)) {
|
||||
if (Operator_Helper(precedence)) {
|
||||
do {
|
||||
if (!Additive()) {
|
||||
throw Eval_Error("Incomplete comparison expression", File_Position(line, col), filename);
|
||||
if (!Operator(precedence+1)) {
|
||||
throw Eval_Error("Incomplete " + std::string(token_type_to_string(operators[precedence])) + " expression",
|
||||
File_Position(line, col), filename);
|
||||
}
|
||||
} while (retval && (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)));
|
||||
} while (Operator_Helper(precedence));
|
||||
|
||||
build_match(Token_Type::Comparison, prev_stack_top);
|
||||
build_match(operators[precedence], prev_stack_top);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string of binary additions/subtractions from input
|
||||
*/
|
||||
bool Additive() {
|
||||
bool retval = false;
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Multiplicative()) {
|
||||
retval = true;
|
||||
if (Symbol("+", true) || Symbol("-", true)) {
|
||||
do {
|
||||
if (!Multiplicative()) {
|
||||
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
|
||||
}
|
||||
} while (retval && (Symbol("+", true) || Symbol("-", true)));
|
||||
|
||||
build_match(Token_Type::Additive, prev_stack_top);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string of multiplication/division/modulus from input
|
||||
*/
|
||||
bool Multiplicative() {
|
||||
bool retval = false;
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Dot_Access()) {
|
||||
retval = true;
|
||||
if (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)) {
|
||||
do {
|
||||
if (!Dot_Access()) {
|
||||
throw Eval_Error("Incomplete math expression", File_Position(line, col), filename);
|
||||
}
|
||||
} while (retval && (Symbol("*", true) || Symbol("/", true) || Symbol("%", true)));
|
||||
|
||||
build_match(Token_Type::Multiplicative, prev_stack_top);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string of dot-notation accesses from input
|
||||
*/
|
||||
bool Dot_Access() {
|
||||
bool retval = false;
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Value()) {
|
||||
retval = true;
|
||||
if (Symbol(".")) {
|
||||
do {
|
||||
if (!Value()) {
|
||||
throw Eval_Error("Incomplete dot notation", File_Position(line, col), filename);
|
||||
}
|
||||
} while (retval && Symbol("."));
|
||||
|
||||
build_match(Token_Type::Dot_Access, prev_stack_top);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Top-level expression, parses a string of binary boolean operators from input
|
||||
*/
|
||||
bool Expression() {
|
||||
bool retval = false;
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Comparison()) {
|
||||
retval = true;
|
||||
if (Symbol("&&", true) || Symbol("||", true)) {
|
||||
do {
|
||||
if (!Comparison()) {
|
||||
throw Eval_Error("Incomplete expression", File_Position(line, col), filename);
|
||||
}
|
||||
} while (retval && (Symbol("&&", true) || Symbol("||", true)));
|
||||
|
||||
build_match(Token_Type::Expression, prev_stack_top);
|
||||
}
|
||||
else {
|
||||
return Value();
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -1562,11 +1610,11 @@ namespace chaiscript
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Expression()) {
|
||||
if (Operator()) {
|
||||
retval = true;
|
||||
if (Symbol(":")) {
|
||||
do {
|
||||
if (!Expression()) {
|
||||
if (!Operator()) {
|
||||
throw Eval_Error("Incomplete map pair", File_Position(line, col), filename);
|
||||
}
|
||||
} while (retval && Symbol(":"));
|
||||
@@ -1588,10 +1636,10 @@ namespace chaiscript
|
||||
std::string::iterator prev_pos = input_pos;
|
||||
int prev_col = col;
|
||||
|
||||
if (Expression()) {
|
||||
if (Operator()) {
|
||||
if (Symbol("..")) {
|
||||
retval = true;
|
||||
if (!Expression()) {
|
||||
if (!Operator()) {
|
||||
throw Eval_Error("Incomplete value range", File_Position(line, col), filename);
|
||||
}
|
||||
|
||||
@@ -1617,10 +1665,12 @@ namespace chaiscript
|
||||
|
||||
int prev_stack_top = match_stack.size();
|
||||
|
||||
if (Expression()) {
|
||||
if (Operator()) {
|
||||
retval = true;
|
||||
if (Symbol("=", true, true) || Symbol(":=", true, true) || Symbol("+=", true, true) ||
|
||||
Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true)) {
|
||||
Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true) ||
|
||||
Symbol("%=", true, true) || Symbol("<<=", true, true) || Symbol(">>=", true, true) ||
|
||||
Symbol("&=", true, true) || Symbol("^=", true, true) || Symbol("|=", true, true)) {
|
||||
if (!Equation()) {
|
||||
throw Eval_Error("Incomplete equation", match_stack.back());
|
||||
}
|
||||
@@ -1712,6 +1762,11 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Block()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else {
|
||||
has_more = false;
|
||||
}
|
||||
|
@@ -12,6 +12,9 @@
|
||||
#define CODE_STRING(x, y) #x ", " #y
|
||||
|
||||
#define chaiscript_prelude CODE_STRING(\
|
||||
def lt(l, r) { if (call_exists(`<`, l, r)) { l < r } else { type_name(l) < type_name(r) } } \n\
|
||||
def gt(l, r) { if (call_exists(`>`, l, r)) { l > r } else { type_name(l) > type_name(r) } } \n\
|
||||
def eq(l, r) { if (call_exists(`==`, l, r)) { l == r } else { false } } \n\
|
||||
def new(x) { eval(type_name(x))(); } \n\
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) { eval(type_name(x))(x); } \n\
|
||||
# to_string for Pair()\n\
|
||||
@@ -89,6 +92,15 @@ def back_inserter(container) { \n\
|
||||
bind(push_back, container, _); \n\
|
||||
}\n\
|
||||
\n\
|
||||
def contains(container, item, compare_func) : call_exists(range, container) { \n\
|
||||
var t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
if ( compare_func(t_range.front(), item) ) { return true; } \n\
|
||||
t_range.pop_front(); \n\
|
||||
} \n\
|
||||
return false; \n\
|
||||
} \n\
|
||||
def contains(container, item) { return contains(container, item, eq) } \n\
|
||||
def map(container, func, inserter) : call_exists(range, container) { \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
@@ -269,37 +281,49 @@ def zip(x, y) { \n\
|
||||
zip_with(collate, x, y); \n\
|
||||
}\n\
|
||||
# Returns the position of the second value string in the first value string\n\
|
||||
def find(str, substr) { \n\
|
||||
int(find(str, substr, size_t(0))); \n\
|
||||
def string::find(substr) : is_type(substr, "string") { \n\
|
||||
int(find(this, substr, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of last match of the second value string in the first value string\n\
|
||||
def rfind(str, substr) { \n\
|
||||
int(rfind(str, substr, size_t(-1))); \n\
|
||||
def string::rfind(substr) : is_type(substr, "string") { \n\
|
||||
int(rfind(this, substr, -1)); \n\
|
||||
} \n\
|
||||
# Returns the position of the first match of elements in the second value string in the first value string\n\
|
||||
def find_first_of(str, list) { \n\
|
||||
int(find_first_of(str, list, size_t(0))); \n\
|
||||
def string::find_first_of(list) : is_type(list, "string") { \n\
|
||||
int(find_first_of(this, list, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of the last match of elements in the second value string in the first value string\n\
|
||||
def find_last_of(str, list) { \n\
|
||||
int(find_last_of(str, list, size_t(-1))); \n\
|
||||
def string::find_last_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
# Returns the position of the first non-matching element in the second value string in the first value string\n\
|
||||
def find_first_not_of(str, list) { \n\
|
||||
int(find_first_not_of(str, list, size_t(0))); \n\
|
||||
def string::find_first_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_first_not_of(this, list, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of the last non-matching element in the second value string in the first value string\n\
|
||||
def find_last_not_of(str, list) { \n\
|
||||
int(find_last_not_of(str, list, size_t(-1))); \n\
|
||||
def string::find_last_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_not_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
def ltrim(str) { \n\
|
||||
drop_while(str, fun(x) { x == ' ' || x == '\t' }); \n\
|
||||
def string::ltrim() { \n\
|
||||
drop_while(this, fun(x) { x == ' ' || x == '\t' }); \n\
|
||||
} \n\
|
||||
def rtrim(str) { \n\
|
||||
reverse(drop_while(reverse(str), fun(x) { x == ' ' || x == '\t' })); \n\
|
||||
def string::rtrim() { \n\
|
||||
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' })); \n\
|
||||
} \n\
|
||||
def trim(str) { \n\
|
||||
ltrim(rtrim(str)); \n\
|
||||
} \
|
||||
def string::trim() { \n\
|
||||
ltrim(rtrim(this)); \n\
|
||||
} \n\
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "function") { \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
if (compare_func(range.front(), value)) { \n\
|
||||
return range; \n\
|
||||
} else { \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
return range; \n\
|
||||
} \n\
|
||||
def find(container, value) { return find(container, value, eq) } \
|
||||
)
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
||||
|
@@ -14,6 +14,6 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalLibraryDirectories="C:\Boost\lib"
|
||||
AdditionalLibraryDirectories="C:\Boost\lib;C:\Programming\Boost\lib"
|
||||
/>
|
||||
</VisualStudioPropertySheet>
|
||||
|
@@ -189,6 +189,10 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\bind_first.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\bootstrap.hpp"
|
||||
>
|
||||
@@ -245,6 +249,10 @@
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\handle_return.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\operators.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\chaiscript\dispatchkit\proxy_constructors.hpp"
|
||||
>
|
||||
|
@@ -1,3 +1,2 @@
|
||||
var i = 1
|
||||
var j = eval("5 + 4")
|
||||
print(j)
|
||||
|
@@ -2,11 +2,11 @@ for (var i = 0; i < 10; ++i) {
|
||||
print(i)
|
||||
}
|
||||
|
||||
for (i = 10; i >= 0; i -= 2) {
|
||||
for (var i = 10; i >= 0; i -= 2) {
|
||||
print(i)
|
||||
}
|
||||
|
||||
i = 0
|
||||
var i = 0
|
||||
|
||||
for (; i < 5; ++i) {
|
||||
print(i)
|
||||
|
@@ -22,6 +22,10 @@ void log(const std::string &module, const std::string &msg)
|
||||
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl;
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
{
|
||||
log(msg);
|
||||
}
|
||||
|
||||
void hello_world(const chaiscript::Boxed_Value &o)
|
||||
{
|
||||
@@ -71,6 +75,9 @@ int main(int argc, char *argv[]) {
|
||||
System system;
|
||||
chai.add(var(&system), "system");
|
||||
|
||||
//Add a bound callback method
|
||||
chai.add(fun(&System::add_callback, system), "add_callback_bound");
|
||||
|
||||
//Register the two methods of the System structure.
|
||||
chai.add(fun(&System::add_callback), "add_callback");
|
||||
chai.add(fun(&System::do_callbacks), "do_callbacks");
|
||||
@@ -103,7 +110,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
//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.add(fun(boost::function<void ()>(boost::bind(&System::do_callbacks, boost::ref(system), "Bound Test"))), "do_callbacks");
|
||||
chai.add(fun(&System::do_callbacks, boost::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
|
||||
//Call bound version of do_callbacks
|
||||
chai("do_callbacks()");
|
||||
@@ -136,6 +143,14 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
log("Functor test output", boost::lexical_cast<std::string>(x));
|
||||
|
||||
chai.add(var(boost::shared_ptr<int>()), "nullvar");
|
||||
chai("print(\"This should be true.\"); print(nullvar.is_null())");
|
||||
|
||||
// test the global const action
|
||||
chai.add_global_const(const_var(1), "constvar");
|
||||
chai("def getvar() { return constvar; }");
|
||||
chai("print( getvar() )");
|
||||
|
||||
|
||||
//Ability to create our own container types when needed. std::vector and std::map are
|
||||
//mostly supported currently
|
||||
@@ -145,6 +160,7 @@ int main(int argc, char *argv[]) {
|
||||
// Test ability to register a function that excepts a shared_ptr version of a type
|
||||
chai("take_shared_ptr(\"Hello World as a shared_ptr\");");
|
||||
|
||||
chai.add(fun(&bound_log, std::string("Msg")), "BoundFun");
|
||||
|
||||
//Dynamic objects test
|
||||
chai.add(chaiscript::Proxy_Function(new Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
|
||||
|
1
unittests/block_start.chai
Normal file
1
unittests/block_start.chai
Normal file
@@ -0,0 +1 @@
|
||||
{print("hello")}
|
1
unittests/block_start.txt
Normal file
1
unittests/block_start.txt
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
7
unittests/classification.chai
Normal file
7
unittests/classification.chai
Normal file
@@ -0,0 +1,7 @@
|
||||
print(1.is_var_const());
|
||||
print(1.is_var_reference());
|
||||
print(1.is_var_pointer());
|
||||
print(1.is_var_null());
|
||||
print(1.is_var_undef());
|
||||
var i;
|
||||
print(i.is_var_undef());
|
6
unittests/classification.txt
Normal file
6
unittests/classification.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
true
|
||||
false
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
@@ -1 +1 @@
|
||||
Error: "Mismatched types in equation" in 'unittests/invalid_function_assignment.chai' at (1, 7)
|
||||
Error: "Mismatched types in equation, lhs is const." in 'unittests/invalid_function_assignment.chai' at (1, 7)
|
||||
|
@@ -1 +1 @@
|
||||
Error: "Mismatched types in equation" in 'unittests/invalid_function_reassignment.chai' at (2, 3)
|
||||
Error: "Mismatched types in equation." in 'unittests/invalid_function_reassignment.chai' at (2, 3)
|
||||
|
4
unittests/is_undef.chai
Normal file
4
unittests/is_undef.chai
Normal file
@@ -0,0 +1,4 @@
|
||||
var i;
|
||||
print(i.is_var_undef());
|
||||
i = 5;
|
||||
print(i.is_var_undef());
|
2
unittests/is_undef.txt
Normal file
2
unittests/is_undef.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
true
|
||||
false
|
2
unittests/number_formats.chai
Normal file
2
unittests/number_formats.chai
Normal file
@@ -0,0 +1,2 @@
|
||||
print(012)
|
||||
print(0x1f)
|
2
unittests/number_formats.txt
Normal file
2
unittests/number_formats.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
10
|
||||
31
|
8
unittests/operator_overload.chai
Normal file
8
unittests/operator_overload.chai
Normal file
@@ -0,0 +1,8 @@
|
||||
def Bob::`+`(y) { this.x + y.x }
|
||||
def Bob::Bob() { }
|
||||
attr Bob::x
|
||||
var b = Bob()
|
||||
var c = Bob()
|
||||
b.x = 4
|
||||
c.x = 5
|
||||
print(b+c)
|
1
unittests/operator_overload.txt
Normal file
1
unittests/operator_overload.txt
Normal file
@@ -0,0 +1 @@
|
||||
9
|
8
unittests/operator_overload2.chai
Normal file
8
unittests/operator_overload2.chai
Normal file
@@ -0,0 +1,8 @@
|
||||
def Bob::Bob() { }
|
||||
attr Bob::x
|
||||
def `-`(a, b) : is_type(a, "Bob") && is_type(b, "Bob") { a.x - b.x }
|
||||
var b = Bob()
|
||||
var c = Bob()
|
||||
b.x = 4
|
||||
c.x = 5
|
||||
print(b-c)
|
1
unittests/operator_overload2.txt
Normal file
1
unittests/operator_overload2.txt
Normal file
@@ -0,0 +1 @@
|
||||
-1
|
15
unittests/operators_float.chai
Normal file
15
unittests/operators_float.chai
Normal file
@@ -0,0 +1,15 @@
|
||||
var i = 1.0;
|
||||
var j = 2.0;
|
||||
var k = 3.0;
|
||||
|
||||
print(i + j);
|
||||
print(+i);
|
||||
print(i - j);
|
||||
print(-i);
|
||||
print(k / j);
|
||||
print(j * k);
|
||||
|
||||
print(i -= 1);
|
||||
print(j *= 1.5);
|
||||
print(j /= 2);
|
||||
print(j += 1);
|
10
unittests/operators_float.txt
Normal file
10
unittests/operators_float.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
3
|
||||
1
|
||||
-1
|
||||
-1
|
||||
1.5
|
||||
6
|
||||
0
|
||||
3
|
||||
1.5
|
||||
2.5
|
32
unittests/operators_int.chai
Normal file
32
unittests/operators_int.chai
Normal file
@@ -0,0 +1,32 @@
|
||||
var i = 1;
|
||||
var j = 2;
|
||||
var k = 3;
|
||||
|
||||
print(i + j);
|
||||
print(+i);
|
||||
print(i - j);
|
||||
print(-i);
|
||||
print(j & k);
|
||||
print(~j);
|
||||
print(j ^ k);
|
||||
print(i | j);
|
||||
print(j / i);
|
||||
print(i << j);
|
||||
print(j * k);
|
||||
print(k % j);
|
||||
print(j >> i);
|
||||
|
||||
print(i &= 2);
|
||||
print(j ^= 3);
|
||||
print(j |= 2);
|
||||
print(i -= 1);
|
||||
print(j <<= 1);
|
||||
print(j *= 2);
|
||||
print(j /= 2);
|
||||
print(j %= 4);
|
||||
print(j >>= 1);
|
||||
print(j += 1);
|
||||
print(--j);
|
||||
print(++j);
|
||||
|
||||
|
25
unittests/operators_int.txt
Normal file
25
unittests/operators_int.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
3
|
||||
1
|
||||
-1
|
||||
-1
|
||||
2
|
||||
-3
|
||||
1
|
||||
3
|
||||
2
|
||||
4
|
||||
6
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
3
|
||||
-1
|
||||
6
|
||||
12
|
||||
6
|
||||
2
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
5
unittests/range_contains.chai
Normal file
5
unittests/range_contains.chai
Normal file
@@ -0,0 +1,5 @@
|
||||
var v = [1,2,"hi", "world", 5.5]
|
||||
print(v.contains(5.5));
|
||||
print(v.contains(0));
|
||||
print(v.contains(1, lt));
|
||||
print(v.contains(2, `==`));
|
4
unittests/range_contains.txt
Normal file
4
unittests/range_contains.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
5
unittests/range_find.chai
Normal file
5
unittests/range_find.chai
Normal file
@@ -0,0 +1,5 @@
|
||||
var v = [2, 1, "Hi", 5.5]
|
||||
var r = v.find("Hi");
|
||||
print(r);
|
||||
var r2 = v.find(2, `<`);
|
||||
print(r2);
|
2
unittests/range_find.txt
Normal file
2
unittests/range_find.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
[Hi, 5.5]
|
||||
[1, Hi, 5.5]
|
1
unittests/shift.chai
Normal file
1
unittests/shift.chai
Normal file
@@ -0,0 +1 @@
|
||||
print(2 << 2)
|
1
unittests/shift.txt
Normal file
1
unittests/shift.txt
Normal file
@@ -0,0 +1 @@
|
||||
8
|
10
unittests/type_info.chai
Normal file
10
unittests/type_info.chai
Normal file
@@ -0,0 +1,10 @@
|
||||
print(string_type.name());
|
||||
print(string_type.is_type_const());
|
||||
print(string_type.is_type_reference());
|
||||
print(string_type.is_type_void());
|
||||
print(string_type.is_type_undef());
|
||||
print(string_type.is_type_pointer());
|
||||
print("string".get_type_info().name());
|
||||
print(string_type.bare_equal("string".get_type_info()));
|
||||
|
||||
print("bob".is_type(string_type));
|
9
unittests/type_info.txt
Normal file
9
unittests/type_info.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
string
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
string
|
||||
true
|
||||
true
|
Reference in New Issue
Block a user