Compare commits

..

20 Commits

Author SHA1 Message Date
Jason Turner
d2d752ecd4 Fix registration of module loading functions 2009-10-19 14:00:48 +00:00
Jason Turner
a18c701866 Fix type-shifting of bind_first for free function pointer types 2009-10-16 15:49:46 +00:00
Jason Turner
9871604a48 Make sure example.cpp compilable with new setup 2009-10-15 15:55:16 +00:00
Jason Turner
b1d12fdc91 Further updates to the new bound function support, plus general cleanup of how it is used 2009-10-15 15:27:16 +00:00
Jason Turner
24e717d532 Fix "bind_first" for non member functions 2009-10-14 22:42:45 +00:00
Jason Turner
1568fedebd Reduce # of required versions for bound_fun and enhance it to work with non-member functions 2009-10-14 17:19:42 +00:00
Jonathan Turner
c88578d537 Add another unit test for operator overloading 2009-10-14 14:00:22 +00:00
Jonathan Turner
9827345213 Fix Id Literals so that they are keyed off an Id search. This allows us to add operator overloading on the parse side. 2009-10-14 13:51:35 +00:00
Jonathan Turner
c51d14fb13 Add some missing unit tests for number formats and block starting 2009-10-14 12:25:21 +00:00
Jason Turner
480761c1f7 Add bound_fun helper and put it to use cleaning up the engine bootstrapping 2009-10-14 02:34:09 +00:00
Jonathan Turner
12e909d9aa Add bit shifting operators 2009-10-13 03:35:01 +00:00
Jason Turner
b1e892487f Enhance "is_type" to be more accurate and to work with Dynamic_Object types 2009-10-13 03:31:56 +00:00
Jason Turner
720eabcb16 Impliment range find functions and add unit test for contains and find. 2009-10-13 02:05:18 +00:00
Jason Turner
1fde71f3f4 Add type generic comparison operations "eq", "gt", and "lt" and port the "contains" operation to use it 2009-10-13 00:18:59 +00:00
Jonathan Turner
90f8b77171 Added .contains() to ranges 2009-10-11 20:02:21 +00:00
Jonathan Turner
315d7521a7 Clean up warnings. Add simple blocks. 2009-10-08 03:01:19 +00:00
Jonathan Turner
ff177b5eaf Add octal support 2009-10-06 21:17:23 +00:00
Jonathan Turner
46fd7e9a58 Add hex value parsing support 2009-10-06 16:04:05 +00:00
Jason Turner
edd274ccce Fix some more obscure warnings 2009-10-06 02:26:47 +00:00
Jonathan Turner
a5b2ec3006 Start code cleanups by moving chaiscript common structures into their own file. 2009-09-23 05:00:14 +00:00
26 changed files with 540 additions and 321 deletions

View File

@@ -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"

View 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

View File

@@ -50,6 +50,18 @@ namespace chaiscript
return p1 % p2;
}
template<typename Ret, typename P1, typename P2>
Ret shift_left(P1 p1, P2 p2)
{
return p1 << p2;
}
template<typename Ret, typename P1, typename P2>
Ret shift_right(P1 p1, P2 p2)
{
return p1 >> p2;
}
template<typename P1, typename P2>
P1 &assign(P1 &p1, const P2 &p2)
{
@@ -717,6 +729,8 @@ namespace chaiscript
opers_arithmetic_pod(m);
m->add(fun(&detail::modulus<int, int, int>), "%");
m->add(fun(&detail::shift_left<int, int, int>), "<<");
m->add(fun(&detail::shift_right<int, int, int>), ">>");
m->add(fun(&print), "print_string");
m->add(fun(&println), "println_string");

View File

@@ -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
@@ -344,11 +345,11 @@ 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;
}
}
@@ -574,13 +575,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();
if (get_type(user_typename).bare_equal(r.get_type_info()))
{
return true;
}
} catch (const std::range_error &) {
return false;
}
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

View File

@@ -359,7 +359,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)
{
}

View File

@@ -4,15 +4,15 @@
// 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>
namespace chaiscript
{
@@ -28,75 +28,63 @@ namespace chaiscript
}
template<typename T>
Proxy_Function fun_helper(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
boost::function<T> mk_boost_fun(const boost::function<T> &f)
{
return f;
}
template<typename T>
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
> mk_boost_fun(T t)
{
return
boost::function<
typename boost::function_types::function_type<boost::function_types::components<T> >::type
>(t);
}
/**
* 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)));
}
template<typename T>
Proxy_Function fun_helper(const boost::function<T> &f)
{
return Proxy_Function(new Proxy_Function_Impl<T>(f));
}
}
}
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/register_function.hpp>
#include BOOST_PP_ITERATE()
template<typename T>
Proxy_Function fun(const boost::function<T> &f)
{
return detail::fun_helper(f);
}
namespace chaiscript
{
template<typename T>
Proxy_Function fun(T t)
{
return detail::fun_helper(t);
return detail::fun_helper(detail::mk_boost_fun(t));
}
template<typename T, typename Q>
Proxy_Function fun(T t, const Q &q)
{
return detail::fun_helper(bind_first(t, q));
}
template<typename T, typename Q, typename R>
Proxy_Function fun(T t, const Q &q, const R &r)
{
return detail::fun_helper(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

View File

@@ -0,0 +1,135 @@
// 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,
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, Shift }; };
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", "Shift"};
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 */

View File

@@ -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);
@@ -295,8 +300,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)
@@ -486,42 +491,29 @@ 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(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::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<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");

View File

@@ -9,6 +9,8 @@
#include <map>
#include <chaiscript/language/chaiscript_common.hpp>
namespace chaiscript
{
/**
@@ -150,22 +152,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,10 +163,10 @@ 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]);
@@ -550,7 +538,6 @@ 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;
@@ -586,9 +573,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);
}
@@ -1115,6 +1100,7 @@ namespace chaiscript
case (Token_Type::Comparison) :
case (Token_Type::Additive) :
case (Token_Type::Multiplicative) :
case (Token_Type::Shift) :
return eval_comp_add_mul(ss, node);
break;

View File

@@ -9,6 +9,7 @@
#include <exception>
#include <fstream>
#include <sstream>
#include "chaiscript_prelude.hpp"
@@ -30,6 +31,9 @@ namespace chaiscript
singleline_comment = "//";
}
ChaiScript_Parser(const ChaiScript_Parser &); // explicitly unimplemented copy constructor
ChaiScript_Parser &operator=(const ChaiScript_Parser &); // explicitly unimplemented assignment operator
/**
* Prints the parsed tokens as a tree
*/
@@ -68,7 +72,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());
@@ -140,6 +144,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 +167,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 +215,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 +242,20 @@ namespace chaiscript
}
else {
std::string match(start, input_pos);
TokenPtr t(new Token(match, Token_Type::Int, filename, prev_line, prev_col, line, col));
match_stack.push_back(t);
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 +278,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,10 +321,19 @@ namespace chaiscript
int prev_col = col;
int prev_line = line;
if (Id_()) {
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;
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;
@@ -935,16 +1036,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();
@@ -1206,7 +1297,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;
@@ -1326,53 +1417,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
*/
@@ -1442,11 +1486,11 @@ namespace chaiscript
int prev_stack_top = match_stack.size();
if (Additive()) {
if (Shift()) {
retval = true;
if (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)) {
do {
if (!Additive()) {
if (!Shift()) {
throw Eval_Error("Incomplete comparison expression", File_Position(line, col), filename);
}
} while (retval && (Symbol(">=", true) || Symbol(">", true) || Symbol("<=", true) || Symbol("<", true) || Symbol("==", true) || Symbol("!=", true)));
@@ -1530,6 +1574,30 @@ namespace chaiscript
return retval;
}
/**
* Top-level expression, parses a string of binary boolean operators from input
*/
bool Shift() {
bool retval = false;
int prev_stack_top = match_stack.size();
if (Additive()) {
retval = true;
if (Symbol("<<", true) || Symbol(">>", true)) {
do {
if (!Additive()) {
throw Eval_Error("Incomplete shift expression", File_Position(line, col), filename);
}
} while (retval && (Symbol("<<", true) || Symbol(">>", true)));
build_match(Token_Type::Shift, prev_stack_top);
}
}
return retval;
}
/**
* Top-level expression, parses a string of binary boolean operators from input
*/
@@ -1712,6 +1780,11 @@ namespace chaiscript
retval = true;
saw_eol = true;
}
else if (Block()) {
has_more = true;
retval = true;
saw_eol = true;
}
else {
has_more = false;
}

View File

@@ -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, size_t(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, size_t(-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, size_t(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, size_t(-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, size_t(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, size_t(-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_ */

View File

@@ -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), "Bound Test"), "do_callbacks");
//Call bound version of do_callbacks
chai("do_callbacks()");
@@ -145,6 +152,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");

View File

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

View File

@@ -0,0 +1 @@
hello

View File

@@ -0,0 +1,2 @@
print(012)
print(0x1f)

View File

@@ -0,0 +1,2 @@
10
31

View 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)

View File

@@ -0,0 +1 @@
9

View 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)

View File

@@ -0,0 +1 @@
-1

View 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, `==`));

View File

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

View 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
View File

@@ -0,0 +1,2 @@
[Hi, 5.5]
[1, Hi, 5.5]

1
unittests/shift.chai Normal file
View File

@@ -0,0 +1 @@
print(2 << 2)

1
unittests/shift.txt Normal file
View File

@@ -0,0 +1 @@
8