Compare commits

...

51 Commits

Author SHA1 Message Date
Jason Turner
4f99687f1e Merge branch 'cleanups_and_reworkds' into typed_reworks 2016-04-20 07:13:28 -06:00
Jason Turner
7d11b7c5f1 Merge branch 'develop' into typed_function_ordering 2016-04-20 06:41:37 -06:00
Jason Turner
06b2893bfb Update tests for removal of ChaiScript_Parser from stdlib 2016-04-17 21:15:59 -06:00
Jason Turner
7ab6bce7fa Untangle chaiscript_engine from the rest of it 2016-04-17 21:14:01 -06:00
Jason Turner
f9294c8cbe Remove ChaiScript_Parser from stdlib, unnecessary 2016-04-17 16:55:08 -06:00
Jason Turner
80cc18bf2f Make type_info fully constexpr
- Minor hit in compile size
 - Minor improvement in runtime
2016-04-17 08:15:24 -06:00
Jason Turner
c68488388e Remove some unused code in Boxed_Value 2016-04-16 22:14:02 -06:00
Jason Turner
7d5a97aa2f Clean up if block parsing and eval 2016-04-16 15:39:32 -06:00
Jason Turner
83c6df11f0 Fix global reference assignment 2016-04-16 14:30:12 -06:00
Jason Turner
10b984556d Add global & test 2016-04-16 14:23:11 -06:00
Jason Turner
cf2fa09d6c Eliminate branching in var decl 2016-04-16 14:13:14 -06:00
Jason Turner
f3f84594ee A few parser cleanups 2016-04-16 12:04:18 -06:00
Jason Turner
57aa874c6e Revert "Prefer make_unique over make_shared"
This reverts commit 5a947b5035dc99d2dbef35a220340036886e189c.
2016-04-16 09:02:38 -06:00
Jason Turner
32bd936a18 Remove 'annotation' feature 2016-04-16 07:52:39 -06:00
Jason Turner
498339c202 Remove some dead parser code 2016-04-16 07:35:30 -06:00
Jason Turner
56b4f465a1 Add warning on platforms without thread_local 2016-04-15 23:09:20 -06:00
Jason Turner
1a42614441 Remove unnecessary code 2016-04-15 23:02:42 -06:00
Jason Turner
6fa83bca85 Remove Do_Call helper class 2016-04-15 15:31:19 -06:00
Jason Turner
7d9dbc3d86 Fix some boxed_cast issues introduced with refactor 2016-04-14 19:06:37 -06:00
Jason Turner
49dfdfd15a Fix some boxed_cast and exception issues 2016-04-14 12:03:55 -06:00
Jason Turner
720395e47a clean up reflection tests for new capabilities 2016-04-14 09:31:38 -06:00
Jason Turner
5e0a882b18 Bootstrap simplifications 2016-04-13 21:08:25 -06:00
Jason Turner
9603d3910a Get multifile compiling 2016-04-13 15:26:36 -06:00
Jason Turner
6f0d02f158 Massive simplification of boxed_cast. More planned 2016-04-13 14:09:08 -06:00
Jason Turner
8d808f75c0 Remove pretty_print functionality 2016-04-13 12:04:55 -06:00
Jason Turner
2a1632f213 Merge branch 'develop' into cleanups_and_reworkds 2016-04-11 17:48:31 -06:00
Jason Turner
b594043eef Clean up redundant code 2016-04-11 09:36:23 -06:00
Jason Turner
fe8f8a89a7 Implement constant expression folding 2016-04-11 08:19:02 -06:00
Jason Turner
40694c798c Eliminate Str_AST_Node 2016-04-10 23:12:35 -06:00
Jason Turner
443828fa23 More parser simplification 2016-04-10 22:27:35 -06:00
Jason Turner
866db4ee8b Reduce instances of Str_AST_Node 2016-04-10 21:38:44 -06:00
Jason Turner
5e97f459d8 Remove unnecessary false 2016-04-10 19:01:55 -06:00
Jason Turner
e02ac78195 Remove Char_AST_Node 2016-04-10 18:57:23 -06:00
Jason Turner
62cd8031ac Make quoted strings into Constants 2016-04-10 18:29:16 -06:00
Jason Turner
61dfcb00c0 Move int/float into Constant 2016-04-10 17:19:48 -06:00
Jason Turner
4bf619c80f some initialization and destructor cleanups 2016-04-09 22:10:06 -06:00
Jason Turner
08a68f310a Move to strongly typed algebraic enum 2016-04-09 21:50:23 -06:00
Jason Turner
641ac1a1ae Split up ifdef'd module code 2016-04-09 21:49:12 -06:00
Jason Turner
2400c64c82 Move to strongly typed enums for node types 2016-04-09 21:15:07 -06:00
Jason Turner
1e584048ce Remove std::function from bind_first 2016-04-09 21:00:07 -06:00
Jason Turner
82a69ca043 Merge branch 'develop' into typed_function_ordering 2016-03-15 12:46:47 -06:00
Jason Turner
dfb2394b0b Merge branch 'update_travis_toolchain' into typed_function_ordering 2016-03-11 15:00:28 -07:00
Jason Turner
c07f413694 Merge branch 'develop' into typed_function_ordering 2016-03-04 13:33:29 -07:00
Jason Turner
172ab7b8e4 Merge branch 'develop' into typed_function_ordering 2016-02-18 08:57:55 -07:00
Jason Turner
fe8ddd1869 Merge branch 'develop' into typed_function_ordering 2016-01-20 18:32:16 -07:00
Jason Turner
5cb6f6a1a2 Merge branch 'develop' into typed_function_ordering 2016-01-20 18:28:28 -07:00
Jason Turner
95256417ac Merge branch 'add_performance_tests' of github.com:ChaiScript/ChaiScript into typed_function_ordering 2015-10-25 15:00:08 -06:00
Jason Turner
2d2251c1da Merge branch 'develop' of github.com:ChaiScript/ChaiScript into typed_function_ordering 2015-08-26 18:58:34 -06:00
Jason Turner
0adacc0b5e Merge branch 'develop' of github.com:ChaiScript/ChaiScript into typed_function_ordering 2015-08-26 18:47:43 -06:00
Jason Turner
818fd0b823 Add function ordering test 2015-08-26 18:47:32 -06:00
Jason Turner
bd9af5eff4 Order typed functions over untyped
specifically the chaiscript defined ones
2015-08-14 21:58:54 -06:00
36 changed files with 1273 additions and 1962 deletions

View File

@ -695,11 +695,10 @@
/// Begins a function or method definition
///
/// ~~~~~~~~
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
/// ~~~~~~~~
///
/// annotation: meta-annotation on function, currently used as documentation. Optional.
/// identifier: name of function. Required.
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
/// guards: guarding statement that act as a prerequisite for the function. Optional.

View File

@ -89,6 +89,54 @@ namespace chaiscript {
#endif
}
struct Build_Info {
static int version_major()
{
return chaiscript::version_major;
}
static int version_minor()
{
return chaiscript::version_minor;
}
static int version_patch()
{
return chaiscript::version_patch;
}
static std::string version()
{
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
{
return chaiscript::compiler_name;
}
static bool debug_build()
{
return chaiscript::debug_build;
}
};
template<typename Iter, typename Distance>
Iter advance_copy(Iter iter, Distance distance) {
std::advance(iter, static_cast<typename std::iterator_traits<Iter>::difference_type>(distance));

View File

@ -14,11 +14,15 @@
#include <vector>
#include "chaiscript_defines.hpp"
#include "dispatchkit/dispatchkit.hpp"
#include "language/chaiscript_common.hpp"
//#include "dispatchkit/dispatchkit.hpp"
#include "dispatchkit/operators.hpp"
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp"
//#include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.hpp"
#include "dispatchkit/register_function.hpp"
#include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS
@ -38,15 +42,15 @@ namespace chaiscript
static ModulePtr library()
{
using namespace bootstrap;
// using namespace bootstrap;
auto lib = std::make_shared<Module>();
Bootstrap::bootstrap(*lib);
bootstrap::Bootstrap::bootstrap(*lib);
standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
standard_library::string_type<std::string>("string", *lib);
standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
bootstrap::standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
bootstrap::standard_library::string_type<std::string>("string", *lib);
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
#ifndef CHAISCRIPT_NO_THREADS
standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);

View File

@ -108,6 +108,9 @@ namespace chaiscript
#else
#pragma message ("Threading without thread_local support is not well supported.")
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
///

View File

@ -27,45 +27,52 @@ namespace chaiscript
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
auto bind_first(Ret (*f)(P1, Param...), O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(std::forward<O>(o), std::forward<Param>(param)...);
}
);
return [f, o](Param...param) -> Ret {
return f(std::forward<O>(o), std::forward<Param>(param)...);
};
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
auto bind_first(Ret (Class::*f)(Param...), O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
return [f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
};
}
template<typename O, typename Ret, typename Class, typename ... Param>
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
}
);
return [f, o](Param...param) -> Ret {
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
};
}
template<typename O, typename Ret, typename P1, typename ... Param>
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
auto bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
{
return std::function<Ret (Param...)>(
[f, o](Param...param) -> Ret {
return f(o, std::forward<Param>(param)...);
});
return [f, o](Param...param) -> Ret {
return f(o, std::forward<Param>(param)...);
};
}
template<typename F, typename O, typename Ret, typename Class, typename P1, typename ... Param>
auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
{
return [fo, o, f](Param ...param) -> Ret {
return (fo.*f)(o, std::forward<Param>(param)...);
};
}
template<typename F, typename O>
auto bind_first(const F &f, O&& o)
{
return bind_first(f, std::forward<O>(o), &F::operator());
}
}
}

View File

@ -7,32 +7,8 @@
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
#define CHAISCRIPT_BOOTSTRAP_HPP_
#include <cstdint>
#include <exception>
#include <functional>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>
#include <iterator>
#include "bad_boxed_cast.hpp"
#include "boxed_cast.hpp"
#include "boxed_number.hpp"
#include "boxed_value.hpp"
#include "dispatchkit.hpp"
#include "type_conversions.hpp"
#include "dynamic_object.hpp"
#include "operators.hpp"
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "proxy_functions_detail.hpp"
#include "register_function.hpp"
#include "type_info.hpp"
#include "../utility/utility.hpp"
#include "../language/chaiscript_common.hpp"
#include "register_function.hpp"
namespace chaiscript
{
@ -138,15 +114,6 @@ namespace chaiscript
}
/// to_string function for internal use. Uses ostream operator<<
template<typename Input>
std::string to_string(Input i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
/// Internal function for converting from a string to a value
/// uses ostream operator >> to perform the conversion
template<typename Input>
@ -288,8 +255,6 @@ namespace chaiscript
m.add(fun(&Boxed_Number::product), "*");
m.add(fun(&Boxed_Number::remainder), "%");
m.add(fun(&Boxed_Number::shift_right), ">>");
}
/// Create a bound function object. The first param is the function to bind
@ -329,26 +294,6 @@ namespace chaiscript
}
}
static void throw_exception(const Boxed_Value &bv) {
throw bv;
}
static std::string what(const std::exception &e)
{
return e.what();
}
/// Boolean specialization of internal to_string function
static std::string bool_to_string(bool b)
{
if (b)
{
return "true";
} else {
return "false";
}
}
template<typename FunctionType>
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
const dispatch::Proxy_Function_Base *b)
@ -384,7 +329,7 @@ namespace chaiscript
}
template<typename Function>
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
static auto return_boxed_value_vector(const Function &f)
{
return [f](const dispatch::Proxy_Function_Base *b) {
return do_return_boxed_value_vector(f, b);
@ -407,13 +352,13 @@ namespace chaiscript
m.add(user_type<std::exception>(), "exception");
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m.add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
m.add(fun([](const std::exception &e){ return std::string(e.what()); }), "what");
m.add(user_type<std::out_of_range>(), "out_of_range");
m.add(user_type<std::logic_error>(), "logic_error");
@ -425,7 +370,6 @@ namespace chaiscript
m.add(chaiscript::base_class<std::exception, std::runtime_error>());
m.add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
m.add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
m.add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
m.add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
@ -520,15 +464,15 @@ namespace chaiscript
operators::equal<bool>(m);
operators::not_equal<bool>(m);
m.add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
m.add(fun(&Bootstrap::bool_to_string), "to_string");
m.add(fun([](const std::string &s) { return s; }), "to_string");
m.add(fun([](const bool b) { return std::string(b?"true":"false"); }), "to_string");
m.add(fun(&unknown_assign), "=");
m.add(fun(&throw_exception), "throw");
m.add(fun(&what), "what");
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
m.add(fun(&to_string<char>), "to_string");
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
m.add(fun(&Boxed_Number::to_string), "to_string");
bootstrap_pod_type<double>("double", m);
bootstrap_pod_type<long double>("long_double", m);
bootstrap_pod_type<float>("float", m);
@ -552,10 +496,21 @@ namespace chaiscript
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
operators::logical_compliment<bool>(m);
opers_arithmetic_pod(m);
m.add(fun(&Build_Info::version_major), "version_major");
m.add(fun(&Build_Info::version_minor), "version_minor");
m.add(fun(&Build_Info::version_patch), "version_patch");
m.add(fun(&Build_Info::version), "version");
m.add(fun(&Build_Info::compiler_version), "compiler_version");
m.add(fun(&Build_Info::compiler_name), "compiler_name");
m.add(fun(&Build_Info::compiler_id), "compiler_id");
m.add(fun(&Build_Info::debug_build), "debug_build");
m.add(fun(&print), "print_string");
m.add(fun(&println), "println_string");
@ -580,9 +535,11 @@ namespace chaiscript
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
@ -593,13 +550,13 @@ namespace chaiscript
{ },
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
std::vector<Boxed_Value> retval;
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<const chaiscript::AST_Node> &>);
return retval;
})), "call_stack"} }
}), "call_stack"} }
);
@ -621,24 +578,16 @@ namespace chaiscript
{fun(&AST_Node::start), "start"},
{fun(&AST_Node::end), "end"},
{fun(&AST_Node::to_string), "to_string"},
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
{fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
std::vector<Boxed_Value> retval;
std::transform(t_node.children.begin(), t_node.children.end(),
std::back_inserter(retval),
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
return retval;
})), "children"},
{fun(&AST_Node::replace_child), "replace_child"}
}), "children"}
}
);
chaiscript::utility::add_class<parser::ChaiScript_Parser>(m,
"ChaiScript_Parser",
{ constructor<parser::ChaiScript_Parser ()>() },
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
);
}
};
}

View File

@ -69,11 +69,11 @@ namespace chaiscript
/// assert(i == 5);
/// \endcode
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
{
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
return(detail::Cast_Helper<Type>::cast(bv, t_conversions));
} catch (const chaiscript::detail::exception::bad_any_cast &) {
}
}
@ -84,11 +84,11 @@ namespace chaiscript
try {
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions);
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
} catch (...) {
try {
// try going the other way
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}

View File

@ -29,21 +29,50 @@ namespace chaiscript
throw std::runtime_error("Attempted to dereference null Boxed_Value");
}
template<typename T>
static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
if (ob.get_type_info() == ti) {
return ptr;
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename T>
static T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
if (!ob.is_const() && ob.get_type_info() == ti) {
return ptr;
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename T>
static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
if (ob.get_type_info().bare_equal_type_info(ti)) {
return throw_if_null(ptr);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
template<typename T>
static T *verify_type(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) {
return throw_if_null(ptr);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
/// Generic Cast_Helper_Inner, for casting to any type
template<typename Result>
struct Cast_Helper_Inner
{
typedef typename std::add_const<Result>::type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
}
};
@ -57,15 +86,9 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<const Result *>
{
typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return static_cast<const Result *>(ob.get_const_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
}
};
@ -73,15 +96,9 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<Result *>
{
typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
{
return static_cast<Result *>(ob.get_ptr());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
}
};
@ -100,17 +117,9 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<const Result &>
{
typedef const Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
auto p = throw_if_null(ob.get_const_ptr());
return *static_cast<const Result *>(p);
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
}
};
@ -120,16 +129,9 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<Result &>
{
typedef Result& Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
{
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
}
};
@ -137,9 +139,7 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<std::shared_ptr<Result> >
{
typedef std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob.get().cast<std::shared_ptr<Result> >();
}
@ -149,9 +149,7 @@ namespace chaiscript
template<typename Result>
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
{
typedef std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
if (!ob.get_type_info().is_const())
{
@ -177,10 +175,7 @@ namespace chaiscript
struct Cast_Helper_Inner<std::shared_ptr<Result> &>
{
static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
typedef Boxed_Value::Sentinel<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
return ob.pointer_sentinel(res);
@ -204,9 +199,7 @@ namespace chaiscript
template<>
struct Cast_Helper_Inner<Boxed_Value>
{
typedef Boxed_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return ob;
}
@ -216,9 +209,7 @@ namespace chaiscript
template<>
struct Cast_Helper_Inner<Boxed_Value &>
{
typedef std::reference_wrapper<Boxed_Value> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return std::ref(const_cast<Boxed_Value &>(ob));
}
@ -272,11 +263,9 @@ namespace chaiscript
template<typename T>
struct Cast_Helper
{
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
}
};
}

View File

@ -162,17 +162,17 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::equals:
case Operators::Opers::equals:
return const_var(t == u);
case Operators::less_than:
case Operators::Opers::less_than:
return const_var(t < u);
case Operators::greater_than:
case Operators::Opers::greater_than:
return const_var(t > u);
case Operators::less_than_equal:
case Operators::Opers::less_than_equal:
return const_var(t <= u);
case Operators::greater_than_equal:
case Operators::Opers::greater_than_equal:
return const_var(t >= u);
case Operators::not_equal:
case Operators::Opers::not_equal:
return const_var(t != u);
default:
throw chaiscript::detail::exception::bad_any_cast();
@ -184,10 +184,10 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::pre_increment:
case Operators::Opers::pre_increment:
++t;
break;
case Operators::pre_decrement:
case Operators::Opers::pre_decrement:
--t;
break;
default:
@ -202,20 +202,20 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::assign:
case Operators::Opers::assign:
t = u;
break;
case Operators::assign_product:
case Operators::Opers::assign_product:
t *= u;
break;
case Operators::assign_sum:
case Operators::Opers::assign_sum:
t += u;
break;
case Operators::assign_quotient:
case Operators::Opers::assign_quotient:
check_divide_by_zero(u);
t /= u;
break;
case Operators::assign_difference:
case Operators::Opers::assign_difference:
t -= u;
break;
default:
@ -230,23 +230,23 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::assign_bitwise_and:
case Operators::Opers::assign_bitwise_and:
t &= u;
break;
case Operators::assign_bitwise_or:
case Operators::Opers::assign_bitwise_or:
t |= u;
break;
case Operators::assign_shift_left:
case Operators::Opers::assign_shift_left:
t <<= u;
break;
case Operators::assign_shift_right:
case Operators::Opers::assign_shift_right:
t >>= u;
break;
case Operators::assign_remainder:
case Operators::Opers::assign_remainder:
check_divide_by_zero(u);
t %= u;
break;
case Operators::assign_bitwise_xor:
case Operators::Opers::assign_bitwise_xor:
t ^= u;
break;
default:
@ -260,7 +260,7 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::bitwise_complement:
case Operators::Opers::bitwise_complement:
return const_var(~t);
default:
throw chaiscript::detail::exception::bad_any_cast();
@ -272,18 +272,18 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::shift_left:
case Operators::Opers::shift_left:
return const_var(t << u);
case Operators::shift_right:
case Operators::Opers::shift_right:
return const_var(t >> u);
case Operators::remainder:
case Operators::Opers::remainder:
check_divide_by_zero(u);
return const_var(t % u);
case Operators::bitwise_and:
case Operators::Opers::bitwise_and:
return const_var(t & u);
case Operators::bitwise_or:
case Operators::Opers::bitwise_or:
return const_var(t | u);
case Operators::bitwise_xor:
case Operators::Opers::bitwise_xor:
return const_var(t ^ u);
default:
throw chaiscript::detail::exception::bad_any_cast();
@ -295,9 +295,9 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::unary_minus:
case Operators::Opers::unary_minus:
return const_var(-t);
case Operators::unary_plus:
case Operators::Opers::unary_plus:
return const_var(+t);
default:
throw chaiscript::detail::exception::bad_any_cast();
@ -309,14 +309,14 @@ namespace chaiscript
{
switch (t_oper)
{
case Operators::sum:
case Operators::Opers::sum:
return const_var(t + u);
case Operators::quotient:
case Operators::Opers::quotient:
check_divide_by_zero(u);
return const_var(t / u);
case Operators::product:
case Operators::Opers::product:
return const_var(t * u);
case Operators::difference:
case Operators::Opers::difference:
return const_var(t - u);
default:
throw chaiscript::detail::exception::bad_any_cast();
@ -328,16 +328,16 @@ namespace chaiscript
-> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
{
typedef typename std::common_type<LHS, RHS>::type common_type;
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
{
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
} else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_int_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
return const_binary_int_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@ -349,12 +349,12 @@ namespace chaiscript
-> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
{
typedef typename std::common_type<LHS, RHS>::type common_type;
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
{
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@ -366,11 +366,11 @@ namespace chaiscript
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
-> typename std::enable_if<!std::is_floating_point<LHS>::value, Boxed_Value>::type
{
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
return const_unary_int_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@ -381,9 +381,9 @@ namespace chaiscript
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
-> typename std::enable_if<std::is_floating_point<LHS>::value, Boxed_Value>::type
{
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
} else if (t_oper > Operators::const_flag) {
} else if (t_oper > Operators::Opers::const_flag) {
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
} else {
throw chaiscript::detail::exception::bad_any_cast();
@ -645,71 +645,6 @@ namespace chaiscript
throw chaiscript::detail::exception::bad_any_cast();
}
bool operator==(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
}
bool operator<(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
}
bool operator>(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
}
bool operator>=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
}
bool operator<=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
}
bool operator!=(const Boxed_Number &t_rhs) const
{
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
}
Boxed_Number operator--()
{
return oper(Operators::pre_decrement, this->bv);
}
Boxed_Number operator++()
{
return oper(Operators::pre_increment, this->bv);
}
Boxed_Number operator+(const Boxed_Number &t_rhs) const
{
return oper(Operators::sum, this->bv, t_rhs.bv);
}
Boxed_Number operator+() const
{
return oper(Operators::unary_plus, this->bv);
}
Boxed_Number operator-() const
{
return oper(Operators::unary_minus, this->bv);
}
Boxed_Number operator-(const Boxed_Number &t_rhs) const
{
return oper(Operators::difference, this->bv, t_rhs.bv);
}
Boxed_Number operator&=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
}
static void validate_boxed_number(const Boxed_Value &v)
{
const Type_Info &inp_ = v.get_type_info();
@ -724,266 +659,165 @@ namespace chaiscript
}
}
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Value &v)
{
validate_boxed_number(v);
bv = v;
return *this;
}
// cppcheck-suppress operatorEq
Boxed_Number operator=(const Boxed_Number &t_rhs) const
{
return oper(Operators::assign, this->bv, t_rhs.bv);
}
Boxed_Number operator|=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator^=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator%=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
}
Boxed_Number operator&(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
}
Boxed_Number operator~() const
{
return oper(Operators::bitwise_complement, this->bv);
}
Boxed_Number operator^(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
}
Boxed_Number operator|(const Boxed_Number &t_rhs) const
{
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
}
Boxed_Number operator*=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, this->bv, t_rhs.bv);
}
Boxed_Number operator/=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator+=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
}
Boxed_Number operator-=(const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
}
Boxed_Number operator/(const Boxed_Number &t_rhs) const
{
return oper(Operators::quotient, this->bv, t_rhs.bv);
}
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_left, this->bv, t_rhs.bv);
}
Boxed_Number operator*(const Boxed_Number &t_rhs) const
{
return oper(Operators::product, this->bv, t_rhs.bv);
}
Boxed_Number operator%(const Boxed_Number &t_rhs) const
{
return oper(Operators::remainder, this->bv, t_rhs.bv);
}
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
{
return oper(Operators::shift_right, this->bv, t_rhs.bv);
}
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
}
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
}
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
}
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
}
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
{
return oper(Operators::pre_decrement, t_lhs.bv);
return oper(Operators::Opers::pre_decrement, t_lhs.bv);
}
static Boxed_Number pre_increment(Boxed_Number t_lhs)
{
return oper(Operators::pre_increment, t_lhs.bv);
return oper(Operators::Opers::pre_increment, t_lhs.bv);
}
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_plus, t_lhs.bv);
return oper(Operators::Opers::unary_plus, t_lhs.bv);
}
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
{
return oper(Operators::unary_minus, t_lhs.bv);
return oper(Operators::Opers::unary_minus, t_lhs.bv);
}
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
{
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
return oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0));
}
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv);
}
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv);
}
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
{
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
return oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv);
}
@ -1009,9 +843,7 @@ namespace chaiscript
template<>
struct Cast_Helper<Boxed_Number>
{
typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
{
return Boxed_Number(ob);
}

View File

@ -77,9 +77,9 @@ namespace chaiscript
struct Object_Data
{
static std::unique_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool t_return_value)
{
return std::make_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
chaiscript::detail::Any(),
false,
@ -89,15 +89,15 @@ namespace chaiscript
}
template<typename T>
static std::unique_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool t_return_value)
{
return get(*obj, t_return_value);
}
template<typename T>
static std::unique_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool t_return_value)
{
return std::make_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(obj),
false,
@ -107,10 +107,10 @@ namespace chaiscript
}
template<typename T>
static std::unique_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool t_return_value)
{
auto ptr = obj.get();
return std::make_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
false,
@ -120,23 +120,23 @@ namespace chaiscript
}
template<typename T>
static std::unique_ptr<Data> get(T *t, bool t_return_value)
static std::shared_ptr<Data> get(T *t, bool t_return_value)
{
return get(std::ref(*t), t_return_value);
}
template<typename T>
static std::unique_ptr<Data> get(const T *t, bool t_return_value)
static std::shared_ptr<Data> get(const T *t, bool t_return_value)
{
return get(std::cref(*t), t_return_value);
}
template<typename T>
static std::unique_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool t_return_value)
{
auto p = &obj.get();
return std::make_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(obj)),
true,
@ -146,11 +146,11 @@ namespace chaiscript
}
template<typename T>
static std::unique_ptr<Data> get(T t, bool t_return_value)
static std::shared_ptr<Data> get(T t, bool t_return_value)
{
auto p = std::make_shared<T>(std::move(t));
auto ptr = p.get();
return std::make_unique<Data>(
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(p)),
false,
@ -159,9 +159,9 @@ namespace chaiscript
);
}
static std::unique_ptr<Data> get()
static std::shared_ptr<Data> get()
{
return std::make_unique<Data>(
return std::make_shared<Data>(
Type_Info(),
chaiscript::detail::Any(),
false,
@ -226,48 +226,39 @@ namespace chaiscript
return m_data->m_type_info.bare_equal(ti);
}
template<typename T>
struct Sentinel {
Sentinel(std::shared_ptr<T> &ptr, Data &data)
: m_ptr(ptr), m_data(data)
{
}
~Sentinel()
{
// save new pointer data
m_data.get().m_data_ptr = m_ptr.get().get();
m_data.get().m_const_data_ptr = m_ptr.get().get();
}
Sentinel& operator=(Sentinel&&s) {
m_ptr = std::move(s.m_ptr);
m_data = std::move(s.m_data);
}
Sentinel(Sentinel &&s)
: m_ptr(std::move(s.m_ptr)),
m_data(std::move(s.m_data))
{
}
operator std::shared_ptr<T>&() const
{
return m_ptr.get();
}
Sentinel &operator=(const Sentinel &) = delete;
Sentinel(Sentinel&) = delete;
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
std::reference_wrapper<Data> m_data;
};
template<typename T>
Sentinel<T> pointer_sentinel(std::shared_ptr<T> &ptr) const
auto pointer_sentinel(std::shared_ptr<T> &ptr) const
{
return Sentinel<T>(ptr, *(m_data.get()));
struct Sentinel {
Sentinel(std::shared_ptr<T> &ptr, Data &data)
: m_ptr(ptr), m_data(data)
{
}
~Sentinel()
{
// save new pointer data
m_data.get().m_data_ptr = m_ptr.get().get();
m_data.get().m_const_data_ptr = m_ptr.get().get();
}
Sentinel& operator=(Sentinel&&s) = default;
Sentinel(Sentinel &&s) = default;
operator std::shared_ptr<T>&() const
{
return m_ptr.get();
}
Sentinel &operator=(const Sentinel &) = delete;
Sentinel(Sentinel&) = delete;
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
std::reference_wrapper<Data> m_data;
};
return Sentinel(ptr, *(m_data.get()));
}
bool is_null() const noexcept

View File

@ -310,11 +310,6 @@ namespace chaiscript
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
}
std::string annotation() const override
{
return "Multiple method dispatch function wrapper.";
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
@ -381,7 +376,6 @@ namespace chaiscript
typedef std::vector<Scope> StackData;
Stack_Holder()
: call_depth(0)
{
stacks.reserve(2);
stacks.emplace_back(1);
@ -392,7 +386,7 @@ namespace chaiscript
std::vector<StackData> stacks;
std::vector<std::vector<Boxed_Value>> call_params;
int call_depth;
int call_depth = 0;
};
/// Main class for the dispatchkit. Handles management
@ -412,11 +406,9 @@ namespace chaiscript
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
std::map<std::string, Boxed_Value> m_global_objects;
Type_Name_Map m_types;
std::set<std::string> m_reserved_words;
State &operator=(const State &) = default;
State() = default;
State(const State &) = default;
std::set<std::string> m_reserved_words
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"};
};
Dispatch_Engine()
@ -424,16 +416,12 @@ namespace chaiscript
{
}
~Dispatch_Engine()
{
}
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
decltype(auto) boxed_cast(const Boxed_Value &bv) const
{
Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
return chaiscript::boxed_cast<Type>(bv, &state);
return(chaiscript::boxed_cast<Type>(bv, &state));
}
/// Add a new conversion for upcasting to a base class
@ -886,12 +874,6 @@ namespace chaiscript
return rets;
}
void add_reserved_word(const std::string &name)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_state.m_reserved_words.insert(name);
}
const Type_Conversions &conversions() const
{
@ -1058,27 +1040,31 @@ namespace chaiscript
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
{
std::vector<Type_Info> params = f.second->get_param_types();
std::string annotation = f.second->annotation();
std::vector<std::pair<std::string, Type_Info>> typed_params;
if (annotation.size() > 0) {
std::cout << annotation;
auto func(std::dynamic_pointer_cast<const dispatch::Dynamic_Function_Interface>(f.second));
if (func) {
typed_params = func->get_dynamic_param_types().types();
}
dump_type(params.front());
std::cout << " " << f.first << "(";
for (std::vector<Type_Info>::const_iterator itr = params.begin() + 1;
itr != params.end();
)
for (size_t i = 1; i < params.size(); ++i)
{
dump_type(*itr);
++itr;
if (!typed_params.empty() && !typed_params[i-1].first.empty()) {
std::cout << typed_params[i-1].first;
} else {
dump_type(params[i]);
}
if (itr != params.end())
{
if (i != params.size() - 1) {
std::cout << ", ";
}
}
std::cout << ") \n";
}
@ -1285,92 +1271,156 @@ namespace chaiscript
return m_state.m_functions;
}
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
static std::vector<Type_Info> param_types(const Proxy_Function &t_f)
{
assert(t_f);
return t_f->get_param_types();
}
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
static std::vector<std::pair<std::string, Type_Info>> param_types(const std::shared_ptr<const dispatch::Dynamic_Function_Interface> &t_f)
{
assert(t_f);
const auto types = t_f->get_dynamic_param_types().types();
std::vector<std::pair<std::string, Type_Info>> ret(1);
ret.insert(ret.end(), types.begin(), types.end());
return ret;
}
if (dynamic_lhs && dynamic_rhs)
static Type_Info type_info(const std::pair<std::string, Type_Info> &t_ti)
{
return t_ti.second;
}
static Type_Info type_info(const Type_Info &t_ti)
{
return t_ti;
}
static std::string dynamic_type_name(const std::pair<std::string, Type_Info> &t_ti)
{
return t_ti.first.empty()?t_ti.second.name():t_ti.first;
}
static std::string dynamic_type_name(const Type_Info &ti)
{
return ti.name();
}
template<typename LHS, typename RHS>
static bool params_less_than(const LHS &t_lhs, const RHS &t_rhs)
{
if (dynamic_lhs->get_guard())
assert(t_lhs);
assert(t_rhs);
const auto lhsparamtypes = param_types(t_lhs);
const auto rhsparamtypes = param_types(t_rhs);
const auto lhssize = lhsparamtypes.size();
const auto rhssize = rhsparamtypes.size();
constexpr auto boxed_type = user_type<Boxed_Value>();
constexpr auto boxed_pod_type = user_type<Boxed_Number>();
constexpr auto dynamic_type = user_type<dispatch::Dynamic_Object>();
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
{
return dynamic_rhs->get_guard() ? false : true;
} else {
return false;
}
}
const Type_Info lt = type_info(lhsparamtypes[i]);
const Type_Info rt = type_info(rhsparamtypes[i]);
const std::string ln = dynamic_type_name(lhsparamtypes[i]);
const std::string rn = dynamic_type_name(rhsparamtypes[i]);
if (dynamic_lhs && !dynamic_rhs)
{
return false;
}
if ( (lt.bare_equal(dynamic_type) || lt.is_undef())
&& (rt.bare_equal(dynamic_type) || rt.is_undef()))
{
if (!dynamic_lhs && dynamic_rhs)
{
return true;
}
if (!ln.empty() && rn.empty()) {
return true;
} else if (ln.empty() && !rn.empty()) {
return false;
} else if (!ln.empty() && !rn.empty()) {
if (ln < rn) {
return true;
} else if (rn < ln) {
return false;
}
const auto &lhsparamtypes = lhs->get_param_types();
const auto &rhsparamtypes = rhs->get_param_types();
// the remaining cases are handled by the is_const rules below
}
}
const auto lhssize = lhsparamtypes.size();
const auto rhssize = rhsparamtypes.size();
if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
{
continue; // The first two types are essentially the same, next iteration
}
static const auto boxed_type = user_type<Boxed_Value>();
static const auto boxed_pod_type = user_type<Boxed_Number>();
// const is after non-const for the same type
if (lt.bare_equal(rt) && lt.is_const() && !rt.is_const())
{
return false;
}
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
{
const Type_Info &lt = lhsparamtypes[i];
const Type_Info &rt = rhsparamtypes[i];
if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
{
continue; // The first two types are essentially the same, next iteration
}
// const is after non-const for the same type
if (lt.bare_equal(rt) && lt.is_const() && !rt.is_const())
{
return false;
}
if (lt.bare_equal(rt) && !lt.is_const())
{
return true;
}
// boxed_values are sorted last
if (lt.bare_equal(boxed_type))
{
return false;
}
if (rt.bare_equal(boxed_type))
{
if (lt.bare_equal(boxed_pod_type))
if (lt.bare_equal(rt) && !lt.is_const())
{
return true;
}
return true;
// boxed_values are sorted last
if (lt.bare_equal(boxed_type))
{
return false;
}
if (rt.bare_equal(boxed_type))
{
return true;
}
if (lt.bare_equal(boxed_pod_type))
{
return false;
}
if (rt.bare_equal(boxed_pod_type))
{
return true;
}
// otherwise, we want to sort by typeid
return lt < rt;
}
if (lt.bare_equal(boxed_pod_type))
{
return false;
// if everything else checks out, sort on guard
//
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_lhs));
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_rhs));
if (dynamic_lhs && dynamic_rhs) {
if (dynamic_lhs->get_guard() && !dynamic_rhs->get_guard()) {
return true;
} else if (dynamic_rhs->get_guard()) {
return false;
}
}
if (rt.bare_equal(boxed_pod_type))
{
return true;
}
// otherwise, we want to sort by typeid
return lt < rt;
return false;
}
return false;
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
{
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Function_Interface>(lhs));
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Function_Interface>(rhs));
if (dynamic_lhs && dynamic_rhs)
{
return params_less_than(dynamic_lhs, dynamic_rhs);
} else if (dynamic_lhs) {
return params_less_than(dynamic_lhs, rhs);
} else if (dynamic_rhs) {
return params_less_than(lhs, dynamic_rhs);
} else {
return params_less_than(lhs, rhs);
}
}
@ -1536,3 +1586,4 @@ namespace chaiscript
#endif

View File

@ -39,7 +39,7 @@ namespace chaiscript
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function final : public Proxy_Function_Base
class Dynamic_Object_Function : public Proxy_Function_Base, public Dynamic_Function_Interface
{
public:
Dynamic_Object_Function(
@ -71,6 +71,17 @@ namespace chaiscript
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
Param_Types get_dynamic_param_types() const override {
auto dynamic(std::dynamic_pointer_cast<dispatch::Dynamic_Function_Interface>(m_func));
if (dynamic) {
return dynamic->get_dynamic_param_types();
} else {
return Param_Types(get_param_types());
}
}
bool operator==(const Proxy_Function_Base &f) const override
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
@ -98,12 +109,6 @@ namespace chaiscript
return {m_func};
}
std::string annotation() const override
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
@ -179,7 +184,7 @@ namespace chaiscript
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor final : public Proxy_Function_Base
class Dynamic_Object_Constructor final : public Proxy_Function_Base, public Dynamic_Function_Interface
{
public:
Dynamic_Object_Constructor(
@ -188,6 +193,7 @@ namespace chaiscript
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
m_type_name(std::move(t_type_name)), m_func(t_func)
{
assert( t_func );
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
@ -205,6 +211,18 @@ namespace chaiscript
return std::vector<Type_Info>(begin, end);
}
virtual Param_Types get_dynamic_param_types() const {
auto dynamic(std::dynamic_pointer_cast<dispatch::Dynamic_Function_Interface>(m_func));
if (dynamic) {
return dynamic->get_dynamic_param_types();
} else {
return Param_Types(get_param_types());
}
}
bool operator==(const Proxy_Function_Base &f) const override
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
@ -219,11 +237,6 @@ namespace chaiscript
return m_func->call_match(new_vals, t_conversions);
}
std::string annotation() const override
{
return m_func->annotation();
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{

View File

@ -81,9 +81,7 @@ namespace chaiscript
template<typename Signature>
struct Cast_Helper<const std::function<Signature> &>
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@ -98,9 +96,7 @@ namespace chaiscript
template<typename Signature>
struct Cast_Helper<std::function<Signature> >
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{
@ -115,9 +111,7 @@ namespace chaiscript
template<typename Signature>
struct Cast_Helper<const std::function<Signature> >
{
typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
{
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{

View File

@ -146,6 +146,14 @@ namespace chaiscript
}
};
template<typename Ret>
struct Handle_Return<const Ret>
{
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
template<typename Ret>
struct Handle_Return<Ret &>
@ -154,11 +162,6 @@ namespace chaiscript
{
return Boxed_Value(std::ref(r));
}
static Boxed_Value handle(const Ret &r)
{
return Boxed_Value(std::cref(r));
}
};
template<>

View File

@ -16,414 +16,202 @@ namespace chaiscript
{
namespace operators
{
namespace detail
{
/// \todo make this return a decltype once we drop gcc 4.6
template<typename L, typename R>
auto assign(L l, R r) -> L&
{
return (l = r);
}
template<typename L, typename R>
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
{
return (l &= r);
}
template<typename L, typename R>
auto assign_xor(L l, R r) -> decltype((l^=r))
{
return (l ^= r);
}
template<typename L, typename R>
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
{
return (l |= r);
}
template<typename L, typename R>
auto assign_difference(L l, R r) -> decltype(( l -= r))
{
return (l -= r);
}
template<typename L, typename R>
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
{
return (l <<= r);
}
template<typename L, typename R>
auto assign_product(L l, R r) -> decltype(( l *= r ))
{
return (l *= r);
}
template<typename L, typename R>
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
{
return (l /= r);
}
template<typename L, typename R>
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
{
return (l %= r);
}
template<typename L, typename R>
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
{
return (l >>= r);
}
/// \todo make this return a decltype once we drop gcc 4.6
template<typename L, typename R>
auto assign_sum(L l, R r) -> L&
{
return (l += r);
}
template<typename L>
auto prefix_decrement(L l) -> decltype(( --l ))
{
return (--l);
}
template<typename L>
auto prefix_increment(L l) -> decltype(( ++l ))
{
return (++l);
}
template<typename L, typename R>
auto equal(L l, R r) -> decltype(( l == r ))
{
return (l == r);
}
template<typename L, typename R>
auto greater_than(L l, R r) -> decltype(( l > r ))
{
return (l > r);
}
template<typename L, typename R>
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
{
return (l >= r);
}
template<typename L, typename R>
auto less_than(L l, R r) -> decltype(( l < r ))
{
return (l < r);
}
template<typename L, typename R>
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
{
return (l <= r);
}
template<typename L>
auto logical_compliment(L l) -> decltype(( !l ))
{
return (!l);
}
template<typename L, typename R>
auto not_equal(L l, R r) -> decltype(( l != r ))
{
return (l != r);
}
template<typename L, typename R>
auto addition(L l, R r) -> decltype(( l + r ))
{
return (l + r);
}
template<typename L>
auto unary_plus(L l) -> decltype(( +l ))
{
return (+l);
}
template<typename L, typename R>
auto subtraction(L l, R r) -> decltype(( l - r ))
{
return (l - r);
}
template<typename L>
auto unary_minus(L l) -> decltype(( -l ))
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4146)
return (-l);
#pragma warning(pop)
#else
return (-l);
#endif
}
template<typename L, typename R>
auto bitwise_and(L l, R r) -> decltype(( l & r ))
{
return (l & r);
}
template<typename L>
auto bitwise_compliment(L l) -> decltype(( ~l ))
{
return (~l);
}
template<typename L, typename R>
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
{
return (l ^ r);
}
template<typename L, typename R>
auto bitwise_or(L l, R r) -> decltype(( l | r ))
{
return (l | r);
}
template<typename L, typename R>
auto division(L l, R r) -> decltype(( l / r ))
{
return (l / r);
}
template<typename L, typename R>
auto left_shift(L l, R r) -> decltype(( l << r ))
{
return l << r;
}
template<typename L, typename R>
auto multiplication(L l, R r) -> decltype(( l * r ))
{
return l * r;
}
template<typename L, typename R>
auto remainder(L l, R r) -> decltype(( l % r ))
{
return (l % r);
}
template<typename L, typename R>
auto right_shift(L l, R r) -> decltype(( l >> r ))
{
return (l >> r);
}
}
template<typename T>
void assign(Module& m)
{
m.add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
}
template<typename T>
void assign_bitwise_and(Module& m)
{
m.add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
}
template<typename T>
void assign_xor(Module& m)
{
m.add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
}
template<typename T>
void assign_bitwise_or(Module& m)
{
m.add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
}
template<typename T>
void assign_difference(Module& m)
{
m.add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
}
template<typename T>
void assign_left_shift(Module& m)
{
m.add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
}
template<typename T>
void assign_product(Module& m)
{
m.add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
}
template<typename T>
void assign_quotient(Module& m)
{
m.add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
}
template<typename T>
void assign_remainder(Module& m)
{
m.add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
}
template<typename T>
void assign_right_shift(Module& m)
{
m.add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
}
template<typename T>
void assign_sum(Module& m)
{
m.add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
}
template<typename T>
void prefix_decrement(Module& m)
{
m.add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
}
template<typename T>
void prefix_increment(Module& m)
{
m.add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
}
template<typename T>
void equal(Module& m)
{
m.add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
}
template<typename T>
void greater_than(Module& m)
{
m.add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
}
template<typename T>
void greater_than_equal(Module& m)
{
m.add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
}
template<typename T>
void less_than(Module& m)
{
m.add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
}
template<typename T>
void less_than_equal(Module& m)
{
m.add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
}
template<typename T>
void logical_compliment(Module& m)
{
m.add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
}
template<typename T>
void not_equal(Module& m)
{
m.add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
}
template<typename T>
void addition(Module& m)
{
m.add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
}
template<typename T>
void unary_plus(Module& m)
{
m.add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
}
template<typename T>
void subtraction(Module& m)
{
m.add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
}
template<typename T>
void unary_minus(Module& m)
{
m.add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
}
template<typename T>
void bitwise_and(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
}
template<typename T>
void bitwise_compliment(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
}
template<typename T>
void bitwise_xor(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
}
template<typename T>
void bitwise_or(Module& m)
{
m.add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
}
template<typename T>
void division(Module& m)
{
m.add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
}
template<typename T>
void left_shift(Module& m)
{
m.add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
}
template<typename T>
void multiplication(Module& m)
{
m.add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
}
template<typename T>
void remainder(Module& m)
{
m.add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
}
template<typename T>
void right_shift(Module& m)
{
m.add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
}
}
}

View File

@ -53,6 +53,13 @@ namespace chaiscript
m_doti(user_type<Dynamic_Object>())
{}
Param_Types(const std::vector<Type_Info> &t_types)
: m_types(build_param_types(t_types)),
m_has_types(false),
m_doti(user_type<Dynamic_Object>())
{
}
Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
: m_types(std::move(t_types)),
m_has_types(false),
@ -61,6 +68,18 @@ namespace chaiscript
update_has_types();
}
static std::vector<std::pair<std::string, Type_Info>> build_param_types(const std::vector<Type_Info> &t_types)
{
std::vector<std::pair<std::string, Type_Info>> retval;
std::transform(t_types.begin(), t_types.end(), std::back_inserter(retval),
[](const Type_Info &ti){
return std::make_pair(std::string(), ti);
}
);
return retval;
}
void push_front(std::string t_name, Type_Info t_ti)
{
m_types.emplace(m_types.begin(), std::move(t_name), std::move(t_ti));
@ -204,8 +223,6 @@ namespace chaiscript
return m_arity;
}
virtual std::string annotation() const = 0;
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
{
if (ti.is_undef()
@ -295,22 +312,28 @@ namespace chaiscript
namespace dispatch
{
class Dynamic_Function_Interface
{
public:
virtual ~Dynamic_Function_Interface() {}
virtual Param_Types get_dynamic_param_types() const = 0;
};
/**
* A Proxy_Function implementation that is not type safe, the called function
* is expecting a vector<Boxed_Value> that it works with how it chooses.
*/
class Dynamic_Proxy_Function : public Proxy_Function_Base
class Dynamic_Proxy_Function : public Proxy_Function_Base, public Dynamic_Function_Interface
{
public:
Dynamic_Proxy_Function(
int t_arity=-1,
AST_NodePtr t_parsenode = AST_NodePtr(),
Param_Types t_param_types = Param_Types(),
std::string t_description = "",
Proxy_Function t_guard = Proxy_Function())
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
m_param_types(std::move(t_param_types)),
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description))
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
{
}
@ -343,12 +366,10 @@ namespace chaiscript
return m_parsenode;
}
virtual std::string annotation() const override
{
return m_description;
virtual Param_Types get_dynamic_param_types() const {
return m_param_types;
}
protected:
bool test_guard(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const
{
@ -366,6 +387,8 @@ namespace chaiscript
}
}
private:
static std::vector<Type_Info> build_param_type_list(const Param_Types &t_types)
{
@ -387,7 +410,6 @@ namespace chaiscript
Param_Types m_param_types;
Proxy_Function m_guard;
AST_NodePtr m_parsenode;
std::string m_description;
};
@ -401,13 +423,11 @@ namespace chaiscript
int t_arity=-1,
AST_NodePtr t_parsenode = AST_NodePtr(),
Param_Types t_param_types = Param_Types(),
std::string t_description = "",
Proxy_Function t_guard = Proxy_Function())
: Dynamic_Proxy_Function(
t_arity,
std::move(t_parsenode),
std::move(t_param_types),
std::move(t_description),
std::move(t_guard)
),
m_f(std::move(t_f))
@ -506,10 +526,6 @@ namespace chaiscript
return args;
}
virtual std::string annotation() const override
{
return "Bound: " + m_f->annotation();
}
protected:
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
@ -554,11 +570,6 @@ namespace chaiscript
{
}
std::string annotation() const override
{
return "";
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return static_cast<int>(vals.size()) == get_arity()
@ -595,8 +606,7 @@ namespace chaiscript
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
typedef typename detail::Function_Signature<Func>::Return_Type Return_Type;
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
return detail::call_func(detail::Function_Signature<Func>(), m_f, params, t_conversions);
}
private:
@ -648,7 +658,7 @@ namespace chaiscript
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return detail::Do_Call<typename std::function<Func>::result_type>::template go<Func>(m_f.get(), params, t_conversions);
return detail::call_func(detail::Function_Signature<Func>(), m_f.get(), params, t_conversions);
}
@ -693,11 +703,6 @@ namespace chaiscript
return vals[0].get_type_info().bare_equal(user_type<Class>());
}
std::string annotation() const override
{
return "";
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
@ -728,13 +733,13 @@ namespace chaiscript
template<typename Type>
auto do_call_impl(Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
return detail::Handle_Return<typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(const Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
}
@ -887,6 +892,15 @@ namespace chaiscript
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
ordered_funcs.reserve(funcs.size());
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
static auto boxed_type = user_type<Boxed_Value>();
static auto dynamic_type = user_type<Dynamic_Object>();
#else
auto boxed_type = user_type<Boxed_Value>();
auto dynamic_type = user_type<Dynamic_Object>();
#endif
for (const auto &func : funcs)
{
const auto arity = func->get_arity();
@ -898,7 +912,10 @@ namespace chaiscript
size_t numdiffs = 0;
for (size_t i = 0; i < plist.size(); ++i)
{
if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info()))
const auto &p_type = plist[i].get_type_info();
const auto &f_type = func->get_param_types()[i+1];
if (!(f_type.bare_equal(boxed_type) && p_type.bare_equal(dynamic_type)) && !f_type.bare_equal(p_type))
{
++numdiffs;
}

View File

@ -99,17 +99,23 @@ namespace chaiscript
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each parameter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
/// The function attempts to unbox each parameter to the expected type.
/// if any unboxing fails the execution of the function fails and
/// the bad_boxed_cast is passed up to the caller.
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
}
template<typename Callable, typename ... Params>
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
return Handle_Return<void>::handle();
}
}
@ -118,34 +124,4 @@ namespace chaiscript
}
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
}
};
template<>
struct Do_Call<void>
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};
}
}
}
#endif

View File

@ -29,8 +29,8 @@ namespace chaiscript
class Type_Info
{
public:
constexpr Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
@ -121,9 +121,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
std::is_reference<T>::value, std::is_pointer<T>::value,
@ -138,9 +136,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<std::shared_ptr<T> >
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@ -158,9 +154,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<const std::shared_ptr<T> &>
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@ -173,9 +167,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<std::reference_wrapper<T> >
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@ -188,9 +180,7 @@ namespace chaiscript
template<typename T>
struct Get_Type_Info<const std::reference_wrapper<T> &>
{
typedef T type;
static Type_Info get()
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
@ -212,7 +202,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
/// \endcode
template<typename T>
Type_Info user_type(const T &/*t*/)
constexpr Type_Info user_type(const T &/*t*/)
{
return detail::Get_Type_Info<T>::get();
}
@ -227,7 +217,7 @@ namespace chaiscript
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
/// \endcode
template<typename T>
Type_Info user_type()
constexpr Type_Info user_type()
{
return detail::Get_Type_Info<T>::get();
}

View File

@ -13,7 +13,7 @@ namespace chaiscript
{
struct Operators {
enum Opers
enum class Opers
{
boolean_flag,
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
@ -31,7 +31,7 @@ namespace chaiscript
};
static const char *to_string(Opers t_oper) {
const char *opers[] = {
static const char *opers[] = {
"",
"==", "<", ">", "<=", ">=", "!=",
"",
@ -46,80 +46,80 @@ namespace chaiscript
"+", "/", "*", "-", "+", "-",
""
};
return opers[t_oper];
return opers[static_cast<int>(t_oper)];
}
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{
if (t_str == "==")
{
return equals;
return Opers::equals;
} else if (t_str == "<") {
return less_than;
return Opers::less_than;
} else if (t_str == ">") {
return greater_than;
return Opers::greater_than;
} else if (t_str == "<=") {
return less_than_equal;
return Opers::less_than_equal;
} else if (t_str == ">=") {
return greater_than_equal;
return Opers::greater_than_equal;
} else if (t_str == "!=") {
return not_equal;
return Opers::not_equal;
} else if (t_str == "=") {
return assign;
return Opers::assign;
} else if (t_str == "++") {
return pre_increment;
return Opers::pre_increment;
} else if (t_str == "--") {
return pre_decrement;
return Opers::pre_decrement;
} else if (t_str == "*=") {
return assign_product;
return Opers::assign_product;
} else if (t_str == "+=") {
return assign_sum;
return Opers::assign_sum;
} else if (t_str == "-=") {
return assign_difference;
return Opers::assign_difference;
} else if (t_str == "&=") {
return assign_bitwise_and;
return Opers::assign_bitwise_and;
} else if (t_str == "|=") {
return assign_bitwise_or;
return Opers::assign_bitwise_or;
} else if (t_str == "<<=") {
return assign_shift_left;
return Opers::assign_shift_left;
} else if (t_str == ">>=") {
return assign_shift_right;
return Opers::assign_shift_right;
} else if (t_str == "%=") {
return assign_remainder;
return Opers::assign_remainder;
} else if (t_str == "^=") {
return assign_bitwise_xor;
return Opers::assign_bitwise_xor;
} else if (t_str == "<<") {
return shift_left;
return Opers::shift_left;
} else if (t_str == ">>") {
return shift_right;
return Opers::shift_right;
} else if (t_str == "%") {
return remainder;
return Opers::remainder;
} else if (t_str == "&") {
return bitwise_and;
return Opers::bitwise_and;
} else if (t_str == "|") {
return bitwise_or;
return Opers::bitwise_or;
} else if (t_str == "^") {
return bitwise_xor;
return Opers::bitwise_xor;
} else if (t_str == "~") {
return bitwise_complement;
return Opers::bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return unary_plus;
return Opers::unary_plus;
} else {
return sum;
return Opers::sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return unary_minus;
return Opers::unary_minus;
} else {
return difference;
return Opers::difference;
}
} else if (t_str == "/") {
return quotient;
return Opers::quotient;
} else if (t_str == "*") {
return product;
return Opers::product;
} else {
return invalid;
return Opers::invalid;
}
}

View File

@ -32,28 +32,26 @@ namespace chaiscript
/// Types of AST nodes available to the parser and eval
class AST_Node_Type {
public:
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, 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, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
};
enum class AST_Node_Type { Id, Fun_Call, Arg_List, Equation, Var_Decl,
Array_Call, Dot_Access,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant
};
enum class Operator_Precidence { Ternary_Cond, Logical_Or, Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And, Equality, Comparison, Shift, Addition, Multiplication };
namespace
{
/// Helper lookup to get the name of each node type
const char *ast_node_type_to_string(int ast_node_type) {
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
static const char * const ast_node_types[] = { "Id", "Fun_Call", "Arg_List", "Equation", "Var_Decl",
"Array_Call", "Dot_Access",
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "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", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Constant"};
return ast_node_types[ast_node_type];
return ast_node_types[static_cast<int>(ast_node_type)];
}
}
@ -101,6 +99,18 @@ namespace chaiscript
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
namespace exception
{
/// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error
{
load_module_error(const std::string &t_reason) noexcept
: std::runtime_error(t_reason)
{
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() noexcept = default;
};
/// Errors generated during parsing or evaluation
struct eval_error : std::runtime_error {
@ -161,12 +171,12 @@ namespace chaiscript
return ss.str();
}
virtual ~eval_error() noexcept {}
virtual ~eval_error() noexcept = default;
private:
template<typename T>
static int id(const T& t)
static AST_Node_Type id(const T& t)
{
return t->identifier;
}
@ -434,11 +444,10 @@ namespace chaiscript
/// \brief Struct that doubles as both a parser ast_node and an AST node.
struct AST_Node : std::enable_shared_from_this<AST_Node> {
public:
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
const AST_Node_Type identifier;
const std::string text;
Parse_Location location;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
const std::string &filename() const {
return *location.filename;
@ -452,14 +461,14 @@ namespace chaiscript
return location.end;
}
virtual std::string pretty_print() const
std::string pretty_print() const
{
std::ostringstream oss;
oss << text;
for (auto & elem : this->children) {
oss << elem->pretty_print();
oss << elem->pretty_print() << ' ';
}
return oss.str();
@ -499,15 +508,15 @@ namespace chaiscript
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
virtual ~AST_Node() = default;
AST_Node(AST_Node &&) = default;
AST_Node &operator=(AST_Node &&) = default;
AST_Node(const AST_Node &) = delete;
AST_Node& operator=(const AST_Node &) = delete;
virtual ~AST_Node() {}
protected:
AST_Node(std::string t_ast_node_text, int t_id, Parse_Location t_loc,
AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc,
std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
identifier(t_id), text(std::move(t_ast_node_text)),
location(std::move(t_loc)),
@ -520,10 +529,6 @@ namespace chaiscript
throw std::runtime_error("Undispatched ast_node (internal error)");
}
private:
// Copy and assignment explicitly unimplemented
AST_Node(const AST_Node &) = delete;
AST_Node& operator=(const AST_Node &) = delete;
};
@ -554,77 +559,83 @@ namespace chaiscript
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(Scope_Push_Pop &&) = default;
Scope_Push_Pop& operator=(Scope_Push_Pop &&) = default;
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_scope(m_ds.get().stack_holder());
m_ds->new_scope(m_ds.stack_holder());
}
~Scope_Push_Pop()
{
m_ds.get()->pop_scope(m_ds.get().stack_holder());
m_ds->pop_scope(m_ds.stack_holder());
}
private:
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
const chaiscript::detail::Dispatch_State &m_ds;
};
/// Creates a new function call and pops it on destruction
struct Function_Push_Pop
{
Function_Push_Pop(Function_Push_Pop &&) = default;
Function_Push_Pop& operator=(Function_Push_Pop &&) = default;
Function_Push_Pop(const Function_Push_Pop &) = delete;
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
}
~Function_Push_Pop()
{
m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
}
void save_params(const std::vector<Boxed_Value> &t_params)
{
m_ds.get()->save_function_params(t_params);
m_ds->save_function_params(t_params);
}
void save_params(std::initializer_list<Boxed_Value> t_params)
{
m_ds.get()->save_function_params(std::move(t_params));
m_ds->save_function_params(std::move(t_params));
}
private:
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
const chaiscript::detail::Dispatch_State &m_ds;
};
/// Creates a new scope then pops it on destruction
struct Stack_Push_Pop
{
Stack_Push_Pop(Stack_Push_Pop &&) = default;
Stack_Push_Pop& operator=(Stack_Push_Pop &&) = default;
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
: m_ds(t_ds)
{
m_ds.get()->new_stack(m_ds.get().stack_holder());
m_ds->new_stack(m_ds.stack_holder());
}
~Stack_Push_Pop()
{
m_ds.get()->pop_stack(m_ds.get().stack_holder());
m_ds->pop_stack(m_ds.stack_holder());
}
private:
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
const chaiscript::detail::Dispatch_State &m_ds;
};
}
}

View File

@ -33,14 +33,15 @@
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
#include <dlfcn.h>
#else
#endif
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#include "chaiscript_windows.hpp"
#elif _POSIX_VERSION
#include "chaiscript_posix.hpp"
#else
#include "chaiscript_unknown.hpp"
#endif
@ -49,205 +50,9 @@
namespace chaiscript
{
namespace exception
{
/// \brief Thrown if an error occurs while attempting to load a binary module
struct load_module_error : std::runtime_error
{
load_module_error(const std::string &t_reason) noexcept
: std::runtime_error(t_reason)
{
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() noexcept {}
};
}
namespace detail
{
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
struct Loadable_Module
{
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
~DLModule()
{
dlclose(m_data);
}
void *m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
static T cast_symbol(void *p)
{
union cast_union
{
T func_ptr;
void *in_ptr;
};
cast_union c;
c.in_ptr = p;
return c.func_ptr;
}
T m_symbol;
};
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_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
#ifdef WIN32
struct Loadable_Module
{
template<typename T>
static std::wstring to_wstring(const T &t_str)
{
return std::wstring(t_str.begin(), t_str.end());
}
template<typename T>
static std::string to_string(const T &t_str)
{
return std::string(t_str.begin(), t_str.end());
}
#if defined(_UNICODE) || defined(UNICODE)
template<typename T>
static std::wstring to_proper_string(const T &t_str)
{
return to_wstring(t_str);
}
#else
template<typename T>
static std::string to_proper_string(const T &t_str)
{
return to_string(t_str);
}
#endif
static std::string get_error_message(DWORD t_err)
{
typedef LPTSTR StringType;
#if defined(_UNICODE) || defined(UNICODE)
std::wstring retval = L"Unknown Error";
#else
std::string retval = "Unknown Error";
#endif
StringType lpMsgBuf = nullptr;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<StringType>(&lpMsgBuf),
0, nullptr ) != 0 && lpMsgBuf)
{
retval = lpMsgBuf;
LocalFree(lpMsgBuf);
}
return to_string(retval);
}
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
~DLModule()
{
FreeLibrary(m_data);
}
HMODULE m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
T m_symbol;
};
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_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
#else
struct Loadable_Module
{
Loadable_Module(const std::string &, const std::string &)
{
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
}
ModulePtr m_moduleptr;
};
#endif
#endif
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
}
@ -286,8 +91,6 @@ namespace chaiscript
/// Evaluates the given file and looks in the 'use' paths
const Boxed_Value internal_eval_file(const std::string &t_filename) {
for (const auto &path : m_use_paths)
@ -325,27 +128,6 @@ namespace chaiscript
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
void build_eval_system(const ModulePtr &t_lib) {
m_engine.add_reserved_word("def");
m_engine.add_reserved_word("fun");
m_engine.add_reserved_word("while");
m_engine.add_reserved_word("for");
m_engine.add_reserved_word("if");
m_engine.add_reserved_word("else");
m_engine.add_reserved_word("&&");
m_engine.add_reserved_word("||");
m_engine.add_reserved_word(",");
m_engine.add_reserved_word("auto");
m_engine.add_reserved_word("return");
m_engine.add_reserved_word("break");
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("class");
m_engine.add_reserved_word("attr");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("global");
m_engine.add_reserved_word("GLOBAL");
m_engine.add_reserved_word("_");
if (t_lib)
{
add(t_lib);
@ -397,16 +179,9 @@ namespace chaiscript
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
m_engine.add(fun(&parse), "parse");
m_engine.add(fun(&ChaiScript::version_major), "version_major");
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
m_engine.add(fun(&ChaiScript::version), "version");
m_engine.add(fun(&ChaiScript::compiler_version), "compiler_version");
m_engine.add(fun(&ChaiScript::compiler_name), "compiler_name");
m_engine.add(fun(&ChaiScript::compiler_id), "compiler_id");
m_engine.add(fun(&ChaiScript::debug_build), "debug_build");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
@ -517,7 +292,7 @@ namespace chaiscript
// attempt to load the stdlib
load_module("chaiscript_stdlib-" + version());
load_module("chaiscript_stdlib-" + Build_Info::version());
build_eval_system(ModulePtr());
}
@ -544,53 +319,6 @@ namespace chaiscript
}
static int version_major()
{
return chaiscript::version_major;
}
static int version_minor()
{
return chaiscript::version_minor;
}
static int version_patch()
{
return chaiscript::version_patch;
}
static std::string version()
{
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
{
return chaiscript::compiler_name;
}
static bool debug_build()
{
return chaiscript::debug_build;
}
std::string get_type_name(const Type_Info &ti) const
{
return m_engine.get_type_name(ti);
@ -805,7 +533,7 @@ namespace chaiscript
{
std::vector<exception::load_module_error> errors;
std::string version_stripped_name = t_module_name;
size_t version_pos = version_stripped_name.find("-"+version());
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
if (version_pos != std::string::npos)
{
version_stripped_name.erase(version_pos);
@ -837,16 +565,14 @@ namespace chaiscript
std::string errstring;
for (std::vector<exception::load_module_error>::const_iterator itr = errors.begin();
itr != errors.end();
++itr)
for (const auto &err : errors)
{
if (!errstring.empty())
{
errstring += "; ";
}
errstring += itr->what();
errstring += err.what();
}
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
@ -886,14 +612,7 @@ namespace chaiscript
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
{
try {
return do_eval(t_script);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return eval(t_script, t_handler);
}
/// \brief Evaluates a string and returns a typesafe result.
@ -912,21 +631,14 @@ namespace chaiscript
template<typename T>
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
{
try {
return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
}
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
decltype(auto) boxed_cast(const Boxed_Value &bv) const
{
return m_engine.boxed_cast<Type>(bv);
return(m_engine.boxed_cast<Type>(bv));
}
@ -958,14 +670,7 @@ namespace chaiscript
/// \return result of the script execution
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return do_eval(load_file(t_filename), t_filename);
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return eval(load_file(t_filename), t_handler, t_filename);
}
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
@ -978,14 +683,7 @@ namespace chaiscript
/// to the requested type.
template<typename T>
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try {
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
} catch (Boxed_Value &bv) {
if (t_handler) {
t_handler->handle(bv, m_engine);
}
throw;
}
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
}
};

View File

@ -93,17 +93,12 @@ namespace chaiscript
return do_oper(t_ss, m_oper, text, lhs, rhs);
}
std::string pretty_print() const override
{
return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")";
}
protected:
Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss,
Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) const
{
try {
if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
if (t_oper != Operators::Opers::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
{
// If it's an arithmetic operation we want to short circuit dispatch
try{
@ -129,95 +124,42 @@ namespace chaiscript
mutable std::atomic_uint_fast32_t m_loc;
};
struct Int_AST_Node final : AST_Node {
Int_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)),
m_value(std::move(t_bv)) { assert(text != ""); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
return m_value;
}
private:
Boxed_Value m_value;
};
struct Constant_AST_Node final : AST_Node {
Constant_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_value)
: AST_Node(t_ast_node_text, AST_Node_Type::Constant, std::move(t_loc)),
m_value(std::move(t_value))
{
}
struct Float_AST_Node final : AST_Node {
Float_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Float, std::move(t_loc)),
m_value(std::move(t_bv)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
return m_value;
}
private:
Boxed_Value m_value;
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
return m_value;
}
Boxed_Value m_value;
};
struct Id_AST_Node final : AST_Node {
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)),
m_value(get_value(t_ast_node_text)), m_loc(0)
m_loc(0)
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
if (!m_value.is_undef())
{
return m_value;
} else {
try {
return t_ss.get_object(this->text, m_loc);
}
catch (std::exception &) {
throw exception::eval_error("Can not find object: " + this->text);
}
try {
return t_ss.get_object(this->text, m_loc);
}
catch (std::exception &) {
throw exception::eval_error("Can not find object: " + this->text);
}
}
private:
static Boxed_Value get_value(const std::string &t_text)
{
if (t_text == "true") {
return const_var(true);
} else if (t_text == "false") {
return const_var(false);
} else if (t_text == "Infinity") {
return const_var(std::numeric_limits<double>::infinity());
} else if (t_text == "NaN") {
return const_var(std::numeric_limits<double>::quiet_NaN());
} else if (t_text == "_") {
return Boxed_Value(std::make_shared<dispatch::Placeholder_Object>());
} else {
return Boxed_Value();
}
}
Boxed_Value m_value;
mutable std::atomic_uint_fast32_t m_loc;
};
struct Char_AST_Node final : AST_Node {
Char_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Char, std::move(t_loc)) { }
};
struct Str_AST_Node final : AST_Node {
Str_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Str, std::move(t_loc)) { }
};
struct Eol_AST_Node final : AST_Node {
Eol_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Eol, std::move(t_loc)) { }
std::string pretty_print() const override
{
return "\n";
}
};
struct Fun_Call_AST_Node final : AST_Node {
@ -265,25 +207,6 @@ namespace chaiscript
}
}
std::string pretty_print() const override
{
std::ostringstream oss;
int count = 0;
for (const auto &child : this->children) {
oss << child->pretty_print();
if (count == 0)
{
oss << "(";
}
++count;
}
oss << ")";
return oss.str();
}
};
@ -293,40 +216,12 @@ namespace chaiscript
Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
std::string pretty_print() const override
{
std::ostringstream oss;
for (size_t j = 0; j < this->children.size(); ++j) {
if (j != 0)
{
oss << " ";
}
oss << this->children[j]->pretty_print();
}
return oss.str();
}
};
struct Arg_List_AST_Node final : AST_Node {
Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
std::string pretty_print() const override
{
std::ostringstream oss;
for (size_t j = 0; j < this->children.size(); ++j) {
if (j != 0)
{
oss << ", ";
}
oss << this->children[j]->pretty_print();
}
return oss.str();
}
static std::string get_arg_name(const AST_NodePtr &t_node) {
if (t_node->children.empty())
@ -375,16 +270,16 @@ namespace chaiscript
struct Equation_AST_Node final : AST_Node {
Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[1]->text))
{ assert(children.size() == 3); }
m_oper(Operators::to_operator(text))
{ assert(children.size() == 2); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value rhs = this->children[2]->eval(t_ss);
Boxed_Value rhs = this->children[1]->eval(t_ss);
Boxed_Value lhs = this->children[0]->eval(t_ss);
if (m_oper != Operators::invalid && lhs.get_type_info().is_arithmetic() &&
if (m_oper != Operators::Opers::invalid && lhs.get_type_info().is_arithmetic() &&
rhs.get_type_info().is_arithmetic())
{
try {
@ -392,7 +287,7 @@ namespace chaiscript
} catch (const std::exception &) {
throw exception::eval_error("Error with unsupported arithmetic assignment operation");
}
} else if (m_oper == Operators::assign) {
} else if (m_oper == Operators::Opers::assign) {
if (lhs.is_return_value()) {
throw exception::eval_error("Error, cannot assign to temporary value.");
}
@ -400,9 +295,13 @@ namespace chaiscript
try {
if (lhs.is_undef()) {
if (!this->children.empty() &&
!this->children[0]->children.empty()
&& this->children[0]->children[0]->identifier == AST_Node_Type::Reference)
if ((!this->children.empty()
&& ((this->children[0]->identifier == AST_Node_Type::Reference)
|| (!this->children[0]->children.empty()
&& this->children[0]->children[0]->identifier == AST_Node_Type::Reference)
)
)
)
{
/// \todo This does not handle the case of an unassigned reference variable
/// being assigned outside of its declaration
@ -419,17 +318,17 @@ namespace chaiscript
}
try {
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss);
}
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, e.functions, false, *t_ss);
}
}
else if (this->children[1]->text == ":=") {
else if (this->text == ":=") {
if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) {
lhs.assign(rhs);
lhs.reset_return_value();
@ -439,9 +338,9 @@ namespace chaiscript
}
else {
try {
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
} catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss);
}
}
@ -484,31 +383,19 @@ namespace chaiscript
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
if (this->children[0]->identifier == AST_Node_Type::Reference)
{
return this->children[0]->eval(t_ss);
} else {
const std::string &idname = this->children[0]->text;
const std::string &idname = this->children[0]->text;
try {
Boxed_Value bv;
t_ss.add_object(idname, bv);
return bv;
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as variable '" + idname + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Variable redefined '" + e.name() + "'");
}
try {
Boxed_Value bv;
t_ss.add_object(idname, bv);
return bv;
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as variable '" + idname + "'");
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Variable redefined '" + e.name() + "'");
}
}
std::string pretty_print() const override
{
return "var " + this->children[0]->text;
}
};
@ -530,20 +417,6 @@ namespace chaiscript
}
}
std::string pretty_print() const override
{
std::ostringstream oss;
oss << this->children[0]->pretty_print();
for (size_t i = 1; i < this->children.size(); ++i)
{
oss << "[";
oss << this->children[i]->pretty_print();
oss << "]";
}
return oss.str();
}
private:
mutable std::atomic_uint_fast32_t m_loc;
@ -553,8 +426,8 @@ namespace chaiscript
Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)),
m_fun_name(
((children[2]->identifier == AST_Node_Type::Fun_Call) || (children[2]->identifier == AST_Node_Type::Array_Call))?
children[2]->children[0]->text:children[2]->text) { }
((children[1]->identifier == AST_Node_Type::Fun_Call) || (children[1]->identifier == AST_Node_Type::Array_Call))?
children[1]->children[0]->text:children[1]->text) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
@ -564,9 +437,9 @@ namespace chaiscript
std::vector<Boxed_Value> params{retval};
bool has_function_params = false;
if (children[2]->children.size() > 1) {
if (children[1]->children.size() > 1) {
has_function_params = true;
for (const auto &child : children[2]->children[1]->children) {
for (const auto &child : children[1]->children[1]->children) {
params.push_back(child->eval(t_ss));
}
}
@ -588,9 +461,9 @@ namespace chaiscript
retval = std::move(rv.retval);
}
if (this->children[2]->identifier == AST_Node_Type::Array_Call) {
if (this->children[1]->identifier == AST_Node_Type::Array_Call) {
try {
retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)}, t_ss.conversions());
retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[1]->children[1]->eval(t_ss)}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
@ -606,41 +479,6 @@ namespace chaiscript
const std::string m_fun_name;
};
struct Quoted_String_AST_Node final : AST_Node {
Quoted_String_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Quoted_String, std::move(t_loc)),
m_value(const_var(text)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
return m_value;
}
std::string pretty_print() const override
{
return "\"" + text + "\"";
}
private:
Boxed_Value m_value;
};
struct Single_Quoted_String_AST_Node final : AST_Node {
Single_Quoted_String_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Single_Quoted_String, std::move(t_loc)),
m_value(const_var(char(text.at(0)))) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
return m_value;
}
std::string pretty_print() const override
{
return "'" + text + "'";
}
private:
Boxed_Value m_value;
};
struct Lambda_AST_Node final : AST_Node {
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
@ -736,7 +574,6 @@ namespace chaiscript
try {
const std::string & l_function_name = this->children[0]->text;
const std::string & l_annotation = this->annotation?this->annotation->text:"";
const auto & func_node = this->children.back();
t_ss->add(
dispatch::make_dynamic_proxy_function(
@ -745,7 +582,7 @@ namespace chaiscript
return detail::eval_function(engine, func_node, t_param_names, t_params);
},
static_cast<int>(numparams), this->children.back(),
param_types, l_annotation, guard), l_function_name);
param_types, guard), l_function_name);
}
catch (const exception::reserved_word_error &e) {
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
@ -816,32 +653,22 @@ namespace chaiscript
struct If_AST_Node final : AST_Node {
If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { }
AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children))
{
assert(children.size() == 2 || children.size() == 3);
}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
if (get_bool_condition(children[0]->eval(t_ss))) {
return children[1]->eval(t_ss);
} else {
if (children.size() > 2) {
size_t i = 2;
while (i < children.size()) {
if (children[i]->text == "else") {
return children[i+1]->eval(t_ss);
}
else if (children[i]->text == "else if") {
if (get_bool_condition(children[i+1]->eval(t_ss))) {
return children[i+2]->eval(t_ss);
}
}
i += 3;
}
if (children.size() == 3) {
return children[2]->eval(t_ss);
} else {
return void_var();
}
}
return void_var();
}
};
struct For_AST_Node final : AST_Node {
@ -973,11 +800,6 @@ namespace chaiscript
}
}
std::string pretty_print() const override
{
return "[" + AST_Node::pretty_print() + "]";
}
private:
mutable std::atomic_uint_fast32_t m_loc;
};
@ -1068,24 +890,24 @@ namespace chaiscript
struct Prefix_AST_Node final : AST_Node {
Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[0]->text, true))
m_oper(Operators::to_operator(text, true))
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
Boxed_Value bv(children[1]->eval(t_ss));
Boxed_Value bv(children[0]->eval(t_ss));
try {
// short circuit arithmetic operations
if (m_oper != Operators::invalid && m_oper != Operators::bitwise_and && bv.get_type_info().is_arithmetic())
if (m_oper != Operators::Opers::invalid && m_oper != Operators::Opers::bitwise_and && bv.get_type_info().is_arithmetic())
{
return Boxed_Number::do_oper(m_oper, bv);
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({bv});
return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)}, t_ss.conversions());
return t_ss->call_function(text, m_loc, {std::move(bv)}, t_ss.conversions());
}
} catch (const exception::dispatch_error &e) {
throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
throw exception::eval_error("Error with prefix operator evaluation: '" + text + "'", e.parameters, e.functions, false, *t_ss);
}
}
@ -1153,11 +975,6 @@ namespace chaiscript
mutable std::atomic_uint_fast32_t m_loc;
};
struct Annotation_AST_Node final : AST_Node {
Annotation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Annotation, std::move(t_loc)) { }
};
struct Try_AST_Node final : AST_Node {
Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { }
@ -1324,7 +1141,6 @@ namespace chaiscript
}
try {
const std::string & l_annotation = annotation?annotation->text:"";
const std::string & function_name = children[static_cast<size_t>(1 + class_offset)]->text;
auto node = children.back();
@ -1337,7 +1153,7 @@ namespace chaiscript
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
},
static_cast<int>(numparams), node, param_types, l_annotation, guard
static_cast<int>(numparams), node, param_types, guard
)
),
function_name);
@ -1353,7 +1169,7 @@ namespace chaiscript
[engine, t_param_names, node](const std::vector<Boxed_Value> &t_params) {
return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params);
},
static_cast<int>(numparams), node, param_types, l_annotation, guard), type),
static_cast<int>(numparams), node, param_types, guard), type),
function_name);
}
}
@ -1406,36 +1222,26 @@ namespace chaiscript
struct Logical_And_AST_Node final : AST_Node {
Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 3); }
{ assert(children.size() == 2); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
return const_var(get_bool_condition(children[0]->eval(t_ss))
&& get_bool_condition(children[2]->eval(t_ss)));
&& get_bool_condition(children[1]->eval(t_ss)));
}
std::string pretty_print() const override
{
return "(" + AST_Node::pretty_print() + ")";
}
};
struct Logical_Or_AST_Node final : AST_Node {
Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 3); }
{ assert(children.size() == 2); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
return const_var(get_bool_condition(children[0]->eval(t_ss))
|| get_bool_condition(children[2]->eval(t_ss)));
|| get_bool_condition(children[1]->eval(t_ss)));
}
std::string pretty_print() const override
{
return "(" + AST_Node::pretty_print() + ")";
}
};
}

View File

@ -147,19 +147,19 @@ namespace chaiscript
}
static const std::array<AST_Node_Type::Type, 11> &create_operators() {
static const std::array<AST_Node_Type::Type, 11> operators = { {
AST_Node_Type::Ternary_Cond,
AST_Node_Type::Logical_Or,
AST_Node_Type::Logical_And,
AST_Node_Type::Bitwise_Or,
AST_Node_Type::Bitwise_Xor,
AST_Node_Type::Bitwise_And,
AST_Node_Type::Equality,
AST_Node_Type::Comparison,
AST_Node_Type::Shift,
AST_Node_Type::Addition,
AST_Node_Type::Multiplication
static const std::array<Operator_Precidence, 11> &create_operators() {
static const std::array<Operator_Precidence, 11> operators = { {
Operator_Precidence::Ternary_Cond,
Operator_Precidence::Logical_Or,
Operator_Precidence::Logical_And,
Operator_Precidence::Bitwise_Or,
Operator_Precidence::Bitwise_Xor,
Operator_Precidence::Bitwise_And,
Operator_Precidence::Equality,
Operator_Precidence::Comparison,
Operator_Precidence::Shift,
Operator_Precidence::Addition,
Operator_Precidence::Multiplication
} };
return operators;
}
@ -167,10 +167,11 @@ namespace chaiscript
static constexpr const char * const m_multiline_comment_begin = "/*";
static constexpr const char * const m_multiline_comment_end = "*/";
static constexpr const char * const m_singleline_comment = "//";
static constexpr const char * const m_annotation = "#";
const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &m_alphabet = create_alphabet();
const std::vector<std::vector<std::string>> &m_operator_matches = create_operator_matches();
const std::array<AST_Node_Type::Type, 11> &m_operators = create_operators();
const std::array<Operator_Precidence, 11> &m_operators = create_operators();
std::shared_ptr<std::string> m_filename;
std::vector<AST_NodePtr> m_match_stack;
@ -178,8 +179,7 @@ namespace chaiscript
struct Position
{
Position()
: line(-1), col(-1), m_last_col(-1) {}
Position() = default;
Position(std::string::const_iterator t_pos, std::string::const_iterator t_end)
: line(1), col(1), m_pos(std::move(t_pos)), m_end(std::move(t_end)), m_last_col(1)
@ -266,13 +266,13 @@ namespace chaiscript
}
}
int line;
int col;
int line = -1;
int col = -1;
private:
std::string::const_iterator m_pos;
std::string::const_iterator m_end;
int m_last_col;
int m_last_col = -1;
};
Position m_position;
@ -298,59 +298,12 @@ namespace chaiscript
}
}
/// Shows the current stack of matched ast_nodes
void show_match_stack() const {
for (auto & elem : m_match_stack) {
//debug_print(match_stack[i]);
std::cout << elem->to_string();
}
}
/// Clears the stack of matched ast_nodes
void clear_match_stack() {
m_match_stack.clear();
}
/// Returns the front-most AST node
AST_NodePtr ast() const {
if (m_match_stack.empty()) throw exception::eval_error("Attempted to access AST of failed parse.");
return m_match_stack.front();
}
static std::map<std::string, int> count_fun_calls(const AST_NodePtr &p, bool in_loop) {
if (p->identifier == AST_Node_Type::Fun_Call) {
if (p->children[0]->identifier == AST_Node_Type::Id) {
return std::map<std::string, int>{ {p->children[0]->text, in_loop?99:1} };
}
return std::map<std::string, int>();
} else {
std::map<std::string, int> counts;
for (const auto &child : p->children) {
auto childcounts = count_fun_calls(child, in_loop || p->identifier == AST_Node_Type::For || p->identifier == AST_Node_Type::While);
for (const auto &count : childcounts) {
counts[count.first] += count.second;
}
}
return counts;
}
}
static void optimize_blocks(AST_NodePtr &p)
{
for (auto &c : p->children)
{
if (c->identifier == AST_Node_Type::Block) {
if (c->children.size() == 1) {
// std::cout << "swapping out block child for block\n";
c = c->children[0];
}
}
optimize_blocks(c);
}
}
static void optimize_returns(AST_NodePtr &p)
{
@ -372,19 +325,8 @@ namespace chaiscript
}
static int count_nodes(const AST_NodePtr &p)
{
int count = 1;
for (auto &c : p->children) {
count += count_nodes(c);
}
return count;
}
AST_NodePtr optimized_ast(bool t_optimize_blocks = false, bool t_optimize_returns = true) {
AST_NodePtr optimized_ast(bool t_optimize_returns = true) {
AST_NodePtr p = ast();
//Note, optimize_blocks is currently broken; it breaks stack management
if (t_optimize_blocks) { optimize_blocks(p); }
if (t_optimize_returns) { optimize_returns(p); }
return p;
}
@ -458,6 +400,19 @@ namespace chaiscript
}
}
return true;
} else if (Symbol_(m_annotation)) {
while (m_position.has_more()) {
if (Symbol_("\r\n")) {
m_position -= 2;
break;
} else if (Char_('\n')) {
--m_position;
break;
} else {
++m_position;
}
}
return true;
}
return false;
}
@ -742,20 +697,20 @@ namespace chaiscript
if (Hex_()) {
auto match = Position::str(start, m_position);
auto bv = buildInt(16, match, true);
m_match_stack.emplace_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
m_match_stack.emplace_back(make_node<eval::Constant_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
return true;
}
if (Binary_()) {
auto match = Position::str(start, m_position);
auto bv = buildInt(2, match, true);
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
return true;
}
if (Float_()) {
auto match = Position::str(start, m_position);
auto bv = buildFloat(match);
m_match_stack.push_back(make_node<eval::Float_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
return true;
}
else {
@ -763,11 +718,11 @@ namespace chaiscript
auto match = Position::str(start, m_position);
if (!match.empty() && (match[0] == '0')) {
auto bv = buildInt(8, match, false);
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
}
else if (!match.empty()) {
auto bv = buildInt(10, match, false);
m_match_stack.push_back(make_node<eval::Int_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(std::move(match), start.line, start.col, std::move(bv)));
} else {
return false;
}
@ -825,16 +780,35 @@ namespace chaiscript
const auto start = m_position;
if (Id_()) {
m_match_stack.push_back(make_node<eval::Id_AST_Node>(
[&]()->std::string{
if (*start == '`') {
//Id Literal
return Position::str(start+1, m_position-1);
} else {
return Position::str(start, m_position);
}
}(),
start.line, start.col));
const auto text = Position::str(start, m_position);
if (text == "true") {
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(text, start.line, start.col, const_var(true)));
} else if (text == "false") {
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(text, start.line, start.col, const_var(false)));
} else if (text == "Infinity") {
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(text, start.line, start.col,
const_var(std::numeric_limits<double>::infinity())));
} else if (text == "NaN") {
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(text, start.line, start.col,
const_var(std::numeric_limits<double>::quiet_NaN())));
} else if (text == "_") {
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(text, start.line, start.col,
Boxed_Value(std::make_shared<dispatch::Placeholder_Object>())));
} else {
m_match_stack.push_back(make_node<eval::Id_AST_Node>(
[&]()->std::string{
if (*start == '`') {
// 'escaped' literal, like an operator name
return Position::str(start+1, m_position-1);
} else {
return text;
}
}(),
start.line, start.col));
}
return true;
} else {
return false;
@ -863,31 +837,6 @@ namespace chaiscript
/// Checks for a node annotation of the form "#<annotation>"
bool Annotation() {
SkipWS();
const auto start = m_position;
if (Symbol_("#")) {
do {
while (m_position.has_more()) {
if (Eol_()) {
break;
}
else {
++m_position;
}
}
} while (Symbol("#"));
auto match = Position::str(start, m_position);
m_match_stack.push_back(make_node<eval::Annotation_AST_Node>(std::move(match), start.line, start.col));
return true;
}
else {
return false;
}
}
/// Reads a quoted string from input, without skipping initial whitespace
bool Quoted_String_() {
if (m_position.has_more() && (*m_position == '\"')) {
@ -933,11 +882,11 @@ namespace chaiscript
{
string_type &match;
typedef typename string_type::value_type char_type;
bool is_escaped;
bool is_interpolated;
bool saw_interpolation_marker;
bool is_octal;
bool is_hex;
bool is_escaped = false;
bool is_interpolated = false;
bool saw_interpolation_marker = false;
bool is_octal = false;
bool is_hex = false;
const bool interpolation_allowed;
string_type octal_matches;
@ -945,11 +894,6 @@ namespace chaiscript
Char_Parser(string_type &t_match, const bool t_interpolation_allowed)
: match(t_match),
is_escaped(false),
is_interpolated(false),
saw_interpolation_marker(false),
is_octal(false),
is_hex(false),
interpolation_allowed(t_interpolation_allowed)
{
}
@ -1086,13 +1030,11 @@ namespace chaiscript
if (*s == '{') {
//We've found an interpolation point
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(match, start.line, start.col, const_var(match)));
if (cparser.is_interpolated) {
//If we've seen previous interpolation, add on instead of making a new one
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, "+");
} else {
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
}
//We've finished with the part of the string up to this point, so clear it
@ -1143,13 +1085,12 @@ namespace chaiscript
return cparser.is_interpolated;
}();
if (is_interpolated) {
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(match, start.line, start.col, const_var(match)));
if (is_interpolated) {
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, "+");
} else {
m_match_stack.push_back(make_node<eval::Quoted_String_AST_Node>(match, start.line, start.col));
}
return true;
} else {
return false;
@ -1209,7 +1150,7 @@ namespace chaiscript
throw exception::eval_error("Single-quoted strings must be 1 character long", File_Position(m_position.line, m_position.col), *m_filename);
}
m_match_stack.push_back(make_node<eval::Single_Quoted_String_AST_Node>(match, start.line, start.col));
m_match_stack.push_back(make_node<eval::Constant_AST_Node>(match, start.line, start.col, const_var(char(match.at(0)))));
return true;
}
else {
@ -1229,20 +1170,9 @@ namespace chaiscript
}
/// Reads (and potentially captures) a char from input if it matches the parameter
bool Char(const char t_c, bool t_capture = false) {
bool Char(const char t_c) {
SkipWS();
if (!t_capture) {
return Char_(t_c);
} else {
const auto start = m_position;
if (Char_(t_c)) {
m_match_stack.push_back(make_node<eval::Char_AST_Node>(Position::str(start, m_position), start.line, start.col));
return true;
} else {
return false;
}
}
return Char_(t_c);
}
/// Reads a string from input if it matches the parameter, without skipping initial whitespace
@ -1265,7 +1195,7 @@ namespace chaiscript
}
/// Reads (and potentially captures) a string from input if it matches the parameter
bool Keyword(const char *t_s, bool t_capture = false) {
bool Keyword(const char *t_s) {
SkipWS();
const auto start = m_position;
bool retval = Keyword_(t_s);
@ -1275,9 +1205,6 @@ namespace chaiscript
retval = false;
}
if ( t_capture && retval ) {
m_match_stack.push_back(make_node<eval::Str_AST_Node>(Position::str(start, m_position), start.line, start.col));
}
return retval;
}
@ -1311,7 +1238,7 @@ namespace chaiscript
}
/// Reads (and potentially captures) a symbol group from input if it matches the parameter
bool Symbol(const char *t_s, const bool t_capture = false, const bool t_disallow_prevention=false) {
bool Symbol(const char *t_s, const bool t_disallow_prevention=false) {
SkipWS();
const auto start = m_position;
bool retval = Symbol_(t_s);
@ -1326,10 +1253,6 @@ namespace chaiscript
}
}
if ( t_capture && retval ) {
m_match_stack.push_back(make_node<eval::Str_AST_Node>(Position::str(start, m_position), start.line, start.col));
}
return retval;
}
@ -1372,14 +1295,13 @@ namespace chaiscript
if (Arg(false)) {
retval = true;
while (Eol()) {}
if (Char(',')) {
do {
while (Eol()) {}
if (!Arg(false)) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_position.line, m_position.col), *m_filename);
}
} while (Char(','));
}
while (Char(',')) {
while (Eol()) {}
if (!Arg(false)) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_position.line, m_position.col), *m_filename);
}
}
}
build_match<eval::Arg_List_AST_Node>(prev_stack_top);
@ -1398,13 +1320,12 @@ namespace chaiscript
if (Arg()) {
retval = true;
while (Eol()) {}
if (Char(',')) {
do {
while (Eol()) {}
if (!Arg()) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_position.line, m_position.col), *m_filename);
}
} while (Char(','));
while (Char(',')) {
while (Eol()) {}
if (!Arg()) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_position.line, m_position.col), *m_filename);
}
}
}
build_match<eval::Arg_List_AST_Node>(prev_stack_top);
@ -1425,13 +1346,11 @@ namespace chaiscript
if (Equation()) {
retval = true;
while (Eol()) {}
if (Char(',')) {
do {
while (Eol()) {}
if (!Equation()) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_position.line, m_position.col), *m_filename);
}
} while (Char(','));
while (Char(',')) {
while (Eol()) {}
if (!Equation()) {
throw exception::eval_error("Unexpected value in parameter list", File_Position(m_position.line, m_position.col), *m_filename);
}
}
}
@ -1455,25 +1374,21 @@ namespace chaiscript
} else if (Map_Pair()) {
retval = true;
while (Eol()) {}
if (Char(',')) {
do {
while (Eol()) {}
if (!Map_Pair()) {
throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename);
}
} while (Char(','));
while (Char(',')) {
while (Eol()) {}
if (!Map_Pair()) {
throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename);
}
}
build_match<eval::Arg_List_AST_Node>(prev_stack_top);
} else if (Operator()) {
retval = true;
while (Eol()) {}
if (Char(',')) {
do {
while (Eol()) {}
if (!Operator()) {
throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename);
}
} while (Char(','));
while (Char(',')) {
while (Eol()) {}
if (!Operator()) {
throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename);
}
}
build_match<eval::Arg_List_AST_Node>(prev_stack_top);
}
@ -1527,13 +1442,6 @@ namespace chaiscript
/// Reads a function definition from input
bool Def(const bool t_class_context = false) {
bool retval = false;
AST_NodePtr annotation;
if (Annotation()) {
while (Eol_()) {}
annotation = m_match_stack.back();
m_match_stack.pop_back();
}
const auto prev_stack_top = m_match_stack.size();
@ -1546,7 +1454,7 @@ namespace chaiscript
bool is_method = false;
if (Symbol("::", false)) {
if (Symbol("::")) {
//We're now a method
is_method = true;
@ -1581,9 +1489,6 @@ namespace chaiscript
build_match<eval::Def_AST_Node>(prev_stack_top);
}
if (annotation) {
m_match_stack.back()->annotation = std::move(annotation);
}
}
return retval;
@ -1608,7 +1513,7 @@ namespace chaiscript
while (has_matches) {
while (Eol()) {}
has_matches = false;
if (Keyword("catch", false)) {
if (Keyword("catch")) {
const auto catch_stack_top = m_match_stack.size();
if (Char('(')) {
if (!(Arg() && Char(')'))) {
@ -1631,7 +1536,7 @@ namespace chaiscript
}
}
while (Eol()) {}
if (Keyword("finally", false)) {
if (Keyword("finally")) {
const auto finally_stack_top = m_match_stack.size();
while (Eol()) {}
@ -1675,25 +1580,8 @@ namespace chaiscript
while (has_matches) {
while (Eol()) {}
has_matches = false;
if (Keyword("else", true)) {
if (Keyword("if")) {
const AST_NodePtr back(m_match_stack.back());
m_match_stack.back() =
chaiscript::make_shared<AST_Node, eval::If_AST_Node>("else if", back->location, back->children);
m_match_stack.back()->annotation = back->annotation;
if (!Char('(')) {
throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_position.line, m_position.col), *m_filename);
}
if (!(Operator() && Char(')'))) {
throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_position.line, m_position.col), *m_filename);
}
while (Eol()) {}
if (!Block()) {
throw exception::eval_error("Incomplete 'else if' block", File_Position(m_position.line, m_position.col), *m_filename);
}
if (Keyword("else")) {
if (If()) {
has_matches = true;
} else {
while (Eol()) {}
@ -2032,7 +1920,7 @@ namespace chaiscript
func_call->children.insert(func_call->children.begin(), dot_access->children.back());
dot_access->children.pop_back();
dot_access->children.push_back(std::move(func_call));
if (dot_access->children.size() != 3) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
if (dot_access->children.size() != 2) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
m_match_stack.push_back(std::move(dot_access));
}
}
@ -2045,13 +1933,13 @@ namespace chaiscript
build_match<eval::Array_Call_AST_Node>(prev_stack_top);
}
else if (Symbol(".", true)) {
else if (Symbol(".")) {
has_more = true;
if (!(Id())) {
throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
}
if ( std::distance(m_match_stack.begin() + static_cast<int>(prev_stack_top), m_match_stack.end()) != 3) {
if ( std::distance(m_match_stack.begin() + static_cast<int>(prev_stack_top), m_match_stack.end()) != 2) {
throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
}
build_match<eval::Dot_Access_AST_Node>(prev_stack_top);
@ -2079,11 +1967,14 @@ namespace chaiscript
} else if (Keyword("auto") || Keyword("var") ) {
retval = true;
if (!(Reference() || Id())) {
if (Reference()) {
// we built a reference node - continue
} else if (Id()) {
build_match<eval::Var_Decl_AST_Node>(prev_stack_top);
} else {
throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename);
}
build_match<eval::Var_Decl_AST_Node>(prev_stack_top);
} else if (Keyword("GLOBAL") || Keyword("global")) {
retval = true;
@ -2098,7 +1989,7 @@ namespace chaiscript
if (!Id()) {
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
}
if (!Symbol("::", false)) {
if (!Symbol("::")) {
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
}
if (!Id()) {
@ -2162,7 +2053,7 @@ namespace chaiscript
bool Reference() {
const auto prev_stack_top = m_match_stack.size();
if (Symbol("&", false)) {
if (Symbol("&")) {
if (!Id()) {
throw exception::eval_error("Incomplete '&' expression", File_Position(m_position.line, m_position.col), *m_filename);
}
@ -2182,13 +2073,13 @@ namespace chaiscript
for (const auto &oper : prefix_opers)
{
bool is_char = oper.size() == 1;
if ((is_char && Char(oper[0], true)) || (!is_char && Symbol(oper.c_str(), true)))
if ((is_char && Char(oper[0])) || (!is_char && Symbol(oper.c_str())))
{
if (!Operator(m_operators.size()-1)) {
throw exception::eval_error("Incomplete prefix '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename);
}
build_match<eval::Prefix_AST_Node>(prev_stack_top);
build_match<eval::Prefix_AST_Node>(prev_stack_top, oper);
return true;
}
}
@ -2201,9 +2092,10 @@ namespace chaiscript
return Var_Decl() || Dot_Fun_Array() || Prefix();
}
bool Operator_Helper(const size_t t_precedence) {
bool Operator_Helper(const size_t t_precedence, std::string &oper) {
for (auto & elem : m_operator_matches[t_precedence]) {
if (Symbol(elem.c_str(), true)) {
if (Symbol(elem.c_str())) {
oper = elem;
return true;
}
}
@ -2217,61 +2109,80 @@ namespace chaiscript
if (t_precedence < m_operators.size()) {
if (Operator(t_precedence+1)) {
retval = true;
if (Operator_Helper(t_precedence)) {
do {
while (Eol()) {}
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete "
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
File_Position(m_position.line, m_position.col), *m_filename);
}
std::string oper;
while (Operator_Helper(t_precedence, oper)) {
while (Eol()) {}
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete '" + oper + "' expression",
File_Position(m_position.line, m_position.col), *m_filename);
}
AST_NodePtr oper = m_match_stack.at(m_match_stack.size()-2);
switch (m_operators[t_precedence]) {
case(AST_Node_Type::Ternary_Cond) :
m_match_stack.erase(advance_copy(m_match_stack.begin(), m_match_stack.size() - 2),
advance_copy(m_match_stack.begin(), m_match_stack.size() - 1));
if (Symbol(":")) {
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete "
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
File_Position(m_position.line, m_position.col), *m_filename);
}
build_match<eval::Ternary_Cond_AST_Node>(prev_stack_top);
}
else {
throw exception::eval_error("Incomplete "
+ std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression",
switch (m_operators[t_precedence]) {
case(Operator_Precidence::Ternary_Cond) :
if (Symbol(":")) {
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete '" + oper + "' expression",
File_Position(m_position.line, m_position.col), *m_filename);
}
break;
build_match<eval::Ternary_Cond_AST_Node>(prev_stack_top);
}
else {
throw exception::eval_error("Incomplete '" + oper + "' expression",
File_Position(m_position.line, m_position.col), *m_filename);
}
break;
case(AST_Node_Type::Addition) :
case(AST_Node_Type::Multiplication) :
case(AST_Node_Type::Shift) :
case(AST_Node_Type::Equality) :
case(AST_Node_Type::Bitwise_And) :
case(AST_Node_Type::Bitwise_Xor) :
case(AST_Node_Type::Bitwise_Or) :
case(AST_Node_Type::Comparison) :
assert(m_match_stack.size() > 1);
m_match_stack.erase(advance_copy(m_match_stack.begin(), m_match_stack.size() - 2),
advance_copy(m_match_stack.begin(), m_match_stack.size() - 1));
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, oper->text);
break;
case(Operator_Precidence::Addition) :
case(Operator_Precidence::Multiplication) :
case(Operator_Precidence::Shift) :
case(Operator_Precidence::Equality) :
case(Operator_Precidence::Bitwise_And) :
case(Operator_Precidence::Bitwise_Xor) :
case(Operator_Precidence::Bitwise_Or) :
case(Operator_Precidence::Comparison) :
{
bool folded = false;
const auto size = m_match_stack.size();
case(AST_Node_Type::Logical_And) :
build_match<eval::Logical_And_AST_Node>(prev_stack_top);
break;
case(AST_Node_Type::Logical_Or) :
build_match<eval::Logical_Or_AST_Node>(prev_stack_top);
break;
try {
if (m_match_stack[size - 1]->identifier == AST_Node_Type::Constant
&& m_match_stack[size - 2]->identifier == AST_Node_Type::Constant) {
const auto parsed = Operators::to_operator(oper);
if (parsed != Operators::Opers::invalid) {
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node>(m_match_stack[size-2])->m_value;
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node>(m_match_stack[size-1])->m_value;
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
const auto start = m_match_stack[size-2]->location;
const auto match = m_match_stack[size-2]->text + " " + oper + " " + m_match_stack[size-1]->text;
m_match_stack.resize(size-2);
m_match_stack.push_back(
make_node<eval::Constant_AST_Node>(std::move(match), start.start.line, start.start.column, std::move(val)));
folded = true;
}
}
}
} catch (const std::exception &) {
//failure to fold
}
default:
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_position.line, m_position.col), *m_filename);
}
} while (Operator_Helper(t_precedence));
if (!folded) {
build_match<eval::Binary_Operator_AST_Node>(prev_stack_top, oper);
}
}
break;
case(Operator_Precidence::Logical_And) :
build_match<eval::Logical_And_AST_Node>(prev_stack_top, oper);
break;
case(Operator_Precidence::Logical_Or) :
build_match<eval::Logical_Or_AST_Node>(prev_stack_top, oper);
break;
default:
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_position.line, m_position.col), *m_filename);
}
}
}
}
@ -2338,26 +2249,25 @@ namespace chaiscript
/// Parses a string of binary equation operators
bool Equation() {
bool retval = false;
const auto prev_stack_top = m_match_stack.size();
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)) {
SkipWS(true);
if (!Equation()) {
throw exception::eval_error("Incomplete equation", File_Position(m_position.line, m_position.col), *m_filename);
}
for (const auto sym : {"=", ":=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|="})
{
if (Symbol(sym, true)) {
SkipWS(true);
if (!Equation()) {
throw exception::eval_error("Incomplete equation", File_Position(m_position.line, m_position.col), *m_filename);
}
build_match<eval::Equation_AST_Node>(prev_stack_top);
build_match<eval::Equation_AST_Node>(prev_stack_top, sym);
return true;
}
}
return true;
}
return retval;
return false;
}
/// Parses statements allowed inside of a class block

View File

@ -0,0 +1,81 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_POSIX_HPP_
#define CHAISCRIPT_POSIX_HPP_
namespace chaiscript
{
namespace detail
{
struct Loadable_Module
{
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
DLModule(DLModule &&) = default;
DLModule &operator=(DLModule &&) = default;
DLModule(const DLModule &) = delete;
DLModule &operator=(const DLModule &) = delete;
~DLModule()
{
dlclose(m_data);
}
void *m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(dlerror());
}
}
static T cast_symbol(void *p)
{
union cast_union
{
T func_ptr;
void *in_ptr;
};
cast_union c;
c.in_ptr = p;
return c.func_ptr;
}
T m_symbol;
};
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_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
}
}
#endif

View File

@ -0,0 +1,27 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_UNKNOWN_HPP_
#define CHAISCRIPT_UNKNOWN_HPP_
namespace chaiscript
{
namespace detail
{
struct Loadable_Module
{
Loadable_Module(const std::string &, const std::string &)
{
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
}
ModulePtr m_moduleptr;
};
}
}
#endif

View File

@ -0,0 +1,133 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_WINDOWS_HPP_
#define CHAISCRIPT_WINDOWS_HPP_
#include <string>
#ifdef CHAISCRIPT_WINDOWS
#define VC_EXTRA_LEAN
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
namespace chaiscript
{
namespace detail
{
struct Loadable_Module
{
template<typename T>
static std::wstring to_wstring(const T &t_str)
{
return std::wstring(t_str.begin(), t_str.end());
}
template<typename T>
static std::string to_string(const T &t_str)
{
return std::string(t_str.begin(), t_str.end());
}
#if defined(_UNICODE) || defined(UNICODE)
template<typename T>
static std::wstring to_proper_string(const T &t_str)
{
return to_wstring(t_str);
}
#else
template<typename T>
static std::string to_proper_string(const T &t_str)
{
return to_string(t_str);
}
#endif
static std::string get_error_message(DWORD t_err)
{
typedef LPTSTR StringType;
#if defined(_UNICODE) || defined(UNICODE)
std::wstring retval = L"Unknown Error";
#else
std::string retval = "Unknown Error";
#endif
StringType lpMsgBuf = nullptr;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
t_err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<StringType>(&lpMsgBuf),
0, nullptr ) != 0 && lpMsgBuf)
{
retval = lpMsgBuf;
LocalFree(lpMsgBuf);
}
return to_string(retval);
}
struct DLModule
{
DLModule(const std::string &t_filename)
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
{
if (!m_data)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
DLModule(DLModule &&) = default;
DLModule &operator=(DLModule &&) = default;
DLModule(const DLModule &) = delete;
DLModule &operator=(const DLModule &) = delete;
~DLModule()
{
FreeLibrary(m_data);
}
HMODULE m_data;
};
template<typename T>
struct DLSym
{
DLSym(DLModule &t_mod, const std::string &t_symbol)
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
{
if (!m_symbol)
{
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
}
}
T m_symbol;
};
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_moduleptr(m_func.m_symbol())
{
}
DLModule m_dlmodule;
DLSym<Create_Module_Func> m_func;
ModulePtr m_moduleptr;
};
}
}
#endif

View File

@ -12,9 +12,8 @@
#include <utility>
#include <vector>
#include "../chaiscript.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/type_info.hpp"
#include "../language/chaiscript_common.hpp"
#include "../dispatchkit/register_function.hpp"
#include "../dispatchkit/operators.hpp"

View File

@ -1,7 +1,6 @@
assert_equal(`==`, `==`);
assert_not_equal(`==`, `<`);
assert_equal(`<`.get_arity(), 2);
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
assert_equal(get_arity.get_contained_functions().size(), 0);
assert_equal(get_arity.get_arity(), 1);
assert_equal(get_arity.get_param_types().size(), 2);

View File

@ -10,7 +10,6 @@ def test_function(a)
// test_function tests
assert_equal(test_function.get_arity(), 1);
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
assert_equal(test_function.get_contained_functions().size(), 0);
assert_equal(test_function.get_param_types().size(), 2);

View File

@ -1,36 +0,0 @@
var parser := ChaiScript_Parser()
var parse_success = parser.parse("3 + 4", "INPUT")
var a := parser.ast()
assert_equal(eval(a), 7)
var childs := a.children.front().children
var node := childs[0]
var parser2 := ChaiScript_Parser()
parser2.parse("9", "INPUT")
a.children.front().replace_child(childs[0], parser2.ast())
assert_equal(eval(a), 13)
assert_equal(node.filename, "INPUT")
def my_fun()
{
return 1;
}
assert_equal(true, my_fun.has_parse_tree());
assert_equal(false, `+`.has_parse_tree());
assert_throws("Function does not have a parse tree", fun() { `+`.get_parse_tree(); } );
var parsetree := my_fun.get_parse_tree();
assert_equal(1, eval(parsetree));
print(parsetree.text());

View File

@ -0,0 +1,38 @@
GLOBAL clone_count = 0;
class Cloneable
{
def Cloneable() {
}
}
def clone(Cloneable c)
{
print("Clone called");
++clone_count;
return c;
}
class MyObject
{
def MyObject() {
this.data = Cloneable();
}
var data;
}
assert_equal(0, clone_count);
var o = MyObject();
assert_equal(0, clone_count);
var p = o;
assert_equal(1, clone_count);

View File

@ -316,7 +316,8 @@ TEST_CASE("Function ordering")
chaiscript::ChaiScript chai;
chai.eval("def test_fun(x) { return 3; }");
chai.eval("def test_fun(x) : x == \"hi\" { return 4; }");
// chai.eval("def test_fun(x) { return 5; }");
chai.eval("def test_fun(double d) { return 5; }");
chai.add(chaiscript::fun(&function_ordering_test_one), "test_fun");
chai.add(chaiscript::fun(&function_ordering_test_two), "test_fun");
@ -324,6 +325,7 @@ TEST_CASE("Function ordering")
CHECK(chai.eval<int>("auto i = 1; test_fun(i)") == 2);
CHECK(chai.eval<int>("test_fun(\"bob\")") == 3);
CHECK(chai.eval<int>("test_fun(\"hi\")") == 4);
CHECK(chai.eval<int>("test_fun(5.0)") == 5);
}

View File

@ -1,7 +1,6 @@
assert_equal(`==`, `==`);
assert_not_equal(`==`, `<`);
assert_equal(`<`.get_arity(), 2);
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
assert_equal(get_arity.get_contained_functions().size(), 0);
assert_equal(get_arity.get_arity(), 1);
assert_equal(get_arity.get_param_types().size(), 2);

View File

@ -10,7 +10,6 @@ def test_function(a)
// test_function tests
assert_equal(test_function.get_arity(), 1);
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
assert_equal(test_function.get_contained_functions().size(), 0);
assert_equal(test_function.get_param_types().size(), 2);

View File

@ -16,3 +16,8 @@ def f() {
f();
global &h = v;
assert_true(h == v)
v = 3;
assert_true(h == 3)

View File

@ -1,22 +1,9 @@
auto& parser = ChaiScript_Parser()
auto parse_success = parser.parse("3 + 4", "INPUT")
auto& a = parser.ast()
auto a = parse("3 + 4")
assert_equal(eval(a), 7)
auto& childs = a.children.front().children
auto& node = childs[0]
auto& parser2 = ChaiScript_Parser()
parser2.parse("9", "INPUT")
a.children.front().replace_child(childs[0], parser2.ast())
assert_equal(eval(a), 13)
assert_equal(node.filename, "INPUT")
assert_equal(1, a.children.size());
assert_equal("3 + 4", a.children[0].text());
def my_fun()
{