diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 79ef8cf..43d3b4f 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -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. diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 4049381..4c31b6e 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -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 Iter advance_copy(Iter iter, Distance distance) { std::advance(iter, static_cast::difference_type>(distance)); diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index 50aa087..a1082c5 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -14,11 +14,15 @@ #include #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(); - Bootstrap::bootstrap(*lib); + bootstrap::Bootstrap::bootstrap(*lib); - standard_library::vector_type >("Vector", *lib); - standard_library::string_type("string", *lib); - standard_library::map_type >("Map", *lib); - standard_library::pair_type >("Pair", *lib); + bootstrap::standard_library::vector_type >("Vector", *lib); + bootstrap::standard_library::string_type("string", *lib); + bootstrap::standard_library::map_type >("Map", *lib); + bootstrap::standard_library::pair_type >("Pair", *lib); #ifndef CHAISCRIPT_NO_THREADS standard_library::future_type>("future", *lib); diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 2250693..0d2825f 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -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. /// diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index fcba534..98da1de 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -27,45 +27,52 @@ namespace chaiscript } template - std::function bind_first(Ret (*f)(P1, Param...), O&& o) + auto bind_first(Ret (*f)(P1, Param...), O&& o) { - return std::function( - [f, o](Param...param) -> Ret { - return f(std::forward(o), std::forward(param)...); - } - ); + return [f, o](Param...param) -> Ret { + return f(std::forward(o), std::forward(param)...); + }; } template - std::function bind_first(Ret (Class::*f)(Param...), O&& o) + auto bind_first(Ret (Class::*f)(Param...), O&& o) { - return std::function( - [f, o](Param...param) -> Ret { - return (get_pointer(o)->*f)(std::forward(param)...); - } - ); + return [f, o](Param...param) -> Ret { + return (get_pointer(o)->*f)(std::forward(param)...); + }; } template - std::function bind_first(Ret (Class::*f)(Param...) const, O&& o) + auto bind_first(Ret (Class::*f)(Param...) const, O&& o) { - return std::function( - [f, o](Param...param) -> Ret { - return (get_pointer(o)->*f)(std::forward(param)...); - } - ); + return [f, o](Param...param) -> Ret { + return (get_pointer(o)->*f)(std::forward(param)...); + }; } template - std::function bind_first(const std::function &f, O&& o) + auto bind_first(const std::function &f, O&& o) { - return std::function( - [f, o](Param...param) -> Ret { - return f(o, std::forward(param)...); - }); + return [f, o](Param...param) -> Ret { + return f(o, std::forward(param)...); + }; } + template + 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)...); + }; + + } + + template + auto bind_first(const F &f, O&& o) + { + return bind_first(f, std::forward(o), &F::operator()); + } } } diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 4bee74d..0d7e8a3 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -7,32 +7,8 @@ #ifndef CHAISCRIPT_BOOTSTRAP_HPP_ #define CHAISCRIPT_BOOTSTRAP_HPP_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - 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 @@ -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 static std::vector do_return_boxed_value_vector(FunctionType f, const dispatch::Proxy_Function_Base *b) @@ -384,7 +329,7 @@ namespace chaiscript } template - static std::function (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(), "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(), "out_of_range"); m.add(user_type(), "logic_error"); @@ -425,7 +370,6 @@ namespace chaiscript m.add(chaiscript::base_class()); m.add(constructor(), "runtime_error"); - m.add(fun(std::function(&what)), "what"); m.add(user_type(), "Dynamic_Object"); m.add(constructor(), "Dynamic_Object"); @@ -520,15 +464,15 @@ namespace chaiscript operators::equal(m); operators::not_equal(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), "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", m); bootstrap_pod_type("long_double", m); bootstrap_pod_type("float", m); @@ -552,10 +496,21 @@ namespace chaiscript bootstrap_pod_type("uint32_t", m); bootstrap_pod_type("uint64_t", m); + operators::logical_compliment(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()); + m.add(chaiscript::base_class()); m.add(chaiscript::user_type(), "arithmetic_error"); m.add(chaiscript::base_class()); + m.add(chaiscript::base_class()); // chaiscript::bootstrap::standard_library::vector_type > >("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 (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector { + {fun([](const chaiscript::exception::eval_error &t_eval_error) { std::vector retval; std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(), std::back_inserter(retval), &chaiscript::var &>); 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 (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector { + {fun([](const chaiscript::AST_Node &t_node) -> std::vector { std::vector retval; std::transform(t_node.children.begin(), t_node.children.end(), std::back_inserter(retval), &chaiscript::var &>); return retval; - })), "children"}, - {fun(&AST_Node::replace_child), "replace_child"} + }), "children"} } ); - - chaiscript::utility::add_class(m, - "ChaiScript_Parser", - { constructor() }, - { {fun(&parser::ChaiScript_Parser::parse), "parse"}, - {fun(&parser::ChaiScript_Parser::ast), "ast"} } - ); } }; } diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 5a11ee9..7fbe78d 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -69,11 +69,11 @@ namespace chaiscript /// assert(i == 5); /// \endcode template - typename detail::Cast_Helper::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()) || (t_conversions && !(*t_conversions)->convertable_type())) { try { - return detail::Cast_Helper::cast(bv, t_conversions); + return(detail::Cast_Helper::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::cast((*t_conversions)->boxed_type_conversion(t_conversions->saves(), bv), t_conversions); + return(detail::Cast_Helper::cast((*t_conversions)->boxed_type_conversion(t_conversions->saves(), bv), t_conversions)); } catch (...) { try { // try going the other way - return detail::Cast_Helper::cast((*t_conversions)->boxed_type_down_conversion(t_conversions->saves(), bv), t_conversions); + return(detail::Cast_Helper::cast((*t_conversions)->boxed_type_down_conversion(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)); } diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index da1e222..6347437 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -29,21 +29,50 @@ namespace chaiscript throw std::runtime_error("Attempted to dereference null Boxed_Value"); } + template + 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 + 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 + 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 + 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 struct Cast_Helper_Inner { - typedef typename std::add_const::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(p); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } + return *static_cast(verify_type(ob, typeid(Result), ob.get_const_ptr())); } }; @@ -57,15 +86,9 @@ namespace chaiscript template struct Cast_Helper_Inner { - 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(ob.get_const_ptr()); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } + return static_cast(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr())); } }; @@ -73,15 +96,9 @@ namespace chaiscript template struct Cast_Helper_Inner { - 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(ob.get_ptr()); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } + return static_cast(verify_type_no_throw(ob, typeid(Result), ob.get_ptr())); } }; @@ -100,17 +117,9 @@ namespace chaiscript template struct Cast_Helper_Inner { - 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(p); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } + return *static_cast(verify_type(ob, typeid(Result), ob.get_const_ptr())); } }; @@ -120,16 +129,9 @@ namespace chaiscript template struct Cast_Helper_Inner { - 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(throw_if_null(ob.get_ptr()))); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } + return *static_cast(verify_type(ob, typeid(Result), ob.get_ptr())); } }; @@ -137,9 +139,7 @@ namespace chaiscript template struct Cast_Helper_Inner > { - typedef std::shared_ptr 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 >(); } @@ -149,9 +149,7 @@ namespace chaiscript template struct Cast_Helper_Inner > { - typedef std::shared_ptr 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 &> { static_assert(!std::is_const::value, "Non-const reference to std::shared_ptr is not supported"); - - typedef Boxed_Value::Sentinel 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 &res = ob.get().cast >(); return ob.pointer_sentinel(res); @@ -204,9 +199,7 @@ namespace chaiscript template<> struct Cast_Helper_Inner { - 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 { - typedef std::reference_wrapper Result_Type; - - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) + static std::reference_wrapper cast(const Boxed_Value &ob, const Type_Conversions_State *) { return std::ref(const_cast(ob)); } @@ -272,11 +263,9 @@ namespace chaiscript template struct Cast_Helper { - typedef typename Cast_Helper_Inner::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::cast(ob, t_conversions); + return(Cast_Helper_Inner::cast(ob, t_conversions)); } }; } diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 7eefe99..2cc06c7 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -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::value && !std::is_floating_point::value, Boxed_Value>::type { typedef typename std::common_type::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(t_lhs), get_as_aux(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(t_lhs.get_ptr()), get_as_aux(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(t_lhs.get_ptr()), get_as_aux(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(t_lhs), get_as_aux(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(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); @@ -349,12 +349,12 @@ namespace chaiscript -> typename std::enable_if::value || std::is_floating_point::value, Boxed_Value>::type { typedef typename std::common_type::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(t_lhs), get_as_aux(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(t_lhs.get_ptr()), get_as_aux(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(t_lhs), get_as_aux(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::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(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(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(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::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(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(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(oper(Operators::equals, this->bv, t_rhs.bv)); - } - - bool operator<(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::less_than, this->bv, t_rhs.bv)); - } - - bool operator>(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::greater_than, this->bv, t_rhs.bv)); - } - - bool operator>=(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::greater_than_equal, this->bv, t_rhs.bv)); - } - - bool operator<=(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::less_than_equal, this->bv, t_rhs.bv)); - } - - bool operator!=(const Boxed_Number &t_rhs) const - { - return boxed_cast(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(oper(Operators::equals, t_lhs.bv, t_rhs.bv)); + return boxed_cast(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(oper(Operators::less_than, t_lhs.bv, t_rhs.bv)); + return boxed_cast(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(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv)); + return boxed_cast(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(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv)); + return boxed_cast(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(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv)); + return boxed_cast(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(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv)); + return boxed_cast(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 { - 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); } diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 538391f..53c5867 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -77,9 +77,9 @@ namespace chaiscript struct Object_Data { - static std::unique_ptr get(Boxed_Value::Void_Type, bool t_return_value) + static std::shared_ptr get(Boxed_Value::Void_Type, bool t_return_value) { - return std::make_unique( + return std::make_shared( detail::Get_Type_Info::get(), chaiscript::detail::Any(), false, @@ -89,15 +89,15 @@ namespace chaiscript } template - static std::unique_ptr get(const std::shared_ptr *obj, bool t_return_value) + static std::shared_ptr get(const std::shared_ptr *obj, bool t_return_value) { return get(*obj, t_return_value); } template - static std::unique_ptr get(const std::shared_ptr &obj, bool t_return_value) + static std::shared_ptr get(const std::shared_ptr &obj, bool t_return_value) { - return std::make_unique( + return std::make_shared( detail::Get_Type_Info::get(), chaiscript::detail::Any(obj), false, @@ -107,10 +107,10 @@ namespace chaiscript } template - static std::unique_ptr get(std::shared_ptr &&obj, bool t_return_value) + static std::shared_ptr get(std::shared_ptr &&obj, bool t_return_value) { auto ptr = obj.get(); - return std::make_unique( + return std::make_shared( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::move(obj)), false, @@ -120,23 +120,23 @@ namespace chaiscript } template - static std::unique_ptr get(T *t, bool t_return_value) + static std::shared_ptr get(T *t, bool t_return_value) { return get(std::ref(*t), t_return_value); } template - static std::unique_ptr get(const T *t, bool t_return_value) + static std::shared_ptr get(const T *t, bool t_return_value) { return get(std::cref(*t), t_return_value); } template - static std::unique_ptr get(std::reference_wrapper obj, bool t_return_value) + static std::shared_ptr get(std::reference_wrapper obj, bool t_return_value) { auto p = &obj.get(); - return std::make_unique( + return std::make_shared( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::move(obj)), true, @@ -146,11 +146,11 @@ namespace chaiscript } template - static std::unique_ptr get(T t, bool t_return_value) + static std::shared_ptr get(T t, bool t_return_value) { auto p = std::make_shared(std::move(t)); auto ptr = p.get(); - return std::make_unique( + return std::make_shared( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::move(p)), false, @@ -159,9 +159,9 @@ namespace chaiscript ); } - static std::unique_ptr get() + static std::shared_ptr get() { - return std::make_unique( + return std::make_shared( Type_Info(), chaiscript::detail::Any(), false, @@ -226,48 +226,39 @@ namespace chaiscript return m_data->m_type_info.bare_equal(ti); } - template - struct Sentinel { - Sentinel(std::shared_ptr &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&() const - { - return m_ptr.get(); - } - - Sentinel &operator=(const Sentinel &) = delete; - Sentinel(Sentinel&) = delete; - - std::reference_wrapper> m_ptr; - std::reference_wrapper m_data; - }; - template - Sentinel pointer_sentinel(std::shared_ptr &ptr) const + auto pointer_sentinel(std::shared_ptr &ptr) const { - return Sentinel(ptr, *(m_data.get())); + struct Sentinel { + Sentinel(std::shared_ptr &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&() const + { + return m_ptr.get(); + } + + Sentinel &operator=(const Sentinel &) = delete; + Sentinel(Sentinel&) = delete; + + std::reference_wrapper> m_ptr; + std::reference_wrapper m_data; + }; + + return Sentinel(ptr, *(m_data.get())); } bool is_null() const noexcept diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 0528cb9..84e35bb 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -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 ¶ms, const Type_Conversions_State &t_conversions) const override { @@ -381,7 +376,6 @@ namespace chaiscript typedef std::vector StackData; Stack_Holder() - : call_depth(0) { stacks.reserve(2); stacks.emplace_back(1); @@ -392,7 +386,7 @@ namespace chaiscript std::vector stacks; std::vector> call_params; - int call_depth; + int call_depth = 0; }; /// Main class for the dispatchkit. Handles management @@ -412,11 +406,9 @@ namespace chaiscript std::vector> m_boxed_functions; std::map m_global_objects; Type_Name_Map m_types; - std::set m_reserved_words; - - State &operator=(const State &) = default; - State() = default; - State(const State &) = default; + std::set 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 detail::Cast_Helper::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(bv, &state); + return(chaiscript::boxed_cast(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 l(m_mutex); - - m_state.m_reserved_words.insert(name); - } const Type_Conversions &conversions() const { @@ -1065,11 +1047,7 @@ namespace chaiscript typed_params = func->get_dynamic_param_types().types(); } - std::string annotation = f.second->annotation(); - if (annotation.size() > 0) { - std::cout << annotation; - } dump_type(params.front()); std::cout << " " << f.first << "("; @@ -1395,10 +1373,6 @@ namespace chaiscript if (rt.bare_equal(boxed_type)) { - if (lt.bare_equal(boxed_pod_type)) - { - return true; - } return true; } @@ -1612,3 +1586,4 @@ namespace chaiscript #endif + diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index 23b20da..f3e1240 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -109,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 ¶ms, const Type_Conversions_State &t_conversions) const override { @@ -243,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 ¶ms, const Type_Conversions_State &t_conversions) const override { diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 990be95..3efb703 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -81,9 +81,7 @@ namespace chaiscript template struct Cast_Helper &> { - typedef std::function Result_Type; - - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) + static std::function cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { @@ -98,9 +96,7 @@ namespace chaiscript template struct Cast_Helper > { - typedef std::function Result_Type; - - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) + static std::function cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { @@ -115,9 +111,7 @@ namespace chaiscript template struct Cast_Helper > { - typedef std::function Result_Type; - - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) + static std::function cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index ca353ec..8ac2d9e 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -146,6 +146,14 @@ namespace chaiscript } }; + template + struct Handle_Return + { + static Boxed_Value handle(const Ret &r) + { + return Boxed_Value(std::cref(r)); + } + }; template struct Handle_Return @@ -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<> diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 8dc54ba..4ebaec5 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -16,414 +16,202 @@ namespace chaiscript { namespace operators { - namespace detail - { - /// \todo make this return a decltype once we drop gcc 4.6 - template - auto assign(L l, R r) -> L& - { - return (l = r); - } - - template - auto assign_bitwise_and(L l, R r) -> decltype((l &= r)) - { - return (l &= r); - } - - template - auto assign_xor(L l, R r) -> decltype((l^=r)) - { - return (l ^= r); - } - - template - auto assign_bitwise_or(L l, R r) -> decltype((l |= r)) - { - return (l |= r); - } - - template - auto assign_difference(L l, R r) -> decltype(( l -= r)) - { - return (l -= r); - } - - template - auto assign_left_shift(L l, R r) -> decltype(( l <<= r)) - { - return (l <<= r); - } - - template - auto assign_product(L l, R r) -> decltype(( l *= r )) - { - return (l *= r); - } - - template - auto assign_quotient(L l, R r) -> decltype(( l /= r )) - { - return (l /= r); - } - - template - auto assign_remainder(L l, R r) -> decltype(( l %= r )) - { - return (l %= r); - } - - template - 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 - auto assign_sum(L l, R r) -> L& - { - return (l += r); - } - - template - auto prefix_decrement(L l) -> decltype(( --l )) - { - return (--l); - } - - template - auto prefix_increment(L l) -> decltype(( ++l )) - { - return (++l); - } - - template - auto equal(L l, R r) -> decltype(( l == r )) - { - return (l == r); - } - - template - auto greater_than(L l, R r) -> decltype(( l > r )) - { - return (l > r); - } - - template - auto greater_than_equal(L l, R r) -> decltype(( l >= r )) - { - return (l >= r); - } - - template - auto less_than(L l, R r) -> decltype(( l < r )) - { - return (l < r); - } - - template - auto less_than_equal(L l, R r) -> decltype(( l <= r )) - { - return (l <= r); - } - - template - auto logical_compliment(L l) -> decltype(( !l )) - { - return (!l); - } - - template - auto not_equal(L l, R r) -> decltype(( l != r )) - { - return (l != r); - } - - template - auto addition(L l, R r) -> decltype(( l + r )) - { - return (l + r); - } - - template - auto unary_plus(L l) -> decltype(( +l )) - { - return (+l); - } - - template - auto subtraction(L l, R r) -> decltype(( l - r )) - { - return (l - r); - } - - template - 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 - auto bitwise_and(L l, R r) -> decltype(( l & r )) - { - return (l & r); - } - - template - auto bitwise_compliment(L l) -> decltype(( ~l )) - { - return (~l); - } - - template - auto bitwise_xor(L l, R r) -> decltype(( l ^ r )) - { - return (l ^ r); - } - - template - auto bitwise_or(L l, R r) -> decltype(( l | r )) - { - return (l | r); - } - - template - auto division(L l, R r) -> decltype(( l / r )) - { - return (l / r); - } - - template - auto left_shift(L l, R r) -> decltype(( l << r )) - { - return l << r; - } - - template - auto multiplication(L l, R r) -> decltype(( l * r )) - { - return l * r; - } - - template - auto remainder(L l, R r) -> decltype(( l % r )) - { - return (l % r); - } - - template - auto right_shift(L l, R r) -> decltype(( l >> r )) - { - return (l >> r); - } - } - - - template void assign(Module& m) { - m.add(chaiscript::fun(&detail::assign), "="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "="); } template void assign_bitwise_and(Module& m) { - m.add(chaiscript::fun(&detail::assign_bitwise_and), "&="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&="); } template void assign_xor(Module& m) { - m.add(chaiscript::fun(&detail::assign_xor), "^="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^="); } template void assign_bitwise_or(Module& m) { - m.add(chaiscript::fun(&detail::assign_bitwise_or), "|="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|="); } template void assign_difference(Module& m) { - m.add(chaiscript::fun(&detail::assign_difference), "-="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-="); } template void assign_left_shift(Module& m) { - m.add(chaiscript::fun(&detail::assign_left_shift), "<<="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<="); } template void assign_product(Module& m) { - m.add(chaiscript::fun(&detail::assign_product), "*="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*="); } template void assign_quotient(Module& m) { - m.add(chaiscript::fun(&detail::assign_quotient), "/="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/="); } template void assign_remainder(Module& m) { - m.add(chaiscript::fun(&detail::assign_remainder), "%="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%="); } template void assign_right_shift(Module& m) { - m.add(chaiscript::fun(&detail::assign_right_shift), ">>="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>="); } template void assign_sum(Module& m) { - m.add(chaiscript::fun(&detail::assign_sum), "+="); + m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+="); } template void prefix_decrement(Module& m) { - m.add(chaiscript::fun(&detail::prefix_decrement), "--"); + m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--"); } template void prefix_increment(Module& m) { - m.add(chaiscript::fun(&detail::prefix_increment), "++"); + m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++"); } template void equal(Module& m) { - m.add(chaiscript::fun(&detail::equal), "=="); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "=="); } template void greater_than(Module& m) { - m.add(chaiscript::fun(&detail::greater_than), ">"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">"); } template void greater_than_equal(Module& m) { - m.add(chaiscript::fun(&detail::greater_than_equal), ">="); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">="); } template void less_than(Module& m) { - m.add(chaiscript::fun(&detail::less_than), "<"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs void less_than_equal(Module& m) { - m.add(chaiscript::fun(&detail::less_than_equal), "<="); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<="); } template void logical_compliment(Module& m) { - m.add(chaiscript::fun(&detail::logical_compliment), "!"); + m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!"); } template void not_equal(Module& m) { - m.add(chaiscript::fun(&detail::not_equal), "!="); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!="); } template void addition(Module& m) { - m.add(chaiscript::fun(&detail::addition), "+"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+"); } template void unary_plus(Module& m) { - m.add(chaiscript::fun(&detail::unary_plus), "+"); + m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+"); } template void subtraction(Module& m) { - m.add(chaiscript::fun(&detail::subtraction), "-"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-"); } template void unary_minus(Module& m) { - m.add(chaiscript::fun(&detail::unary_minus), "-"); + m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-"); } template void bitwise_and(Module& m) { - m.add(chaiscript::fun(&detail::bitwise_and), "&"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&"); } template void bitwise_compliment(Module& m) { - m.add(chaiscript::fun(&detail::bitwise_compliment), "~"); + m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~"); } template void bitwise_xor(Module& m) { - m.add(chaiscript::fun(&detail::bitwise_xor), "^"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^"); } template void bitwise_or(Module& m) { - m.add(chaiscript::fun(&detail::bitwise_or), "|"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|"); } template void division(Module& m) { - m.add(chaiscript::fun(&detail::division), "/"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/"); } template void left_shift(Module& m) { - m.add(chaiscript::fun(&detail::left_shift), "<<"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs< void multiplication(Module& m) { - m.add(chaiscript::fun(&detail::multiplication), "*"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*"); } template void remainder(Module& m) { - m.add(chaiscript::fun(&detail::remainder), "%"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%"); } template void right_shift(Module& m) { - m.add(chaiscript::fun(&detail::right_shift), ">>"); + m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>"); } } } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 1e27db3..e5a51bb 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -223,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() @@ -332,11 +330,10 @@ 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()) : 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)) { } @@ -369,11 +366,6 @@ 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; } @@ -418,7 +410,6 @@ namespace chaiscript Param_Types m_param_types; Proxy_Function m_guard; AST_NodePtr m_parsenode; - std::string m_description; }; @@ -432,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)) @@ -537,10 +526,6 @@ namespace chaiscript return args; } - virtual std::string annotation() const override - { - return "Bound: " + m_f->annotation(); - } protected: static std::vector build_param_type_info(const Const_Proxy_Function &t_f, @@ -585,11 +570,6 @@ namespace chaiscript { } - std::string annotation() const override - { - return ""; - } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return static_cast(vals.size()) == get_arity() @@ -626,8 +606,7 @@ namespace chaiscript protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { - typedef typename detail::Function_Signature::Return_Type Return_Type; - return detail::Do_Call::template go(m_f, params, t_conversions); + return detail::call_func(detail::Function_Signature(), m_f, params, t_conversions); } private: @@ -679,7 +658,7 @@ namespace chaiscript protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { - return detail::Do_Call::result_type>::template go(m_f.get(), params, t_conversions); + return detail::call_func(detail::Function_Signature(), m_f.get(), params, t_conversions); } @@ -724,11 +703,6 @@ namespace chaiscript return vals[0].get_type_info().bare_equal(user_type()); } - std::string annotation() const override - { - return ""; - } - protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { @@ -759,13 +733,13 @@ namespace chaiscript template auto do_call_impl(Class *o) const -> std::enable_if_t::value, Boxed_Value> { - return detail::Handle_Return::type>::handle(o->*m_attr); + return detail::Handle_Return::type>::handle(o->*m_attr); } template auto do_call_impl(const Class *o) const -> std::enable_if_t::value, Boxed_Value> { - return detail::Handle_Return::type>::handle(o->*m_attr); + return detail::Handle_Return::type>::type>::handle(o->*m_attr); } diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 69b88a8..54a1c6e 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -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 - Ret call_func(const chaiscript::dispatch::detail::Function_Signature &sig, const Callable &f, + Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature &sig, const Callable &f, const std::vector ¶ms, const Type_Conversions_State &t_conversions) { - return call_func(sig, std::index_sequence_for{}, f, params, t_conversions); + return Handle_Return::handle(call_func(sig, std::index_sequence_for{}, f, params, t_conversions)); + } + + template + Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature &sig, const Callable &f, + const std::vector ¶ms, const Type_Conversions_State &t_conversions) + { + call_func(sig, std::index_sequence_for{}, f, params, t_conversions); + return Handle_Return::handle(); } } @@ -118,34 +124,4 @@ namespace chaiscript } -namespace chaiscript -{ - namespace dispatch - { - namespace detail - { - template - struct Do_Call - { - template - static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions_State &t_conversions) - { - return Handle_Return::handle(call_func(Function_Signature(), fun, params, t_conversions)); - } - }; - - template<> - struct Do_Call - { - template - static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions_State &t_conversions) - { - call_func(Function_Signature(), fun, params, t_conversions); - return Handle_Return::handle(); - } - }; - } - } -} - #endif diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 59235f5..de8e252 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -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(t_is_const) << is_const_flag) + (static_cast(t_is_reference) << is_reference_flag) @@ -121,9 +121,7 @@ namespace chaiscript template struct Get_Type_Info { - typedef T type; - - constexpr static Type_Info get() + static constexpr Type_Info get() { return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, @@ -138,9 +136,7 @@ namespace chaiscript template struct Get_Type_Info > { - typedef T type; - - constexpr static Type_Info get() + static constexpr Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -158,9 +154,7 @@ namespace chaiscript template struct Get_Type_Info &> { - typedef T type; - - constexpr static Type_Info get() + static constexpr Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -173,9 +167,7 @@ namespace chaiscript template struct Get_Type_Info > { - typedef T type; - - constexpr static Type_Info get() + static constexpr Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -188,9 +180,7 @@ namespace chaiscript template struct Get_Type_Info &> { - typedef T type; - - constexpr static Type_Info get() + static constexpr Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -212,7 +202,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(i); /// \endcode template - constexpr Type_Info user_type(const T &/*t*/) + constexpr Type_Info user_type(const T &/*t*/) { return detail::Get_Type_Info::get(); } @@ -227,7 +217,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(); /// \endcode template - constexpr Type_Info user_type() + constexpr Type_Info user_type() { return detail::Get_Type_Info::get(); } diff --git a/include/chaiscript/language/chaiscript_algebraic.hpp b/include/chaiscript/language/chaiscript_algebraic.hpp index 52441e8..0338a02 100644 --- a/include/chaiscript/language/chaiscript_algebraic.hpp +++ b/include/chaiscript/language/chaiscript_algebraic.hpp @@ -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(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; } } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 27ac85f..0ab8a4f 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -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(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 - 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 { 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 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 t_children = std::vector()) : 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 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 &t_params) { - m_ds.get()->save_function_params(t_params); + m_ds->save_function_params(t_params); } void save_params(std::initializer_list 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 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 m_ds; + const chaiscript::detail::Dispatch_State &m_ds; }; } } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 78d86ee..95c8165 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -33,14 +33,15 @@ #if defined(_POSIX_VERSION) && !defined(__CYGWIN__) #include -#else +#endif + + #ifdef CHAISCRIPT_WINDOWS -#define VC_EXTRA_LEAN -#if !defined(WIN32_LEAN_AND_MEAN) -#define WIN32_LEAN_AND_MEAN -#endif -#include -#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 - 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 m_func; - ModulePtr m_moduleptr; - }; -#else - -#ifdef WIN32 - - - struct Loadable_Module - { - template - static std::wstring to_wstring(const T &t_str) - { - return std::wstring(t_str.begin(), t_str.end()); - } - - template - static std::string to_string(const T &t_str) - { - return std::string(t_str.begin(), t_str.end()); - } - -#if defined(_UNICODE) || defined(UNICODE) - template - static std::wstring to_proper_string(const T &t_str) - { - return to_wstring(t_str); - } -#else - template - 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(&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 - struct DLSym - { - DLSym(DLModule &t_mod, const std::string &t_symbol) - : m_symbol(reinterpret_cast(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 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_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 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::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 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(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(eval(t_input, t_handler, t_filename)); } /// \brief casts an object while applying any Dynamic_Conversion available template - typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv) const + decltype(auto) boxed_cast(const Boxed_Value &bv) const { - return m_engine.boxed_cast(bv); + return(m_engine.boxed_cast(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 T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { - try { - return m_engine.boxed_cast(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(eval_file(t_filename, t_handler)); } }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index b692538..2977043 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -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::infinity()); - } else if (t_text == "NaN") { - return const_var(std::numeric_limits::quiet_NaN()); - } else if (t_text == "_") { - return Boxed_Value(std::make_shared()); - } 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 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 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 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 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 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 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(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 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 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 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(1 + class_offset)]->text; auto node = children.back(); @@ -1337,7 +1153,7 @@ namespace chaiscript [engine, t_param_names, node](const std::vector &t_params) { return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params); }, - static_cast(numparams), node, param_types, l_annotation, guard + static_cast(numparams), node, param_types, guard ) ), function_name); @@ -1353,7 +1169,7 @@ namespace chaiscript [engine, t_param_names, node](const std::vector &t_params) { return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params); }, - static_cast(numparams), node, param_types, l_annotation, guard), type), + static_cast(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 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 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() + ")"; - } - }; } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 1ea7371..6f77a67 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -147,19 +147,19 @@ namespace chaiscript } - static const std::array &create_operators() { - static const std::array 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 &create_operators() { + static const std::array 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, detail::max_alphabet> &m_alphabet = create_alphabet(); const std::vector> &m_operator_matches = create_operator_matches(); - const std::array &m_operators = create_operators(); + const std::array &m_operators = create_operators(); std::shared_ptr m_filename; std::vector 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 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{ {p->children[0]->text, in_loop?99:1} }; - } - return std::map(); - } else { - std::map 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(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.emplace_back(make_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(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_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(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_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(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_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(std::move(match), start.line, start.col, std::move(bv))); + m_match_stack.push_back(make_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( - [&]()->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(text, start.line, start.col, const_var(true))); + } else if (text == "false") { + m_match_stack.push_back(make_node(text, start.line, start.col, const_var(false))); + } else if (text == "Infinity") { + m_match_stack.push_back(make_node(text, start.line, start.col, + const_var(std::numeric_limits::infinity()))); + } else if (text == "NaN") { + m_match_stack.push_back(make_node(text, start.line, start.col, + const_var(std::numeric_limits::quiet_NaN()))); + } else if (text == "_") { + m_match_stack.push_back(make_node(text, start.line, start.col, + Boxed_Value(std::make_shared()))); + } else { + m_match_stack.push_back(make_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 "#" - 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(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(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(match, start.line, start.col)); - build_match(prev_stack_top, "+"); - } else { - m_match_stack.push_back(make_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(match, start.line, start.col)); + m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); + if (is_interpolated) { build_match(prev_stack_top, "+"); - } else { - m_match_stack.push_back(make_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(match, start.line, start.col)); + m_match_stack.push_back(make_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(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(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(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(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(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(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(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(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("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(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(prev_stack_top), m_match_stack.end()) != 3) { + if ( std::distance(m_match_stack.begin() + static_cast(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(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(prev_stack_top); + } else { throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(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(prev_stack_top); + build_match(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(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(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(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(prev_stack_top); - break; - case(AST_Node_Type::Logical_Or) : - build_match(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(m_match_stack[size-2])->m_value; + const auto rhs = std::dynamic_pointer_cast(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(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(prev_stack_top, oper); + } + } + + break; + + case(Operator_Precidence::Logical_And) : + build_match(prev_stack_top, oper); + break; + case(Operator_Precidence::Logical_Or) : + build_match(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(prev_stack_top); + build_match(prev_stack_top, sym); + return true; + } } + return true; } - return retval; + return false; } /// Parses statements allowed inside of a class block diff --git a/include/chaiscript/language/chaiscript_posix.hpp b/include/chaiscript/language/chaiscript_posix.hpp new file mode 100644 index 0000000..c22fe87 --- /dev/null +++ b/include/chaiscript/language/chaiscript_posix.hpp @@ -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 + 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 m_func; + ModulePtr m_moduleptr; + }; + } +} +#endif + diff --git a/include/chaiscript/language/chaiscript_unknown.hpp b/include/chaiscript/language/chaiscript_unknown.hpp new file mode 100644 index 0000000..2e5c228 --- /dev/null +++ b/include/chaiscript/language/chaiscript_unknown.hpp @@ -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 + diff --git a/include/chaiscript/language/chaiscript_windows.hpp b/include/chaiscript/language/chaiscript_windows.hpp new file mode 100644 index 0000000..049e341 --- /dev/null +++ b/include/chaiscript/language/chaiscript_windows.hpp @@ -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 + +#ifdef CHAISCRIPT_WINDOWS +#define VC_EXTRA_LEAN +#if !defined(WIN32_LEAN_AND_MEAN) +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + + +namespace chaiscript +{ + namespace detail + { + struct Loadable_Module + { + template + static std::wstring to_wstring(const T &t_str) + { + return std::wstring(t_str.begin(), t_str.end()); + } + + template + static std::string to_string(const T &t_str) + { + return std::string(t_str.begin(), t_str.end()); + } + +#if defined(_UNICODE) || defined(UNICODE) + template + static std::wstring to_proper_string(const T &t_str) + { + return to_wstring(t_str); + } +#else + template + 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(&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 + struct DLSym + { + DLSym(DLModule &t_mod, const std::string &t_symbol) + : m_symbol(reinterpret_cast(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 m_func; + ModulePtr m_moduleptr; + }; + } +} +#endif + diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 1ca0dfb..fa2bbdb 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -12,9 +12,8 @@ #include #include -#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" diff --git a/unittests/3.x/dispatch_functions.chai b/unittests/3.x/dispatch_functions.chai index 528d5b3..f25ae01 100644 --- a/unittests/3.x/dispatch_functions.chai +++ b/unittests/3.x/dispatch_functions.chai @@ -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); diff --git a/unittests/3.x/function_introspection.chai b/unittests/3.x/function_introspection.chai index 5ad76fc..96b2ec6 100644 --- a/unittests/3.x/function_introspection.chai +++ b/unittests/3.x/function_introspection.chai @@ -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); diff --git a/unittests/3.x/reflection_test.chai b/unittests/3.x/reflection_test.chai deleted file mode 100644 index 25a2416..0000000 --- a/unittests/3.x/reflection_test.chai +++ /dev/null @@ -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()); diff --git a/unittests/dispatch_functions.chai b/unittests/dispatch_functions.chai index 1887844..6780516 100644 --- a/unittests/dispatch_functions.chai +++ b/unittests/dispatch_functions.chai @@ -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); diff --git a/unittests/function_introspection.chai b/unittests/function_introspection.chai index 6d808df..fbfee5a 100644 --- a/unittests/function_introspection.chai +++ b/unittests/function_introspection.chai @@ -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); diff --git a/unittests/global_lcase.chai b/unittests/global_lcase.chai index 7f8959a..21fdecd 100644 --- a/unittests/global_lcase.chai +++ b/unittests/global_lcase.chai @@ -16,3 +16,8 @@ def f() { f(); + +global &h = v; +assert_true(h == v) +v = 3; +assert_true(h == 3) diff --git a/unittests/reflection_test.chai b/unittests/reflection_test.chai index 16ef7e9..c7bc89d 100644 --- a/unittests/reflection_test.chai +++ b/unittests/reflection_test.chai @@ -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() {