From 1e584048ceb777fabf9aa7207dee939e36bcdf51 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 9 Apr 2016 21:00:07 -0600 Subject: [PATCH 001/108] Remove std::function from bind_first --- include/chaiscript/dispatchkit/bind_first.hpp | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index fcba5348..98da1deb 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()); + } } } From 2400c64c82cfbaaed4f14f202fa8f78963ff605d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 9 Apr 2016 21:15:07 -0600 Subject: [PATCH 002/108] Move to strongly typed enums for node types --- .../language/chaiscript_algebraic.hpp | 2 +- .../chaiscript/language/chaiscript_common.hpp | 25 ++++++++----------- .../chaiscript/language/chaiscript_parser.hpp | 6 ++--- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/include/chaiscript/language/chaiscript_algebraic.hpp b/include/chaiscript/language/chaiscript_algebraic.hpp index 52441e8f..b196db41 100644 --- a/include/chaiscript/language/chaiscript_algebraic.hpp +++ b/include/chaiscript/language/chaiscript_algebraic.hpp @@ -31,7 +31,7 @@ namespace chaiscript }; static const char *to_string(Opers t_oper) { - const char *opers[] = { + static const char *opers[] = { "", "==", "<", ">", "<=", ">=", "!=", "", diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 27ac85f3..f20ed09c 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,28 +32,25 @@ 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 { 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 }; 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", + const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { + static const char * const 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", "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"}; - return ast_node_types[ast_node_type]; + return ast_node_types[static_cast(ast_node_type)]; } } @@ -166,7 +163,7 @@ namespace chaiscript private: template - static int id(const T& t) + static AST_Node_Type id(const T& t) { return t->identifier; } @@ -434,7 +431,7 @@ 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; @@ -507,7 +504,7 @@ namespace chaiscript 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)), diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 715d90cf..2c61d832 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -146,8 +146,8 @@ namespace chaiscript } - static const std::array &create_operators() { - static const std::array operators = { { + 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, @@ -169,7 +169,7 @@ namespace chaiscript 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; From 641ac1a1aecb9f02d9df8717ce68b9ccf8f42b6d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 9 Apr 2016 21:49:12 -0600 Subject: [PATCH 003/108] Split up ifdef'd module code --- .../chaiscript/language/chaiscript_engine.hpp | 213 +----------------- .../chaiscript/language/chaiscript_posix.hpp | 79 +++++++ .../language/chaiscript_unknown.hpp | 27 +++ .../language/chaiscript_windows.hpp | 128 +++++++++++ 4 files changed, 242 insertions(+), 205 deletions(-) create mode 100644 include/chaiscript/language/chaiscript_posix.hpp create mode 100644 include/chaiscript/language/chaiscript_unknown.hpp create mode 100644 include/chaiscript/language/chaiscript_windows.hpp diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 78d86ee7..4aaf0f48 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) diff --git a/include/chaiscript/language/chaiscript_posix.hpp b/include/chaiscript/language/chaiscript_posix.hpp new file mode 100644 index 00000000..08cb53d2 --- /dev/null +++ b/include/chaiscript/language/chaiscript_posix.hpp @@ -0,0 +1,79 @@ +// 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(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; + }; + } +} +#endif + diff --git a/include/chaiscript/language/chaiscript_unknown.hpp b/include/chaiscript/language/chaiscript_unknown.hpp new file mode 100644 index 00000000..2e5c2283 --- /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 00000000..f36db1ec --- /dev/null +++ b/include/chaiscript/language/chaiscript_windows.hpp @@ -0,0 +1,128 @@ +// 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() + { + 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 + From 08a68f310a76138f17e6cb734a38a67ad23ba9d2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 9 Apr 2016 21:50:23 -0600 Subject: [PATCH 004/108] Move to strongly typed algebraic enum --- .../chaiscript/dispatchkit/boxed_number.hpp | 218 +++++++++--------- .../language/chaiscript_algebraic.hpp | 68 +++--- .../chaiscript/language/chaiscript_common.hpp | 12 + .../chaiscript/language/chaiscript_eval.hpp | 8 +- 4 files changed, 159 insertions(+), 147 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 7eefe991..6bbf0881 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(); @@ -647,67 +647,67 @@ namespace chaiscript bool operator==(const Boxed_Number &t_rhs) const { - return boxed_cast(oper(Operators::equals, this->bv, t_rhs.bv)); + return boxed_cast(oper(Operators::Opers::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)); + return boxed_cast(oper(Operators::Opers::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)); + return boxed_cast(oper(Operators::Opers::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)); + return boxed_cast(oper(Operators::Opers::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)); + return boxed_cast(oper(Operators::Opers::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)); + return boxed_cast(oper(Operators::Opers::not_equal, this->bv, t_rhs.bv)); } Boxed_Number operator--() { - return oper(Operators::pre_decrement, this->bv); + return oper(Operators::Opers::pre_decrement, this->bv); } Boxed_Number operator++() { - return oper(Operators::pre_increment, this->bv); + return oper(Operators::Opers::pre_increment, this->bv); } Boxed_Number operator+(const Boxed_Number &t_rhs) const { - return oper(Operators::sum, this->bv, t_rhs.bv); + return oper(Operators::Opers::sum, this->bv, t_rhs.bv); } Boxed_Number operator+() const { - return oper(Operators::unary_plus, this->bv); + return oper(Operators::Opers::unary_plus, this->bv); } Boxed_Number operator-() const { - return oper(Operators::unary_minus, this->bv); + return oper(Operators::Opers::unary_minus, this->bv); } Boxed_Number operator-(const Boxed_Number &t_rhs) const { - return oper(Operators::difference, this->bv, t_rhs.bv); + return oper(Operators::Opers::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); + return oper(Operators::Opers::assign_bitwise_and, this->bv, t_rhs.bv); } static void validate_boxed_number(const Boxed_Value &v) @@ -735,255 +735,255 @@ namespace chaiscript // cppcheck-suppress operatorEq Boxed_Number operator=(const Boxed_Number &t_rhs) const { - return oper(Operators::assign, this->bv, t_rhs.bv); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::bitwise_and, this->bv, t_rhs.bv); } Boxed_Number operator~() const { - return oper(Operators::bitwise_complement, this->bv); + return oper(Operators::Opers::bitwise_complement, this->bv); } Boxed_Number operator^(const Boxed_Number &t_rhs) const { - return oper(Operators::bitwise_xor, this->bv, t_rhs.bv); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); + return oper(Operators::Opers::product, this->bv, t_rhs.bv); } Boxed_Number operator%(const Boxed_Number &t_rhs) const { - return oper(Operators::remainder, this->bv, t_rhs.bv); + return oper(Operators::Opers::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); + return oper(Operators::Opers::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); } diff --git a/include/chaiscript/language/chaiscript_algebraic.hpp b/include/chaiscript/language/chaiscript_algebraic.hpp index b196db41..0338a029 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, @@ -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 f20ed09c..22f75482 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -98,6 +98,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 {} + }; + /// Errors generated during parsing or evaluation struct eval_error : std::runtime_error { diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index b692538c..a4ac5fec 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -103,7 +103,7 @@ namespace chaiscript 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{ @@ -384,7 +384,7 @@ namespace chaiscript Boxed_Value rhs = this->children[2]->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 +392,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."); } @@ -1076,7 +1076,7 @@ namespace chaiscript 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 { From 4bf619c80fc370b181c207cb5ce3a034b4249822 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 9 Apr 2016 22:10:06 -0600 Subject: [PATCH 005/108] some initialization and destructor cleanups --- .../chaiscript/dispatchkit/dispatchkit.hpp | 18 +++------------- .../chaiscript/language/chaiscript_common.hpp | 11 +++++++++- .../chaiscript/language/chaiscript_engine.hpp | 21 ------------------- .../chaiscript/language/chaiscript_posix.hpp | 6 ++++-- .../language/chaiscript_windows.hpp | 5 +++++ 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 352b086f..54bef227 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -418,11 +418,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() @@ -430,10 +428,6 @@ 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 @@ -892,12 +886,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 { diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 22f75482..a36bc1a3 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -513,7 +513,10 @@ namespace chaiscript std::replace(children.begin(), children.end(), t_child, t_new_child); } - virtual ~AST_Node() {} + virtual ~AST_Node() = default; + AST_Node(AST_Node &&) = default; + AST_Node &operator=(AST_Node &&) = default; + protected: AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc, @@ -563,6 +566,8 @@ 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; @@ -585,6 +590,8 @@ namespace chaiscript /// 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; @@ -617,6 +624,8 @@ namespace chaiscript /// 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; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 4aaf0f48..bc00f7af 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -128,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); diff --git a/include/chaiscript/language/chaiscript_posix.hpp b/include/chaiscript/language/chaiscript_posix.hpp index 08cb53d2..c22fe87c 100644 --- a/include/chaiscript/language/chaiscript_posix.hpp +++ b/include/chaiscript/language/chaiscript_posix.hpp @@ -24,8 +24,10 @@ namespace chaiscript } } - DLModule(const DLModule &); // Explicitly unimplemented copy constructor - DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator + DLModule(DLModule &&) = default; + DLModule &operator=(DLModule &&) = default; + DLModule(const DLModule &) = delete; + DLModule &operator=(const DLModule &) = delete; ~DLModule() { diff --git a/include/chaiscript/language/chaiscript_windows.hpp b/include/chaiscript/language/chaiscript_windows.hpp index f36db1ec..049e3416 100644 --- a/include/chaiscript/language/chaiscript_windows.hpp +++ b/include/chaiscript/language/chaiscript_windows.hpp @@ -89,6 +89,11 @@ namespace chaiscript } } + DLModule(DLModule &&) = default; + DLModule &operator=(DLModule &&) = default; + DLModule(const DLModule &) = delete; + DLModule &operator=(const DLModule &) = delete; + ~DLModule() { FreeLibrary(m_data); From 61dfcb00c0f3f8b3ec5ad4fec3137dcd1506e45e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 17:19:48 -0600 Subject: [PATCH 006/108] Move int/float into Constant --- .../chaiscript/language/chaiscript_common.hpp | 8 +- .../chaiscript/language/chaiscript_eval.hpp | 76 ++++--------------- .../chaiscript/language/chaiscript_parser.hpp | 49 ++++++++---- 3 files changed, 54 insertions(+), 79 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index a36bc1a3..09e16d22 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,11 +32,11 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, + enum class AST_Node_Type { Error, 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 + Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant }; namespace @@ -44,11 +44,11 @@ namespace chaiscript /// Helper lookup to get the name of each node type const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { - static const char * const ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", + static const char * const ast_node_types[] = { "Internal Parser Error", "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 Condition", "Noop", "Class", "Binary", "Arg"}; + "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Constant"}; return ast_node_types[static_cast(ast_node_type)]; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index a4ac5fec..61413a78 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -129,72 +129,38 @@ 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; }; @@ -209,16 +175,6 @@ namespace chaiscript 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 { Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 2c61d832..ee745b73 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -741,20 +741,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 { @@ -762,11 +762,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; } @@ -824,16 +824,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; From 62cd8031ac8b1bd20ffdc113f5cdd44182e974fd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 18:29:16 -0600 Subject: [PATCH 007/108] Make quoted strings into Constants --- .../chaiscript/language/chaiscript_common.hpp | 4 +-- .../chaiscript/language/chaiscript_eval.hpp | 35 ------------------- .../chaiscript/language/chaiscript_parser.hpp | 10 +++--- 3 files changed, 7 insertions(+), 42 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 09e16d22..38cf8e65 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -33,7 +33,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval enum class AST_Node_Type { Error, 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, + Comparison, Addition, Subtraction, Multiplication, Division, Modulus, 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_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant @@ -45,7 +45,7 @@ namespace chaiscript /// Helper lookup to get the name of each node type const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { static const char * const ast_node_types[] = { "Internal Parser Error", "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", + "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "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", "Constant"}; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 61413a78..bb4fa3c8 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -562,41 +562,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) : diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index ee745b73..2df9d3f9 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1106,11 +1106,11 @@ namespace chaiscript 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)); + m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); build_match(prev_stack_top, "+"); } else { - 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))); } //We've finished with the part of the string up to this point, so clear it @@ -1162,11 +1162,11 @@ namespace chaiscript }(); 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))); build_match(prev_stack_top, "+"); } else { - 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))); } return true; } else { @@ -1227,7 +1227,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 { From e02ac7819570897c3d468d8a736e39762617dd10 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 18:57:23 -0600 Subject: [PATCH 008/108] Remove Char_AST_Node --- .../chaiscript/language/chaiscript_common.hpp | 4 ++-- .../chaiscript/language/chaiscript_eval.hpp | 12 ++++-------- .../chaiscript/language/chaiscript_parser.hpp | 19 ++++--------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 38cf8e65..7d0a6df8 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,7 +32,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Error, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, + enum class AST_Node_Type { Error, Id, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, 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, @@ -44,7 +44,7 @@ namespace chaiscript /// Helper lookup to get the name of each node type const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { - static const char * const ast_node_types[] = { "Internal Parser Error", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", + static const char * const ast_node_types[] = { "Internal Parser Error", "Id", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "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", diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index bb4fa3c8..63e4e859 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -165,10 +165,6 @@ namespace chaiscript 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) : @@ -989,11 +985,11 @@ 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 @@ -1003,10 +999,10 @@ namespace chaiscript } 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); } } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 2df9d3f9..aa922b27 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1247,20 +1247,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 @@ -2200,13 +2189,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; } } From 5e97f459d8599e134b2c49ce949251bc475ce19a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 19:01:55 -0600 Subject: [PATCH 009/108] Remove unnecessary false --- include/chaiscript/language/chaiscript_parser.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index aa922b27..1141351e 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1615,7 +1615,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(')'))) { @@ -1638,7 +1638,7 @@ namespace chaiscript } } while (Eol()) {} - if (Keyword("finally", false)) { + if (Keyword("finally")) { const auto finally_stack_top = m_match_stack.size(); while (Eol()) {} From 866db4ee8b95463055153253adccb0a2d65c27a0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 21:38:44 -0600 Subject: [PATCH 010/108] Reduce instances of Str_AST_Node --- .../chaiscript/language/chaiscript_eval.hpp | 16 +++---- .../chaiscript/language/chaiscript_parser.hpp | 46 +++++++++---------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 63e4e859..7debbecb 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -327,13 +327,13 @@ 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::Opers::invalid && lhs.get_type_info().is_arithmetic() && @@ -371,17 +371,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(); @@ -391,9 +391,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); } } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 1141351e..9b4370f9 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1272,7 +1272,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); @@ -1282,9 +1282,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; } @@ -1553,7 +1550,7 @@ namespace chaiscript bool is_method = false; - if (Symbol("::", false)) { + if (Symbol("::")) { //We're now a method is_method = true; @@ -1682,12 +1679,11 @@ namespace chaiscript while (has_matches) { while (Eol()) {} has_matches = false; - if (Keyword("else", true)) { + const auto line = m_position.line; + const auto col = m_position.col; + if (Keyword("else")) { 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; + m_match_stack.emplace_back(make_node("else if", line, col, std::vector())); if (!Char('(')) { throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1703,6 +1699,7 @@ namespace chaiscript } has_matches = true; } else { + m_match_stack.emplace_back(make_node("else", line, col, std::vector())); while (Eol()) {} if (!Block()) { @@ -2105,7 +2102,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()) { @@ -2169,7 +2166,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); } @@ -2345,26 +2342,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, false, 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 From 443828fa2375d2e7f0168f5958d1db394ea533d0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 22:27:35 -0600 Subject: [PATCH 011/108] More parser simplification --- .../chaiscript/language/chaiscript_eval.hpp | 12 +-- .../chaiscript/language/chaiscript_parser.hpp | 96 +++++++++---------- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 7debbecb..e1a2e19c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -505,8 +505,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); @@ -516,9 +516,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)); } } @@ -540,9 +540,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); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 9b4370f9..879ab60a 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2036,7 +2036,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)); } } @@ -2049,13 +2049,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); @@ -2221,61 +2221,59 @@ 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); - } + while (Operator_Helper(t_precedence)) { + 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); + } - AST_NodePtr oper = m_match_stack.at(m_match_stack.size()-2); + 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 { + 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); } - break; + build_match(prev_stack_top); + } + else { + 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); + } + 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(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(AST_Node_Type::Logical_And) : - build_match(prev_stack_top); - break; - case(AST_Node_Type::Logical_Or) : - build_match(prev_stack_top); - break; + case(AST_Node_Type::Logical_And) : + build_match(prev_stack_top); + break; + case(AST_Node_Type::Logical_Or) : + build_match(prev_stack_top); + break; - 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)); + default: + throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_position.line, m_position.col), *m_filename); + } } } } From 40694c798c4f4a488aa14568b5da0ed9173ea3f4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 10 Apr 2016 23:12:35 -0600 Subject: [PATCH 012/108] Eliminate Str_AST_Node --- .../chaiscript/language/chaiscript_common.hpp | 4 +-- .../chaiscript/language/chaiscript_eval.hpp | 13 +++------ .../chaiscript/language/chaiscript_parser.hpp | 29 +++++++------------ 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 7d0a6df8..cb1266dd 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,7 +32,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Error, Id, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, + enum class AST_Node_Type { Error, Id, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, 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, @@ -44,7 +44,7 @@ namespace chaiscript /// Helper lookup to get the name of each node type const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { - static const char * const ast_node_types[] = { "Internal Parser Error", "Id", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", + static const char * const ast_node_types[] = { "Internal Parser Error", "Id", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "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", diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index e1a2e19c..ba36c7a7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -166,11 +166,6 @@ namespace chaiscript }; - 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 Fun_Call_AST_Node final : AST_Node { Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : @@ -1323,12 +1318,12 @@ 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 @@ -1340,12 +1335,12 @@ namespace chaiscript 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 diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 879ab60a..4980014a 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1315,7 +1315,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); @@ -1330,10 +1330,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; } @@ -2205,9 +2201,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; } } @@ -2221,7 +2218,8 @@ namespace chaiscript if (t_precedence < m_operators.size()) { if (Operator(t_precedence+1)) { retval = true; - while (Operator_Helper(t_precedence)) { + std::string oper; + while (Operator_Helper(t_precedence, oper)) { while (Eol()) {} if (!Operator(t_precedence+1)) { throw exception::eval_error("Incomplete " @@ -2229,12 +2227,8 @@ namespace chaiscript 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 " @@ -2258,17 +2252,14 @@ namespace chaiscript 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); + build_match(prev_stack_top, oper); break; case(AST_Node_Type::Logical_And) : - build_match(prev_stack_top); + build_match(prev_stack_top, oper); break; case(AST_Node_Type::Logical_Or) : - build_match(prev_stack_top); + build_match(prev_stack_top, oper); break; default: @@ -2345,7 +2336,7 @@ namespace chaiscript if (Operator()) { for (const auto sym : {"=", ":=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|="}) { - if (Symbol(sym, false, true)) { + if (Symbol(sym, true)) { SkipWS(true); if (!Equation()) { throw exception::eval_error("Incomplete equation", File_Position(m_position.line, m_position.col), *m_filename); From fe8f8a89a7abc61c0e106888e3fcc70bb22e6899 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 11 Apr 2016 08:19:02 -0600 Subject: [PATCH 013/108] Implement constant expression folding --- .../chaiscript/language/chaiscript_eval.hpp | 1 + .../chaiscript/language/chaiscript_parser.hpp | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index ba36c7a7..6ef776bf 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -737,6 +737,7 @@ namespace chaiscript } else { if (children.size() > 2) { size_t i = 2; + /// \todo these string comparisons are clunky while (i < children.size()) { if (children[i]->text == "else") { return children[i+1]->eval(t_ss); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 4980014a..d1d80841 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2252,7 +2252,37 @@ namespace chaiscript case(AST_Node_Type::Bitwise_Xor) : case(AST_Node_Type::Bitwise_Or) : case(AST_Node_Type::Comparison) : - build_match(prev_stack_top, oper); + { + bool folded = false; + const auto size = m_match_stack.size(); + + 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 + } + + if (!folded) { + build_match(prev_stack_top, oper); + } + } + break; case(AST_Node_Type::Logical_And) : From b594043eef0e9dd06db3d8c08007c4f6ef1c1321 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 11 Apr 2016 09:36:23 -0600 Subject: [PATCH 014/108] Clean up redundant code --- include/chaiscript/dispatchkit/bootstrap.hpp | 5 +-- .../chaiscript/language/chaiscript_common.hpp | 5 --- .../chaiscript/language/chaiscript_engine.hpp | 42 +++---------------- 3 files changed, 8 insertions(+), 44 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 1f519dc8..6776e9f6 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -629,14 +629,13 @@ 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"} } ); diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index cb1266dd..14b90344 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -508,11 +508,6 @@ 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; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index bc00f7af..84f25bcc 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -619,16 +619,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); @@ -668,14 +666,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. @@ -694,14 +685,7 @@ 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 @@ -740,14 +724,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. @@ -760,14 +737,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)); } }; From 8d808f75c0a113ca9ec12cac883435e8f6e28b38 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 13 Apr 2016 12:04:55 -0600 Subject: [PATCH 015/108] Remove pretty_print functionality --- .../chaiscript/language/chaiscript_common.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 85 ------------------- 2 files changed, 2 insertions(+), 87 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 14b90344..ca29b166 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -461,7 +461,7 @@ namespace chaiscript return location.end; } - virtual std::string pretty_print() const + std::string pretty_print() const { std::ostringstream oss; @@ -528,7 +528,7 @@ namespace chaiscript } private: - // Copy and assignment explicitly unimplemented + // Copy and assignment explicitly deleted AST_Node(const AST_Node &) = delete; AST_Node& operator=(const AST_Node &) = delete; }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 6ef776bf..0b9311d7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -93,11 +93,6 @@ 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 @@ -212,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(); - } }; @@ -240,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()) @@ -451,10 +399,6 @@ namespace chaiscript } - std::string pretty_print() const override - { - return "var " + this->children[0]->text; - } }; @@ -477,20 +421,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; @@ -886,11 +816,6 @@ namespace chaiscript } } - std::string pretty_print() const override - { - return "[" + AST_Node::pretty_print() + "]"; - } - private: mutable std::atomic_uint_fast32_t m_loc; }; @@ -1327,10 +1252,6 @@ namespace chaiscript && 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 { @@ -1343,12 +1264,6 @@ namespace chaiscript return const_var(get_bool_condition(children[0]->eval(t_ss)) || get_bool_condition(children[1]->eval(t_ss))); } - - std::string pretty_print() const override - { - return "(" + AST_Node::pretty_print() + ")"; - } - }; } From 6f0d02f158bc4a141e3fed452b69c2f7ccf868da Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 13 Apr 2016 14:09:08 -0600 Subject: [PATCH 016/108] Massive simplification of boxed_cast. More planned --- include/chaiscript/dispatchkit/boxed_cast.hpp | 2 +- .../dispatchkit/boxed_cast_helper.hpp | 103 +++++++----------- .../chaiscript/dispatchkit/boxed_number.hpp | 4 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 2 +- .../chaiscript/dispatchkit/function_call.hpp | 12 +- .../chaiscript/language/chaiscript_engine.hpp | 2 +- 6 files changed, 46 insertions(+), 79 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 5a11ee9d..395cf836 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -69,7 +69,7 @@ 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) + auto boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr) -> decltype(detail::Cast_Helper::cast(bv, nullptr)) { if (!t_conversions || bv.get_type_info().bare_equal(user_type()) || (t_conversions && !(*t_conversions)->convertable_type())) { try { diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index da1e222e..36c15f76 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -29,21 +29,36 @@ namespace chaiscript throw std::runtime_error("Attempted to dereference null Boxed_Value"); } + const void *verify_type(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { + if (!ob.get_type_info().bare_equal_type_info(ti)) { + throw chaiscript::detail::exception::bad_any_cast(); + } else { + return throw_if_null(ptr); + } + } + + void *verify_type(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { + if (ptr == nullptr || !ob.get_type_info().bare_equal_type_info(ti)) { + throw chaiscript::detail::exception::bad_any_cast(); + } else { + return ptr; + } + } + + /* + template> + Result cast_helper_inner(const Boxed_Value &ob, const Type_Conversions_State *) + { + } +*/ + /// 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 +72,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 auto 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(ob, typeid(Result), ob.get_const_ptr())); } }; @@ -73,15 +82,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 auto 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(ob, typeid(Result), ob.get_ptr())); } }; @@ -100,17 +103,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 +115,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 +125,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 +135,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 +161,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 +185,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 +195,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,9 +249,7 @@ 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 auto cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) -> decltype(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 6bbf0881..ad2775be 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -1009,9 +1009,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/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index f10d3401..1c5809cb 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -424,7 +424,7 @@ namespace chaiscript /// \brief casts an object while applying any Dynamic_Conversion available template - typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv) const + auto boxed_cast(const Boxed_Value &bv) const -> decltype(chaiscript::boxed_cast(bv, nullptr)) { Type_Conversions_State state(m_conversions, m_conversions.conversion_saves()); return chaiscript::boxed_cast(bv, &state); diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 990be95a..3efb7031 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/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 84f25bcc..761bd61e 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -690,7 +690,7 @@ namespace chaiscript /// \brief casts an object while applying any Dynamic_Conversion available template - typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv) const + auto boxed_cast(const Boxed_Value &bv) const -> decltype(m_engine.boxed_cast(bv)) { return m_engine.boxed_cast(bv); } From 9603d3910a5a8427abb9e67f5f0c6d8f79a18d5e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 13 Apr 2016 15:26:36 -0600 Subject: [PATCH 017/108] Get multifile compiling --- include/chaiscript/dispatchkit/boxed_cast_helper.hpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 36c15f76..5178a735 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -29,7 +29,7 @@ namespace chaiscript throw std::runtime_error("Attempted to dereference null Boxed_Value"); } - const void *verify_type(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { + static const void *verify_type(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { if (!ob.get_type_info().bare_equal_type_info(ti)) { throw chaiscript::detail::exception::bad_any_cast(); } else { @@ -37,7 +37,7 @@ namespace chaiscript } } - void *verify_type(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { + static void *verify_type(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { if (ptr == nullptr || !ob.get_type_info().bare_equal_type_info(ti)) { throw chaiscript::detail::exception::bad_any_cast(); } else { @@ -45,13 +45,6 @@ namespace chaiscript } } - /* - template> - Result cast_helper_inner(const Boxed_Value &ob, const Type_Conversions_State *) - { - } -*/ - /// Generic Cast_Helper_Inner, for casting to any type template struct Cast_Helper_Inner From 5e0a882b182d7a2c5a848036a5abe6d6bd0f8645 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 13 Apr 2016 21:08:25 -0600 Subject: [PATCH 018/108] Bootstrap simplifications --- include/chaiscript/dispatchkit/bootstrap.hpp | 48 ++++---------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 4c0b5a4a..17352bc2 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -138,15 +138,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 +279,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 +318,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 +353,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); @@ -414,6 +383,7 @@ namespace chaiscript 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 +395,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,13 +489,12 @@ 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); @@ -593,13 +561,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"} } ); From 720395e47a280ec54130b470ef81482ba5eb4c7f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 14 Apr 2016 09:31:38 -0600 Subject: [PATCH 019/108] clean up reflection tests for new capabilities --- unittests/3.x/reflection_test.chai | 36 ------------------------------ unittests/reflection_test.chai | 15 ++----------- 2 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 unittests/3.x/reflection_test.chai diff --git a/unittests/3.x/reflection_test.chai b/unittests/3.x/reflection_test.chai deleted file mode 100644 index 25a24168..00000000 --- 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/reflection_test.chai b/unittests/reflection_test.chai index 16ef7e9f..80e8f269 100644 --- a/unittests/reflection_test.chai +++ b/unittests/reflection_test.chai @@ -4,19 +4,8 @@ auto& a = parser.ast() 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() { From 49dfdfd15afb30365dac96701750ad31744971fd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 14 Apr 2016 12:03:55 -0600 Subject: [PATCH 020/108] Fix some boxed_cast and exception issues --- include/chaiscript/dispatchkit/bootstrap.hpp | 2 ++ include/chaiscript/dispatchkit/boxed_cast.hpp | 8 ++++---- .../chaiscript/dispatchkit/boxed_cast_helper.hpp | 16 ++++++++-------- include/chaiscript/dispatchkit/dispatchkit.hpp | 4 ++-- .../chaiscript/language/chaiscript_engine.hpp | 4 ++-- include/chaiscript/utility/utility.hpp | 2 +- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 17352bc2..74614f88 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -548,9 +548,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); diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 395cf836..7fbe78d3 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 - auto boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr) -> decltype(detail::Cast_Helper::cast(bv, 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 5178a735..9476e0a1 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -30,18 +30,18 @@ namespace chaiscript } static const void *verify_type(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { - if (!ob.get_type_info().bare_equal_type_info(ti)) { - throw chaiscript::detail::exception::bad_any_cast(); - } else { + if (ob.get_type_info().bare_equal_type_info(ti)) { return throw_if_null(ptr); + } else { + throw chaiscript::detail::exception::bad_any_cast(); } } static void *verify_type(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { - if (ptr == nullptr || !ob.get_type_info().bare_equal_type_info(ti)) { - throw chaiscript::detail::exception::bad_any_cast(); + if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) { + return throw_if_null(ptr); } else { - return ptr; + throw chaiscript::detail::exception::bad_any_cast(); } } @@ -242,9 +242,9 @@ namespace chaiscript template struct Cast_Helper { - static auto cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) -> decltype(Cast_Helper_Inner::cast(ob, 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/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 1c5809cb..b5ed3f75 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -424,10 +424,10 @@ namespace chaiscript /// \brief casts an object while applying any Dynamic_Conversion available template - auto boxed_cast(const Boxed_Value &bv) const -> decltype(chaiscript::boxed_cast(bv, nullptr)) + 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 diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 761bd61e..fca14ded 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -690,9 +690,9 @@ namespace chaiscript /// \brief casts an object while applying any Dynamic_Conversion available template - auto boxed_cast(const Boxed_Value &bv) const -> decltype(m_engine.boxed_cast(bv)) + decltype(auto) boxed_cast(const Boxed_Value &bv) const { - return m_engine.boxed_cast(bv); + return(m_engine.boxed_cast(bv)); } diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 1ca0dfbb..87dd8764 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -15,7 +15,7 @@ #include "../chaiscript.hpp" #include "../dispatchkit/proxy_functions.hpp" #include "../dispatchkit/type_info.hpp" -#include "../dispatchkit/operators.hpp" +//#include "../dispatchkit/operators.hpp" namespace chaiscript From 7d9dbc3d86582c36cb9e5a40212c33f2fe70b013 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 14 Apr 2016 19:06:37 -0600 Subject: [PATCH 021/108] Fix some boxed_cast issues introduced with refactor --- .../dispatchkit/boxed_cast_helper.hpp | 25 ++++++++++++++++--- include/chaiscript/utility/utility.hpp | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 9476e0a1..104abc75 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -29,6 +29,23 @@ namespace chaiscript throw std::runtime_error("Attempted to dereference null Boxed_Value"); } + static const void *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { + if (ob.get_type_info() == ti) { + return ptr; + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + static void *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { + if (!ob.is_const() && ob.get_type_info() == ti) { + return ptr; + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + static const void *verify_type(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { if (ob.get_type_info().bare_equal_type_info(ti)) { return throw_if_null(ptr); @@ -65,9 +82,9 @@ namespace chaiscript template struct Cast_Helper_Inner { - static auto cast(const Boxed_Value &ob, const Type_Conversions_State *) + static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *) { - return static_cast(verify_type(ob, typeid(Result), ob.get_const_ptr())); + return static_cast(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr())); } }; @@ -75,9 +92,9 @@ namespace chaiscript template struct Cast_Helper_Inner { - static auto cast(const Boxed_Value &ob, const Type_Conversions_State *) + static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *) { - return static_cast(verify_type(ob, typeid(Result), ob.get_ptr())); + return static_cast(verify_type_no_throw(ob, typeid(Result), ob.get_ptr())); } }; diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 87dd8764..1ca0dfbb 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -15,7 +15,7 @@ #include "../chaiscript.hpp" #include "../dispatchkit/proxy_functions.hpp" #include "../dispatchkit/type_info.hpp" -//#include "../dispatchkit/operators.hpp" +#include "../dispatchkit/operators.hpp" namespace chaiscript From fd57bec676b6ad0df83ec6b6f8ffb8b781a98a9f Mon Sep 17 00:00:00 2001 From: Hristo Petrov Date: Fri, 15 Apr 2016 16:11:36 +0100 Subject: [PATCH 022/108] Update cheatsheet.md Added missing parameters to the examples of "Adding Method / Member" --- cheatsheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheatsheet.md b/cheatsheet.md index c37045f7..916a5ca0 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -23,8 +23,8 @@ chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdl ``` chai.add(chaiscript::fun(&function_name), "function_name"); -chai.add(chaiscript::fun(&Class::method_name), "method_name"); -chai.add(chaiscript::fun(&Class::member_name), "member_name"); +chai.add(chaiscript::fun(&Class::method_name, Class_instance_ptr), "method_name"); +chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name"); ``` ### With Overloads From 6fa83bca857e277c1ad5fdd98162619135eb88a1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 15 Apr 2016 15:31:19 -0600 Subject: [PATCH 023/108] Remove Do_Call helper class --- .../chaiscript/dispatchkit/boxed_value.hpp | 77 +++++++++---------- .../dispatchkit/proxy_functions.hpp | 5 +- .../dispatchkit/proxy_functions_detail.hpp | 52 ++++--------- 3 files changed, 54 insertions(+), 80 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 538391f6..d394d697 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -226,48 +226,47 @@ 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) { + 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; + }; + + return Sentinel(ptr, *(m_data.get())); } bool is_null() const noexcept diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index e7a8ad90..7a2fa289 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -595,8 +595,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: @@ -648,7 +647,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); } diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 69b88a82..54a1c6e0 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 From 1a4261444161bfc3d5c4bf89e741d8e7152581a9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 15 Apr 2016 23:02:42 -0600 Subject: [PATCH 024/108] Remove unnecessary code --- .../dispatchkit/boxed_cast_helper.hpp | 12 +- .../chaiscript/dispatchkit/boxed_value.hpp | 12 +- .../chaiscript/dispatchkit/handle_return.hpp | 13 +- include/chaiscript/dispatchkit/operators.hpp | 278 +++--------------- .../dispatchkit/proxy_functions.hpp | 4 +- 5 files changed, 53 insertions(+), 266 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 104abc75..6347437e 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -29,7 +29,8 @@ namespace chaiscript throw std::runtime_error("Attempted to dereference null Boxed_Value"); } - static const void *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { + 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 { @@ -37,7 +38,8 @@ namespace chaiscript } } - static void *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { + 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 { @@ -46,7 +48,8 @@ namespace chaiscript } - static const void *verify_type(const Boxed_Value &ob, const std::type_info &ti, const void *ptr) { + 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 { @@ -54,7 +57,8 @@ namespace chaiscript } } - static void *verify_type(const Boxed_Value &ob, const std::type_info &ti, void *ptr) { + 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 { diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index d394d697..1e0ec99c 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -243,16 +243,8 @@ namespace chaiscript 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)) - { - } + Sentinel& operator=(Sentinel&&s) = default; + Sentinel(Sentinel &&s) = default; operator std::shared_ptr&() const { diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index ca353ecf..8ac2d9e4 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 8dc54ba0..4ebaec55 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 7a2fa289..8723d823 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -727,13 +727,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); } From 56b4f465a140660b8c59926a292fa2464c9cb367 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 15 Apr 2016 23:09:20 -0600 Subject: [PATCH 025/108] Add warning on platforms without thread_local --- include/chaiscript/chaiscript_threading.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 22506936..0d2825f7 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. /// From 498339c202d4e57d42a76e10b92aedd39ea551a7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 07:35:30 -0600 Subject: [PATCH 026/108] Remove some dead parser code --- .../chaiscript/language/chaiscript_parser.hpp | 69 ++----------------- 1 file changed, 5 insertions(+), 64 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index d1d80841..5a6c1c60 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -177,8 +177,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) @@ -265,13 +264,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; @@ -297,59 +296,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) { @@ -371,19 +323,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; } From 32bd936a18be10167c343b060e88cf172edd11ed Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 07:52:39 -0600 Subject: [PATCH 027/108] Remove 'annotation' feature --- include/chaiscript/chaiscript.hpp | 5 +- include/chaiscript/dispatchkit/bootstrap.hpp | 1 - .../chaiscript/dispatchkit/dispatchkit.hpp | 10 +--- .../dispatchkit/dynamic_object_detail.hpp | 11 ----- .../dispatchkit/proxy_functions.hpp | 27 +--------- .../chaiscript/language/chaiscript_common.hpp | 5 +- .../chaiscript/language/chaiscript_eval.hpp | 13 ++--- .../chaiscript/language/chaiscript_parser.hpp | 49 ++++++------------- unittests/3.x/dispatch_functions.chai | 1 - unittests/3.x/function_introspection.chai | 1 - unittests/function_introspection.chai | 1 - 11 files changed, 23 insertions(+), 101 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 79ef8cf4..43d3b4f6 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/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 74614f88..918d9ce2 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -376,7 +376,6 @@ 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==), "=="); diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index b5ed3f75..ec47d50a 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 { @@ -1046,11 +1041,7 @@ namespace chaiscript void dump_function(const std::pair &f) const { std::vector params = f.second->get_param_types(); - std::string annotation = f.second->annotation(); - if (annotation.size() > 0) { - std::cout << annotation; - } dump_type(params.front()); std::cout << " " << f.first << "("; @@ -1524,3 +1515,4 @@ namespace chaiscript #endif + diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index 76e3cbf4..93031cff 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -98,12 +98,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 { @@ -219,11 +213,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/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 8723d823..ae6952d6 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -204,8 +204,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() @@ -306,11 +304,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)) { } @@ -343,11 +340,6 @@ namespace chaiscript return m_parsenode; } - virtual std::string annotation() const override - { - return m_description; - } - protected: bool test_guard(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const @@ -387,7 +379,6 @@ namespace chaiscript Param_Types m_param_types; Proxy_Function m_guard; AST_NodePtr m_parsenode; - std::string m_description; }; @@ -401,13 +392,11 @@ namespace chaiscript int t_arity=-1, AST_NodePtr t_parsenode = AST_NodePtr(), Param_Types t_param_types = Param_Types(), - std::string t_description = "", Proxy_Function t_guard = Proxy_Function()) : Dynamic_Proxy_Function( t_arity, std::move(t_parsenode), std::move(t_param_types), - std::move(t_description), std::move(t_guard) ), m_f(std::move(t_f)) @@ -506,10 +495,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, @@ -554,11 +539,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() @@ -692,11 +672,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 { diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index ca29b166..3efe902e 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -35,7 +35,7 @@ namespace chaiscript enum class AST_Node_Type { Error, Id, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, Comparison, Addition, Subtraction, Multiplication, Division, Modulus, 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, + Inline_Range, 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, Constant }; @@ -47,7 +47,7 @@ namespace chaiscript static const char * const ast_node_types[] = { "Internal Parser Error", "Id", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "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", + "Inline_Range", "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", "Constant"}; return ast_node_types[static_cast(ast_node_type)]; @@ -447,7 +447,6 @@ namespace chaiscript const std::string text; Parse_Location location; std::vector children; - AST_NodePtr annotation; const std::string &filename() const { return *location.filename; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 0b9311d7..20593c14 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -578,7 +578,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( @@ -587,7 +586,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() + "'"); @@ -991,11 +990,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)) { } @@ -1162,7 +1156,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(); @@ -1175,7 +1168,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); @@ -1191,7 +1184,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); } } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5a6c1c60..2377d1e1 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -166,6 +166,7 @@ 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(); @@ -398,6 +399,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; } @@ -822,31 +836,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 == '\"')) { @@ -1468,13 +1457,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(); @@ -1522,9 +1504,6 @@ namespace chaiscript build_match(prev_stack_top); } - if (annotation) { - m_match_stack.back()->annotation = std::move(annotation); - } } return retval; diff --git a/unittests/3.x/dispatch_functions.chai b/unittests/3.x/dispatch_functions.chai index 528d5b30..f25ae017 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 5ad76fc7..96b2ec67 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/function_introspection.chai b/unittests/function_introspection.chai index 6d808dfe..fbfee5a4 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); From 57aa874c6e70ca4c289400499eb7179ac77fd4d2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 09:02:38 -0600 Subject: [PATCH 028/108] Revert "Prefer make_unique over make_shared" This reverts commit 5a947b5035dc99d2dbef35a220340036886e189c. --- .../chaiscript/dispatchkit/boxed_value.hpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 1e0ec99c..53c58678 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, From f3f84594eedb928062ff30889b94df5ee359fb03 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 12:04:18 -0600 Subject: [PATCH 029/108] A few parser cleanups --- .../chaiscript/language/chaiscript_common.hpp | 14 +- .../chaiscript/language/chaiscript_parser.hpp | 151 ++++++++---------- unittests/dispatch_functions.chai | 1 - 3 files changed, 74 insertions(+), 92 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 3efe902e..cda76711 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,22 +32,24 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Error, Id, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl, - Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, + 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, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or, + 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(AST_Node_Type ast_node_type) { - static const char * const ast_node_types[] = { "Internal Parser Error", "Id", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl", - "Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", + 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", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or", + "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[static_cast(ast_node_type)]; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 2377d1e1..fec5458a 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -146,19 +146,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; } @@ -170,7 +170,7 @@ namespace chaiscript 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; @@ -881,11 +881,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; @@ -893,11 +893,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) { } @@ -1034,13 +1029,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, const_var(match))); - build_match(prev_stack_top, "+"); - } else { - m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); } //We've finished with the part of the string up to this point, so clear it @@ -1091,13 +1084,12 @@ namespace chaiscript return cparser.is_interpolated; }(); - if (is_interpolated) { - m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); + 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, const_var(match))); } + return true; } else { return false; @@ -1302,14 +1294,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); @@ -1328,13 +1319,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); @@ -1355,13 +1345,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); + } } } @@ -1385,25 +1373,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); } @@ -2142,36 +2126,33 @@ namespace chaiscript while (Operator_Helper(t_precedence, oper)) { while (Eol()) {} if (!Operator(t_precedence+1)) { - throw exception::eval_error("Incomplete " - + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", + throw exception::eval_error("Incomplete '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename); } switch (m_operators[t_precedence]) { - case(AST_Node_Type::Ternary_Cond) : + case(Operator_Precidence::Ternary_Cond) : if (Symbol(":")) { if (!Operator(t_precedence+1)) { - throw exception::eval_error("Incomplete " - + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", + throw exception::eval_error("Incomplete '" + oper + "' 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", + 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) : + 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(); @@ -2205,10 +2186,10 @@ namespace chaiscript break; - case(AST_Node_Type::Logical_And) : + case(Operator_Precidence::Logical_And) : build_match(prev_stack_top, oper); break; - case(AST_Node_Type::Logical_Or) : + case(Operator_Precidence::Logical_Or) : build_match(prev_stack_top, oper); break; diff --git a/unittests/dispatch_functions.chai b/unittests/dispatch_functions.chai index 1887844e..67805164 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); From cf2fa09d6cbc395c6e1a39b49634f148869eeac3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 14:13:14 -0600 Subject: [PATCH 030/108] Eliminate branching in var decl --- .../chaiscript/language/chaiscript_eval.hpp | 33 +++++++------------ .../chaiscript/language/chaiscript_parser.hpp | 7 ++-- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 20593c14..8ba24e52 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -295,9 +295,8 @@ 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) { /// \todo This does not handle the case of an unassigned reference variable /// being assigned outside of its declaration @@ -379,27 +378,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() + "'"); } - } - - }; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index fec5458a..6422e3b5 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1983,11 +1983,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; From 10b984556d8f24247c81c5a5f5470ed0cf2191b7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 14:23:11 -0600 Subject: [PATCH 031/108] Add global & test --- unittests/global_lcase.chai | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/unittests/global_lcase.chai b/unittests/global_lcase.chai index 7f8959a6..21fdecdb 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) From 83c6df11f008d7e758736997c23605647543bd30 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 14:30:12 -0600 Subject: [PATCH 032/108] Fix global reference assignment --- include/chaiscript/language/chaiscript_eval.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 8ba24e52..eafa01c9 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -295,8 +295,13 @@ namespace chaiscript try { if (lhs.is_undef()) { - if (!this->children.empty() - && this->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 From 7d5a97aa2f2c4fd8391bd2a71fb4107fc77e05e2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 15:39:32 -0600 Subject: [PATCH 033/108] Clean up if block parsing and eval --- .../chaiscript/language/chaiscript_eval.hpp | 27 ++++++------------- .../chaiscript/language/chaiscript_parser.hpp | 19 +------------ 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index eafa01c9..2977043c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -653,33 +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; - /// \todo these string comparisons are clunky - 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 { diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 6422e3b5..2bdddc12 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1579,27 +1579,10 @@ namespace chaiscript while (has_matches) { while (Eol()) {} has_matches = false; - const auto line = m_position.line; - const auto col = m_position.col; if (Keyword("else")) { - if (Keyword("if")) { - m_match_stack.emplace_back(make_node("else if", line, col, std::vector())); - 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 (If()) { has_matches = true; } else { - m_match_stack.emplace_back(make_node("else", line, col, std::vector())); while (Eol()) {} if (!Block()) { From c68488388e1abe2affbd299b739998a01330bef4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 16 Apr 2016 22:14:02 -0600 Subject: [PATCH 034/108] Remove some unused code in Boxed_Value --- .../chaiscript/dispatchkit/boxed_number.hpp | 166 ------------------ .../chaiscript/dispatchkit/dispatchkit.hpp | 7 +- .../chaiscript/language/chaiscript_common.hpp | 22 +-- 3 files changed, 12 insertions(+), 183 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index ad2775be..2cc06c73 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -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::Opers::equals, this->bv, t_rhs.bv)); - } - - bool operator<(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::Opers::less_than, this->bv, t_rhs.bv)); - } - - bool operator>(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::Opers::greater_than, this->bv, t_rhs.bv)); - } - - bool operator>=(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::Opers::greater_than_equal, this->bv, t_rhs.bv)); - } - - bool operator<=(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::Opers::less_than_equal, this->bv, t_rhs.bv)); - } - - bool operator!=(const Boxed_Number &t_rhs) const - { - return boxed_cast(oper(Operators::Opers::not_equal, this->bv, t_rhs.bv)); - } - - Boxed_Number operator--() - { - return oper(Operators::Opers::pre_decrement, this->bv); - } - - Boxed_Number operator++() - { - return oper(Operators::Opers::pre_increment, this->bv); - } - - Boxed_Number operator+(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::sum, this->bv, t_rhs.bv); - } - - Boxed_Number operator+() const - { - return oper(Operators::Opers::unary_plus, this->bv); - } - - Boxed_Number operator-() const - { - return oper(Operators::Opers::unary_minus, this->bv); - } - - Boxed_Number operator-(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::difference, this->bv, t_rhs.bv); - } - - Boxed_Number operator&=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::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,107 +659,6 @@ 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::Opers::assign, this->bv, t_rhs.bv); - } - - Boxed_Number operator|=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_bitwise_or, this->bv, t_rhs.bv); - } - - Boxed_Number operator^=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_bitwise_xor, this->bv, t_rhs.bv); - } - - Boxed_Number operator%=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_remainder, this->bv, t_rhs.bv); - } - - Boxed_Number operator<<=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_shift_left, this->bv, t_rhs.bv); - } - - Boxed_Number operator>>=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_shift_right, this->bv, t_rhs.bv); - } - - Boxed_Number operator&(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::bitwise_and, this->bv, t_rhs.bv); - } - - Boxed_Number operator~() const - { - return oper(Operators::Opers::bitwise_complement, this->bv); - } - - Boxed_Number operator^(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::bitwise_xor, this->bv, t_rhs.bv); - } - - Boxed_Number operator|(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::bitwise_or, this->bv, t_rhs.bv); - } - - Boxed_Number operator*=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_product, this->bv, t_rhs.bv); - } - Boxed_Number operator/=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_quotient, this->bv, t_rhs.bv); - } - Boxed_Number operator+=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_sum, this->bv, t_rhs.bv); - } - Boxed_Number operator-=(const Boxed_Number &t_rhs) - { - return oper(Operators::Opers::assign_difference, this->bv, t_rhs.bv); - } - - Boxed_Number operator/(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::quotient, this->bv, t_rhs.bv); - } - - Boxed_Number operator<<(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::shift_left, this->bv, t_rhs.bv); - } - - Boxed_Number operator*(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::product, this->bv, t_rhs.bv); - } - - Boxed_Number operator%(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::remainder, this->bv, t_rhs.bv); - } - - Boxed_Number operator>>(const Boxed_Number &t_rhs) const - { - return oper(Operators::Opers::shift_right, this->bv, t_rhs.bv); - } - static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index ec47d50a..a5c46e4c 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -376,7 +376,6 @@ namespace chaiscript typedef std::vector StackData; Stack_Holder() - : call_depth(0) { stacks.reserve(2); stacks.emplace_back(1); @@ -387,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 @@ -1328,10 +1327,6 @@ namespace chaiscript if (rt.bare_equal(boxed_type)) { - if (lt.bare_equal(boxed_pod_type)) - { - return true; - } return true; } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index cda76711..9816f36b 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -570,17 +570,17 @@ namespace chaiscript 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 @@ -594,27 +594,27 @@ namespace chaiscript 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 @@ -628,17 +628,17 @@ namespace chaiscript 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; }; } } From 80cc18bf2f901fdc2c34c5bbce78ec272fdd9821 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 17 Apr 2016 08:15:24 -0600 Subject: [PATCH 035/108] Make type_info fully constexpr - Minor hit in compile size - Minor improvement in runtime --- include/chaiscript/dispatchkit/type_info.hpp | 28 +++++++------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 9dfdb8f0..664e4d3c 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; - - 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,9 @@ namespace chaiscript template struct Get_Type_Info > { - typedef T type; +// typedef T type; - 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 +156,7 @@ namespace chaiscript template struct Get_Type_Info &> { - typedef T type; - - 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 +169,7 @@ namespace chaiscript template struct Get_Type_Info > { - typedef T type; - - 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 +182,7 @@ namespace chaiscript template struct Get_Type_Info &> { - typedef T type; - - 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 +204,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(i); /// \endcode template - Type_Info user_type(const T &/*t*/) + constexpr Type_Info user_type(const T &/*t*/) { return detail::Get_Type_Info::get(); } @@ -227,7 +219,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(); /// \endcode template - Type_Info user_type() + constexpr Type_Info user_type() { return detail::Get_Type_Info::get(); } From f9294c8cbe8c1787dc38f60c798c85ffed798cc2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 17 Apr 2016 16:55:08 -0600 Subject: [PATCH 036/108] Remove ChaiScript_Parser from stdlib, unnecessary --- include/chaiscript/dispatchkit/bootstrap.hpp | 18 +++++++++++------- .../chaiscript/language/chaiscript_common.hpp | 8 +++----- .../chaiscript/language/chaiscript_engine.hpp | 9 +-------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 918d9ce2..1d6532fd 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -496,6 +496,7 @@ namespace chaiscript 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); @@ -519,10 +520,20 @@ 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(&ChaiScript::version_major), "version_major"); + m.add(fun(&ChaiScript::version_minor), "version_minor"); + m.add(fun(&ChaiScript::version_patch), "version_patch"); + m.add(fun(&ChaiScript::version), "version"); + m.add(fun(&ChaiScript::compiler_version), "compiler_version"); + m.add(fun(&ChaiScript::compiler_name), "compiler_name"); + m.add(fun(&ChaiScript::compiler_id), "compiler_id"); + m.add(fun(&ChaiScript::debug_build), "debug_build"); + m.add(fun(&print), "print_string"); m.add(fun(&println), "println_string"); @@ -600,13 +611,6 @@ namespace chaiscript } ); - - 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/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 9816f36b..2fed03af 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -469,7 +469,7 @@ namespace chaiscript oss << text; for (auto & elem : this->children) { - oss << elem->pretty_print(); + oss << elem->pretty_print() << ' '; } return oss.str(); @@ -512,6 +512,8 @@ namespace chaiscript 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; protected: @@ -528,10 +530,6 @@ namespace chaiscript throw std::runtime_error("Undispatched ast_node (internal error)"); } - private: - // Copy and assignment explicitly deleted - AST_Node(const AST_Node &) = delete; - AST_Node& operator=(const AST_Node &) = delete; }; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index fca14ded..bfd9cca9 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -179,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"); From 7ab6bce7faf0ba466b38a9ed31ccbdadbbd99ecd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 17 Apr 2016 21:14:01 -0600 Subject: [PATCH 037/108] Untangle chaiscript_engine from the rest of it --- include/chaiscript/chaiscript_defines.hpp | 48 +++++++++++++++++ include/chaiscript/chaiscript_stdlib.hpp | 20 +++++--- include/chaiscript/dispatchkit/bootstrap.hpp | 43 ++++------------ .../chaiscript/language/chaiscript_common.hpp | 5 +- .../chaiscript/language/chaiscript_engine.hpp | 51 +------------------ include/chaiscript/utility/utility.hpp | 5 +- 6 files changed, 76 insertions(+), 96 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 4049381a..4c31b6e4 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 50aa087a..a1082c53 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/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 1d6532fd..0d7e8a37 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 { @@ -525,14 +501,15 @@ namespace chaiscript opers_arithmetic_pod(m); - m.add(fun(&ChaiScript::version_major), "version_major"); - m.add(fun(&ChaiScript::version_minor), "version_minor"); - m.add(fun(&ChaiScript::version_patch), "version_patch"); - m.add(fun(&ChaiScript::version), "version"); - m.add(fun(&ChaiScript::compiler_version), "compiler_version"); - m.add(fun(&ChaiScript::compiler_name), "compiler_name"); - m.add(fun(&ChaiScript::compiler_id), "compiler_id"); - m.add(fun(&ChaiScript::debug_build), "debug_build"); + + 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"); diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 2fed03af..0ab8a4fd 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -43,7 +43,6 @@ namespace chaiscript namespace { - /// Helper lookup to get the name of each node type 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", @@ -109,7 +108,7 @@ namespace chaiscript } load_module_error(const load_module_error &) = default; - virtual ~load_module_error() noexcept {} + virtual ~load_module_error() noexcept = default; }; @@ -172,7 +171,7 @@ namespace chaiscript return ss.str(); } - virtual ~eval_error() noexcept {} + virtual ~eval_error() noexcept = default; private: diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index bfd9cca9..95c8165c 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -292,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()); } @@ -319,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); @@ -580,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); diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 1ca0dfbb..fa2bbdbe 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" From 06b2893bfbc03fde19d1824deb756cf2a7c41bcb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 17 Apr 2016 21:15:59 -0600 Subject: [PATCH 038/108] Update tests for removal of ChaiScript_Parser from stdlib --- unittests/reflection_test.chai | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/unittests/reflection_test.chai b/unittests/reflection_test.chai index 80e8f269..c7bc89d6 100644 --- a/unittests/reflection_test.chai +++ b/unittests/reflection_test.chai @@ -1,6 +1,4 @@ -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) From 647f8842fd7174e8efc66da83c1a5559ac64fe70 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 Apr 2016 07:26:42 -0600 Subject: [PATCH 039/108] Optimize dispatch for perfect match case --- .../chaiscript/dispatchkit/proxy_functions.hpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index ae6952d6..b991d600 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -181,20 +181,15 @@ namespace chaiscript //! to the passed in values bool filter(const std::vector &vals, const Type_Conversions_State &t_conversions) const { + assert(m_arity == -1 || (m_arity > 1 && vals.size() == m_arity)); + if (m_arity < 0) { return true; - } else if (static_cast(m_arity) == vals.size()) { - if (m_arity == 0) - { - return true; - } else if (m_arity > 1) { - return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions); - } else { - return compare_type_to_param(m_types[1], vals[0], t_conversions); - } + } else if (m_arity > 1) { + return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions); } else { - return false; + return compare_type_to_param(m_types[1], vals[0], t_conversions); } } @@ -887,7 +882,7 @@ namespace chaiscript for (const auto &func : ordered_funcs ) { try { - if (func.first == i && func.second->filter(plist, t_conversions)) + if (func.first == i && (i == 0 || func.second->filter(plist, t_conversions))) { return (*(func.second))(plist, t_conversions); } From 683164650a462b6d5ea58bb899f4c2e668243a1d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 21 Apr 2016 08:09:10 -0600 Subject: [PATCH 040/108] Add ability to 'compile' for loops --- .../chaiscript/language/chaiscript_common.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 14 +++ .../chaiscript/language/chaiscript_parser.hpp | 97 ++++++++++++++++++- 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 0ab8a4fd..2519021c 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -36,7 +36,7 @@ namespace chaiscript 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 + Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled }; enum class Operator_Precidence { Ternary_Cond, Logical_Or, Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And, Equality, Comparison, Shift, Addition, Multiplication }; @@ -49,7 +49,7 @@ namespace chaiscript "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 Condition", "Noop", "Class", "Binary", "Arg", "Constant"}; + "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"}; return ast_node_types[static_cast(ast_node_type)]; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 2977043c..742be5a7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -81,6 +81,20 @@ namespace chaiscript } } + struct Compiled_AST_Node : AST_Node { + Compiled_AST_Node(std::string t_text, Parse_Location t_loc, std::vector t_children, + std::function &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) : + AST_Node(std::move(t_text), AST_Node_Type::Compiled, std::move(t_loc), std::move(t_children)), + m_func(std::move(t_func)) + { } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + return m_func(children, t_ss); + } + + std::function &, const chaiscript::detail::Dispatch_State &t_ss)> m_func; + }; + struct Binary_Operator_AST_Node : AST_Node { Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector t_children) : AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 2bdddc12..fa009b46 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1686,6 +1686,57 @@ namespace chaiscript return true; } + + auto standard_for_loop(const size_t t_prev_top) { + assert(t_prev_top = m_match_stack.size() - 4); + + struct Result { + Result(const bool t_is, std::string t_id, const int t_start, const int t_stop) + : is_standard(t_is), id(std::move(t_id)), start(t_start), stop(t_stop) {} + Result() = default; + bool is_standard = false; + std::string id = ""; + int start = 0; + int stop = 0; + }; + + const auto eq_node = m_match_stack.at(t_prev_top); + const auto binary_node = m_match_stack.at(t_prev_top+1); + const auto prefix_node = m_match_stack.at(t_prev_top+2); + + if (eq_node->identifier == AST_Node_Type::Equation + && eq_node->children.size() == 2 + && eq_node->children[0]->identifier == AST_Node_Type::Var_Decl + && eq_node->children[1]->identifier == AST_Node_Type::Constant + && binary_node->identifier == AST_Node_Type::Binary + && binary_node->children.size() == 2 + && binary_node->text == "<" + && binary_node->children[0]->identifier == AST_Node_Type::Id + && binary_node->children[0]->text == eq_node->children[0]->children.at(0)->text + && binary_node->children[1]->identifier == AST_Node_Type::Constant + && prefix_node->identifier == AST_Node_Type::Prefix + && prefix_node->children.size() == 1 + && prefix_node->text == "++" + && prefix_node->children[0]->identifier == AST_Node_Type::Id + && prefix_node->children[0]->text == eq_node->children[0]->children.at(0)->text) + { + const Boxed_Value &begin = std::dynamic_pointer_cast(eq_node->children[1])->m_value; + const Boxed_Value &end = std::dynamic_pointer_cast(binary_node->children[1])->m_value; + const std::string &id = prefix_node->children[0]->text; + + if (begin.get_type_info().bare_equal(user_type()) + && end.get_type_info().bare_equal(user_type())) { + return Result(true, id, boxed_cast(begin), boxed_cast(end)); + } else { + return Result(); + } + } else { + return Result(); + } + } + + + /// Reads a for block from input bool For() { bool retval = false; @@ -1709,12 +1760,54 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + const auto for_loop_params = standard_for_loop(prev_stack_top); + if (for_loop_params.is_standard) { + const auto body = m_match_stack.back(); + const auto start = m_match_stack[prev_stack_top]->location; + m_match_stack.pop_back(); + m_match_stack.pop_back(); + m_match_stack.pop_back(); + m_match_stack.pop_back(); + + m_match_stack.push_back( + make_node(std::string(), start.start.line, start.start.column, std::vector({body}), + + [for_loop_params](const std::vector &children, const chaiscript::detail::Dispatch_State &t_ss) { + assert(children.size() == 1); + chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + + int i = for_loop_params.start; + t_ss.add_object(for_loop_params.id, var(&i)); + + try { + for (; i < for_loop_params.stop; ++i) { + try { + // Body of Loop + children[0]->eval(t_ss); + } catch (eval::detail::Continue_Loop &) { + // we got a continue exception, which means all of the remaining + // loop implementation is skipped and we just need to continue to + // the next iteration step + } + } + } catch (eval::detail::Break_Loop &) { + // loop broken + } + + return void_var(); + } + ) + ); + + } else { + build_match(prev_stack_top); + } } return retval; } + /// Reads a case block from input bool Case() { bool retval = false; @@ -2352,7 +2445,7 @@ namespace chaiscript throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname); } else { build_match(0); - //debug_print(ast()); + // debug_print(ast()); return true; } } else { From 25575564c007047f726c489536b2c38709448360 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 Apr 2016 15:47:39 -0600 Subject: [PATCH 041/108] Make module load error much more explicit --- .../chaiscript/language/chaiscript_common.hpp | 18 ++++++++ .../chaiscript/language/chaiscript_engine.hpp | 41 +++++++++++-------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 2519021c..073e2862 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -107,8 +107,26 @@ namespace chaiscript { } + load_module_error(const std::string &t_name, const std::vector &t_errors) + : std::runtime_error(format_error(t_name, t_errors)) + { + } + load_module_error(const load_module_error &) = default; virtual ~load_module_error() noexcept = default; + + static std::string format_error(const std::string &t_name, const std::vector &t_errors) + { + std::stringstream ss; + ss << "Error loading module '" << t_name << "'\n" + << " The following locations were searched:\n"; + + for (const auto &err : t_errors) { + ss << " " << err.what() << "\n"; + } + + return ss.str(); + } }; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 95c8165c..aa079842 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -180,7 +180,8 @@ namespace chaiscript 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([](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse"); + m_engine.add(fun([](const std::string &t_str){ return parse(t_str); }), "parse"); 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"); @@ -291,8 +292,21 @@ namespace chaiscript #endif - // attempt to load the stdlib - load_module("chaiscript_stdlib-" + Build_Info::version()); + try { + // attempt to load the stdlib + load_module("chaiscript_stdlib-" + Build_Info::version()); + } catch (const exception::load_module_error &t_err) { + std::cout << "An error occured while trying to load the chaiscript standard library.\n" + << "\n" + << "You must either provide a standard library, or compile it in.\n" + << "For an example of compiling the standard library in,\n" + << "see: https://gist.github.com/lefticus/9456197\n" + << "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n" + << "\n" + << "\n" + << t_err.what(); + throw; + } build_eval_system(ModulePtr()); } @@ -307,11 +321,14 @@ namespace chaiscript } } - static AST_NodePtr parse(const std::string &t_input) + static AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) { parser::ChaiScript_Parser parser; if (parser.parse(t_input, "PARSE")) { - //parser.show_match_stack(); + const auto ast = parser.optimized_ast(); + if (t_debug_print) { + parser.debug_print(ast); + } return parser.optimized_ast(); } else { throw chaiscript::exception::eval_error("Unknown error while parsing"); @@ -563,19 +580,7 @@ namespace chaiscript } } - std::string errstring; - - for (const auto &err : errors) - { - if (!errstring.empty()) - { - errstring += "; "; - } - - errstring += err.what(); - } - - throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring); + throw chaiscript::exception::load_module_error(t_module_name, errors); } /// \brief Load a binary module from a dynamic library. Works on platforms that support From ff2ab6bb8dfc72f89128382d73b7d36ebcb4630a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 Apr 2016 15:52:19 -0600 Subject: [PATCH 042/108] Make optimizer split out --- .../chaiscript/language/chaiscript_eval.hpp | 9 +- .../language/chaiscript_optimizer.hpp | 120 ++++++++++++++++++ .../chaiscript/language/chaiscript_parser.hpp | 108 ++-------------- 3 files changed, 136 insertions(+), 101 deletions(-) create mode 100644 include/chaiscript/language/chaiscript_optimizer.hpp diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 742be5a7..e7263ba0 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -82,10 +82,11 @@ namespace chaiscript } struct Compiled_AST_Node : AST_Node { - Compiled_AST_Node(std::string t_text, Parse_Location t_loc, std::vector t_children, + Compiled_AST_Node(AST_NodePtr t_original_node, std::vector t_children, std::function &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) : - AST_Node(std::move(t_text), AST_Node_Type::Compiled, std::move(t_loc), std::move(t_children)), - m_func(std::move(t_func)) + AST_Node(t_original_node->text, AST_Node_Type::Compiled, t_original_node->location, std::move(t_children)), + m_func(std::move(t_func)), + m_original_node(std::move(t_original_node)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -93,6 +94,7 @@ namespace chaiscript } std::function &, const chaiscript::detail::Dispatch_State &t_ss)> m_func; + AST_NodePtr m_original_node; }; struct Binary_Operator_AST_Node : AST_Node { @@ -170,7 +172,6 @@ namespace chaiscript } private: - mutable std::atomic_uint_fast32_t m_loc; }; diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp new file mode 100644 index 00000000..8d1173b2 --- /dev/null +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -0,0 +1,120 @@ +// 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_OPTIMIZER_HPP_ +#define CHAISCRIPT_OPTIMIZER_HPP_ + +#include "chaiscript_eval.hpp" + + +namespace chaiscript { + namespace optimizer { + + + template + auto child_at(const T &node, const size_t offset) { + if (node->identifier == AST_Node_Type::Compiled) { + return dynamic_cast(*node).m_original_node->children[offset]; + } else { + return node->children[offset]; + } + } + + template + auto child_count(const T &node) { + if (node->identifier == AST_Node_Type::Compiled) { + return dynamic_cast(*node).m_original_node->children.size(); + } else { + return node->children.size(); + } + } + + template + AST_NodePtr make_compiled_node(const AST_NodePtr &original_node, std::vector children, T callable) + { + return chaiscript::make_shared(original_node, children, std::move(callable)); + } + + struct For_Loop_Optimizer { + AST_NodePtr optimize(const AST_NodePtr &for_node) { + + if (for_node->identifier != AST_Node_Type::For) { + return for_node; + } + + const auto eq_node = child_at(for_node, 0); + const auto binary_node = child_at(for_node, 1); + const auto prefix_node = child_at(for_node, 2); + + if (eq_node->identifier == AST_Node_Type::Equation + && child_count(eq_node) == 2 + && child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl + && child_at(eq_node, 1)->identifier == AST_Node_Type::Constant + && binary_node->identifier == AST_Node_Type::Binary + && binary_node->text == "<" + && child_count(binary_node) == 2 + && child_at(binary_node, 0)->identifier == AST_Node_Type::Id + && child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text + && child_at(binary_node, 1)->identifier == AST_Node_Type::Constant + && prefix_node->identifier == AST_Node_Type::Prefix + && prefix_node->text == "++" + && child_count(prefix_node) == 1 + && child_at(prefix_node, 0)->identifier == AST_Node_Type::Id + && child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text) + { + const Boxed_Value &begin = std::dynamic_pointer_cast(child_at(eq_node, 1))->m_value; + const Boxed_Value &end = std::dynamic_pointer_cast(child_at(binary_node, 1))->m_value; + const std::string &id = child_at(prefix_node, 0)->text; + + if (begin.get_type_info().bare_equal(user_type()) + && end.get_type_info().bare_equal(user_type())) { + + const auto start_int = boxed_cast(begin); + const auto end_int = boxed_cast(end); + + const auto body = child_at(for_node, 3); + + return make_compiled_node(for_node, {body}, + [id, start_int, end_int](const std::vector &children, const chaiscript::detail::Dispatch_State &t_ss) { + assert(children.size() == 1); + chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + + int i = start_int; + t_ss.add_object(id, var(&i)); + + try { + for (; i < end_int; ++i) { + try { + // Body of Loop + children[0]->eval(t_ss); + } catch (eval::detail::Continue_Loop &) { + // we got a continue exception, which means all of the remaining + // loop implementation is skipped and we just need to continue to + // the next iteration step + } + } + } catch (eval::detail::Break_Loop &) { + // loop broken + } + + return void_var(); + } + ); + } else { + return for_node; + } + } else { + return for_node; + } + } + }; + + + } +} + + +#endif diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index fa009b46..e1597a88 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -20,7 +20,7 @@ #include "../dispatchkit/boxed_value.hpp" #include "chaiscript_common.hpp" - +#include "chaiscript_optimizer.hpp" #if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min) #pragma push_macro("max") // Why Microsoft? why? This is worse than bad @@ -276,8 +276,11 @@ namespace chaiscript Position m_position; + optimizer::For_Loop_Optimizer m_optimizer; + public: ChaiScript_Parser() + : m_optimizer(optimizer::For_Loop_Optimizer()) { m_match_stack.reserve(2); } @@ -368,10 +371,12 @@ namespace chaiscript /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position m_match_stack.push_back( - chaiscript::make_shared( - std::move(t_text), - std::move(filepos), - std::move(new_children))); + m_optimizer.optimize( + chaiscript::make_shared( + std::move(t_text), + std::move(filepos), + std::move(new_children))) + ); } @@ -1687,56 +1692,6 @@ namespace chaiscript } - auto standard_for_loop(const size_t t_prev_top) { - assert(t_prev_top = m_match_stack.size() - 4); - - struct Result { - Result(const bool t_is, std::string t_id, const int t_start, const int t_stop) - : is_standard(t_is), id(std::move(t_id)), start(t_start), stop(t_stop) {} - Result() = default; - bool is_standard = false; - std::string id = ""; - int start = 0; - int stop = 0; - }; - - const auto eq_node = m_match_stack.at(t_prev_top); - const auto binary_node = m_match_stack.at(t_prev_top+1); - const auto prefix_node = m_match_stack.at(t_prev_top+2); - - if (eq_node->identifier == AST_Node_Type::Equation - && eq_node->children.size() == 2 - && eq_node->children[0]->identifier == AST_Node_Type::Var_Decl - && eq_node->children[1]->identifier == AST_Node_Type::Constant - && binary_node->identifier == AST_Node_Type::Binary - && binary_node->children.size() == 2 - && binary_node->text == "<" - && binary_node->children[0]->identifier == AST_Node_Type::Id - && binary_node->children[0]->text == eq_node->children[0]->children.at(0)->text - && binary_node->children[1]->identifier == AST_Node_Type::Constant - && prefix_node->identifier == AST_Node_Type::Prefix - && prefix_node->children.size() == 1 - && prefix_node->text == "++" - && prefix_node->children[0]->identifier == AST_Node_Type::Id - && prefix_node->children[0]->text == eq_node->children[0]->children.at(0)->text) - { - const Boxed_Value &begin = std::dynamic_pointer_cast(eq_node->children[1])->m_value; - const Boxed_Value &end = std::dynamic_pointer_cast(binary_node->children[1])->m_value; - const std::string &id = prefix_node->children[0]->text; - - if (begin.get_type_info().bare_equal(user_type()) - && end.get_type_info().bare_equal(user_type())) { - return Result(true, id, boxed_cast(begin), boxed_cast(end)); - } else { - return Result(); - } - } else { - return Result(); - } - } - - - /// Reads a for block from input bool For() { bool retval = false; @@ -1760,48 +1715,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' block", File_Position(m_position.line, m_position.col), *m_filename); } - const auto for_loop_params = standard_for_loop(prev_stack_top); - if (for_loop_params.is_standard) { - const auto body = m_match_stack.back(); - const auto start = m_match_stack[prev_stack_top]->location; - m_match_stack.pop_back(); - m_match_stack.pop_back(); - m_match_stack.pop_back(); - m_match_stack.pop_back(); - - m_match_stack.push_back( - make_node(std::string(), start.start.line, start.start.column, std::vector({body}), - - [for_loop_params](const std::vector &children, const chaiscript::detail::Dispatch_State &t_ss) { - assert(children.size() == 1); - chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - - int i = for_loop_params.start; - t_ss.add_object(for_loop_params.id, var(&i)); - - try { - for (; i < for_loop_params.stop; ++i) { - try { - // Body of Loop - children[0]->eval(t_ss); - } catch (eval::detail::Continue_Loop &) { - // we got a continue exception, which means all of the remaining - // loop implementation is skipped and we just need to continue to - // the next iteration step - } - } - } catch (eval::detail::Break_Loop &) { - // loop broken - } - - return void_var(); - } - ) - ); - - } else { - build_match(prev_stack_top); - } + build_match(prev_stack_top); } return retval; From 5b78d5a898cae40515a6bf37246b2260fb3dd027 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 Apr 2016 20:22:17 -0600 Subject: [PATCH 043/108] Make optimizer pluggable --- .../dispatchkit/proxy_functions.hpp | 2 +- .../chaiscript/language/chaiscript_engine.hpp | 36 +++++------ .../chaiscript/language/chaiscript_parser.hpp | 59 ++++++++++++------- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index b991d600..2bf81d36 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -181,7 +181,7 @@ namespace chaiscript //! to the passed in values bool filter(const std::vector &vals, const Type_Conversions_State &t_conversions) const { - assert(m_arity == -1 || (m_arity > 1 && vals.size() == m_arity)); + assert(m_arity == -1 || (m_arity > 0 && static_cast(vals.size()) == m_arity)); if (m_arity < 0) { diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index aa079842..d4fce2d0 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -72,17 +72,14 @@ namespace chaiscript chaiscript::detail::Dispatch_Engine m_engine; + std::unique_ptr m_parser; + /// Evaluates the given string in by parsing it and running the results through the evaluator Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) { try { - parser::ChaiScript_Parser parser; - if (parser.parse(t_input, t_filename)) { - //parser.show_match_stack(); - return parser.optimized_ast()->eval(m_engine); - } else { - return Boxed_Value(); - } + const auto p = m_parser->parse(t_input, t_filename); + return p->eval(m_engine); } catch (chaiscript::eval::detail::Return_Value &rv) { return rv.retval; @@ -180,8 +177,8 @@ namespace chaiscript 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([](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse"); - m_engine.add(fun([](const std::string &t_str){ return parse(t_str); }), "parse"); + m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse"); + m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse"); 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"); @@ -221,7 +218,8 @@ namespace chaiscript ChaiScript(const ModulePtr &t_lib, std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) - : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)) + : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), + m_parser(std::make_unique>()) { if (m_module_paths.empty()) { @@ -245,7 +243,8 @@ namespace chaiscript /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) - : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)) + : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), + m_parser(std::make_unique>()) { if (m_module_paths.empty()) { @@ -321,18 +320,13 @@ namespace chaiscript } } - static AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) + AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) { - parser::ChaiScript_Parser parser; - if (parser.parse(t_input, "PARSE")) { - const auto ast = parser.optimized_ast(); - if (t_debug_print) { - parser.debug_print(ast); - } - return parser.optimized_ast(); - } else { - throw chaiscript::exception::eval_error("Unknown error while parsing"); + const auto ast = m_parser->parse(t_input, "PARSE"); + if (t_debug_print) { + m_parser->debug_print(ast); } + return ast; } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index e1597a88..526d7353 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -56,7 +56,21 @@ namespace chaiscript }; } - class ChaiScript_Parser { + class ChaiScript_Parser_Base + { + public: + virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; + virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; + virtual ~ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; + ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; + ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; + ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; + }; + + template + class ChaiScript_Parser : public ChaiScript_Parser_Base { static std::array, detail::max_alphabet> build_alphabet() { @@ -276,24 +290,26 @@ namespace chaiscript Position m_position; - optimizer::For_Loop_Optimizer m_optimizer; + Optimizer m_optimizer; public: - ChaiScript_Parser() - : m_optimizer(optimizer::For_Loop_Optimizer()) + explicit ChaiScript_Parser(Optimizer optimizer=Optimizer()) + : m_optimizer(std::move(optimizer)) { m_match_stack.reserve(2); } - ChaiScript_Parser(const ChaiScript_Parser &) = delete; + ChaiScript_Parser(const ChaiScript_Parser &) = default; ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete; + ChaiScript_Parser(ChaiScript_Parser &&) = default; + ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete; /// test a char in an m_alphabet bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast(c)]; } /// Prints the parsed ast_nodes as a tree - void debug_print(AST_NodePtr t, std::string prepend = "") const { + void debug_print(AST_NodePtr t, std::string prepend = "") const override { std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n'; for (unsigned int j = 0; j < t->children.size(); ++j) { debug_print(t->children[j], prepend + " "); @@ -301,10 +317,6 @@ namespace chaiscript } /// 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 void optimize_returns(AST_NodePtr &p) @@ -327,10 +339,10 @@ namespace chaiscript } - AST_NodePtr optimized_ast(bool t_optimize_returns = true) { - AST_NodePtr p = ast(); - if (t_optimize_returns) { optimize_returns(p); } - return p; + AST_NodePtr ast(bool t_optimize_returns = true) { + auto ptr = m_match_stack.front(); + if (t_optimize_returns) { optimize_returns(ptr); } + return ptr; } @@ -1063,9 +1075,7 @@ namespace chaiscript const auto ev_stack_top = m_match_stack.size(); try { - ChaiScript_Parser parser; - parser.parse(eval_match, "instr eval"); - m_match_stack.push_back(parser.ast()); + m_match_stack.push_back(parse(eval_match, "instr eval")); } catch (const exception::eval_error &e) { throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename); } @@ -2342,8 +2352,15 @@ namespace chaiscript return retval; } + AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override + { + ChaiScript_Parser parser(*this); + + return parser.parse_internal(t_input, t_fname); + } + /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. - bool parse(const std::string &t_input, std::string t_fname) { + AST_NodePtr parse_internal(const std::string &t_input, std::string t_fname) { m_position = Position(t_input.begin(), t_input.end()); m_filename = std::make_shared(std::move(t_fname)); @@ -2359,12 +2376,12 @@ namespace chaiscript throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname); } else { build_match(0); - // debug_print(ast()); - return true; } } else { - return false; + m_match_stack.push_back(chaiscript::make_shared()); } + + return ast(); } }; } From 4324a700ad43a00716c70a53b1f70a2e22006554 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 Apr 2016 21:00:32 -0600 Subject: [PATCH 044/108] Fix instring eval parsing --- include/chaiscript/language/chaiscript_parser.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 526d7353..e41bd7e8 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -63,10 +63,12 @@ namespace chaiscript virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; virtual ~ChaiScript_Parser_Base() = default; ChaiScript_Parser_Base() = default; - ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; + + protected: + ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; }; template @@ -2355,7 +2357,7 @@ namespace chaiscript AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override { ChaiScript_Parser parser(*this); - + parser.m_match_stack.clear(); return parser.parse_internal(t_input, t_fname); } From 4dbf1ee2bd645b8e6170f608e60ffaa714f29a71 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 Apr 2016 22:12:08 -0600 Subject: [PATCH 045/108] Pull out Return_Optimizer --- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../language/chaiscript_optimizer.hpp | 39 ++++++++++++++++++- .../chaiscript/language/chaiscript_parser.hpp | 31 +-------------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index d4fce2d0..27161273 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { @@ -244,7 +244,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 8d1173b2..8fc10d83 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -13,6 +13,20 @@ namespace chaiscript { namespace optimizer { + template + struct Optimizer : T... + { + Optimizer() = default; + Optimizer(T ... t) + : T(std::move(t))... + { + } + + AST_NodePtr optimize(AST_NodePtr p) { + (void)std::initializer_list{ (p = T::optimize(p), 0)... }; + return p; + } + }; template auto child_at(const T &node, const size_t offset) { @@ -35,9 +49,32 @@ namespace chaiscript { template AST_NodePtr make_compiled_node(const AST_NodePtr &original_node, std::vector children, T callable) { - return chaiscript::make_shared(original_node, children, std::move(callable)); + return chaiscript::make_shared(original_node, std::move(children), std::move(callable)); } + + struct Return_Optimizer { + AST_NodePtr optimize(const AST_NodePtr &p) + { + if (p->identifier == AST_Node_Type::Def + && !p->children.empty()) + { + auto &last_child = p->children.back(); + if (last_child->identifier == AST_Node_Type::Block) { + auto &block_last_child = last_child->children.back(); + if (block_last_child->identifier == AST_Node_Type::Return) { + if (block_last_child->children.size() == 1) { + last_child->children.back() = block_last_child->children[0]; + } + } + } + } + + return p; + } + }; + + struct For_Loop_Optimizer { AST_NodePtr optimize(const AST_NodePtr &for_node) { diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index e41bd7e8..0b5af4ba 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -318,35 +318,6 @@ namespace chaiscript } } - /// Returns the front-most AST node - - - static void optimize_returns(AST_NodePtr &p) - { - for (auto &c : p->children) - { - if (c->identifier == AST_Node_Type::Def && c->children.size() > 0) { - auto &last_child = c->children.back(); - if (last_child->identifier == AST_Node_Type::Block) { - auto &block_last_child = last_child->children.back(); - if (block_last_child->identifier == AST_Node_Type::Return) { - if (block_last_child->children.size() == 1) { - block_last_child = block_last_child->children[0]; - } - } - } - } - optimize_returns(c); - } - } - - - AST_NodePtr ast(bool t_optimize_returns = true) { - auto ptr = m_match_stack.front(); - if (t_optimize_returns) { optimize_returns(ptr); } - return ptr; - } - /// Helper function that collects ast_nodes from a starting position to the top of the stack into a new AST node template @@ -2383,7 +2354,7 @@ namespace chaiscript m_match_stack.push_back(chaiscript::make_shared()); } - return ast(); + return m_match_stack.front(); } }; } From 71caf5006f0b2eb6c3ad77657ea6693dbe63df67 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 Apr 2016 22:27:34 -0600 Subject: [PATCH 046/108] Pull constant folding optimizer out --- .../chaiscript/language/chaiscript_engine.hpp | 4 +-- .../language/chaiscript_optimizer.hpp | 27 ++++++++++++++-- .../chaiscript/language/chaiscript_parser.hpp | 32 +------------------ 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 27161273..1449b2ff 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { @@ -244,7 +244,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 8fc10d83..3e82edd0 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -53,7 +53,7 @@ namespace chaiscript { } - struct Return_Optimizer { + struct Return { AST_NodePtr optimize(const AST_NodePtr &p) { if (p->identifier == AST_Node_Type::Def @@ -74,8 +74,31 @@ namespace chaiscript { } }; + struct Constant_Fold { + AST_NodePtr optimize(const AST_NodePtr &node) { + if (node->identifier == AST_Node_Type::Binary + && node->children.size() == 2 + && node->children[0]->identifier == AST_Node_Type::Constant + && node->children[1]->identifier == AST_Node_Type::Constant) + { + const auto oper = node->text; + const auto parsed = Operators::to_operator(oper); + if (parsed != Operators::Opers::invalid) { + const auto lhs = std::dynamic_pointer_cast(node->children[0])->m_value; + const auto rhs = std::dynamic_pointer_cast(node->children[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 match = node->children[0]->text + " " + oper + " " + node->children[1]->text; + return chaiscript::make_shared(std::move(match), node->location, std::move(val)); + } + } + } - struct For_Loop_Optimizer { + return node; + } + }; + + struct For_Loop { AST_NodePtr optimize(const AST_NodePtr &for_node) { if (for_node->identifier != AST_Node_Type::For) { diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 0b5af4ba..deae9410 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2129,37 +2129,7 @@ namespace chaiscript case(Operator_Precidence::Bitwise_Xor) : case(Operator_Precidence::Bitwise_Or) : case(Operator_Precidence::Comparison) : - { - bool folded = false; - const auto size = m_match_stack.size(); - - 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 - } - - if (!folded) { - build_match(prev_stack_top, oper); - } - } - + build_match(prev_stack_top, oper); break; case(Operator_Precidence::Logical_And) : From 184ca7f7b26de6b14369a8c5ec82592895ef989b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 24 Apr 2016 07:49:00 -0600 Subject: [PATCH 047/108] Create Block reducing optimizer --- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../language/chaiscript_optimizer.hpp | 56 ++++++++++++++++--- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 1449b2ff..fdc5f609 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { @@ -244,7 +244,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 3e82edd0..2e7064d2 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -74,23 +74,61 @@ namespace chaiscript { } }; + template + bool contains_var_decl_in_scope(const T &node) + { + if (node->identifier == AST_Node_Type::Var_Decl) { + return true; + } + + const auto num = child_count(node); + + for (size_t i = 0; i < num; ++i) { + const auto &child = child_at(node, i); + if (child->identifier != AST_Node_Type::Block + && contains_var_decl_in_scope(child)) { + return true; + } + } + + return false; + } + + struct Block { + AST_NodePtr optimize(const AST_NodePtr &node) { + if (node->identifier == AST_Node_Type::Block + && node->children.size() == 1 + && !contains_var_decl_in_scope(node)) + { + return node->children[0]; + } else { + return node; + } + } + }; + struct Constant_Fold { AST_NodePtr optimize(const AST_NodePtr &node) { + if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2 && node->children[0]->identifier == AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) { - const auto oper = node->text; - const auto parsed = Operators::to_operator(oper); - if (parsed != Operators::Opers::invalid) { - const auto lhs = std::dynamic_pointer_cast(node->children[0])->m_value; - const auto rhs = std::dynamic_pointer_cast(node->children[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 match = node->children[0]->text + " " + oper + " " + node->children[1]->text; - return chaiscript::make_shared(std::move(match), node->location, std::move(val)); + try { + const auto oper = node->text; + const auto parsed = Operators::to_operator(oper); + if (parsed != Operators::Opers::invalid) { + const auto lhs = std::dynamic_pointer_cast(node->children[0])->m_value; + const auto rhs = std::dynamic_pointer_cast(node->children[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 match = node->children[0]->text + " " + oper + " " + node->children[1]->text; + return chaiscript::make_shared(std::move(match), node->location, std::move(val)); + } } + } catch (const std::exception &) { + //failure to fold, that's OK } } From f6c69f28265e8b5ae195102418893a1b5c4621b7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 25 Apr 2016 21:32:48 -0600 Subject: [PATCH 048/108] Allow folding of if blocks --- .../chaiscript/language/chaiscript_engine.hpp | 4 ++-- .../chaiscript/language/chaiscript_eval.hpp | 2 +- .../language/chaiscript_optimizer.hpp | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index fdc5f609..2f26dca8 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { @@ -244,7 +244,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()) { if (m_module_paths.empty()) { diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index e7263ba0..d02e328b 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -653,7 +653,7 @@ namespace chaiscript struct Ternary_Cond_AST_Node final : AST_Node { Ternary_Cond_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::Ternary_Cond, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 2e7064d2..370c3c49 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -107,6 +107,26 @@ namespace chaiscript { } }; + struct If { + AST_NodePtr optimize(const AST_NodePtr &node) { + if ((node->identifier == AST_Node_Type::If || node->identifier == AST_Node_Type::Ternary_Cond) + && node->children.size() >= 2 + && node->children[0]->identifier == AST_Node_Type::Constant) + { + const auto condition = std::dynamic_pointer_cast(node->children[0])->m_value; + if (condition.get_type_info().bare_equal_type_info(typeid(bool))) { + if (boxed_cast(condition)) { + return node->children[1]; + } else if (node->children.size() == 3) { + return node->children[2]; + } + } + } + + return node; + } + }; + struct Constant_Fold { AST_NodePtr optimize(const AST_NodePtr &node) { From 70cdbef69333a5fecd6e9e034d9e1428a544c8a5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 Apr 2016 07:09:57 -0600 Subject: [PATCH 049/108] Fix threading build --- include/chaiscript/chaiscript_stdlib.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index a1082c53..832439bd 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -53,7 +53,7 @@ namespace chaiscript bootstrap::standard_library::pair_type >("Pair", *lib); #ifndef CHAISCRIPT_NO_THREADS - standard_library::future_type>("future", *lib); + bootstrap::standard_library::future_type>("future", *lib); lib->add(chaiscript::fun([](const std::function &t_func){ return std::async(std::launch::async, t_func);}), "async"); #endif From 41c1c490c8af4eabdf50b5078853d9ea5cb308bc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 Apr 2016 08:31:59 -0600 Subject: [PATCH 050/108] Add support for *& return types --- .../chaiscript/dispatchkit/handle_return.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 2650e3b7..58bfafb7 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -115,6 +115,24 @@ namespace chaiscript } }; + template + struct Handle_Return + { + static Boxed_Value handle(Ret *p) + { + return Boxed_Value(p, true); + } + }; + + template + struct Handle_Return + { + static Boxed_Value handle(const Ret *p) + { + return Boxed_Value(p, true); + } + }; + template struct Handle_Return { From 03803ee4c46617d15242110365fb0ea16fe7a1f1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 Apr 2016 20:53:01 -0600 Subject: [PATCH 051/108] Initial take on Tracer hooks This will allow the user to add hooks in for debugging / execution tracing / throttling / etc for each node execution The cost is *almost* 0 if no tracing is enabled. --- include/chaiscript/dispatchkit/bootstrap.hpp | 3 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 16 +- .../chaiscript/language/chaiscript_common.hpp | 53 +- .../chaiscript/language/chaiscript_engine.hpp | 11 +- .../chaiscript/language/chaiscript_eval.hpp | 495 ++++++++++-------- .../language/chaiscript_optimizer.hpp | 46 +- .../chaiscript/language/chaiscript_parser.hpp | 211 ++++---- .../chaiscript/language/chaiscript_tracer.hpp | 43 ++ 8 files changed, 523 insertions(+), 355 deletions(-) create mode 100644 include/chaiscript/language/chaiscript_tracer.hpp diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 0d7e8a37..c689ad81 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -580,7 +580,8 @@ namespace chaiscript {fun(&AST_Node::to_string), "to_string"}, {fun([](const chaiscript::AST_Node &t_node) -> std::vector { std::vector retval; - std::transform(t_node.children.begin(), t_node.children.end(), + const auto children = t_node.get_children(); + std::transform(children.begin(), children.end(), std::back_inserter(retval), &chaiscript::var &>); return retval; diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a5c46e4c..80bbf367 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -37,6 +37,9 @@ class Boxed_Number; } // namespace chaiscript namespace chaiscript { + namespace parser { + class ChaiScript_Parser_Base; + } namespace dispatch { class Dynamic_Proxy_Function; class Proxy_Function_Base; @@ -45,6 +48,7 @@ struct Placeholder_Object; } // namespace chaiscript + /// \namespace chaiscript::dispatch /// \brief Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use to the end user. @@ -411,8 +415,10 @@ namespace chaiscript "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; }; - Dispatch_Engine() - : m_stack_holder(this) + Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser) + : m_stack_holder(this), + m_parser(parser) + { } @@ -1231,6 +1237,11 @@ namespace chaiscript return m_stack_holder->stacks.back(); } + parser::ChaiScript_Parser_Base &get_parser() + { + return m_parser.get(); + } + private: const std::vector> &get_boxed_functions_int() const @@ -1456,6 +1467,7 @@ namespace chaiscript Type_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; + std::reference_wrapper m_parser; mutable std::atomic_uint_fast32_t m_method_missing_loc; diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 073e2862..2f06f211 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -465,7 +465,6 @@ namespace chaiscript const AST_Node_Type identifier; const std::string text; Parse_Location location; - std::vector children; const std::string &filename() const { return *location.filename; @@ -485,13 +484,16 @@ namespace chaiscript oss << text; - for (auto & elem : this->children) { + for (auto & elem : this->get_children()) { oss << elem->pretty_print() << ' '; } return oss.str(); } + virtual std::vector get_children() const = 0; + virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0; + /// Prints the contents of an AST node, including its children, recursively std::string to_string(const std::string &t_prepend = "") const { @@ -500,21 +502,12 @@ namespace chaiscript oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n'; - for (auto & elem : this->children) { + for (auto & elem : this->get_children()) { oss << elem->to_string(t_prepend + " "); } return oss.str(); } - Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const - { - try { - return eval_internal(t_e); - } catch (exception::eval_error &ee) { - ee.call_stack.push_back(shared_from_this()); - throw; - } - } static bool get_bool_condition(const Boxed_Value &t_bv) { try { @@ -534,21 +527,39 @@ namespace chaiscript protected: - 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)), - children(std::move(t_children)) + AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc) + : identifier(t_id), text(std::move(t_ast_node_text)), + location(std::move(t_loc)) { } - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const - { - throw std::runtime_error("Undispatched ast_node (internal error)"); - } }; + namespace parser { + class ChaiScript_Parser_Base + { + public: + virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; + virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; + virtual void *get_tracer_ptr() = 0; + virtual ~ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; + ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; + ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; + + template + T &get_tracer() + { + // to do type check this somehow? + return static_cast(*get_tracer_ptr()); + } + + protected: + ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; + }; + } namespace eval { diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 2f26dca8..05f0e846 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -70,10 +70,10 @@ namespace chaiscript std::vector m_module_paths; std::vector m_use_paths; - chaiscript::detail::Dispatch_Engine m_engine; - std::unique_ptr m_parser; + chaiscript::detail::Dispatch_Engine m_engine; + /// Evaluates the given string in by parsing it and running the results through the evaluator Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) { @@ -219,7 +219,9 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()), + m_engine(*m_parser) + { if (m_module_paths.empty()) { @@ -244,7 +246,8 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()) + m_parser(std::make_unique>>()), + m_engine(*m_parser) { if (m_module_paths.empty()) { diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index d02e328b..0464e4d8 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -41,10 +41,15 @@ namespace chaiscript /// \brief Classes and functions that are part of the runtime eval system namespace eval { + template struct AST_Node_Impl; + + template using AST_Node_Impl_Ptr = typename std::shared_ptr>; + namespace detail { /// Helper function that will set up the scope around a function call, including handling the named function parameters - static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr) { + template + static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr) { chaiscript::detail::Dispatch_State state(t_ss); const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{ @@ -81,32 +86,72 @@ namespace chaiscript } } - struct Compiled_AST_Node : AST_Node { - Compiled_AST_Node(AST_NodePtr t_original_node, std::vector t_children, - std::function &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) : - AST_Node(t_original_node->text, AST_Node_Type::Compiled, t_original_node->location, std::move(t_children)), + + + template + struct AST_Node_Impl : AST_Node + { + AST_Node_Impl(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc, + std::vector> t_children = std::vector>()) + : AST_Node(std::move(t_ast_node_text), std::move(t_id), std::move(t_loc)), + children(std::move(t_children)) + { + } + + + std::vector get_children() const final { + return {children.begin(), children.end()}; + } + + Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final + { + try { + T::trace(t_e, this); + return eval_internal(t_e); + } catch (exception::eval_error &ee) { + ee.call_stack.push_back(shared_from_this()); + throw; + } + } + + std::vector> children; + + protected: + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const + { + throw std::runtime_error("Undispatched ast_node (internal error)"); + } + }; + + + template + struct Compiled_AST_Node : AST_Node_Impl { + Compiled_AST_Node(AST_Node_Impl_Ptr t_original_node, std::vector> t_children, + std::function> &, const chaiscript::detail::Dispatch_State &t_ss)> t_func) : + AST_Node_Impl(t_original_node->text, AST_Node_Type::Compiled, t_original_node->location, std::move(t_children)), m_func(std::move(t_func)), m_original_node(std::move(t_original_node)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - return m_func(children, t_ss); + return m_func(this->children, t_ss); } - std::function &, const chaiscript::detail::Dispatch_State &t_ss)> m_func; - AST_NodePtr m_original_node; + std::function> &, const chaiscript::detail::Dispatch_State &t_ss)> m_func; + AST_Node_Impl_Ptr m_original_node; }; - struct Binary_Operator_AST_Node : AST_Node { - Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector t_children) : - AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), + template + struct Binary_Operator_AST_Node : AST_Node_Impl { + Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), m_oper(Operators::to_operator(t_oper)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { auto lhs = this->children[0]->eval(t_ss); auto rhs = this->children[1]->eval(t_ss); - return do_oper(t_ss, m_oper, text, lhs, rhs); + return do_oper(t_ss, m_oper, this->text, lhs, rhs); } protected: @@ -141,10 +186,10 @@ namespace chaiscript }; - - struct Constant_AST_Node final : AST_Node { + template + struct Constant_AST_Node final : AST_Node_Impl { 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)), + : AST_Node_Impl(t_ast_node_text, AST_Node_Type::Constant, std::move(t_loc)), m_value(std::move(t_value)) { } @@ -156,9 +201,10 @@ namespace chaiscript Boxed_Value m_value; }; - struct Id_AST_Node final : AST_Node { + template + struct Id_AST_Node final : AST_Node_Impl { 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)), + AST_Node_Impl(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), m_loc(0) { } @@ -177,9 +223,10 @@ namespace chaiscript - struct Fun_Call_AST_Node final : AST_Node { - Fun_Call_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::Fun_Call, std::move(t_loc), std::move(t_children)) { } + template + struct Fun_Call_AST_Node final : AST_Node_Impl { + Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -227,18 +274,20 @@ namespace chaiscript - struct Arg_AST_Node final : AST_Node { - 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)) { } + template + struct Arg_AST_Node final : AST_Node_Impl { + Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } }; - 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)) { } + template + struct Arg_List_AST_Node final : AST_Node_Impl { + Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } - static std::string get_arg_name(const AST_NodePtr &t_node) { + static std::string get_arg_name(const AST_Node_Impl_Ptr &t_node) { if (t_node->children.empty()) { return t_node->text; @@ -249,7 +298,7 @@ namespace chaiscript } } - static std::vector get_arg_names(const AST_NodePtr &t_node) { + static std::vector get_arg_names(const AST_Node_Impl_Ptr &t_node) { std::vector retval; for (const auto &node : t_node->children) @@ -260,7 +309,7 @@ namespace chaiscript return retval; } - static std::pair get_arg_type(const AST_NodePtr &t_node, const chaiscript::detail::Dispatch_State &t_ss) + static std::pair get_arg_type(const AST_Node_Impl_Ptr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { if (t_node->children.size() < 2) { @@ -270,7 +319,7 @@ namespace chaiscript } } - static dispatch::Param_Types get_arg_types(const AST_NodePtr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { + static dispatch::Param_Types get_arg_types(const AST_Node_Impl_Ptr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { std::vector> retval; for (const auto &child : t_node->children) @@ -282,10 +331,11 @@ 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(text)) + template + struct Equation_AST_Node final : AST_Node_Impl { + Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)), + m_oper(Operators::to_operator(this->text)) { assert(children.size() == 2); } @@ -368,17 +418,18 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_clone_loc; }; - struct Global_Decl_AST_Node final : AST_Node { - Global_Decl_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::Global_Decl, std::move(t_loc), std::move(t_children)) { } + template + struct Global_Decl_AST_Node final : AST_Node_Impl { + Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const std::string &idname = [&]()->const std::string & { - if (children[0]->identifier == AST_Node_Type::Reference) { - return children[0]->children[0]->text; + if (this->children[0]->identifier == AST_Node_Type::Reference) { + return this->children[0]->children[0]->text; } else { - return children[0]->text; + return this->children[0]->text; } }(); @@ -393,9 +444,10 @@ namespace chaiscript }; - struct Var_Decl_AST_Node final : AST_Node { - Var_Decl_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::Var_Decl, std::move(t_loc), std::move(t_children)) { } + template + struct Var_Decl_AST_Node final : AST_Node_Impl { + Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(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 { const std::string &idname = this->children[0]->text; @@ -414,14 +466,15 @@ namespace chaiscript }; - struct Array_Call_AST_Node final : AST_Node { - Array_Call_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::Array_Call, std::move(t_loc), std::move(t_children)) { } + template + struct Array_Call_AST_Node final : AST_Node_Impl { + Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - const std::vector params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; + const std::vector params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)}; try { fpp.save_params(params); @@ -437,24 +490,25 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Dot_Access_AST_Node final : AST_Node { - 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)), + template + struct Dot_Access_AST_Node final : AST_Node_Impl { + Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)), m_fun_name( - ((children[1]->identifier == AST_Node_Type::Fun_Call) || (children[1]->identifier == AST_Node_Type::Array_Call))? - children[1]->children[0]->text:children[1]->text) { } + ((this->children[1]->identifier == AST_Node_Type::Fun_Call) || (this->children[1]->identifier == AST_Node_Type::Array_Call))? + this->children[1]->children[0]->text:this->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); - Boxed_Value retval = children[0]->eval(t_ss); + Boxed_Value retval = this->children[0]->eval(t_ss); std::vector params{retval}; bool has_function_params = false; - if (children[1]->children.size() > 1) { + if (this->children[1]->children.size() > 1) { has_function_params = true; - for (const auto &child : children[1]->children[1]->children) { + for (const auto &child : this->children[1]->children[1]->children) { params.push_back(child->eval(t_ss)); } } @@ -495,23 +549,24 @@ namespace chaiscript }; - struct Lambda_AST_Node final : AST_Node { - Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : - AST_Node(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), - m_param_names(Arg_List_AST_Node::get_arg_names(children[1])) { } + template + struct Lambda_AST_Node final : AST_Node_Impl { + Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), + m_param_names(Arg_List_AST_Node::get_arg_names(this->children[1])) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const auto captures = [&]()->std::map{ std::map named_captures; - for (const auto &capture : children[0]->children) { + for (const auto &capture : this->children[0]->children) { named_captures.insert(std::make_pair(capture->children[0]->text, capture->children[0]->eval(t_ss))); } return named_captures; }(); const auto numparams = this->children[1]->children.size(); - const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); + const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); const auto &lambda_node = this->children.back(); std::reference_wrapper engine(*t_ss); @@ -532,36 +587,38 @@ namespace chaiscript }; - struct Block_AST_Node final : AST_Node { - Block_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::Block, std::move(t_loc), std::move(t_children)) { } + template + struct Block_AST_Node final : AST_Node_Impl { + Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - const auto num_children = children.size(); + const auto num_children = this->children.size(); for (size_t i = 0; i < num_children-1; ++i) { - children[i]->eval(t_ss); + this->children[i]->eval(t_ss); } - return children.back()->eval(t_ss); + return this->children.back()->eval(t_ss); } }; - struct Def_AST_Node final : AST_Node { - Def_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::Def, std::move(t_loc), std::move(t_children)) { } + template + struct Def_AST_Node final : AST_Node_Impl { + Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ std::vector t_param_names; size_t numparams = 0; - AST_NodePtr guardnode; + AST_Node_Impl_Ptr guardnode; dispatch::Param_Types param_types; if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { numparams = this->children[1]->children.size(); - t_param_names = Arg_List_AST_Node::get_arg_names(this->children[1]); - param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); + t_param_names = Arg_List_AST_Node::get_arg_names(this->children[1]); + param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); if (this->children.size() > 3) { guardnode = this->children[2]; @@ -609,15 +666,16 @@ namespace chaiscript }; - struct While_AST_Node final : AST_Node { - While_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::While, std::move(t_loc), std::move(t_children)) { } + template + struct While_AST_Node final : AST_Node_Impl { + While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { - while (get_bool_condition(this->children[0]->eval(t_ss))) { + while (this->get_bool_condition(this->children[0]->eval(t_ss))) { try { this->children[1]->eval(t_ss); } catch (detail::Continue_Loop &) { @@ -634,51 +692,54 @@ namespace chaiscript } }; - struct Class_AST_Node final : AST_Node { - Class_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::Class, std::move(t_loc), std::move(t_children)) { } + template + struct Class_AST_Node final : AST_Node_Impl { + Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); /// \todo do this better // put class name in current scope so it can be looked up by the attrs and methods - t_ss.add_object("_current_class_name", const_var(children[0]->text)); + t_ss.add_object("_current_class_name", const_var(this->children[0]->text)); - children[1]->eval(t_ss); + this->children[1]->eval(t_ss); return void_var(); } }; - struct Ternary_Cond_AST_Node final : AST_Node { - Ternary_Cond_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::Ternary_Cond, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 3); } + template + struct Ternary_Cond_AST_Node final : AST_Node_Impl { + Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Ternary_Cond, std::move(t_loc), std::move(t_children)) + { assert(this->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); + if (this->get_bool_condition(this->children[0]->eval(t_ss))) { + return this->children[1]->eval(t_ss); } else { - return children[2]->eval(t_ss); + return this->children[2]->eval(t_ss); } } }; - 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)) + template + struct If_AST_Node final : AST_Node_Impl { + If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(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); + assert(this->children.size() == 2 || this->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); + if (this->get_bool_condition(this->children[0]->eval(t_ss))) { + return this->children[1]->eval(t_ss); } else { - if (children.size() == 3) { - return children[2]->eval(t_ss); + if (this->children.size() == 3) { + return this->children[2]->eval(t_ss); } else { return void_var(); } @@ -686,23 +747,24 @@ namespace chaiscript } }; - struct For_AST_Node final : AST_Node { - For_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::For, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 4); } + template + struct For_AST_Node final : AST_Node_Impl { + For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::For, std::move(t_loc), std::move(t_children)) + { assert(this->children.size() == 4); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { for ( - children[0]->eval(t_ss); - get_bool_condition(children[1]->eval(t_ss)); - children[2]->eval(t_ss) + this->children[0]->eval(t_ss); + this->get_bool_condition(this->children[1]->eval(t_ss)); + this->children[2]->eval(t_ss) ) { try { // Body of Loop - children[3]->eval(t_ss); + this->children[3]->eval(t_ss); } catch (detail::Continue_Loop &) { // we got a continue exception, which means all of the remaining // loop implementation is skipped and we just need to continue to @@ -718,9 +780,10 @@ namespace chaiscript }; - struct Switch_AST_Node final : AST_Node { - Switch_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::Switch, std::move(t_loc), std::move(t_children)) { } + template + struct Switch_AST_Node final : AST_Node_Impl { + Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { bool breaking = false; @@ -761,45 +824,48 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Case_AST_Node final : AST_Node { - Case_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::Case, std::move(t_loc), std::move(t_children)) + template + struct Case_AST_Node final : AST_Node_Impl { + Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children)) { assert(children.size() == 2); /* how many children does it have? */ } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - children[1]->eval(t_ss); + this->children[1]->eval(t_ss); return void_var(); } }; - struct Default_AST_Node final : AST_Node { - Default_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::Default, std::move(t_loc), std::move(t_children)) + template + struct Default_AST_Node final : AST_Node_Impl { + Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - children[0]->eval(t_ss); + this->children[0]->eval(t_ss); return void_var(); } }; - struct Inline_Array_AST_Node final : AST_Node { - Inline_Array_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::Inline_Array, std::move(t_loc), std::move(t_children)) { } + template + struct Inline_Array_AST_Node final : AST_Node_Impl { + Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { std::vector vec; - if (!children.empty()) { - vec.reserve(children[0]->children.size()); - for (const auto &child : children[0]->children) { + if (!this->children.empty()) { + vec.reserve(this->children[0]->children.size()); + for (const auto &child : this->children[0]->children) { auto obj = child->eval(t_ss); if (!obj.is_return_value()) { vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions())); @@ -819,15 +885,16 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Inline_Map_AST_Node final : AST_Node { - Inline_Map_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::Inline_Map, std::move(t_loc), std::move(t_children)) { } + template + struct Inline_Map_AST_Node final : AST_Node_Impl { + Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { std::map retval; - for (const auto &child : children[0]->children) { + for (const auto &child : this->children[0]->children) { auto obj = child->children[1]->eval(t_ss); if (!obj.is_return_value()) { obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()); @@ -847,13 +914,14 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Return_AST_Node final : AST_Node { - Return_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::Return, std::move(t_loc), std::move(t_children)) { } + template + struct Return_AST_Node final : AST_Node_Impl { + Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ if (!this->children.empty()) { - throw detail::Return_Value(children[0]->eval(t_ss)); + throw detail::Return_Value(this->children[0]->eval(t_ss)); } else { throw detail::Return_Value(void_var()); @@ -861,19 +929,20 @@ namespace chaiscript } }; - struct File_AST_Node final : AST_Node { - File_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::File, std::move(t_loc), std::move(t_children)) { } + template + struct File_AST_Node final : AST_Node_Impl { + File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { - const auto num_children = children.size(); + const auto num_children = this->children.size(); if (num_children > 0) { for (size_t i = 0; i < num_children-1; ++i) { - children[i]->eval(t_ss); + this->children[i]->eval(t_ss); } - return children.back()->eval(t_ss); + return this->children.back()->eval(t_ss); } else { return void_var(); } @@ -885,9 +954,10 @@ namespace chaiscript } }; - struct Reference_AST_Node final : AST_Node { - Reference_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::Reference, std::move(t_loc), std::move(t_children)) + template + struct Reference_AST_Node final : AST_Node_Impl { + Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ @@ -902,14 +972,15 @@ 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(text, true)) + template + struct Prefix_AST_Node final : AST_Node_Impl { + Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)), + m_oper(Operators::to_operator(this->text, true)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ - Boxed_Value bv(children[0]->eval(t_ss)); + Boxed_Value bv(this->children[0]->eval(t_ss)); try { // short circuit arithmetic operations @@ -919,10 +990,10 @@ namespace chaiscript } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); fpp.save_params({bv}); - return t_ss->call_function(text, m_loc, {std::move(bv)}, t_ss.conversions()); + return t_ss->call_function(this->text, m_loc, {std::move(bv)}, t_ss.conversions()); } } catch (const exception::dispatch_error &e) { - throw exception::eval_error("Error with prefix operator evaluation: '" + text + "'", e.parameters, e.functions, false, *t_ss); + throw exception::eval_error("Error with prefix operator evaluation: '" + this->text + "'", e.parameters, e.functions, false, *t_ss); } } @@ -931,27 +1002,30 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Break_AST_Node final : AST_Node { - Break_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::Break, std::move(t_loc), std::move(t_children)) { } + template + struct Break_AST_Node final : AST_Node_Impl { + Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Break_Loop(); } }; - struct Continue_AST_Node final : AST_Node { - Continue_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::Continue, std::move(t_loc), std::move(t_children)) { } + template + struct Continue_AST_Node final : AST_Node_Impl { + Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Continue_Loop(); } }; - struct Noop_AST_Node final : public AST_Node { + template + struct Noop_AST_Node final : AST_Node_Impl { Noop_AST_Node() : - AST_Node("", AST_Node_Type::Noop, Parse_Location()) + AST_Node_Impl("", AST_Node_Type::Noop, Parse_Location()) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ @@ -961,24 +1035,27 @@ namespace chaiscript } }; - struct Map_Pair_AST_Node final : AST_Node { - Map_Pair_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::Map_Pair, std::move(t_loc), std::move(t_children)) { } + template + struct Map_Pair_AST_Node final : AST_Node_Impl { + Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Map_Pair, std::move(t_loc), std::move(t_children)) { } }; - struct Value_Range_AST_Node final : AST_Node { - Value_Range_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::Value_Range, std::move(t_loc), std::move(t_children)) { } + template + struct Value_Range_AST_Node final : AST_Node_Impl { + Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Value_Range, std::move(t_loc), std::move(t_children)) { } }; - struct Inline_Range_AST_Node final : AST_Node { - Inline_Range_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::Inline_Range, std::move(t_loc), std::move(t_children)) { } + template + struct Inline_Range_AST_Node final : AST_Node_Impl { + Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { - auto oper1 = children[0]->children[0]->children[0]->eval(t_ss); - auto oper2 = children[0]->children[0]->children[1]->eval(t_ss); + auto oper1 = this->children[0]->children[0]->children[0]->eval(t_ss); + auto oper2 = this->children[0]->children[0]->children[1]->eval(t_ss); return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions()); } catch (const exception::dispatch_error &e) { @@ -990,9 +1067,10 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_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)) { } + template + struct Try_AST_Node final : AST_Node_Impl { + Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { } Boxed_Value handle_exception(const chaiscript::detail::Dispatch_State &t_ss, const Boxed_Value &t_except) const { @@ -1005,17 +1083,17 @@ namespace chaiscript } for (size_t i = 1; i < end_point; ++i) { chaiscript::eval::detail::Scope_Push_Pop catch_scope(t_ss); - AST_NodePtr catch_block = this->children[i]; + AST_Node_Impl_Ptr catch_block = this->children[i]; if (catch_block->children.size() == 1) { //No variable capture, no guards retval = catch_block->children[0]->eval(t_ss); break; } else if (catch_block->children.size() == 2 || catch_block->children.size() == 3) { - const auto name = Arg_List_AST_Node::get_arg_name(catch_block->children[0]); + const auto name = Arg_List_AST_Node::get_arg_name(catch_block->children[0]); if (dispatch::Param_Types( - std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} + std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} ).match(std::vector{t_except}, t_ss.conversions())) { t_ss.add_object(name, t_except); @@ -1099,23 +1177,26 @@ namespace chaiscript }; - struct Catch_AST_Node final : AST_Node { - Catch_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::Catch, std::move(t_loc), std::move(t_children)) { } + template + struct Catch_AST_Node final : AST_Node_Impl { + Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Catch, std::move(t_loc), std::move(t_children)) { } }; - struct Finally_AST_Node final : AST_Node { - Finally_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::Finally, std::move(t_loc), std::move(t_children)) { } + template + struct Finally_AST_Node final : AST_Node_Impl { + Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Finally, std::move(t_loc), std::move(t_children)) { } }; - struct Method_AST_Node final : AST_Node { - Method_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::Method, std::move(t_loc), std::move(t_children)) { } + template + struct Method_AST_Node final : AST_Node_Impl { + Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ - AST_NodePtr guardnode; + AST_Node_Impl_Ptr guardnode; const auto d = t_ss->get_parent_locals(); const auto itr = d.find("_current_class_name"); @@ -1126,20 +1207,21 @@ namespace chaiscript std::vector t_param_names{"this"}; dispatch::Param_Types param_types; - if ((children.size() > static_cast(3 + class_offset)) && (children[static_cast(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { - auto args = Arg_List_AST_Node::get_arg_names(children[static_cast(2 + class_offset)]); + if ((this->children.size() > static_cast(3 + class_offset)) + && (this->children[static_cast(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { + auto args = Arg_List_AST_Node::get_arg_names(this->children[static_cast(2 + class_offset)]); t_param_names.insert(t_param_names.end(), args.begin(), args.end()); - param_types = Arg_List_AST_Node::get_arg_types(children[static_cast(2 + class_offset)], t_ss); + param_types = Arg_List_AST_Node::get_arg_types(this->children[static_cast(2 + class_offset)], t_ss); - if (children.size() > static_cast(4 + class_offset)) { - guardnode = children[static_cast(3 + class_offset)]; + if (this->children.size() > static_cast(4 + class_offset)) { + guardnode = this->children[static_cast(3 + class_offset)]; } } else { //no parameters - if (children.size() > static_cast(3 + class_offset)) { - guardnode = children[static_cast(2 + class_offset)]; + if (this->children.size() > static_cast(3 + class_offset)) { + guardnode = this->children[static_cast(2 + class_offset)]; } } @@ -1156,8 +1238,8 @@ namespace chaiscript } try { - const std::string & function_name = children[static_cast(1 + class_offset)]->text; - auto node = children.back(); + const std::string & function_name = this->children[static_cast(1 + class_offset)]->text; + auto node = this->children.back(); if (function_name == class_name) { param_types.push_front(class_name, Type_Info()); @@ -1198,9 +1280,10 @@ namespace chaiscript }; - struct Attr_Decl_AST_Node final : AST_Node { - Attr_Decl_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::Attr_Decl, std::move(t_loc), std::move(t_children)) { } + template + struct Attr_Decl_AST_Node final : AST_Node_Impl { + Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -1234,28 +1317,30 @@ 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() == 2); } + template + struct Logical_And_AST_Node final : AST_Node_Impl { + Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children)) + { assert(this->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[1]->eval(t_ss))); + return const_var(this->get_bool_condition(this->children[0]->eval(t_ss)) + && this->get_bool_condition(this->children[1]->eval(t_ss))); } }; - 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() == 2); } + template + struct Logical_Or_AST_Node final : AST_Node_Impl { + Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children)) + { assert(this->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[1]->eval(t_ss))); + return const_var(this->get_bool_condition(this->children[0]->eval(t_ss)) + || this->get_bool_condition(this->children[1]->eval(t_ss))); } }; } diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 370c3c49..ccf89786 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -22,39 +22,41 @@ namespace chaiscript { { } - AST_NodePtr optimize(AST_NodePtr p) { + template + auto optimize(eval::AST_Node_Impl_Ptr p) { (void)std::initializer_list{ (p = T::optimize(p), 0)... }; return p; } }; template - auto child_at(const T &node, const size_t offset) { + auto child_at(const eval::AST_Node_Impl_Ptr &node, const size_t offset) { if (node->identifier == AST_Node_Type::Compiled) { - return dynamic_cast(*node).m_original_node->children[offset]; + return dynamic_cast&>(*node).m_original_node->children[offset]; } else { return node->children[offset]; } } template - auto child_count(const T &node) { + auto child_count(const eval::AST_Node_Impl_Ptr &node) { if (node->identifier == AST_Node_Type::Compiled) { - return dynamic_cast(*node).m_original_node->children.size(); + return dynamic_cast&>(*node).m_original_node->children.size(); } else { return node->children.size(); } } - template - AST_NodePtr make_compiled_node(const AST_NodePtr &original_node, std::vector children, T callable) + template + auto make_compiled_node(const eval::AST_Node_Impl_Ptr &original_node, std::vector> children, Callable callable) { - return chaiscript::make_shared(original_node, std::move(children), std::move(callable)); + return chaiscript::make_shared, eval::Compiled_AST_Node>(original_node, std::move(children), std::move(callable)); } struct Return { - AST_NodePtr optimize(const AST_NodePtr &p) + template + auto optimize(const eval::AST_Node_Impl_Ptr &p) { if (p->identifier == AST_Node_Type::Def && !p->children.empty()) @@ -95,7 +97,8 @@ namespace chaiscript { } struct Block { - AST_NodePtr optimize(const AST_NodePtr &node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { if (node->identifier == AST_Node_Type::Block && node->children.size() == 1 && !contains_var_decl_in_scope(node)) @@ -108,12 +111,13 @@ namespace chaiscript { }; struct If { - AST_NodePtr optimize(const AST_NodePtr &node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { if ((node->identifier == AST_Node_Type::If || node->identifier == AST_Node_Type::Ternary_Cond) && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) { - const auto condition = std::dynamic_pointer_cast(node->children[0])->m_value; + const auto condition = std::dynamic_pointer_cast>(node->children[0])->m_value; if (condition.get_type_info().bare_equal_type_info(typeid(bool))) { if (boxed_cast(condition)) { return node->children[1]; @@ -128,7 +132,8 @@ namespace chaiscript { }; struct Constant_Fold { - AST_NodePtr optimize(const AST_NodePtr &node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2 @@ -139,12 +144,12 @@ namespace chaiscript { const auto oper = node->text; const auto parsed = Operators::to_operator(oper); if (parsed != Operators::Opers::invalid) { - const auto lhs = std::dynamic_pointer_cast(node->children[0])->m_value; - const auto rhs = std::dynamic_pointer_cast(node->children[1])->m_value; + const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; + const auto rhs = std::dynamic_pointer_cast>(node->children[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 match = node->children[0]->text + " " + oper + " " + node->children[1]->text; - return chaiscript::make_shared(std::move(match), node->location, std::move(val)); + return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); } } } catch (const std::exception &) { @@ -157,7 +162,8 @@ namespace chaiscript { }; struct For_Loop { - AST_NodePtr optimize(const AST_NodePtr &for_node) { + template + auto optimize(const eval::AST_Node_Impl_Ptr &for_node) { if (for_node->identifier != AST_Node_Type::For) { return for_node; @@ -183,8 +189,8 @@ namespace chaiscript { && child_at(prefix_node, 0)->identifier == AST_Node_Type::Id && child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text) { - const Boxed_Value &begin = std::dynamic_pointer_cast(child_at(eq_node, 1))->m_value; - const Boxed_Value &end = std::dynamic_pointer_cast(child_at(binary_node, 1))->m_value; + const Boxed_Value &begin = std::dynamic_pointer_cast>(child_at(eq_node, 1))->m_value; + const Boxed_Value &end = std::dynamic_pointer_cast>(child_at(binary_node, 1))->m_value; const std::string &id = child_at(prefix_node, 0)->text; if (begin.get_type_info().bare_equal(user_type()) @@ -196,7 +202,7 @@ namespace chaiscript { const auto body = child_at(for_node, 3); return make_compiled_node(for_node, {body}, - [id, start_int, end_int](const std::vector &children, const chaiscript::detail::Dispatch_State &t_ss) { + [id, start_int, end_int](const std::vector> &children, const chaiscript::detail::Dispatch_State &t_ss) { assert(children.size() == 1); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index f8cb549e..bba9b6a5 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -21,6 +21,7 @@ #include "../dispatchkit/boxed_value.hpp" #include "chaiscript_common.hpp" #include "chaiscript_optimizer.hpp" +#include "chaiscript_tracer.hpp" #if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min) #define CHAISCRIPT_PUSHED_MIN_MAX @@ -57,23 +58,12 @@ namespace chaiscript }; } - class ChaiScript_Parser_Base - { - public: - virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; - virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; - virtual ~ChaiScript_Parser_Base() = default; - ChaiScript_Parser_Base() = default; - ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; - ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; - ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; - protected: - ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; - }; - - template - class ChaiScript_Parser : public ChaiScript_Parser_Base { + template + class ChaiScript_Parser final : public ChaiScript_Parser_Base { + void *get_tracer_ptr() { + return &m_tracer; + } static std::array, detail::max_alphabet> build_alphabet() { @@ -190,7 +180,7 @@ namespace chaiscript const std::array &m_operators = create_operators(); std::shared_ptr m_filename; - std::vector m_match_stack; + std::vector> m_match_stack; struct Position @@ -293,11 +283,13 @@ namespace chaiscript Position m_position; + Tracer m_tracer; Optimizer m_optimizer; public: - explicit ChaiScript_Parser(Optimizer optimizer=Optimizer()) - : m_optimizer(std::move(optimizer)) + explicit ChaiScript_Parser(Tracer tracer = Tracer(), Optimizer optimizer=Optimizer()) + : m_tracer(std::move(tracer)), + m_optimizer(std::move(optimizer)) { m_match_stack.reserve(2); } @@ -314,8 +306,8 @@ namespace chaiscript /// Prints the parsed ast_nodes as a tree void debug_print(AST_NodePtr t, std::string prepend = "") const override { std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n'; - for (unsigned int j = 0; j < t->children.size(); ++j) { - debug_print(t->children[j], prepend + " "); + for (const auto &node : t->get_children()) { + debug_print(node, prepend + " "); } } @@ -347,7 +339,7 @@ namespace chaiscript } }(); - std::vector new_children; + std::vector> new_children; if (is_deep) { new_children.assign(std::make_move_iterator(m_match_stack.begin() + static_cast(t_match_start)), @@ -358,7 +350,7 @@ namespace chaiscript /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position m_match_stack.push_back( m_optimizer.optimize( - chaiscript::make_shared( + chaiscript::make_shared, NodeType>( std::move(t_text), std::move(filepos), std::move(new_children))) @@ -669,9 +661,9 @@ namespace chaiscript } template - std::shared_ptr make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) + std::shared_ptr> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) { - return chaiscript::make_shared(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward(param)...); + return chaiscript::make_shared, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward(param)...); } /// Reads a number from the input, detecting if it's an integer or floating point @@ -687,20 +679,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 { @@ -708,11 +700,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; } @@ -773,20 +765,20 @@ namespace chaiscript 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))); + 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))); + 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, + 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, + 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, + 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( + m_match_stack.push_back(make_node>( [&]()->std::string{ if (*start == '`') { // 'escaped' literal, like an operator name @@ -820,7 +812,7 @@ namespace chaiscript Id(); } - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } @@ -1020,11 +1012,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))); + 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 - build_match(prev_stack_top, "+"); + build_match>(prev_stack_top, "+"); } //We've finished with the part of the string up to this point, so clear it @@ -1044,19 +1036,19 @@ namespace chaiscript const auto tostr_stack_top = m_match_stack.size(); - m_match_stack.push_back(make_node("to_string", start.line, start.col)); + m_match_stack.push_back(make_node>("to_string", start.line, start.col)); const auto ev_stack_top = m_match_stack.size(); try { - m_match_stack.push_back(parse(eval_match, "instr eval")); + m_match_stack.push_back(parse_instr_eval(eval_match)); } catch (const exception::eval_error &e) { throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename); } - build_match(ev_stack_top); - build_match(tostr_stack_top); - build_match(prev_stack_top, "+"); + build_match>(ev_stack_top); + build_match>(tostr_stack_top); + build_match>(prev_stack_top, "+"); } else { throw exception::eval_error("Unclosed in-string eval", File_Position(start.line, start.col), *m_filename); } @@ -1073,10 +1065,10 @@ namespace chaiscript return cparser.is_interpolated; }(); - m_match_stack.push_back(make_node(match, start.line, start.col, const_var(match))); + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); if (is_interpolated) { - build_match(prev_stack_top, "+"); + build_match>(prev_stack_top, "+"); } return true; @@ -1138,7 +1130,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, const_var(char(match.at(0))))); + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(char(match.at(0))))); return true; } else { @@ -1291,7 +1283,7 @@ namespace chaiscript } } } - build_match(prev_stack_top); + build_match>(prev_stack_top); SkipWS(true); @@ -1316,7 +1308,7 @@ namespace chaiscript } } } - build_match(prev_stack_top); + build_match>(prev_stack_top); SkipWS(true); @@ -1342,7 +1334,7 @@ namespace chaiscript } } - build_match(prev_stack_top); + build_match>(prev_stack_top); SkipWS(true); @@ -1358,7 +1350,7 @@ namespace chaiscript if (Value_Range()) { retval = true; - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Map_Pair()) { retval = true; while (Eol()) {} @@ -1368,7 +1360,7 @@ namespace chaiscript throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename); } } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Operator()) { retval = true; while (Eol()) {} @@ -1378,7 +1370,7 @@ namespace chaiscript throw exception::eval_error("Unexpected value in container", File_Position(m_position.line, m_position.col), *m_filename); } } - build_match(prev_stack_top); + build_match>(prev_stack_top); } SkipWS(true); @@ -1402,7 +1394,7 @@ namespace chaiscript } } else { // make sure we always have the same number of nodes - build_match(prev_stack_top); + build_match>(prev_stack_top); } if (Char('(')) { @@ -1421,7 +1413,7 @@ namespace chaiscript throw exception::eval_error("Incomplete anonymous function", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1472,9 +1464,9 @@ namespace chaiscript } if (is_method || t_class_context) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { - build_match(prev_stack_top); + build_match>(prev_stack_top); } } @@ -1519,7 +1511,7 @@ namespace chaiscript if (!Block()) { throw exception::eval_error("Incomplete 'catch' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(catch_stack_top); + build_match>(catch_stack_top); has_matches = true; } } @@ -1532,10 +1524,10 @@ namespace chaiscript if (!Block()) { throw exception::eval_error("Incomplete 'finally' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(finally_stack_top); + build_match>(finally_stack_top); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1582,7 +1574,7 @@ namespace chaiscript } } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1608,7 +1600,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'class' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1638,7 +1630,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'while' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1653,7 +1645,7 @@ namespace chaiscript { throw exception::eval_error("'for' loop initial statment missing", File_Position(m_position.line, m_position.col), *m_filename); } else { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } } @@ -1663,13 +1655,13 @@ namespace chaiscript { throw exception::eval_error("'for' loop condition missing", File_Position(m_position.line, m_position.col), *m_filename); } else { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } } if (!Equation()) { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } return true; @@ -1699,7 +1691,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1729,7 +1721,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'case' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Keyword("default")) { retval = true; @@ -1739,7 +1731,7 @@ namespace chaiscript throw exception::eval_error("Incomplete 'default' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1779,7 +1771,7 @@ namespace chaiscript throw exception::eval_error("Incomplete block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { @@ -1804,10 +1796,10 @@ namespace chaiscript } if (m_match_stack.size() == prev_stack_top) { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1828,10 +1820,10 @@ namespace chaiscript } if (m_match_stack.size() == prev_stack_top) { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -1843,7 +1835,7 @@ namespace chaiscript if (Keyword("return")) { Operator(); - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -1855,7 +1847,7 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); if (Keyword("break")) { - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -1867,7 +1859,7 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); if (Keyword("continue")) { - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -1896,14 +1888,14 @@ namespace chaiscript throw exception::eval_error("Incomplete function call", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); /// \todo Work around for method calls until we have a better solution if (!m_match_stack.back()->children.empty()) { if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Dot_Access) { if (m_match_stack.empty()) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); if (m_match_stack.back()->children.empty()) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); - AST_NodePtr dot_access = m_match_stack.back()->children[0]; - AST_NodePtr func_call = m_match_stack.back(); + auto dot_access = m_match_stack.back()->children[0]; + auto func_call = m_match_stack.back(); m_match_stack.pop_back(); func_call->children.erase(func_call->children.begin()); if (dot_access->children.empty()) throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); @@ -1921,7 +1913,7 @@ namespace chaiscript throw exception::eval_error("Incomplete array access", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Symbol(".")) { has_more = true; @@ -1932,7 +1924,7 @@ namespace chaiscript 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); + build_match>(prev_stack_top); } } } @@ -1953,14 +1945,14 @@ namespace chaiscript throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Keyword("auto") || Keyword("var") ) { retval = true; if (Reference()) { // we built a reference node - continue } else if (Id()) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1972,7 +1964,7 @@ namespace chaiscript throw exception::eval_error("Incomplete global declaration", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (Keyword("attr")) { retval = true; @@ -1987,7 +1979,7 @@ namespace chaiscript } - build_match(prev_stack_top); + build_match>(prev_stack_top); } return retval; @@ -2020,17 +2012,17 @@ namespace chaiscript } if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) { if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Map_Pair) { - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { - build_match(prev_stack_top); + build_match>(prev_stack_top); } } else { - build_match(prev_stack_top); + build_match>(prev_stack_top); } return true; @@ -2048,7 +2040,7 @@ namespace chaiscript throw exception::eval_error("Incomplete '&' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); return true; } else { return false; @@ -2069,7 +2061,7 @@ namespace chaiscript throw exception::eval_error("Incomplete prefix '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); return true; } } @@ -2114,7 +2106,7 @@ namespace chaiscript throw exception::eval_error("Incomplete '" + oper + "' expression", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { throw exception::eval_error("Incomplete '" + oper + "' expression", @@ -2130,14 +2122,14 @@ namespace chaiscript case(Operator_Precidence::Bitwise_Xor) : case(Operator_Precidence::Bitwise_Or) : case(Operator_Precidence::Comparison) : - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); break; case(Operator_Precidence::Logical_And) : - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); break; case(Operator_Precidence::Logical_Or) : - build_match(prev_stack_top, oper); + build_match>(prev_stack_top, oper); break; default: @@ -2167,7 +2159,7 @@ namespace chaiscript throw exception::eval_error("Incomplete map pair", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { m_position = prev_pos; @@ -2194,7 +2186,7 @@ namespace chaiscript throw exception::eval_error("Incomplete value range", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top); + build_match>(prev_stack_top); } else { m_position = prev_pos; @@ -2220,7 +2212,7 @@ namespace chaiscript throw exception::eval_error("Incomplete equation", File_Position(m_position.line, m_position.col), *m_filename); } - build_match(prev_stack_top, sym); + build_match>(prev_stack_top, sym); return true; } } @@ -2298,11 +2290,26 @@ namespace chaiscript AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override { - ChaiScript_Parser parser(*this); + ChaiScript_Parser parser(*this); parser.m_match_stack.clear(); return parser.parse_internal(t_input, t_fname); } + eval::AST_Node_Impl_Ptr parse_instr_eval(const std::string &t_input) + { + const auto last_position = m_position; + const auto last_filename = m_filename; + const auto last_match_stack = std::exchange(m_match_stack, decltype(m_match_stack){}); + + const auto retval = parse_internal(t_input, "instr eval"); + + m_position = std::move(last_position); + m_filename = std::move(last_filename); + m_match_stack = std::move(last_match_stack); + + return std::dynamic_pointer_cast>(retval); + } + /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. AST_NodePtr parse_internal(const std::string &t_input, std::string t_fname) { m_position = Position(t_input.begin(), t_input.end()); @@ -2319,10 +2326,10 @@ namespace chaiscript if (m_position.has_more()) { throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname); } else { - build_match(0); + build_match>(0); } } else { - m_match_stack.push_back(chaiscript::make_shared()); + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } return m_match_stack.front(); diff --git a/include/chaiscript/language/chaiscript_tracer.hpp b/include/chaiscript/language/chaiscript_tracer.hpp new file mode 100644 index 00000000..938b6670 --- /dev/null +++ b/include/chaiscript/language/chaiscript_tracer.hpp @@ -0,0 +1,43 @@ +// 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_TRACER_HPP_ +#define CHAISCRIPT_TRACER_HPP_ + +namespace chaiscript { + namespace eval { + + struct Noop_Tracer + { + template + static void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl *) + { + } + }; + + template + struct Tracer : T... + { + Tracer() = default; + Tracer(T ... t) + : T(std::move(t))... + { + } + + void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl> *node) { + (void)std::initializer_list{ (T::trace(ds, node), 0)... }; + } + + static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl> *node) { + ds->get_parser().get_tracer>().do_trace(ds, node); + } + }; + + } +} + +#endif + From 9a526bc1ec2244daf69febd4abdb98be08e25a8e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 1 May 2016 12:46:15 -0600 Subject: [PATCH 052/108] Allow constant folding to do conversions also --- .../chaiscript/dispatchkit/boxed_number.hpp | 54 +++++++++---------- .../language/chaiscript_optimizer.hpp | 30 ++++++++++- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 2cc06c73..4517de28 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -502,7 +502,7 @@ namespace chaiscript { } - Boxed_Number(Boxed_Value v) + explicit Boxed_Number(Boxed_Value v) : bv(std::move(v)) { validate_boxed_number(bv); @@ -693,131 +693,131 @@ namespace chaiscript static Boxed_Number pre_decrement(Boxed_Number t_lhs) { - return oper(Operators::Opers::pre_decrement, t_lhs.bv); + return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv)); } static Boxed_Number pre_increment(Boxed_Number t_lhs) { - return oper(Operators::Opers::pre_increment, t_lhs.bv); + return Boxed_Number(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::Opers::sum, t_lhs.bv, t_rhs.bv); + return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv)); } static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) { - return oper(Operators::Opers::unary_plus, t_lhs.bv); + return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv)); } static const Boxed_Number unary_minus(const Boxed_Number &t_lhs) { - return oper(Operators::Opers::unary_minus, t_lhs.bv); + return Boxed_Number(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::Opers::difference, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_remainder, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::bitwise_and, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)); + return Boxed_Number(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::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::bitwise_or, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_product, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_quotient, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_sum, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::assign_difference, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::quotient, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::shift_left, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::product, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::remainder, t_lhs.bv, t_rhs.bv); + return Boxed_Number(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::Opers::shift_right, t_lhs.bv, t_rhs.bv); + return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv)); } diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index ccf89786..dd3bb1f1 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -141,7 +141,7 @@ namespace chaiscript { && node->children[1]->identifier == AST_Node_Type::Constant) { try { - const auto oper = node->text; + const auto &oper = node->text; const auto parsed = Operators::to_operator(oper); if (parsed != Operators::Opers::invalid) { const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; @@ -155,6 +155,34 @@ namespace chaiscript { } catch (const std::exception &) { //failure to fold, that's OK } + } else if (node->identifier == AST_Node_Type::Fun_Call + && node->children.size() == 2 + && node->children[0]->identifier == AST_Node_Type::Id + && node->children[1]->identifier == AST_Node_Type::Arg_List + && node->children[1]->children.size() == 1 + && node->children[1]->children[0]->identifier == AST_Node_Type::Constant) { + + const auto arg = std::dynamic_pointer_cast>(node->children[1]->children[0])->m_value; + if (arg.get_type_info().is_arithmetic()) { + const auto &fun_name = node->children[0]->text; + + const auto make_constant = [&node, &fun_name](auto val){ + const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")"; + return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(val)); + }; + + if (fun_name == "double") { + return make_constant(Boxed_Number(arg).get_as()); + } else if (fun_name == "int") { + return make_constant(Boxed_Number(arg).get_as()); + } else if (fun_name == "float") { + return make_constant(Boxed_Number(arg).get_as()); + } else if (fun_name == "long") { + return make_constant(Boxed_Number(arg).get_as()); + } + + } + } return node; From 17821be1e2883051bde941ed5411483c597aaac0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 3 May 2016 08:51:44 -0600 Subject: [PATCH 053/108] Reduce shared_ptr copies during dispatch --- include/chaiscript/dispatchkit/dispatchkit.hpp | 4 ++-- include/chaiscript/language/chaiscript_eval.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 80bbf367..b94152e8 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -935,14 +935,14 @@ namespace chaiscript This_Foist fi(*this, l_params.front()); - auto func = boxed_cast>(bv); + auto func = boxed_cast(bv); try { return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions); } catch (const chaiscript::exception::bad_boxed_cast &) { } catch (const chaiscript::exception::arity_error &) { } catch (const chaiscript::exception::guard_error &) { } - throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector{func}); + throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector{boxed_cast(bv)}); } else { return bv; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 0464e4d8..753389d2 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -244,7 +244,7 @@ namespace chaiscript Boxed_Value fn(this->children[0]->eval(t_ss)); try { - return (*t_ss->boxed_cast(fn))(params, t_ss.conversions()); + return (*t_ss->boxed_cast(fn))(params, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); From 5373bbd52ef8c2101031afe06e7bbb40b47072cb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 3 May 2016 10:21:59 -0600 Subject: [PATCH 054/108] Add Fold-Right optimizer --- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 50 ++++++++++++++++++- .../language/chaiscript_optimizer.hpp | 28 +++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 05f0e846..1fb42404 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { @@ -246,7 +246,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { if (m_module_paths.empty()) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 753389d2..e4d60313 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -141,11 +141,59 @@ namespace chaiscript AST_Node_Impl_Ptr m_original_node; }; + + template + struct Fold_Right_Binary_Operator_AST_Node : AST_Node_Impl { + Fold_Right_Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector> t_children, Boxed_Value t_rhs) : + AST_Node_Impl(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), + m_oper(Operators::to_operator(t_oper)), + m_rhs(std::move(t_rhs)), + m_loc(0) + { } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + return do_oper(t_ss, this->text, this->children[0]->eval(t_ss)); + } + + protected: + Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss, + const std::string &t_oper_string, const Boxed_Value &t_lhs) const + { + try { + if (t_lhs.get_type_info().is_arithmetic()) + { + // If it's an arithmetic operation we want to short circuit dispatch + try{ + return Boxed_Number::do_oper(m_oper, t_lhs, m_rhs); + } catch (const chaiscript::exception::arithmetic_error &) { + throw; + } catch (...) { + throw exception::eval_error("Error with numeric operator calling: " + t_oper_string); + } + } else { + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); + fpp.save_params({t_lhs, m_rhs}); + return t_ss->call_function(t_oper_string, m_loc, {t_lhs, m_rhs}, t_ss.conversions()); + } + } + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, *t_ss); + } + } + + private: + Operators::Opers m_oper; + Boxed_Value m_rhs; + mutable std::atomic_uint_fast32_t m_loc; + }; + + template struct Binary_Operator_AST_Node : AST_Node_Impl { Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), - m_oper(Operators::to_operator(t_oper)) + m_oper(Operators::to_operator(t_oper)), + m_loc(0) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index dd3bb1f1..2ff4ad0c 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -131,6 +131,34 @@ namespace chaiscript { } }; + struct Partial_Fold { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { + + // Fold right side + if (node->identifier == AST_Node_Type::Binary + && node->children.size() == 2 + && node->children[0]->identifier != AST_Node_Type::Constant + && node->children[1]->identifier == AST_Node_Type::Constant) + { + try { + const auto &oper = node->text; + const auto parsed = Operators::to_operator(oper); + if (parsed != Operators::Opers::invalid) { + const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; + if (rhs.get_type_info().is_arithmetic()) { + return chaiscript::make_shared, eval::Fold_Right_Binary_Operator_AST_Node>(node->text, node->location, node->children, rhs); + } + } + } catch (const std::exception &) { + //failure to fold, that's OK + } + } + + return node; + } + }; + struct Constant_Fold { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { From 7b3f06b269809f9be10fa41c1ce5cf761dd1b8fb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 3 May 2016 14:41:16 -0600 Subject: [PATCH 055/108] Even more scope / block simplification --- .../chaiscript/language/chaiscript_common.hpp | 4 +-- .../chaiscript/language/chaiscript_eval.hpp | 14 ++++++++++ .../language/chaiscript_optimizer.hpp | 27 ++++++++++++++----- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 2f06f211..17a74925 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -34,7 +34,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval 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, + Lambda, Block, Scopeless_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, Compiled }; @@ -47,7 +47,7 @@ namespace chaiscript 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", + "Lambda", "Block", "Scopeless_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 Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"}; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index e4d60313..c3c473b3 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -635,6 +635,20 @@ namespace chaiscript }; + template + struct Scopeless_Block_AST_Node final : AST_Node_Impl { + Scopeless_Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Scopeless_Block, std::move(t_loc), std::move(t_children)) { } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + const auto num_children = this->children.size(); + for (size_t i = 0; i < num_children-1; ++i) { + this->children[i]->eval(t_ss); + } + return this->children.back()->eval(t_ss); + } + }; + template struct Block_AST_Node final : AST_Node_Impl { Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 2ff4ad0c..92f4ad13 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -31,11 +31,20 @@ namespace chaiscript { template auto child_at(const eval::AST_Node_Impl_Ptr &node, const size_t offset) { + if (node->children[offset]->identifier == AST_Node_Type::Compiled) { + return dynamic_cast&>(*node->children[offset]).m_original_node; + } else { + return node->children[offset]; + } + + + /* if (node->identifier == AST_Node_Type::Compiled) { return dynamic_cast&>(*node).m_original_node->children[offset]; } else { return node->children[offset]; } + */ } template @@ -88,6 +97,7 @@ namespace chaiscript { for (size_t i = 0; i < num; ++i) { const auto &child = child_at(node, i); if (child->identifier != AST_Node_Type::Block + && child->identifier != AST_Node_Type::For && contains_var_decl_in_scope(child)) { return true; } @@ -99,14 +109,19 @@ namespace chaiscript { struct Block { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { - if (node->identifier == AST_Node_Type::Block - && node->children.size() == 1 - && !contains_var_decl_in_scope(node)) + if (node->identifier == AST_Node_Type::Block) { - return node->children[0]; - } else { - return node; + if (!contains_var_decl_in_scope(node)) + { + if (node->children.size() == 1) { + return node->children[0]; + } else { + return chaiscript::make_shared, eval::Scopeless_Block_AST_Node>(node->text, node->location, node->children); + } + } } + + return node; } }; From 039d0edce39d1d1005726d46d16f511f27c26e1d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 12 May 2016 08:53:38 -0600 Subject: [PATCH 056/108] Move to std::next instead of homebrewed function --- include/chaiscript/chaiscript_defines.hpp | 7 ------- include/chaiscript/dispatchkit/dispatchkit.hpp | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 4c31b6e4..0ff0ac3f 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -137,13 +137,6 @@ namespace chaiscript { }; - template - Iter advance_copy(Iter iter, Distance distance) { - std::advance(iter, static_cast::difference_type>(distance)); - return iter; - } - - template auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type { diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index b94152e8..f9159d68 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1410,7 +1410,7 @@ namespace chaiscript static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint) { if (t_c.size() > t_hint && t_c[t_hint].first == t_key) { - return advance_copy(t_c.begin(), t_hint); + return std::next(t_c.begin(), t_hint); } else { return find_keyed_value(t_c, t_key); } From b72eed3921655ca6c093f49e66ce585212df9649 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 12 May 2016 08:55:01 -0600 Subject: [PATCH 057/108] Update docs to reflect C++14 closes #268 --- readme.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 339b8052..ddb0ed3d 100644 --- a/readme.md +++ b/readme.md @@ -43,10 +43,9 @@ languages: Requirements ============ -ChaiScript requires a C++11 compiler to build with support for variadic -templates. It has been tested with gcc 4.6 and clang 3.1 (with libcxx). MacOS -10.8 (Mountain Lion) is also known to support the C++11 build with Apple's -clang 4.0. MSVC 2013 or newer is supports also. For more information see the build +ChaiScript requires a C++14 compiler to build with support for variadic +templates. It has been tested with gcc 4.9 and clang 3.6 (with libcxx). +For more information see the build [dashboard](http://chaiscript.com/ChaiScript-BuildResults/index.html). Usage From ee68ff20ed89ed6f618884eac92814c6c17e47b3 Mon Sep 17 00:00:00 2001 From: Richard Powell Date: Sat, 14 May 2016 09:40:22 -0600 Subject: [PATCH 058/108] Fix for: samples/example.cpp crashes #269 Add the system as global. --- samples/example.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/example.cpp b/samples/example.cpp index 507c5c0e..0316ebf6 100644 --- a/samples/example.cpp +++ b/samples/example.cpp @@ -73,7 +73,7 @@ int main(int /*argc*/, char * /*argv*/[]) { //Create a new system object and share it with the chaiscript engine System system; - chai.add(var(&system), "system"); + chai.add_global(var(&system), "system"); //Add a bound callback method chai.add(fun(&System::add_callback, std::ref(system)), "add_callback_bound"); From 228c942b6c60a518a2d9cd9c5b28d2eabf534df1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 7 Jun 2016 12:26:30 -0600 Subject: [PATCH 059/108] Use std::exchange --- include/chaiscript/language/chaiscript_parser.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index bba9b6a5..5262b64e 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -200,8 +200,7 @@ namespace chaiscript if (m_pos != m_end) { if (*m_pos == '\n') { ++line; - m_last_col = col; - col = 1; + m_last_col = std::exchange(col, 1); } else { ++col; } From 52a191df9e228eee061ed7a2a0d38f51d1d132c5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 19 Jun 2016 20:20:51 -0600 Subject: [PATCH 060/108] Add optimization for unused return values --- .../chaiscript/language/chaiscript_common.hpp | 4 +- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 46 +++++++++++++++++++ .../language/chaiscript_optimizer.hpp | 33 +++++++++++++ 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 17a74925..27453736 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -32,7 +32,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval - enum class AST_Node_Type { Id, Fun_Call, Arg_List, Equation, Var_Decl, + enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl, Array_Call, Dot_Access, Lambda, Block, Scopeless_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, @@ -45,7 +45,7 @@ namespace chaiscript { /// Helper lookup to get the name of each node type 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", + static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_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", diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 1fb42404..779d13df 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { @@ -246,7 +246,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { if (m_module_paths.empty()) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index c3c473b3..be37c658 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -270,6 +270,52 @@ namespace chaiscript }; + template + struct Unused_Return_Fun_Call_AST_Node final : AST_Node_Impl { + Unused_Return_Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Unused_Return_Fun_Call, std::move(t_loc), std::move(t_children)) { } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override + { + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); + + std::vector params; + + params.reserve(this->children[1]->children.size()); + for (const auto &child : this->children[1]->children) { + params.push_back(child->eval(t_ss)); + } + + Boxed_Value fn(this->children[0]->eval(t_ss)); + + try { + return (*t_ss->boxed_cast(fn))(params, t_ss.conversions()); + } + catch(const exception::dispatch_error &e){ + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); + } + catch(const exception::bad_boxed_cast &){ + try { + Const_Proxy_Function f = t_ss->boxed_cast(fn); + // handle the case where there is only 1 function to try to call and dispatch fails on it + throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss); + } catch (const exception::bad_boxed_cast &) { + throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function."); + } + } + catch(const exception::arity_error &e){ + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + } + catch(const exception::guard_error &e){ + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + } + catch(detail::Return_Value &rv) { + return rv.retval; + } + } + }; + + template struct Fun_Call_AST_Node final : AST_Node_Impl { diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 92f4ad13..aa4f0a24 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -125,6 +125,39 @@ namespace chaiscript { } }; + struct Unused_Return { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { + if ((node->identifier == AST_Node_Type::Block + || node->identifier == AST_Node_Type::Scopeless_Block) + && node->children.size() > 0) + { + for (size_t i = 0; i < node->children.size()-1; ++i) { + auto child = node->children[i]; + if (child->identifier == AST_Node_Type::Fun_Call) { + node->children[i] = chaiscript::make_shared, eval::Unused_Return_Fun_Call_AST_Node>(child->text, child->location, std::move(child->children)); + } + } + } else if ((node->identifier == AST_Node_Type::For + || node->identifier == AST_Node_Type::While) + && child_count(node) > 0) { + auto child = child_at(node, child_count(node) - 1); + if (child->identifier == AST_Node_Type::Block + || child->identifier == AST_Node_Type::Scopeless_Block) + { + auto num_sub_children = child_count(child); + for (size_t i = 0; i < num_sub_children; ++i) { + auto sub_child = child_at(child, i); + if (sub_child->identifier == AST_Node_Type::Fun_Call) { + child->children[i] = chaiscript::make_shared, eval::Unused_Return_Fun_Call_AST_Node>(sub_child->text, sub_child->location, std::move(sub_child->children)); + } + } + } + } + return node; + } + }; + struct If { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { From c31ebb5665fc3cf6511d46b50f9ce45f948ddfd6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 23 Jun 2016 10:23:40 -0600 Subject: [PATCH 061/108] Move checking of valid object names to parse time --- .../chaiscript/dispatchkit/dispatchkit.hpp | 26 ------------ .../chaiscript/language/chaiscript_common.hpp | 24 +++++++++++ .../chaiscript/language/chaiscript_engine.hpp | 4 ++ .../chaiscript/language/chaiscript_eval.hpp | 31 ++------------ .../chaiscript/language/chaiscript_parser.hpp | 40 ++++++++++++------- 5 files changed, 58 insertions(+), 67 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index f9159d68..3b3bf3b3 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -410,9 +410,6 @@ namespace chaiscript std::vector> m_boxed_functions; std::map m_global_objects; Type_Name_Map m_types; - std::set m_reserved_words - = {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto", - "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; }; Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser) @@ -439,7 +436,6 @@ namespace chaiscript /// Add a new named Proxy_Function to the system void add(const Proxy_Function &f, const std::string &name) { - validate_object_name(name); add_function(f, name); } @@ -447,7 +443,6 @@ namespace chaiscript /// is not available in the current scope it is created void add(Boxed_Value obj, const std::string &name) { - validate_object_name(name); auto &stack = get_stack_data(); for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) @@ -497,7 +492,6 @@ namespace chaiscript /// Adds a new global shared object, between all the threads void add_global_const(const Boxed_Value &obj, const std::string &name) { - validate_object_name(name); if (!obj.is_const()) { throw chaiscript::exception::global_non_const(); @@ -516,8 +510,6 @@ namespace chaiscript /// Adds a new global (non-const) shared object, between all the threads Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name) { - validate_object_name(name); - chaiscript::detail::threading::unique_lock l(m_mutex); const auto itr = m_state.m_global_objects.find(name); @@ -534,8 +526,6 @@ namespace chaiscript /// Adds a new global (non-const) shared object, between all the threads void add_global(const Boxed_Value &obj, const std::string &name) { - validate_object_name(name); - chaiscript::detail::threading::unique_lock l(m_mutex); if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end()) @@ -549,8 +539,6 @@ namespace chaiscript /// Updates an existing global shared object or adds a new global shared object if not found void set_global(const Boxed_Value &obj, const std::string &name) { - validate_object_name(name); - chaiscript::detail::threading::unique_lock l(m_mutex); const auto itr = m_state.m_global_objects.find(name); @@ -1359,20 +1347,6 @@ namespace chaiscript } - /// Throw a reserved_word exception if the name is not allowed - void validate_object_name(const std::string &name) const - { - if (name.find("::") != std::string::npos) { - throw chaiscript::exception::illegal_name_error(name); - } - - chaiscript::detail::threading::shared_lock l(m_mutex); - - if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end()) - { - throw chaiscript::exception::reserved_word_error(name); - } - } template static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 27453736..3f093da8 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -26,6 +26,30 @@ struct AST_Node; namespace chaiscript { + static bool is_reserved_word(const std::string &name) + { + static const std::set m_reserved_words + = {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto", + "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; + return m_reserved_words.count(name) > 0; + } + + static bool valid_object_name(const std::string &name) + { + return name.find("::") == std::string::npos && !is_reserved_word(name); + } + + static void validate_object_name(const std::string &name) + { + if (is_reserved_word(name)) { + throw exception::reserved_word_error(name); + } + + if (name.find("::") != std::string::npos) { + throw exception::illegal_name_error(name); + } + } + /// Signature of module entry point that all binary loadable modules must implement. typedef ModulePtr (*Create_Module_Func)(); diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 779d13df..73e0784b 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -387,6 +387,7 @@ namespace chaiscript /// \sa Boxed_Value::is_const ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) { + validate_object_name(t_name); m_engine.add_global_const(t_bv, t_name); return *this; } @@ -398,12 +399,14 @@ namespace chaiscript /// ChaiScript is thread-safe but provides no threading locking mechanism to the script ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name) { + validate_object_name(t_name); m_engine.add_global(t_bv, t_name); return *this; } ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name) { + validate_object_name(t_name); m_engine.set_global(t_bv, t_name); return *this; } @@ -503,6 +506,7 @@ namespace chaiscript template ChaiScript &add(const T &t_t, const std::string &t_name) { + validate_object_name(t_name); m_engine.add(t_t, t_name); return *this; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index be37c658..463f40a4 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -527,12 +527,7 @@ namespace chaiscript } }(); - try { - return t_ss->add_global_no_throw(Boxed_Value(), idname); - } - catch (const exception::reserved_word_error &) { - throw exception::eval_error("Reserved word used as global '" + idname + "'"); - } + return t_ss->add_global_no_throw(Boxed_Value(), idname); } }; @@ -550,9 +545,6 @@ namespace chaiscript 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() + "'"); } @@ -763,9 +755,6 @@ namespace chaiscript }, static_cast(numparams), this->children.back(), 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() + "'"); } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Function redefined '" + e.name() + "'"); } @@ -1069,14 +1058,9 @@ namespace chaiscript { assert(children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ - try { - Boxed_Value bv; - t_ss.add_object(this->children[0]->text, bv); - return bv; - } - catch (const exception::reserved_word_error &) { - throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'"); - } + Boxed_Value bv; + t_ss.add_object(this->children[0]->text, bv); + return bv; } }; @@ -1377,9 +1361,6 @@ namespace chaiscript static_cast(numparams), node, param_types, guard), type), function_name); } - } - catch (const exception::reserved_word_error &e) { - throw exception::eval_error("Reserved word used as method name '" + e.word() + "'"); } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Method redefined '" + e.name() + "'"); } @@ -1412,10 +1393,6 @@ namespace chaiscript true ), this->children[static_cast(1 + class_offset)]->text); - - } - catch (const exception::reserved_word_error &) { - throw exception::eval_error("Reserved word used as attribute '" + this->children[static_cast(1 + class_offset)]->text + "'"); } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Attribute redefined '" + e.name() + "'"); } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5262b64e..2f136305 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -285,6 +285,13 @@ namespace chaiscript Tracer m_tracer; Optimizer m_optimizer; + void validate_object_name(const std::string &name) const + { + if (!valid_object_name(name)) { + throw exception::eval_error("Invalid Object Name: " + name, File_Position(m_position.line, m_position.col), *m_filename); + } + } + public: explicit ChaiScript_Parser(Tracer tracer = Tracer(), Optimizer optimizer=Optimizer()) : m_tracer(std::move(tracer)), @@ -756,13 +763,18 @@ namespace chaiscript } /// Reads (and potentially captures) an identifier from input - bool Id() { + bool Id(const bool validate) { SkipWS(); const auto start = m_position; if (Id_()) { const auto text = Position::str(start, m_position); + + if (validate) { + validate_object_name(text); + } + if (text == "true") { m_match_stack.push_back(make_node>(text, start.line, start.col, const_var(true))); } else if (text == "false") { @@ -801,14 +813,14 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); SkipWS(); - if (!Id()) { + if (!Id(true)) { return false; } SkipWS(); if (t_type_allowed) { - Id(); + Id(true); } build_match>(prev_stack_top); @@ -1427,7 +1439,7 @@ namespace chaiscript if (Keyword("def")) { retval = true; - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Missing function name in definition", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1437,7 +1449,7 @@ namespace chaiscript //We're now a method is_method = true; - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Missing method name in definition", File_Position(m_position.line, m_position.col), *m_filename); } } @@ -1588,7 +1600,7 @@ namespace chaiscript if (Keyword("class")) { retval = true; - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Missing class name in definition", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1871,7 +1883,7 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) || - Paren_Expression() || Inline_Container() || Id()) + Paren_Expression() || Inline_Container() || Id(false)) { retval = true; bool has_more = true; @@ -1916,7 +1928,7 @@ namespace chaiscript } else if (Symbol(".")) { has_more = true; - if (!(Id())) { + if (!(Id(true))) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1940,7 +1952,7 @@ namespace chaiscript if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) { retval = true; - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1950,7 +1962,7 @@ namespace chaiscript if (Reference()) { // we built a reference node - continue - } else if (Id()) { + } else if (Id(true)) { build_match>(prev_stack_top); } else { throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename); @@ -1959,7 +1971,7 @@ namespace chaiscript } else if (Keyword("GLOBAL") || Keyword("global")) { retval = true; - if (!(Reference() || Id())) { + if (!(Reference() || Id(true))) { throw exception::eval_error("Incomplete global declaration", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1967,13 +1979,13 @@ namespace chaiscript } else if (Keyword("attr")) { retval = true; - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename); } if (!Symbol("::")) { throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename); } - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Missing attribute name in definition", File_Position(m_position.line, m_position.col), *m_filename); } @@ -2035,7 +2047,7 @@ namespace chaiscript const auto prev_stack_top = m_match_stack.size(); if (Symbol("&")) { - if (!Id()) { + if (!Id(true)) { throw exception::eval_error("Incomplete '&' expression", File_Position(m_position.line, m_position.col), *m_filename); } From 09bdec48828d4e223e729cef78c9e8a400244fd3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 26 Jun 2016 20:00:01 -0600 Subject: [PATCH 062/108] Add ranged-for loops closes [#145] --- cheatsheet.md | 18 ++++ .../chaiscript/dispatchkit/dispatchkit.hpp | 28 ++++++- .../chaiscript/language/chaiscript_common.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 83 +++++++++++++++++++ .../chaiscript/language/chaiscript_parser.hpp | 21 +++-- unittests/ranged_for.chai | 21 +++++ 6 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 unittests/ranged_for.chai diff --git a/cheatsheet.md b/cheatsheet.md index c37045f7..dbaf5da4 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -111,6 +111,7 @@ chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global cons chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object ``` + # Using STL ChaiScript recognize many types from STL, but you have to add specific instantiation yourself. @@ -260,6 +261,23 @@ if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hi GLOBAL g3; // all upper case version also accepted ``` +## Looping + +``` +// c-style for loops +for (var i = 0; i < 100; ++i) { print(i); } +``` + +``` +// while +while (some_condition()) { /* do something */ } +``` + +``` +// ranged for +for (x : [1,2,3]) { print(i); } +``` + ## Built in Types ``` diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 3b3bf3b3..2bed224e 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -462,6 +462,26 @@ namespace chaiscript add_object(name, std::move(obj)); } + /// Adds a named object to the current scope + /// \warning This version does not check the validity of the name + /// it is meant for internal use only + Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder) + { + auto &stack_elem = get_stack_data(t_holder).back(); + + if (std::any_of(stack_elem.begin(), stack_elem.end(), + [&](const std::pair &o) { + return o.first == t_name; + })) + { + throw chaiscript::exception::name_conflict_error(t_name); + } + + stack_elem.emplace_back(t_name, std::move(obj)); + return stack_elem.back().second; + } + + /// Adds a named object to the current scope /// \warning This version does not check the validity of the name /// it is meant for internal use only @@ -477,7 +497,7 @@ namespace chaiscript throw chaiscript::exception::name_conflict_error(t_name); } - get_stack_data(t_holder).back().emplace_back(t_name, std::move(obj)); + stack_elem.emplace_back(t_name, std::move(obj)); } @@ -1478,8 +1498,12 @@ namespace chaiscript return m_conversions.saves(); } + Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj) const { + return m_engine.get().add_get_object(t_name, std::move(obj), m_stack_holder.get()); + } + void add_object(const std::string &t_name, Boxed_Value obj) const { - m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get()); + return m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get()); } Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const { diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 3f093da8..59db2e5f 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -58,7 +58,7 @@ namespace chaiscript /// Types of AST nodes available to the parser and eval enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl, Array_Call, Dot_Access, - Lambda, Block, Scopeless_Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range, + Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_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, Compiled }; @@ -71,7 +71,7 @@ namespace chaiscript const char *ast_node_type_to_string(AST_Node_Type ast_node_type) { static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Array_Call", "Dot_Access", - "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", + "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_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 Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"}; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 463f40a4..717a3b30 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -844,6 +844,89 @@ namespace chaiscript } }; + template + struct Ranged_For_AST_Node final : AST_Node_Impl { + Ranged_For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Ranged_For, std::move(t_loc), std::move(t_children)), + m_range_loc(0), + m_empty_loc(0), + m_front_loc(0), + m_pop_front_loc(0) + { assert(this->children.size() == 3); } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + const auto get_function = [&t_ss](const std::string &t_name, auto &t_hint){ + uint_fast32_t hint = t_hint; + auto funs = t_ss->get_function(t_name, hint); + if (funs.first != hint) t_hint = uint_fast32_t(funs.first); + return std::move(funs.second); + }; + + const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) { + return dispatch::dispatch(*t_funcs, {t_param}, t_ss.conversions()); + }; + + + const std::string &loop_var_name = this->children[0]->text; + Boxed_Value range_expression_result = this->children[1]->eval(t_ss); + + + const auto do_loop = [&loop_var_name, &t_ss, this](const auto &ranged_thing){ + try { + chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + Boxed_Value &obj = t_ss.add_get_object(loop_var_name, void_var()); + for (auto loop_var : ranged_thing) { + obj = Boxed_Value(std::move(loop_var)); + try { + this->children[2]->eval(t_ss); + } catch (detail::Continue_Loop &) { + } + } + } catch (detail::Break_Loop &) { + // loop broken + } + return void_var(); + }; + + if (range_expression_result.get_type_info().bare_equal_type_info(typeid(std::vector))) { + return do_loop(boxed_cast &>(range_expression_result)); + } else if (range_expression_result.get_type_info().bare_equal_type_info(typeid(std::map))) { + return do_loop(boxed_cast &>(range_expression_result)); + } else { + const auto range_funcs = get_function("range", m_range_loc); + const auto empty_funcs = get_function("empty", m_empty_loc); + const auto front_funcs = get_function("front", m_front_loc); + const auto pop_front_funcs = get_function("pop_front", m_pop_front_loc); + + try { + const auto range_obj = call_function(range_funcs, range_expression_result); + chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + Boxed_Value &obj = t_ss.add_get_object(loop_var_name, void_var()); + while (!boxed_cast(call_function(empty_funcs, range_obj))) { + obj = call_function(front_funcs, range_obj); + try { + this->children[2]->eval(t_ss); + } catch (detail::Continue_Loop &) { + } + call_function(pop_front_funcs, range_obj); + } + } catch (detail::Break_Loop &) { + // loop broken + } + return void_var(); + } + + } + +private: + mutable std::atomic_uint_fast32_t m_range_loc; + mutable std::atomic_uint_fast32_t m_empty_loc; + mutable std::atomic_uint_fast32_t m_front_loc; + mutable std::atomic_uint_fast32_t m_pop_front_loc; + + }; + + template struct For_AST_Node final : AST_Node_Impl { For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 2f136305..5fc7e278 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1647,14 +1647,20 @@ namespace chaiscript return retval; } + /// Reads the ranged `for` conditions from input + bool Range_Expression() { + // the first element will have already been captured by the For_Guards() call that preceeds it + return Char(':') && Equation(); + } - /// Reads the C-style for conditions from input + + /// Reads the C-style `for` conditions from input bool For_Guards() { if (!(Equation() && Eol())) { if (!Eol()) { - throw exception::eval_error("'for' loop initial statment missing", File_Position(m_position.line, m_position.col), *m_filename); + return false; } else { m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } @@ -1664,7 +1670,7 @@ namespace chaiscript { if (!Eol()) { - throw exception::eval_error("'for' loop condition missing", File_Position(m_position.line, m_position.col), *m_filename); + return false; } else { m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); } @@ -1692,7 +1698,8 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' expression", File_Position(m_position.line, m_position.col), *m_filename); } - if (!(For_Guards() && Char(')'))) { + const bool classic_for = For_Guards() && Char(')'); + if (!classic_for && !(Range_Expression() && Char(')'))) { throw exception::eval_error("Incomplete 'for' expression", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1702,7 +1709,11 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' block", File_Position(m_position.line, m_position.col), *m_filename); } - build_match>(prev_stack_top); + if (classic_for) { + build_match>(prev_stack_top); + } else { + build_match>(prev_stack_top); + } } return retval; diff --git a/unittests/ranged_for.chai b/unittests/ranged_for.chai new file mode 100644 index 00000000..9ef34fed --- /dev/null +++ b/unittests/ranged_for.chai @@ -0,0 +1,21 @@ +var sum = 0; + +for (x : [1,2,3,4]) { + sum += x; +} + +assert_equal(sum, 10) + +var result = 0.0; + +for (x : retro(range([1,2,3,4]))) { + if (result == 0.0) { + result = x; + } else { + result /= x; + } +} + +assert_true(result > .6 && result < .7); + + From e3d1741c6304a6e66af65489f4662a3c9931c062 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 26 Jun 2016 22:10:53 -0600 Subject: [PATCH 063/108] Add C++17-style if-init blocks --- cheatsheet.md | 12 ++++++++++ .../chaiscript/language/chaiscript_eval.hpp | 23 +++++++++++++++++++ .../chaiscript/language/chaiscript_parser.hpp | 14 +++++++++-- unittests/init_if.chai | 7 ++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 unittests/init_if.chai diff --git a/cheatsheet.md b/cheatsheet.md index dbaf5da4..700d422e 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -278,6 +278,18 @@ while (some_condition()) { /* do something */ } for (x : [1,2,3]) { print(i); } ``` +## Conditionals + +``` +if (expression) { } +``` + +``` +// C++17-style init-if blocks +// Value of 'statement' is scoped for entire `if` block +if (statement; expression) { } +``` + ## Built in Types ``` diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 717a3b30..ee9eba7d 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -823,6 +823,29 @@ namespace chaiscript }; + template + struct If_Init_AST_Node final : AST_Node_Impl { + If_Init_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) + { + assert(this->children.size() == 3 || this->children.size() == 4); + } + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + this->children[0]->eval(t_ss); + if (this->get_bool_condition(this->children[1]->eval(t_ss))) { + return this->children[2]->eval(t_ss); + } else { + if (this->children.size() == 4) { + return this->children[3]->eval(t_ss); + } else { + return void_var(); + } + } + } + }; + template struct If_AST_Node final : AST_Node_Impl { If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5fc7e278..0601d906 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1557,7 +1557,13 @@ namespace chaiscript throw exception::eval_error("Incomplete 'if' expression", File_Position(m_position.line, m_position.col), *m_filename); } - if (!(Operator() && Char(')'))) { + if (!Equation()) { + throw exception::eval_error("Incomplete 'if' expression", File_Position(m_position.line, m_position.col), *m_filename); + } + + const bool is_if_init = Eol() && Equation(); + + if (!Char(')')) { throw exception::eval_error("Incomplete 'if' expression", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1585,7 +1591,11 @@ namespace chaiscript } } - build_match>(prev_stack_top); + if (!is_if_init) { + build_match>(prev_stack_top); + } else { + build_match>(prev_stack_top); + } } return retval; diff --git a/unittests/init_if.chai b/unittests/init_if.chai new file mode 100644 index 00000000..01c05c7e --- /dev/null +++ b/unittests/init_if.chai @@ -0,0 +1,7 @@ +if (var x = 2; x == 3) { + assert_true(false); +} else if (var y = 3; y == 6) { + assert_true(false); +} else { + assert_equal(5, y + x); +} From 19a730b78b8aa3a38a468f927567a4d94d4f7f2c Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 11:52:22 +0300 Subject: [PATCH 064/108] Basic support for Unicode 'slash'uABCD escape notation - parser understands escape sequence and following data --- .../chaiscript/language/chaiscript_parser.hpp | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 1ea73716..4104278f 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -928,6 +928,29 @@ namespace chaiscript return false; } + // Generic for u16, u32 and (probably) wchar + template + static string_type str_from_ll(long long val) + { + return string_type(1, string_type::value_type(val)); //size, character + } + + // Specialization for char + template<> + static std::string str_from_ll(long long val) + { + std::string::value_type c[2]; + c[1] = val; + c[0] = val >> 8; + + if (c[0] == 0) + { + return std::string(1, c[1]); //size, character + } + + return std::string(c, 2); //char buffer, size + } + template struct Char_Parser { @@ -938,6 +961,7 @@ namespace chaiscript bool saw_interpolation_marker; bool is_octal; bool is_hex; + bool is_unicode; const bool interpolation_allowed; string_type octal_matches; @@ -950,6 +974,7 @@ namespace chaiscript saw_interpolation_marker(false), is_octal(false), is_hex(false), + is_unicode(false), interpolation_allowed(t_interpolation_allowed) { } @@ -964,6 +989,10 @@ namespace chaiscript if (is_hex) { process_hex(); } + + if (is_unicode) { + process_unicode(); + } } void process_hex() @@ -985,9 +1014,23 @@ namespace chaiscript is_octal = false; } + + void process_unicode() + { + auto val = stoll(hex_matches, 0, 16); + hex_matches.clear(); + match += str_from_ll(val); + is_escaped = false; + is_unicode = false; + } + void parse(const char_type t_char, const int line, const int col, const std::string &filename) { const bool is_octal_char = t_char >= '0' && t_char <= '7'; + const bool is_hex_char = (t_char >= '0' && t_char <= '9') + || (t_char >= 'a' && t_char <= 'f') + || (t_char >= 'A' && t_char <= 'F'); + if (is_octal) { if (is_octal_char) { octal_matches.push_back(t_char); @@ -1000,10 +1043,6 @@ namespace chaiscript process_octal(); } } else if (is_hex) { - const bool is_hex_char = (t_char >= '0' && t_char <= '9') - || (t_char >= 'a' && t_char <= 'f') - || (t_char >= 'A' && t_char <= 'F'); - if (is_hex_char) { hex_matches.push_back(t_char); @@ -1018,6 +1057,21 @@ namespace chaiscript } else { process_hex(); } + } else if (is_unicode) { + if (is_hex_char) { + hex_matches.push_back(t_char); + + if(hex_matches.size() == 4) { + // Format is specified to be 'slash'uABCD + // on collecting from A to D do parsing + process_unicode(); + } + return; + } else { + // Not a unicode anymore, try parsing any way + // May be someone used 'slash'uAA only + process_unicode(); + } } if (t_char == '\\') { @@ -1034,6 +1088,8 @@ namespace chaiscript octal_matches.push_back(t_char); } else if (t_char == 'x') { is_hex = true; + } else if (t_char == 'u') { + is_unicode = true; } else { switch (t_char) { case ('\'') : match.push_back('\''); break; From bd263555167768ecfa61073bf4d6f2a2e5054fd4 Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 12:38:50 +0300 Subject: [PATCH 065/108] No warnings from MSVC --- include/chaiscript/language/chaiscript_parser.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 4104278f..5e9765f2 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -940,8 +940,8 @@ namespace chaiscript static std::string str_from_ll(long long val) { std::string::value_type c[2]; - c[1] = val; - c[0] = val >> 8; + c[1] = std::string::value_type(val); + c[0] = std::string::value_type(val >> 8); if (c[0] == 0) { From 2adefaf46d81c12e59985951b7b30da830a3d1e1 Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 12:39:03 +0300 Subject: [PATCH 066/108] Basic unit tests --- unittests/string_unicode_ascii.chai | 8 ++++++++ unittests/string_unicode_parse.chai | 11 +++++++++++ unittests/string_unicode_unicode.chai | 5 +++++ 3 files changed, 24 insertions(+) create mode 100644 unittests/string_unicode_ascii.chai create mode 100644 unittests/string_unicode_parse.chai create mode 100644 unittests/string_unicode_unicode.chai diff --git a/unittests/string_unicode_ascii.chai b/unittests/string_unicode_ascii.chai new file mode 100644 index 00000000..aca62d8f --- /dev/null +++ b/unittests/string_unicode_ascii.chai @@ -0,0 +1,8 @@ +assert_equal('\u0020', ' ') +assert_equal('\u0021', '!') +assert_equal('\u0030', '0') +assert_equal('\u0040', '@') +assert_equal('\u005B', '[') +assert_equal('\u005d', ']') +assert_equal('\u0061', 'a') +assert_equal('\u007e', '~') diff --git a/unittests/string_unicode_parse.chai b/unittests/string_unicode_parse.chai new file mode 100644 index 00000000..8807126e --- /dev/null +++ b/unittests/string_unicode_parse.chai @@ -0,0 +1,11 @@ +assert_equal('\u00aa', '\u00AA') +assert_equal('\u00bb', '\uBB') +assert_equal('\ucc', '\u00CC') +assert_equal('\udd', '\uDD') + +assert_equal('\u0ee', '\uEE') +assert_equal('\ue', '\u000E') + +assert_equal("\u30\u31\u32", "123") +assert_equal("\u33Test", "4Test") +assert_equal("Test\u0040", "Test@") diff --git a/unittests/string_unicode_unicode.chai b/unittests/string_unicode_unicode.chai new file mode 100644 index 00000000..3911d8e3 --- /dev/null +++ b/unittests/string_unicode_unicode.chai @@ -0,0 +1,5 @@ +assert_equal('\u0220', 'Ü') +assert_equal("U for \u0220mlauts", "U for Ümlauts") +assert_equal("More \u0220ml\u0228\u0252ts", "More Ümläüts") + +assert_equal("Happy \u30C4 face", "Happy ツ face") From 8478ddc47089f44e2f8685f504325e4e20735e54 Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 12:45:38 +0300 Subject: [PATCH 067/108] Move details to detail namespace, make to standard --- .../chaiscript/language/chaiscript_parser.hpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5e9765f2..8120fac6 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -55,6 +55,29 @@ namespace chaiscript , max_alphabet , lengthof_alphabet = 256 }; + + // Generic for u16, u32 and (probably) wchar + template + static string_type str_from_ll(long long val) + { + return string_type(1, string_type::value_type(val)); //size, character + } + + // Specialization for char + template<> + static std::string str_from_ll(long long val) + { + std::string::value_type c[2]; + c[1] = std::string::value_type(val); + c[0] = std::string::value_type(val >> 8); + + if (c[0] == 0) + { + return std::string(1, c[1]); //size, character + } + + return std::string(c, 2); //char buffer, size + } } class ChaiScript_Parser { @@ -928,29 +951,6 @@ namespace chaiscript return false; } - // Generic for u16, u32 and (probably) wchar - template - static string_type str_from_ll(long long val) - { - return string_type(1, string_type::value_type(val)); //size, character - } - - // Specialization for char - template<> - static std::string str_from_ll(long long val) - { - std::string::value_type c[2]; - c[1] = std::string::value_type(val); - c[0] = std::string::value_type(val >> 8); - - if (c[0] == 0) - { - return std::string(1, c[1]); //size, character - } - - return std::string(c, 2); //char buffer, size - } - template struct Char_Parser { @@ -1019,7 +1019,7 @@ namespace chaiscript { auto val = stoll(hex_matches, 0, 16); hex_matches.clear(); - match += str_from_ll(val); + match += detail::str_from_ll(val); is_escaped = false; is_unicode = false; } From e3e90de02a51f0ce859638854074166e3923e500 Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 13:09:32 +0300 Subject: [PATCH 068/108] Proper comparison in unit tests; remove leftover static keyword --- include/chaiscript/language/chaiscript_parser.hpp | 4 ++-- unittests/string_unicode_parse.chai | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 8120fac6..f67bbf78 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -58,14 +58,14 @@ namespace chaiscript // Generic for u16, u32 and (probably) wchar template - static string_type str_from_ll(long long val) + string_type str_from_ll(long long val) { return string_type(1, string_type::value_type(val)); //size, character } // Specialization for char template<> - static std::string str_from_ll(long long val) + std::string str_from_ll(long long val) { std::string::value_type c[2]; c[1] = std::string::value_type(val); diff --git a/unittests/string_unicode_parse.chai b/unittests/string_unicode_parse.chai index 8807126e..50da68bb 100644 --- a/unittests/string_unicode_parse.chai +++ b/unittests/string_unicode_parse.chai @@ -6,6 +6,6 @@ assert_equal('\udd', '\uDD') assert_equal('\u0ee', '\uEE') assert_equal('\ue', '\u000E') -assert_equal("\u30\u31\u32", "123") -assert_equal("\u33Test", "4Test") +assert_equal("\u30\u31\u32", "012") +assert_equal("\u33Test", "3Test") assert_equal("Test\u0040", "Test@") From 368a3b78a26e2ae7b2174454c8c0fc45742e6d7d Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 13:46:37 +0300 Subject: [PATCH 069/108] create holder class --- .../chaiscript/language/chaiscript_parser.hpp | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index f67bbf78..c866c1ed 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -58,26 +58,32 @@ namespace chaiscript // Generic for u16, u32 and (probably) wchar template - string_type str_from_ll(long long val) + struct Char_Parser_Helper { - return string_type(1, string_type::value_type(val)); //size, character - } + static string_type str_from_ll(long long val) + { + return string_type(1, string_type::value_type(val)); //size, character + } + }; // Specialization for char template<> - std::string str_from_ll(long long val) + struct Char_Parser_Helper { - std::string::value_type c[2]; - c[1] = std::string::value_type(val); - c[0] = std::string::value_type(val >> 8); - - if (c[0] == 0) + static std::string str_from_ll(long long val) { - return std::string(1, c[1]); //size, character - } + std::string::value_type c[2]; + c[1] = std::string::value_type(val); + c[0] = std::string::value_type(val >> 8); - return std::string(c, 2); //char buffer, size - } + if (c[0] == 0) + { + return std::string(1, c[1]); //size, character + } + + return std::string(c, 2); //char buffer, size + } + }; } class ChaiScript_Parser { @@ -1019,7 +1025,7 @@ namespace chaiscript { auto val = stoll(hex_matches, 0, 16); hex_matches.clear(); - match += detail::str_from_ll(val); + match += detail::Char_Parser_Helper::str_from_ll(val); is_escaped = false; is_unicode = false; } From 830b7c93ca3a33ad4d20e69699455936a56208a2 Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 15:26:07 +0300 Subject: [PATCH 070/108] Fix unit test, limit unit test to UTF-8 --- unittests/string_unicode_unicode.chai | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unittests/string_unicode_unicode.chai b/unittests/string_unicode_unicode.chai index 3911d8e3..93092167 100644 --- a/unittests/string_unicode_unicode.chai +++ b/unittests/string_unicode_unicode.chai @@ -1,5 +1,5 @@ -assert_equal('\u0220', 'Ü') -assert_equal("U for \u0220mlauts", "U for Ümlauts") -assert_equal("More \u0220ml\u0228\u0252ts", "More Ümläüts") +assert_equal('\uc39c', 'Ü') +assert_equal("U for \uc39cmlauts", "U for Ümlauts") +assert_equal("More \uc39cml\uc3a4\uc3bcts", "More Ümläüts") -assert_equal("Happy \u30C4 face", "Happy ツ face") +assert_equal("Thorn \uc3be sign", "Thorn þ sign") From 58ebb22c55414f1533517a985fabc3ee0fea321d Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 16:03:32 +0300 Subject: [PATCH 071/108] clean-up conversion for other than std:string --- .../chaiscript/language/chaiscript_parser.hpp | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index c866c1ed..95b297c1 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include @@ -56,32 +58,43 @@ namespace chaiscript , lengthof_alphabet = 256 }; - // Generic for u16, u32 and (probably) wchar + // Generic for u16, u32 and wchar template struct Char_Parser_Helper { + typedef typename string_type::value_type target_char_type; + static string_type str_from_ll(long long val) { - return string_type(1, string_type::value_type(val)); //size, character + // make proper UTF-8 string + const std::string intermediate = Char_Parser_Helper::str_from_ll(val); + // prepare converter + std::wstring_convert, target_char_type> converter; + // convert + const string_type result = converter.from_bytes(intermediate); + + return result; } }; - // Specialization for char + // Specialization for char AKA UTF-8 template<> struct Char_Parser_Helper { + typedef std::string::value_type char_type; + static std::string str_from_ll(long long val) { - std::string::value_type c[2]; - c[1] = std::string::value_type(val); - c[0] = std::string::value_type(val >> 8); + char_type c[2]; + c[1] = char_type(val); + c[0] = char_type(val >> 8); if (c[0] == 0) { - return std::string(1, c[1]); //size, character + return std::string(1, c[1]); // size, character } - return std::string(c, 2); //char buffer, size + return std::string(c, 2); // char buffer, size } }; } From 201fef49c6ff10c59e688127c113ad12674d18cd Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 17:40:43 +0300 Subject: [PATCH 072/108] More standard compliant, use converter only where available --- include/chaiscript/chaiscript_defines.hpp | 4 ++ .../chaiscript/language/chaiscript_parser.hpp | 52 +++++++++++-------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 4049381a..b3fabf2f 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -60,6 +60,10 @@ #define CHAISCRIPT_MODULE_EXPORT extern "C" #endif +#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ >= 5) || defined(CHAISCRIPT_CLANG) +#define CHAISCRIPT_UTF16_UTF32 +#endif + #ifdef _DEBUG #define CHAISCRIPT_DEBUG true #else diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 95b297c1..887400ff 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -15,8 +15,11 @@ #include #include #include + +#if defined(CHAISCRIPT_UTF16_UTF32) #include #include +#endif @@ -62,29 +65,11 @@ namespace chaiscript template struct Char_Parser_Helper { - typedef typename string_type::value_type target_char_type; - - static string_type str_from_ll(long long val) + // common for all implementations + static std::string u8str_from_ll(long long val) { - // make proper UTF-8 string - const std::string intermediate = Char_Parser_Helper::str_from_ll(val); - // prepare converter - std::wstring_convert, target_char_type> converter; - // convert - const string_type result = converter.from_bytes(intermediate); + typedef std::string::value_type char_type; - return result; - } - }; - - // Specialization for char AKA UTF-8 - template<> - struct Char_Parser_Helper - { - typedef std::string::value_type char_type; - - static std::string str_from_ll(long long val) - { char_type c[2]; c[1] = char_type(val); c[0] = char_type(val >> 8); @@ -96,6 +81,31 @@ namespace chaiscript return std::string(c, 2); // char buffer, size } + + static string_type str_from_ll(long long val) + { + typedef typename string_type::value_type target_char_type; +#if defined (CHAISCRIPT_UTF16_UTF32) + // prepare converter + std::wstring_convert, target_char_type> converter; + // convert + return converter.from_bytes(u8str_from_ll(val)); +#else + // no conversion available, just put value as character + return string_type(1, target_char_type(val)); // size, character +#endif + } + }; + + // Specialization for char AKA UTF-8 + template<> + struct Char_Parser_Helper + { + static std::string str_from_ll(long long val) + { + // little SFINAE trick to avoid base class + return Char_Parser_Helper::u8str_from_ll(val); + } }; } From 9e16cc2a7905e2685dc76f6389d18d77b6f2371f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 27 Jun 2016 08:56:03 -0600 Subject: [PATCH 073/108] Simplify and normalize if block code --- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 43 ++++++------------- .../language/chaiscript_optimizer.hpp | 34 +++++++++++++++ .../chaiscript/language/chaiscript_parser.hpp | 12 +++++- 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 73e0784b..7429746c 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -219,7 +219,7 @@ namespace chaiscript std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { @@ -246,7 +246,7 @@ namespace chaiscript ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + m_parser(std::make_unique>>()), m_engine(*m_parser) { if (m_module_paths.empty()) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index ee9eba7d..601ad6f7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -242,6 +242,12 @@ namespace chaiscript { } + Constant_AST_Node(Boxed_Value t_value) + : AST_Node_Impl("", AST_Node_Type::Constant, Parse_Location()), + m_value(std::move(t_value)) + { + } + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override { return m_value; } @@ -823,46 +829,20 @@ namespace chaiscript }; - template - struct If_Init_AST_Node final : AST_Node_Impl { - If_Init_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : - AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) - { - assert(this->children.size() == 3 || this->children.size() == 4); - } - - Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - this->children[0]->eval(t_ss); - if (this->get_bool_condition(this->children[1]->eval(t_ss))) { - return this->children[2]->eval(t_ss); - } else { - if (this->children.size() == 4) { - return this->children[3]->eval(t_ss); - } else { - return void_var(); - } - } - } - }; template struct If_AST_Node final : AST_Node_Impl { If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { - assert(this->children.size() == 2 || this->children.size() == 3); + assert(this->children.size() == 3); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (this->get_bool_condition(this->children[0]->eval(t_ss))) { return this->children[1]->eval(t_ss); } else { - if (this->children.size() == 3) { - return this->children[2]->eval(t_ss); - } else { - return void_var(); - } + return this->children[2]->eval(t_ss); } } }; @@ -1227,10 +1207,11 @@ private: { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ - // It's a no-op, that evaluates to "true" - // the magic-static version of const_var(true) helps us here - return const_var(true); + // It's a no-op, that evaluates to "void" + return val; } + + Boxed_Value val = void_var(); }; template diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index aa4f0a24..991227b9 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -125,6 +125,40 @@ namespace chaiscript { } }; + struct Dead_Code { + template + auto optimize(const eval::AST_Node_Impl_Ptr &node) { + if (node->identifier == AST_Node_Type::Block) + { + std::vector keepers; + const auto num_children = node->children.size(); + keepers.reserve(num_children); + + for (size_t i = 0; i < num_children; ++i) { + auto child = node->children[i]; + if ( (child->identifier != AST_Node_Type::Id + && child->identifier != AST_Node_Type::Constant) + || i == num_children - 1) { + keepers.push_back(i); + } + } + + if (keepers.size() == num_children) { + return node; + } else { + std::vector> new_children; + for (const auto x : keepers) + { + new_children.push_back(node->children[x]); + } + return chaiscript::make_shared, eval::Block_AST_Node>(node->text, node->location, new_children); + } + } else { + return node; + } + } + }; + struct Unused_Return { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 0601d906..48341dd0 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1591,10 +1591,18 @@ namespace chaiscript } } + const auto num_children = m_match_stack.size() - prev_stack_top; + + if ((is_if_init && num_children == 3) + || (!is_if_init && num_children == 2)) { + m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + } + if (!is_if_init) { build_match>(prev_stack_top); } else { - build_match>(prev_stack_top); + build_match>(prev_stack_top+1); + build_match>(prev_stack_top); } } @@ -1682,7 +1690,7 @@ namespace chaiscript { return false; } else { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_shared, eval::Constant_AST_Node>(Boxed_Value(true))); } } From 5642e062e673bc57926ca4aef0371bd8852396c8 Mon Sep 17 00:00:00 2001 From: ELynx Date: Mon, 27 Jun 2016 18:02:50 +0300 Subject: [PATCH 074/108] Fix unittest --- unittests/string_unicode_unicode.chai | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/string_unicode_unicode.chai b/unittests/string_unicode_unicode.chai index 93092167..2a237ed8 100644 --- a/unittests/string_unicode_unicode.chai +++ b/unittests/string_unicode_unicode.chai @@ -1,4 +1,4 @@ -assert_equal('\uc39c', 'Ü') +assert_equal("\uc39c", "Ü") assert_equal("U for \uc39cmlauts", "U for Ümlauts") assert_equal("More \uc39cml\uc3a4\uc3bcts", "More Ümläüts") From a14f1983e8b189c4cfd351ee2135feff02d283f7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 27 Jun 2016 12:56:43 -0600 Subject: [PATCH 075/108] Handle a few more optimization cases --- .../chaiscript/language/chaiscript_eval.hpp | 2 +- .../language/chaiscript_optimizer.hpp | 47 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 601ad6f7..85352f99 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1184,7 +1184,7 @@ private: struct Break_AST_Node final : AST_Node_Impl { Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } - + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Break_Loop(); } diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 991227b9..be58157f 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -137,7 +137,8 @@ namespace chaiscript { for (size_t i = 0; i < num_children; ++i) { auto child = node->children[i]; if ( (child->identifier != AST_Node_Type::Id - && child->identifier != AST_Node_Type::Constant) + && child->identifier != AST_Node_Type::Constant + && child->identifier != AST_Node_Type::Noop) || i == num_children - 1) { keepers.push_back(i); } @@ -245,7 +246,46 @@ namespace chaiscript { template auto optimize(const eval::AST_Node_Impl_Ptr &node) { - if (node->identifier == AST_Node_Type::Binary + if (node->identifier == AST_Node_Type::Prefix + && node->children.size() == 1 + && node->children[0]->identifier == AST_Node_Type::Constant) + { + try { + const auto &oper = node->text; + const auto parsed = Operators::to_operator(oper, true); + const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; + const auto match = oper + node->children[0]->text; + + if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) { + const auto val = Boxed_Number::do_oper(parsed, lhs); + return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); + } else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") { + return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(!boxed_cast(lhs))); + } + } catch (const std::exception &e) { + //failure to fold, that's OK + } + } else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or) + && node->children.size() == 2 + && node->children[0]->identifier == AST_Node_Type::Constant + && node->children[1]->identifier == AST_Node_Type::Constant) + { + try { + const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; + const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; + if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) { + const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text; + const auto val = [lhs_val = boxed_cast(lhs), rhs_val = boxed_cast(rhs), id = node->identifier] { + if (id == AST_Node_Type::Logical_And) { return Boxed_Value(lhs_val && rhs_val); } + else { return Boxed_Value(lhs_val || rhs_val); } + }(); + + return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); + } + } catch (const std::exception &) { + //failure to fold, that's OK + } + } else if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2 && node->children[0]->identifier == AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) @@ -289,8 +329,11 @@ namespace chaiscript { return make_constant(Boxed_Number(arg).get_as()); } else if (fun_name == "long") { return make_constant(Boxed_Number(arg).get_as()); + } else if (fun_name == "size_t") { + return make_constant(Boxed_Number(arg).get_as()); } + } } From a1d90c95f031ebb21ad91472c96a8667461ad60c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 28 Jun 2016 10:34:30 -0600 Subject: [PATCH 076/108] Create DesignGoals.md --- DesignGoals.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 DesignGoals.md diff --git a/DesignGoals.md b/DesignGoals.md new file mode 100644 index 00000000..c9971556 --- /dev/null +++ b/DesignGoals.md @@ -0,0 +1,28 @@ +# Introduction + +This document outlines the principles that drive the development of ChaiScript. ChaiScript does not intent to be the perfect tool for *every* situation, but it does intend to be a good general purpose tool for *most* situations. + +# Goals + +1. Trivially easy to integrate with C++ projects +2. 0 external depenencies +3. "Perfect" integration with C++ + * Direct mapping between ChaiScript objects and C++ objects + * Direct mapping between ChaiScript functions and C++ functions + * Direct mapping between ChaiScript exceptions and C++ exceptions +3. Never surprise the C++ developer + * Object lifetimes managed by the stack + * Familiar syntax to C++ developers +4. Perform "well enough" to not get in the way + + +# Alternatives + +## Sol2 + +If you are looking for the fastest performing scripting language and don't mind Lua, you might want to consider [sol2](https://github.com/ThePhD/sol2). + +## SWIG + +If you are looking for the most flexible solution to be able to support multiple target languages, consider [SWIG](http://swig.org) + From 62639a435963afc65b08ea845b194d5e34901b10 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 29 Jun 2016 16:06:27 -0600 Subject: [PATCH 077/108] Get building with libc++ again --- include/chaiscript/utility/json.hpp | 91 ++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 294901e1..561b93e5 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -47,6 +47,79 @@ class JSON }; private: + + struct QuickFlatMap + { + auto find(const std::string &s) { + return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; }); + } + + auto find(const std::string &s) const { + return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; }); + } + + auto size() const { + return data.size(); + } + + auto begin() const { + return data.begin(); + } + + auto end() const { + return data.end(); + } + + + auto begin() { + return data.begin(); + } + + auto end() { + return data.end(); + } + + + JSON &operator[](const std::string &s) { + const auto itr = find(s); + if (itr != data.end()) { + return itr->second; + } else { + data.emplace_back(s, JSON()); + return data.back().second; + } + } + + JSON &at(const std::string &s) { + const auto itr = find(s); + if (itr != data.end()) { + return itr->second; + } else { + throw std::out_of_range("Unknown key: " + s); + } + } + + const JSON &at(const std::string &s) const { + const auto itr = find(s); + if (itr != data.end()) { + return itr->second; + } else { + throw std::out_of_range("Unknown key: " + s); + } + } + + size_t count(const std::string &s) const { + return (find(s) != data.end())?1:0; + } + + std::vector> data; + + using iterator = decltype(data)::iterator; + using const_iterator = decltype(data)::const_iterator; + + + }; + struct Internal { template auto clone(const std::unique_ptr &ptr) { @@ -100,7 +173,7 @@ class JSON String.reset(); switch( type ) { - case Class::Object: Map = std::make_unique>(); break; + case Class::Object: Map = std::make_unique(); break; case Class::Array: List = std::make_unique>(); break; case Class::String: String = std::make_unique(); break; case Class::Floating: Float = 0.0; break; @@ -116,7 +189,7 @@ class JSON Internal &operator=(Internal &&) = default; std::unique_ptr> List; - std::unique_ptr> Map; + std::unique_ptr Map; std::unique_ptr String; double Float = 0; long Int = 0; @@ -229,7 +302,7 @@ class JSON bool has_key( const std::string &key ) const { if( internal.Type == Class::Object ) { - return internal.Map->find( key ) != internal.Map->end(); + return internal.Map->count(key) != 0; } return false; @@ -274,11 +347,11 @@ class JSON return ok ? internal.Bool : false; } - JSONWrapper> object_range() { + JSONWrapper object_range() { if( internal.Type == Class::Object ) { - return JSONWrapper>( internal.Map.get() ); + return JSONWrapper( internal.Map.get() ); } else { - return JSONWrapper>( nullptr ); + return JSONWrapper( nullptr ); } } @@ -290,11 +363,11 @@ class JSON } } - JSONConstWrapper> object_range() const { + JSONConstWrapper object_range() const { if( internal.Type == Class::Object ) { - return JSONConstWrapper>( internal.Map.get() ); + return JSONConstWrapper( internal.Map.get() ); } else { - return JSONConstWrapper>( nullptr ); + return JSONConstWrapper( nullptr ); } } From e44724c780f27b864cc0ff5d3f1d82fdf327f580 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 29 Jun 2016 17:27:07 -0600 Subject: [PATCH 078/108] Fix debug/clang build issues --- .../chaiscript/dispatchkit/boxed_value.hpp | 4 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 2 +- .../chaiscript/language/chaiscript_common.hpp | 43 ++++++++++--------- .../chaiscript/language/chaiscript_engine.hpp | 8 ++-- .../chaiscript/language/chaiscript_eval.hpp | 8 ++-- .../language/chaiscript_optimizer.hpp | 2 +- .../chaiscript/language/chaiscript_parser.hpp | 8 ++-- 7 files changed, 38 insertions(+), 37 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 53c58678..4d017a4f 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -231,8 +231,8 @@ namespace chaiscript auto pointer_sentinel(std::shared_ptr &ptr) const { struct Sentinel { - Sentinel(std::shared_ptr &ptr, Data &data) - : m_ptr(ptr), m_data(data) + Sentinel(std::shared_ptr &t_ptr, Data &data) + : m_ptr(t_ptr), m_data(data) { } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 2bed224e..2ce9dbad 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1404,7 +1404,7 @@ namespace chaiscript static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint) { if (t_c.size() > t_hint && t_c[t_hint].first == t_key) { - return std::next(t_c.begin(), t_hint); + return std::next(t_c.begin(), static_cast::difference_type>(t_hint)); } else { return find_keyed_value(t_c, t_key); } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 59db2e5f..fb850c83 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -26,30 +26,31 @@ struct AST_Node; namespace chaiscript { - static bool is_reserved_word(const std::string &name) - { - static const std::set m_reserved_words - = {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto", - "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; - return m_reserved_words.count(name) > 0; - } - - static bool valid_object_name(const std::string &name) - { - return name.find("::") == std::string::npos && !is_reserved_word(name); - } - - static void validate_object_name(const std::string &name) - { - if (is_reserved_word(name)) { - throw exception::reserved_word_error(name); + struct Name_Validator { + static bool is_reserved_word(const std::string &name) + { + static const std::set m_reserved_words + = {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto", + "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; + return m_reserved_words.count(name) > 0; } - if (name.find("::") != std::string::npos) { - throw exception::illegal_name_error(name); + static bool valid_object_name(const std::string &name) + { + return name.find("::") == std::string::npos && !is_reserved_word(name); } - } + static void validate_object_name(const std::string &name) + { + if (is_reserved_word(name)) { + throw exception::reserved_word_error(name); + } + + if (name.find("::") != std::string::npos) { + throw exception::illegal_name_error(name); + } + } + }; /// Signature of module entry point that all binary loadable modules must implement. typedef ModulePtr (*Create_Module_Func)(); @@ -577,7 +578,7 @@ namespace chaiscript T &get_tracer() { // to do type check this somehow? - return static_cast(*get_tracer_ptr()); + return *static_cast(get_tracer_ptr()); } protected: diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 7429746c..25413951 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -387,7 +387,7 @@ namespace chaiscript /// \sa Boxed_Value::is_const ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) { - validate_object_name(t_name); + Name_Validator::validate_object_name(t_name); m_engine.add_global_const(t_bv, t_name); return *this; } @@ -399,14 +399,14 @@ namespace chaiscript /// ChaiScript is thread-safe but provides no threading locking mechanism to the script ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name) { - validate_object_name(t_name); + Name_Validator::validate_object_name(t_name); m_engine.add_global(t_bv, t_name); return *this; } ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name) { - validate_object_name(t_name); + Name_Validator::validate_object_name(t_name); m_engine.set_global(t_bv, t_name); return *this; } @@ -506,7 +506,7 @@ namespace chaiscript template ChaiScript &add(const T &t_t, const std::string &t_name) { - validate_object_name(t_name); + Name_Validator::validate_object_name(t_name); m_engine.add(t_t, t_name); return *this; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 85352f99..b3c92806 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -436,7 +436,7 @@ namespace chaiscript Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)), m_oper(Operators::to_operator(this->text)) - { assert(children.size() == 2); } + { assert(this->children.size() == 2); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -1011,7 +1011,7 @@ private: struct Case_AST_Node final : AST_Node_Impl { Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 2); /* how many children does it have? */ } + { assert(this->children.size() == 2); /* how many children does it have? */ } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1026,7 +1026,7 @@ private: struct Default_AST_Node final : AST_Node_Impl { Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 1); } + { assert(this->children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1141,7 +1141,7 @@ private: struct Reference_AST_Node final : AST_Node_Impl { Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) - { assert(children.size() == 1); } + { assert(this->children.size() == 1); } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ Boxed_Value bv; diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index be58157f..f892f567 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -262,7 +262,7 @@ namespace chaiscript { } else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") { return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(!boxed_cast(lhs))); } - } catch (const std::exception &e) { + } catch (const std::exception &) { //failure to fold, that's OK } } else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 8da5c702..3cbd2cd4 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -113,7 +113,7 @@ namespace chaiscript template class ChaiScript_Parser final : public ChaiScript_Parser_Base { - void *get_tracer_ptr() { + void *get_tracer_ptr() override { return &m_tracer; } @@ -339,7 +339,7 @@ namespace chaiscript void validate_object_name(const std::string &name) const { - if (!valid_object_name(name)) { + if (!Name_Validator::valid_object_name(name)) { throw exception::eval_error("Invalid Object Name: " + name, File_Position(m_position.line, m_position.col), *m_filename); } } @@ -2256,8 +2256,8 @@ namespace chaiscript 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); +// default: +// throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_position.line, m_position.col), *m_filename); } } } From 7561aa8828e100e8834e074fffda50e20ddd037a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 29 Jun 2016 21:06:31 -0600 Subject: [PATCH 079/108] Get all unit tests passing --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_stdlib.hpp | 2 ++ unittests/3.x/eval_error.chai | 2 +- unittests/eval_error.chai | 2 +- unittests/fuzzy_tests-2015-07-16.tar.bz2 | Bin 85787 -> 0 bytes unittests/fuzzy_tests-2016-06-29.tar.bz2 | Bin 0 -> 85071 bytes 6 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 unittests/fuzzy_tests-2015-07-16.tar.bz2 create mode 100644 unittests/fuzzy_tests-2016-06-29.tar.bz2 diff --git a/CMakeLists.txt b/CMakeLists.txt index f1b3108d..f3e0c41f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,7 +295,7 @@ if (RUN_FUZZY_TESTS) file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests") execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2 + COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests ) diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index 832439bd..be3875f1 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -16,6 +16,8 @@ #include "chaiscript_defines.hpp" #include "language/chaiscript_common.hpp" +#include "dispatchkit/function_call.hpp" + //#include "dispatchkit/dispatchkit.hpp" #include "dispatchkit/operators.hpp" #include "dispatchkit/bootstrap.hpp" diff --git a/unittests/3.x/eval_error.chai b/unittests/3.x/eval_error.chai index 39a6541e..b5814450 100644 --- a/unittests/3.x/eval_error.chai +++ b/unittests/3.x/eval_error.chai @@ -35,4 +35,4 @@ def while_doing() var f = fun() { while_doing(); } -assert_equal(get_eval_error(f).call_stack.size(), 16) +assert_true(get_eval_error(f).call_stack.size() <= 16) diff --git a/unittests/eval_error.chai b/unittests/eval_error.chai index fde7847b..756cd15c 100644 --- a/unittests/eval_error.chai +++ b/unittests/eval_error.chai @@ -35,4 +35,4 @@ def while_doing() auto f = fun() { while_doing(); } -assert_equal(get_eval_error(f).call_stack.size(), 16) +assert_true(get_eval_error(f).call_stack.size() <= 16) diff --git a/unittests/fuzzy_tests-2015-07-16.tar.bz2 b/unittests/fuzzy_tests-2015-07-16.tar.bz2 deleted file mode 100644 index 9768b8e44cf430b648631185558eafa1c3cb0e86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85787 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 y#N#RfDdq(3epHbpz4xHf<+>KlbsOb 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 literal 0 HcmV?d00001 From 4e6e63ab5d9537c6c9129a12710fa79145c8684d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 27 Aug 2016 10:33:44 -0600 Subject: [PATCH 080/108] Cleanups and split up into _basic options --- CMakeLists.txt | 25 +-- include/chaiscript/chaiscript.hpp | 26 ++- include/chaiscript/chaiscript_basic.hpp | 39 +++++ include/chaiscript/chaiscript_stdlib.hpp | 2 - include/chaiscript/dispatchkit/any.hpp | 10 +- .../chaiscript/dispatchkit/bad_boxed_cast.hpp | 4 +- include/chaiscript/dispatchkit/bootstrap.hpp | 19 +-- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 28 ++-- .../chaiscript/dispatchkit/boxed_value.hpp | 23 ++- .../chaiscript/dispatchkit/dispatchkit.hpp | 63 +++++-- .../chaiscript/dispatchkit/short_alloc.hpp | 157 ++++++++++++++++++ .../chaiscript/language/chaiscript_engine.hpp | 43 ++--- .../language/chaiscript_optimizer.hpp | 2 + .../chaiscript/language/chaiscript_parser.hpp | 9 +- samples/factory.cpp | 3 +- samples/fun_call_performance.cpp | 3 +- samples/inheritance.cpp | 3 +- samples/memory_leak_test.cpp | 10 +- samples/test_num_exceptions.cpp | 3 +- ...tdlib.cpp => chaiscript_stdlib_module.cpp} | 0 src/main.cpp | 9 +- src/stl_extra.cpp | 2 +- src/test_module.cpp | 2 +- static_libs/chaiscript_parser.cpp | 8 + static_libs/chaiscript_parser.hpp | 13 ++ static_libs/chaiscript_stdlib.cpp | 8 + static_libs/chaiscript_stdlib.hpp | 11 ++ unittests/c_linkage_test.cpp | 7 +- unittests/compiled_tests.cpp | 66 ++++---- unittests/integer_literal_test.cpp | 7 +- unittests/multifile_test_chai.cpp | 6 +- unittests/multifile_test_chai.hpp | 6 +- unittests/multifile_test_main.cpp | 4 +- unittests/multifile_test_module.cpp | 2 +- unittests/multifile_test_module.hpp | 2 +- unittests/multithreaded_test.cpp | 10 +- 36 files changed, 450 insertions(+), 185 deletions(-) create mode 100644 include/chaiscript/chaiscript_basic.hpp create mode 100644 include/chaiscript/dispatchkit/short_alloc.hpp rename src/{chaiscript_stdlib.cpp => chaiscript_stdlib_module.cpp} (100%) create mode 100644 static_libs/chaiscript_parser.cpp create mode 100644 static_libs/chaiscript_parser.hpp create mode 100644 static_libs/chaiscript_stdlib.cpp create mode 100644 static_libs/chaiscript_stdlib.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f3e0c41f..fbba252b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,27 +249,30 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}") +add_library(stdlib STATIC static_libs/chaiscript_stdlib.cpp) +add_library(parser STATIC static_libs/chaiscript_parser.cpp) -add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib.cpp) +add_library(chaiscript_stdlib-${CHAI_VERSION} MODULE src/chaiscript_stdlib_module.cpp) target_link_libraries(chaiscript_stdlib-${CHAI_VERSION} ${LIBS} ${CMAKE_THREAD_LIBS_INIT}) +set(CHAISCRIPT_LIBS stdlib parser) + add_executable(chai src/main.cpp ${Chai_INCLUDES}) -target_link_libraries(chai ${LIBS}) -add_dependencies(chai chaiscript_stdlib-${CHAI_VERSION}) +target_link_libraries(chai ${LIBS} ${CHAISCRIPT_LIBS}) if(BUILD_SAMPLES) add_executable(example samples/example.cpp) target_link_libraries(example ${LIBS}) add_executable(test_num_exceptions samples/test_num_exceptions.cpp) - target_link_libraries(test_num_exceptions ${LIBS}) + target_link_libraries(test_num_exceptions ${LIBS} ${CHAISCRIPT_LIBS}) add_executable(memory_leak_test samples/memory_leak_test.cpp) - target_link_libraries(memory_leak_test ${LIBS}) + target_link_libraries(memory_leak_test ${LIBS} ${CHAISCRIPT_LIBS}) add_executable(inheritance samples/inheritance.cpp) - target_link_libraries(inheritance ${LIBS}) + target_link_libraries(inheritance ${LIBS} ${CHAISCRIPT_LIBS}) add_executable(factory samples/factory.cpp) - target_link_libraries(factory ${LIBS}) + target_link_libraries(factory ${LIBS} ${CHAISCRIPT_LIBS}) add_executable(fun_call_performance samples/fun_call_performance.cpp) - target_link_libraries(fun_call_performance ${LIBS}) + target_link_libraries(fun_call_performance ${LIBS} ${CHAISCRIPT_LIBS}) endif() @@ -421,7 +424,7 @@ if(BUILD_TESTING) if(NOT UNIT_TEST_LIGHT) add_executable(compiled_tests unittests/compiled_tests.cpp) - target_link_libraries(compiled_tests ${LIBS}) + target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS}) ADD_CATCH_TESTS(compiled_tests) @@ -434,11 +437,11 @@ if(BUILD_TESTING) add_test(NAME Type_Info_Test COMMAND type_info_test) add_executable(c_linkage_test unittests/c_linkage_test.cpp) - target_link_libraries(c_linkage_test ${LIBS}) + target_link_libraries(c_linkage_test ${LIBS} ${CHAISCRIPT_LIBS}) add_test(NAME C_Linkage_Test COMMAND c_linkage_test) add_executable(integer_literal_test unittests/integer_literal_test.cpp) - target_link_libraries(integer_literal_test ${LIBS}) + target_link_libraries(integer_literal_test ${LIBS} ${CHAISCRIPT_LIBS}) add_test(NAME Integer_Literal_Test COMMAND integer_literal_test) if(MULTITHREAD_SUPPORT_ENABLED) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 43d3b4f6..2df9535c 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -816,16 +816,24 @@ /// @namespace chaiscript::detail /// @brief Classes and functions reserved for internal use. Items in this namespace are not supported. -#include "chaiscript_defines.hpp" - -#include "dispatchkit/dispatchkit.hpp" -#include "dispatchkit/function_call.hpp" -#include "dispatchkit/dynamic_object.hpp" -#include "dispatchkit/boxed_number.hpp" - -#include "language/chaiscript_eval.hpp" -#include "language/chaiscript_engine.hpp" +#include "chaiscript_basic.hpp" +#include "language/chaiscript_parser.hpp" +#include "chaiscript_stdlib.hpp" +namespace chaiscript +{ + class ChaiScript : public ChaiScript_Basic + { + ChaiScript(std::vector t_modulepaths = {}, + std::vector t_usepaths = {}) + : ChaiScript_Basic( + chaiscript::Std_Lib::library(), + std::make_unique>(), + t_modulepaths, t_usepaths) + { + } + }; +} #endif /* CHAISCRIPT_HPP_ */ diff --git a/include/chaiscript/chaiscript_basic.hpp b/include/chaiscript/chaiscript_basic.hpp new file mode 100644 index 00000000..28f26d79 --- /dev/null +++ b/include/chaiscript/chaiscript_basic.hpp @@ -0,0 +1,39 @@ +// 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_BASIC_HPP_ +#define CHAISCRIPT_BASIC_HPP_ + +#include "chaiscript_defines.hpp" + +#include "dispatchkit/dispatchkit.hpp" +#include "dispatchkit/function_call.hpp" +#include "dispatchkit/dynamic_object.hpp" +#include "dispatchkit/boxed_number.hpp" + +#include "language/chaiscript_eval.hpp" +#include "language/chaiscript_engine.hpp" + +// This file includes all of the basic requirements for ChaiScript, +// to use, you might do something like: +// + +/* + +#include "chaiscript_stdlib.hpp" +#include "language/chaiscript_parser.hpp" + +ChaiScript_Basic chai( + chaiscript::Std_Lib::library(), + std::make_unique>()); + +*/ + +// If you want a fully packaged ready to go ChaiScript, use chaiscript.hpp + + + +#endif /* CHAISCRIPT_BASIC_HPP_ */ diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index be3875f1..ed56b234 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -44,8 +44,6 @@ namespace chaiscript static ModulePtr library() { - // using namespace bootstrap; - auto lib = std::make_shared(); bootstrap::Bootstrap::bootstrap(*lib); diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index e4920319..4d47b88f 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -21,10 +21,7 @@ namespace chaiscript { class bad_any_cast : public std::bad_cast { public: - bad_any_cast() noexcept - : m_what("bad any cast") - { - } + bad_any_cast() = default; bad_any_cast(const bad_any_cast &) = default; @@ -37,7 +34,7 @@ namespace chaiscript { } private: - std::string m_what; + std::string m_what = "bad any cast"; }; } @@ -151,8 +148,7 @@ namespace chaiscript { const std::type_info & type() const { - if (m_data) - { + if (m_data) { return m_data->type(); } else { return typeid(void); diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index ee2be60f..d0b7c94b 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -41,7 +41,7 @@ namespace chaiscript } explicit bad_boxed_cast(std::string t_what) noexcept - : to(nullptr), m_what(std::move(t_what)) + : m_what(std::move(t_what)) { } @@ -55,7 +55,7 @@ namespace chaiscript } Type_Info from; ///< Type_Info contained in the Boxed_Value - const std::type_info *to; ///< std::type_info of the desired (but failed) result type + const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type private: std::string m_what; diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index c689ad81..dcd65d78 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -15,18 +15,6 @@ namespace chaiscript /// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types namespace bootstrap { - namespace detail - { - /// \brief Constructs a new POD value object from a Boxed_Number - /// \param[in] v Boxed_Number to copy into the new object - /// \returns The newly created object. - template - std::shared_ptr construct_pod(const Boxed_Number &v) - { - return std::make_shared(v.get_as()); - } - } - template::value>::type > void array(const std::string &type, Module& m) { @@ -110,7 +98,7 @@ namespace chaiscript template void construct_pod(const std::string &type, Module& m) { - m.add(fun(&detail::construct_pod), type); + m.add(fun([](const Boxed_Number &bn){ return bn.get_as(); }), type); } @@ -161,15 +149,14 @@ namespace chaiscript /// for handling of Proxy_Function object (that is, /// function variables. template - std::shared_ptr shared_ptr_clone(const std::shared_ptr &p) + auto shared_ptr_clone(const std::shared_ptr &p) { return p; } /// Specific version of shared_ptr_clone just for Proxy_Functions template - std::shared_ptr::type> - shared_ptr_unconst_clone(const std::shared_ptr::type> &p) + auto shared_ptr_unconst_clone(const std::shared_ptr::type> &p) { return std::const_pointer_cast::type>(p); } diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index b9e0a9f5..6f59ff07 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -41,7 +41,6 @@ namespace chaiscript struct Bidir_Range { typedef Container container_type; - typedef typename std::iterator_traits::reference reference_type; Bidir_Range(Container &c) : m_begin(c.begin()), m_end(c.end()) @@ -71,16 +70,16 @@ namespace chaiscript --m_end; } - reference_type front() const + decltype(auto) front() const { if (empty()) { throw std::range_error("Range empty"); } - return *m_begin; + return (*m_begin); } - reference_type back() const + decltype(auto) back() const { if (empty()) { @@ -88,7 +87,7 @@ namespace chaiscript } typename Container::iterator pos = m_end; --pos; - return *(pos); + return (*(pos)); } typename Container::iterator m_begin; @@ -129,24 +128,24 @@ namespace chaiscript --m_end; } - const_reference_type front() const + decltype(auto) front() const { if (empty()) { throw std::range_error("Range empty"); } - return *m_begin; + return (*m_begin); } - const_reference_type back() const + decltype(auto) back() const { if (empty()) { throw std::range_error("Range empty"); } - typename Container::const_iterator pos = m_end; + auto pos = m_end; --pos; - return *(pos); + return (*(pos)); } typename Container::const_iterator m_begin; @@ -482,12 +481,8 @@ namespace chaiscript { m.add(user_type(), type); - - typename PairType::first_type PairType::* f = &PairType::first; - typename PairType::second_type PairType::* s = &PairType::second; - - m.add(fun(f), "first"); - m.add(fun(s), "second"); + m.add(fun(&PairType::first), "first"); + m.add(fun(&PairType::second), "second"); basic_constructors(type, m); m.add(constructor(), type); @@ -605,7 +600,6 @@ namespace chaiscript } - /// hopefully working List type /// http://www.sgi.com/tech/stl/List.html template void list_type(const std::string &type, Module& m) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 4d017a4f..70a1b967 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -77,7 +77,7 @@ namespace chaiscript struct Object_Data { - static std::shared_ptr get(Boxed_Value::Void_Type, bool t_return_value) + static auto get(Boxed_Value::Void_Type, bool t_return_value) { return std::make_shared( detail::Get_Type_Info::get(), @@ -89,13 +89,13 @@ namespace chaiscript } template - static std::shared_ptr get(const std::shared_ptr *obj, bool t_return_value) + static auto get(const std::shared_ptr *obj, bool t_return_value) { return get(*obj, t_return_value); } template - static std::shared_ptr get(const std::shared_ptr &obj, bool t_return_value) + static auto get(const std::shared_ptr &obj, bool t_return_value) { return std::make_shared( detail::Get_Type_Info::get(), @@ -107,7 +107,7 @@ namespace chaiscript } template - static std::shared_ptr get(std::shared_ptr &&obj, bool t_return_value) + static auto get(std::shared_ptr &&obj, bool t_return_value) { auto ptr = obj.get(); return std::make_shared( @@ -120,20 +120,20 @@ namespace chaiscript } template - static std::shared_ptr get(T *t, bool t_return_value) + static auto get(T *t, bool t_return_value) { return get(std::ref(*t), t_return_value); } template - static std::shared_ptr get(const T *t, bool t_return_value) + static auto get(const T *t, bool t_return_value) { return get(std::cref(*t), t_return_value); } template - static std::shared_ptr get(std::reference_wrapper obj, bool t_return_value) + static auto get(std::reference_wrapper obj, bool t_return_value) { auto p = &obj.get(); return std::make_shared( @@ -146,7 +146,7 @@ namespace chaiscript } template - static std::shared_ptr get(T t, bool t_return_value) + static auto get(T t, bool t_return_value) { auto p = std::make_shared(std::move(t)); auto ptr = p.get(); @@ -182,10 +182,7 @@ namespace chaiscript } /// Unknown-type constructor - Boxed_Value() - : m_data(Object_Data::get()) - { - } + Boxed_Value() = default; Boxed_Value(Boxed_Value&&) = default; Boxed_Value& operator=(Boxed_Value&&) = default; @@ -349,7 +346,7 @@ namespace chaiscript : m_data(t_data) { } - std::shared_ptr m_data; + std::shared_ptr m_data = Object_Data::get(); }; /// @brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 2ce9dbad..0c9e0be1 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -8,7 +8,6 @@ #define CHAISCRIPT_DISPATCHKIT_HPP_ #include -#include #include #include #include @@ -31,6 +30,7 @@ #include "proxy_constructors.hpp" #include "proxy_functions.hpp" #include "type_info.hpp" +#include "short_alloc.hpp" namespace chaiscript { class Boxed_Number; @@ -376,20 +376,55 @@ namespace chaiscript { struct Stack_Holder { - typedef std::vector> Scope; - typedef std::vector StackData; + //template + // using SmallVector = std::vector>; + + template + using SmallVector = std::vector; + + + typedef SmallVector> Scope; + typedef SmallVector StackData; + typedef SmallVector Stacks; + typedef SmallVector Call_Param_List; + typedef SmallVector Call_Params; Stack_Holder() { - stacks.reserve(2); - stacks.emplace_back(1); - call_params.emplace_back(); - call_params.back().reserve(2); + push_stack(); + push_call_params(); } - std::vector stacks; + void push_stack_data() + { + stacks.back().emplace_back(); +// stacks.back().emplace_back(Scope(scope_allocator)); + } + + void push_stack() + { + stacks.emplace_back(1); +// stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator)); + } + + void push_call_params() + { + call_params.emplace_back(); +// call_params.emplace_back(Call_Param_List(call_param_list_allocator)); + } + + //Scope::allocator_type::arena_type scope_allocator; + //StackData::allocator_type::arena_type stack_data_allocator; + //Stacks::allocator_type::arena_type stacks_allocator; + //Call_Param_List::allocator_type::arena_type call_param_list_allocator; + //Call_Params::allocator_type::arena_type call_params_allocator; + +// Stacks stacks = Stacks(stacks_allocator); +// Call_Params call_params = Call_Params(call_params_allocator); + + Stacks stacks; + Call_Params call_params; - std::vector> call_params; int call_depth = 0; }; @@ -401,7 +436,7 @@ namespace chaiscript public: typedef std::map Type_Name_Map; typedef std::vector> Scope; - typedef std::vector StackData; + typedef Stack_Holder::StackData StackData; struct State { @@ -585,8 +620,8 @@ namespace chaiscript /// Adds a new scope to the stack static void new_scope(Stack_Holder &t_holder) { - get_stack_data(t_holder).emplace_back(); - t_holder.call_params.emplace_back(); + t_holder.push_stack_data(); + t_holder.push_call_params(); } /// Pops the current scope from the stack @@ -605,7 +640,7 @@ namespace chaiscript static void new_stack(Stack_Holder &t_holder) { // add a new Stack with 1 element - t_holder.stacks.emplace_back(1); + t_holder.push_stack(); } static void pop_stack(Stack_Holder &t_holder) @@ -817,7 +852,7 @@ namespace chaiscript { auto &stack = get_stack_data(); auto &scope = stack.front(); - scope = std::vector>(t_locals.begin(), t_locals.end()); + scope.assign(t_locals.begin(), t_locals.end()); } diff --git a/include/chaiscript/dispatchkit/short_alloc.hpp b/include/chaiscript/dispatchkit/short_alloc.hpp new file mode 100644 index 00000000..3cb04223 --- /dev/null +++ b/include/chaiscript/dispatchkit/short_alloc.hpp @@ -0,0 +1,157 @@ +#ifndef SHORT_ALLOC_H +#define SHORT_ALLOC_H + +// The MIT License (MIT) +// +// Copyright (c) 2015 Howard Hinnant +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include +#include + +template +class arena +{ + alignas(alignment) char buf_[N]; + char* ptr_; + +public: + ~arena() {ptr_ = nullptr;} + arena() noexcept : ptr_(buf_) {} + arena(const arena&) = delete; + arena& operator=(const arena&) = delete; + + template char* allocate(std::size_t n); + void deallocate(char* p, std::size_t n) noexcept; + + static constexpr std::size_t size() noexcept {return N;} + std::size_t used() const noexcept {return static_cast(ptr_ - buf_);} + void reset() noexcept {ptr_ = buf_;} + +private: + static + std::size_t + align_up(std::size_t n) noexcept + {return (n + (alignment-1)) & ~(alignment-1);} + + bool + pointer_in_buffer(char* p) noexcept + {return buf_ <= p && p <= buf_ + N;} +}; + +template +template +char* +arena::allocate(std::size_t n) +{ + static_assert(ReqAlign <= alignment, "alignment is too small for this arena"); + assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena"); + auto const aligned_n = align_up(n); + if (static_cast(buf_ + N - ptr_) >= aligned_n) + { + char* r = ptr_; + ptr_ += aligned_n; + return r; + } + + static_assert(alignment <= alignof(std::max_align_t), "you've chosen an " + "alignment that is larger than alignof(std::max_align_t), and " + "cannot be guaranteed by normal operator new"); + return static_cast(::operator new(n)); +} + +template +void +arena::deallocate(char* p, std::size_t n) noexcept +{ + assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena"); + if (pointer_in_buffer(p)) + { + n = align_up(n); + if (p + n == ptr_) + ptr_ = p; + } + else + ::operator delete(p); +} + +template +class short_alloc +{ +public: + using value_type = T; + static auto constexpr alignment = Align; + static auto constexpr size = N; + using arena_type = arena; + +private: + arena_type& a_; + +public: + short_alloc(const short_alloc&) = default; + short_alloc& operator=(const short_alloc&) = delete; + + short_alloc(arena_type& a) noexcept : a_(a) + { + static_assert(size % alignment == 0, + "size N needs to be a multiple of alignment Align"); + } + template + short_alloc(const short_alloc& a) noexcept + : a_(a.a_) {} + + template struct rebind {using other = short_alloc<_Up, N, alignment>;}; + + T* allocate(std::size_t n) + { + return reinterpret_cast(a_.template allocate(n*sizeof(T))); + } + void deallocate(T* p, std::size_t n) noexcept + { + a_.deallocate(reinterpret_cast(p), n*sizeof(T)); + } + + template + friend + bool + operator==(const short_alloc& x, const short_alloc& y) noexcept; + + template friend class short_alloc; +}; + +template +inline +bool +operator==(const short_alloc& x, const short_alloc& y) noexcept +{ + return N == M && A1 == A2 && &x.a_ == &y.a_; +} + +template +inline +bool +operator!=(const short_alloc& x, const short_alloc& y) noexcept +{ + return !(x == y); +} + +#endif // SHORT_ALLOC_HPP + diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 25413951..003af4e2 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "../chaiscript_defines.hpp" #include "../chaiscript_threading.hpp" @@ -46,7 +47,6 @@ #include "../dispatchkit/exception_specification.hpp" -#include "chaiscript_parser.hpp" namespace chaiscript { @@ -58,7 +58,7 @@ namespace chaiscript /// \brief The main object that the ChaiScript user will use. - class ChaiScript { + class ChaiScript_Basic { mutable chaiscript::detail::threading::shared_mutex m_mutex; mutable chaiscript::detail::threading::recursive_mutex m_use_mutex; @@ -215,13 +215,14 @@ namespace chaiscript /// \param[in] t_lib Standard library to apply to this ChaiScript instance /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file - ChaiScript(const ModulePtr &t_lib, - std::vector t_modulepaths = std::vector(), - std::vector t_usepaths = std::vector()) - : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + ChaiScript_Basic(const ModulePtr &t_lib, + std::unique_ptr &&parser, + std::vector t_modulepaths = {}, + std::vector t_usepaths = {}) + : m_module_paths(std::move(t_modulepaths)), + m_use_paths(std::move(t_usepaths)), + m_parser(std::move(parser)), m_engine(*m_parser) - { if (m_module_paths.empty()) { @@ -243,10 +244,12 @@ namespace chaiscript /// /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file - ChaiScript( std::vector t_modulepaths = std::vector(), - std::vector t_usepaths = std::vector()) - : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), - m_parser(std::make_unique>>()), + ChaiScript_Basic(std::unique_ptr &&parser, + std::vector t_modulepaths = {}, + std::vector t_usepaths = {}) + : m_module_paths(std::move(t_modulepaths)), + m_use_paths(std::move(t_usepaths)), + m_parser(std::move(parser)), m_engine(*m_parser) { if (m_module_paths.empty()) @@ -265,14 +268,14 @@ namespace chaiscript union cast_union { - Boxed_Value (ChaiScript::*in_ptr)(const std::string&); + Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&); void *out_ptr; }; Dl_info rInfo; memset( &rInfo, 0, sizeof(rInfo) ); cast_union u; - u.in_ptr = &ChaiScript::use; + u.in_ptr = &ChaiScript_Basic::use; if ( dladdr(static_cast(u.out_ptr), &rInfo) && rInfo.dli_fname ) { std::string dllpath(rInfo.dli_fname); const size_t lastslash = dllpath.rfind('/'); @@ -385,7 +388,7 @@ namespace chaiscript /// \param[in] t_name Name of the value to add /// \throw chaiscript::exception::global_non_const If t_bv is not a constant object /// \sa Boxed_Value::is_const - ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) + ChaiScript_Basic &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) { Name_Validator::validate_object_name(t_name); m_engine.add_global_const(t_bv, t_name); @@ -397,14 +400,14 @@ namespace chaiscript /// \param[in] t_name Name of the value to add /// \warning The user is responsible for making sure the object is thread-safe if necessary /// ChaiScript is thread-safe but provides no threading locking mechanism to the script - ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name) + ChaiScript_Basic &add_global(const Boxed_Value &t_bv, const std::string &t_name) { Name_Validator::validate_object_name(t_name); m_engine.add_global(t_bv, t_name); return *this; } - ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name) + ChaiScript_Basic &set_global(const Boxed_Value &t_bv, const std::string &t_name) { Name_Validator::validate_object_name(t_name); m_engine.set_global(t_bv, t_name); @@ -504,7 +507,7 @@ namespace chaiscript /// /// \sa \ref adding_items template - ChaiScript &add(const T &t_t, const std::string &t_name) + ChaiScript_Basic &add(const T &t_t, const std::string &t_name) { Name_Validator::validate_object_name(t_name); m_engine.add(t_t, t_name); @@ -520,7 +523,7 @@ namespace chaiscript /// chaiscript::ChaiScript chai; /// chai.add(chaiscript::base_class()); /// \endcode - ChaiScript &add(const Type_Conversion &d) + ChaiScript_Basic &add(const Type_Conversion &d) { m_engine.add(d); return *this; @@ -529,7 +532,7 @@ namespace chaiscript /// \brief Adds all elements of a module to ChaiScript runtime /// \param[in] t_p The module to add. /// \sa chaiscript::Module - ChaiScript &add(const ModulePtr &t_p) + ChaiScript_Basic &add(const ModulePtr &t_p) { t_p->apply(*this, this->get_eval_engine()); return *this; diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index f892f567..9b406338 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -417,6 +417,8 @@ namespace chaiscript { } }; + typedef Optimizer Optimizer_Default; } } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 3cbd2cd4..b8f23bdb 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -16,10 +16,6 @@ #include #include -#if defined(CHAISCRIPT_UTF16_UTF32) -#include -#include -#endif @@ -28,6 +24,11 @@ #include "chaiscript_optimizer.hpp" #include "chaiscript_tracer.hpp" +#if defined(CHAISCRIPT_UTF16_UTF32) +#include +#include +#endif + #if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min) #define CHAISCRIPT_PUSHED_MIN_MAX #pragma push_macro("max") // Why Microsoft? why? This is worse than bad diff --git a/samples/factory.cpp b/samples/factory.cpp index ac8eb476..976868b5 100644 --- a/samples/factory.cpp +++ b/samples/factory.cpp @@ -1,5 +1,4 @@ #include -#include class Entity { @@ -57,7 +56,7 @@ class Factory int main() { - chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); + chaiscript::ChaiScript chai; chai.add(chaiscript::fun(&Entity::width), "width"); chai.add(chaiscript::fun(&Entity::height), "height"); diff --git a/samples/fun_call_performance.cpp b/samples/fun_call_performance.cpp index 6b91fed9..90fd7d94 100644 --- a/samples/fun_call_performance.cpp +++ b/samples/fun_call_performance.cpp @@ -13,7 +13,6 @@ #endif #include -#include #ifdef READLINE_AVAILABLE #include @@ -291,7 +290,7 @@ int main(int argc, char *argv[]) } //chaiscript::ChaiScript chai(modulepaths, usepaths); - chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths); + chaiscript::ChaiScript chai(usepaths); chai.add(chaiscript::fun(&myexit), "exit"); chai.add(chaiscript::fun(&myexit), "quit"); diff --git a/samples/inheritance.cpp b/samples/inheritance.cpp index 133feb95..aba619a4 100644 --- a/samples/inheritance.cpp +++ b/samples/inheritance.cpp @@ -1,5 +1,4 @@ #include -#include class BaseClass { @@ -70,7 +69,7 @@ class ChaiScriptDerived : public BaseClass int main() { - chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); + chaiscript::ChaiScript chai; chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething"); chai.add(chaiscript::fun(&BaseClass::setValue), "setValue"); chai.add(chaiscript::fun(&BaseClass::getValue), "getValue"); diff --git a/samples/memory_leak_test.cpp b/samples/memory_leak_test.cpp index 13afbb45..513656b7 100644 --- a/samples/memory_leak_test.cpp +++ b/samples/memory_leak_test.cpp @@ -1,7 +1,6 @@ #include #include -#include #ifdef READLINE_AVAILABLE #include @@ -32,16 +31,9 @@ void function(void) class test { chaiscript::ChaiScript chai; - chaiscript::ChaiScript::State backupState; + chaiscript::ChaiScript::State backupState = chai.get_state(); public: - test() - : chai(chaiscript::Std_Lib::library()) - { - backupState = chai.get_state(); - } - ~test(){} - void ResetState() { chai.set_state(backupState); diff --git a/samples/test_num_exceptions.cpp b/samples/test_num_exceptions.cpp index 3a35fb7c..8347c4a0 100644 --- a/samples/test_num_exceptions.cpp +++ b/samples/test_num_exceptions.cpp @@ -1,11 +1,10 @@ #include -#include #include #include int main( int /*argc*/ , char * /*argv*/[] ) { - chaiscript::ChaiScript ch( chaiscript::Std_Lib::library( ) ); + chaiscript::ChaiScript ch; try diff --git a/src/chaiscript_stdlib.cpp b/src/chaiscript_stdlib_module.cpp similarity index 100% rename from src/chaiscript_stdlib.cpp rename to src/chaiscript_stdlib_module.cpp diff --git a/src/main.cpp b/src/main.cpp index 7ac9b2b6..4e73389b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,10 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#include +#include +#include "../static_libs/chaiscript_parser.hpp" +#include "../static_libs/chaiscript_stdlib.hpp" + #ifdef READLINE_AVAILABLE #include @@ -217,7 +220,7 @@ void myexit(int return_val) { exit(return_val); } -void interactive(chaiscript::ChaiScript& chai) +void interactive(chaiscript::ChaiScript_Basic& chai) { using_history(); @@ -288,7 +291,7 @@ int main(int argc, char *argv[]) modulepaths.push_back(modulepath); } - chaiscript::ChaiScript chai(modulepaths,usepaths); + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(),modulepaths,usepaths); chai.add(chaiscript::fun(&myexit), "exit"); chai.add(chaiscript::fun(&myexit), "quit"); diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index d3ee3754..07bc0609 100644 --- a/src/stl_extra.cpp +++ b/src/stl_extra.cpp @@ -4,7 +4,7 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com -#include +#include #include #include #include diff --git a/src/test_module.cpp b/src/test_module.cpp index 731e3271..fcb255e5 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -1,5 +1,5 @@ -#include +#include #include #include diff --git a/static_libs/chaiscript_parser.cpp b/static_libs/chaiscript_parser.cpp new file mode 100644 index 00000000..15199bf3 --- /dev/null +++ b/static_libs/chaiscript_parser.cpp @@ -0,0 +1,8 @@ +#include "../include/chaiscript/language/chaiscript_parser.hpp" +#include "chaiscript_parser.hpp" + +std::unique_ptr create_chaiscript_parser() +{ + return std::make_unique>(); +} + diff --git a/static_libs/chaiscript_parser.hpp b/static_libs/chaiscript_parser.hpp new file mode 100644 index 00000000..6086749d --- /dev/null +++ b/static_libs/chaiscript_parser.hpp @@ -0,0 +1,13 @@ + +#ifndef CHAISCRIPT_PARSER_LIB +#define CHAISCRIPT_PARSER_LIB + +namespace chaiscript { + namespace parser { + class ChaiScript_Parser_Base; + } +} + +std::unique_ptr create_chaiscript_parser(); + +#endif diff --git a/static_libs/chaiscript_stdlib.cpp b/static_libs/chaiscript_stdlib.cpp new file mode 100644 index 00000000..c786ece8 --- /dev/null +++ b/static_libs/chaiscript_stdlib.cpp @@ -0,0 +1,8 @@ +#include "../include/chaiscript/chaiscript_stdlib.hpp" +#include "chaiscript_stdlib.hpp" + +std::shared_ptr create_chaiscript_stdlib() +{ + return chaiscript::Std_Lib::library(); +} + diff --git a/static_libs/chaiscript_stdlib.hpp b/static_libs/chaiscript_stdlib.hpp new file mode 100644 index 00000000..3bd0d83a --- /dev/null +++ b/static_libs/chaiscript_stdlib.hpp @@ -0,0 +1,11 @@ + +#ifndef CHAISCRIPT_STDLIB +#define CHAISCRIPT_STDLIB + +namespace chaiscript { + class Module; +} + +std::shared_ptr create_chaiscript_stdlib(); + +#endif diff --git a/unittests/c_linkage_test.cpp b/unittests/c_linkage_test.cpp index 28ec17aa..180686af 100644 --- a/unittests/c_linkage_test.cpp +++ b/unittests/c_linkage_test.cpp @@ -1,4 +1,6 @@ -#include +#include +#include "../static_libs/chaiscript_parser.hpp" +#include "../static_libs/chaiscript_stdlib.hpp" extern "C" @@ -11,8 +13,7 @@ extern "C" int main() { - - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::fun(&do_something), "do_something"); return chai.eval("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE; diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index edc62e2d..61e642a6 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -15,10 +15,12 @@ #endif -#include +#include #include #include +#include "../static_libs/chaiscript_parser.hpp" +#include "../static_libs/chaiscript_stdlib.hpp" @@ -34,7 +36,7 @@ TEST_CASE("C++11 Lambdas Can Be Registered") // We cannot deduce the type of a lambda expression, you must either wrap it // in an std::function or provide the signature - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::fun([]()->std::string { return "hello"; } ), "f1"); @@ -49,7 +51,7 @@ TEST_CASE("C++11 Lambdas Can Be Registered") // dynamic_object tests TEST_CASE("Dynamic_Object attributes can be shared with C++") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai("attr bob::z; def bob::bob() { this.z = 10 }; auto x = bob()"); @@ -77,7 +79,7 @@ TEST_CASE("Dynamic_Object attributes can be shared with C++") TEST_CASE("Function objects can be created from chaiscript functions") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.eval("def func() { print(\"Hello World\"); } "); @@ -91,7 +93,7 @@ TEST_CASE("Function objects can be created from chaiscript functions") TEST_CASE("ChaiScript can be created and destroyed on heap") { - chaiscript::ChaiScript *chai = new chaiscript::ChaiScript(); + auto *chai = new chaiscript::ChaiScript_Basic(create_chaiscript_stdlib(),create_chaiscript_parser()); delete chai; } @@ -123,7 +125,7 @@ void arithmetic_conversions_f_func_return(const std::function()); @@ -189,7 +191,7 @@ TEST_CASE("Throw an int") TEST_CASE("Throw int or double") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); try { chai.eval("throw(1.0)", chaiscript::exception_specification()); @@ -201,7 +203,7 @@ TEST_CASE("Throw int or double") TEST_CASE("Throw a runtime_error") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); try { chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification()); @@ -221,7 +223,7 @@ TEST_CASE("Throw a runtime_error") TEST_CASE("Throw unhandled type") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); try { chai.eval("throw(\"error\")", chaiscript::exception_specification()); @@ -250,7 +252,7 @@ int expected_eval_errors_test_one(const int &) TEST_CASE("No unexpected exceptions leak") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::fun(&expected_eval_errors_test_one), "test_fun"); chai.eval("def guard_fun(i) : i.get_type_info().is_type_arithmetic() {} "); @@ -313,7 +315,7 @@ int function_ordering_test_two(int &) TEST_CASE("Function ordering") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.eval("def test_fun(x) { return 3; }"); chai.eval("def test_fun(x) : x == \"hi\" { return 4; }"); // chai.eval("def test_fun(x) { return 5; }"); @@ -337,7 +339,7 @@ int functor_cast_test_call(const std::function &f, int val) TEST_CASE("Functor cast") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::fun(&functor_cast_test_call), "test_call"); @@ -356,10 +358,10 @@ int set_state_test_myfun() TEST_CASE("Set and restore chai state") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); // save the initial state of globals and locals - chaiscript::ChaiScript::State firststate = chai.get_state(); + auto firststate = chai.get_state(); std::map locals = chai.get_locals(); // add some new globals and locals @@ -402,7 +404,7 @@ class Short_Comparison_Test { TEST_CASE("Short comparison with int") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::user_type(), "Test"); chai.add(chaiscript::constructor(), "Test"); @@ -425,7 +427,7 @@ class Type_Name_MyClass TEST_CASE("Test lookup of type names") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); auto type = chaiscript::user_type(); chai.add(type, "MyClass"); @@ -451,13 +453,13 @@ int simultaneous_chaiscript_do_something_else(int i) TEST_CASE("Simultaneous ChaiScript tests") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::fun(&simultaneous_chaiscript_do_something), "do_something"); chai.add(chaiscript::var(1), "i"); for (int i = 0; i < 10; ++i) { - chaiscript::ChaiScript chai2; + chaiscript::ChaiScript_Basic chai2(create_chaiscript_stdlib(),create_chaiscript_parser()); chai2.add(chaiscript::fun(&simultaneous_chaiscript_do_something_else), "do_something_else"); CHECK(chai.eval("do_something(" + std::to_string(i) + ")") == i + 2); @@ -506,7 +508,7 @@ TEST_CASE("Utility_Test utility class wrapper") ); - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(m); CHECK(chai.eval("auto t = Utility_Test(); t.function2(); ") == "Function2"); @@ -549,7 +551,7 @@ TEST_CASE("Utility_Test utility class wrapper for enum") ); - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(m); CHECK(chai.eval("ONE ") == 0); @@ -644,7 +646,7 @@ TEST_CASE("Object copy counts") m->add(chaiscript::constructor(), "Object_Copy_Count_Test"); m->add(chaiscript::fun(&object_copy_count_create), "create"); - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(m); chai.eval(" { auto i = create(); } "); @@ -700,7 +702,7 @@ TEST_CASE("Object lifetime tests") m->add(chaiscript::constructor(), "Object_Lifetime_Test"); m->add(chaiscript::fun(&Object_Lifetime_Test::count), "count"); - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(m); CHECK(chai.eval("count()") == 0); @@ -753,7 +755,7 @@ Object_Lifetime_Vector2 Object_Lifetime_Vector2_GetValue() TEST_CASE("Object lifetime test 2") { - chaiscript::ChaiScript _script; + chaiscript::ChaiScript_Basic _script(create_chaiscript_stdlib(),create_chaiscript_parser()); //Registering stuff _script.add(chaiscript::user_type>(), "Object_Lifetime_Vector2f"); @@ -794,7 +796,7 @@ int myfunction(Non_Poly_Base *) TEST_CASE("Test Derived->Base with non-polymorphic classes") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::base_class()); Non_Poly_Derived d; chai.add(chaiscript::var(&d), "d"); @@ -813,7 +815,7 @@ struct TestCppVariableScope TEST_CASE("Variable Scope When Calling From C++") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::user_type(), "Test"); chai.add(chaiscript::constructor(), "Test"); chai.add(chaiscript::fun(&TestCppVariableScope::print), "print"); @@ -836,7 +838,7 @@ TEST_CASE("Variable Scope When Calling From C++") TEST_CASE("Variable Scope When Calling From C++ 2") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.eval("var obj = 2;"); auto func = chai.eval>("fun(){ return obj; }"); CHECK_THROWS(func()); @@ -853,7 +855,7 @@ void longlong(long long i) { TEST_CASE("Test long long dispatch") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::fun(&longlong), "longlong"); chai.add(chaiscript::fun(&ulonglong), "ulonglong"); chai.eval("longlong(15)"); @@ -873,7 +875,7 @@ struct Returned_Converted_Config TEST_CASE("Return of converted type from script") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::constructor(), "Returned_Converted_Config"); chai.add(chaiscript::fun(&Returned_Converted_Config::num_iterations), "num_iterations"); @@ -921,7 +923,7 @@ int get_value_a(const std::map &t_m) TEST_CASE("Map conversions") { - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::map_conversion>()); chai.add(chaiscript::fun(&get_value_a), "get_value_a"); @@ -941,7 +943,7 @@ TEST_CASE("Parse floats with non-posix locale") #else std::setlocale(LC_ALL, "en_ZA.utf8"); #endif - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); const double parsed = chai.eval("print(1.3); 1.3"); CHECK(parsed == Approx(1.3)); const std::string str = chai.eval("to_string(1.3)"); diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 58e954a9..0cb41c37 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -1,4 +1,7 @@ -#include +#include +#include "../static_libs/chaiscript_parser.hpp" +#include "../static_libs/chaiscript_stdlib.hpp" + #define TEST_LITERAL(v) test_literal(v, #v) @@ -6,7 +9,7 @@ template bool test_literal(T val, const std::string &str) { std::cout << "Comparing : " << val; - chaiscript::ChaiScript chai; + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); T val2 = chai.eval(str); std::cout << " " << val2 << '\n'; return val == val2; diff --git a/unittests/multifile_test_chai.cpp b/unittests/multifile_test_chai.cpp index ac288ffc..f57157d4 100644 --- a/unittests/multifile_test_chai.cpp +++ b/unittests/multifile_test_chai.cpp @@ -1,14 +1,16 @@ #include "multifile_test_chai.hpp" #include +#include Multi_Test_Chai::Multi_Test_Chai() - : m_chai(new chaiscript::ChaiScript(chaiscript::Std_Lib::library())) + : m_chai(new chaiscript::ChaiScript_Basic(chaiscript::Std_Lib::library(), + std::make_unique>())) { } -std::shared_ptr Multi_Test_Chai::get_chai() +std::shared_ptr Multi_Test_Chai::get_chai() { return m_chai; } diff --git a/unittests/multifile_test_chai.hpp b/unittests/multifile_test_chai.hpp index c2e306d5..681c2c2a 100644 --- a/unittests/multifile_test_chai.hpp +++ b/unittests/multifile_test_chai.hpp @@ -1,14 +1,14 @@ -#include +#include class Multi_Test_Chai { public: Multi_Test_Chai(); - std::shared_ptr get_chai(); + std::shared_ptr get_chai(); private: - std::shared_ptr m_chai; + std::shared_ptr m_chai; }; diff --git a/unittests/multifile_test_main.cpp b/unittests/multifile_test_main.cpp index 94bbb6f9..24b03b2d 100644 --- a/unittests/multifile_test_main.cpp +++ b/unittests/multifile_test_main.cpp @@ -1,14 +1,14 @@ #include "multifile_test_chai.hpp" #include "multifile_test_module.hpp" -#include +#include int main() { Multi_Test_Chai chaitest; Multi_Test_Module chaimodule; - std::shared_ptr chai = chaitest.get_chai(); + std::shared_ptr chai = chaitest.get_chai(); chai->add(chaimodule.get_module()); return chai->eval("get_module_value()"); } diff --git a/unittests/multifile_test_module.cpp b/unittests/multifile_test_module.cpp index 2457416f..ec1df238 100644 --- a/unittests/multifile_test_module.cpp +++ b/unittests/multifile_test_module.cpp @@ -1,4 +1,4 @@ -#include +#include #include "multifile_test_module.hpp" diff --git a/unittests/multifile_test_module.hpp b/unittests/multifile_test_module.hpp index f01d8f1a..b09dca39 100644 --- a/unittests/multifile_test_module.hpp +++ b/unittests/multifile_test_module.hpp @@ -1,4 +1,4 @@ -#include +#include class Multi_Test_Module { diff --git a/unittests/multithreaded_test.cpp b/unittests/multithreaded_test.cpp index 225353c0..990bf7e9 100644 --- a/unittests/multithreaded_test.cpp +++ b/unittests/multithreaded_test.cpp @@ -2,7 +2,8 @@ #include -#include +#include +#include int expected_value(int num_iters) { @@ -62,7 +63,12 @@ int main() modulepaths.push_back(modulepath); } - chaiscript::ChaiScript chai(modulepaths,usepaths); + + // For this test we are going to load the dynamic stdlib + // to make sure it continues to work + chaiscript::ChaiScript_Basic chai( + std::make_unique>(), + modulepaths,usepaths); std::vector > threads; From cefb4d3c7801ee9b0e45a74c16ef1953a8893f1c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 16 Sep 2016 12:33:07 -0600 Subject: [PATCH 081/108] Update release notes for 5.x --- releasenotes.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/releasenotes.md b/releasenotes.md index d448be4a..2ff69476 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,9 @@ Notes: ======= -Current Version: 5.8.2 +Current Version: 5.8.3 + +### Changes since 5.8.2 +* Add support for reference of pointer return types ### Changes since 5.8.1 * Allow casting to non-const & std::shared_ptr From 26e6f51fa8e66eeaa91b5e058fd040a2411acf47 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 16 Sep 2016 12:39:42 -0600 Subject: [PATCH 082/108] Add notes on bound member function --- cheatsheet.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cheatsheet.md b/cheatsheet.md index df71cec0..ab85c167 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -23,6 +23,13 @@ chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdl ``` chai.add(chaiscript::fun(&function_name), "function_name"); +chai.add(chaiscript::fun(&Class::method_name), "method_name"); +chai.add(chaiscript::fun(&Class::member_name), "member_name"); +``` + +### Bound Member Functions + +``` chai.add(chaiscript::fun(&Class::method_name, Class_instance_ptr), "method_name"); chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name"); ``` From 8cb3bd4af8cc2754b500c156d2bafe46a58b83fd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 16 Sep 2016 12:47:01 -0600 Subject: [PATCH 083/108] Fix gcc 4.9 build --- include/chaiscript/dispatchkit/bootstrap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index dcd65d78..553ff768 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -156,7 +156,7 @@ namespace chaiscript /// Specific version of shared_ptr_clone just for Proxy_Functions template - auto shared_ptr_unconst_clone(const std::shared_ptr::type> &p) + std::shared_ptr::type> shared_ptr_unconst_clone(const std::shared_ptr::type> &p) { return std::const_pointer_cast::type>(p); } From 3b2c82ba2c37d1b398bb92d53ed5f266d8f51666 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 16 Sep 2016 14:20:11 -0600 Subject: [PATCH 084/108] Add 6.0.0 release notes --- releasenotes.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/releasenotes.md b/releasenotes.md index 2ff69476..162bb752 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,45 @@ Notes: ======= -Current Version: 5.8.3 +Current Version: 6.0.0 + +### Changes since 5.8.3 + +*6.0.0 is a massive rework compared to 5.x. It now requires a C++14 enabled compiler* + +#### Compiler Requirements + +* MSVC 2015 or greater +* g++ 4.9 or greater +* clang 3.6 or greater + +#### Breaking Changes + +* Instantiating a ChaiScript object now, by default, builds the stdlib in + * This was done to address the most common support issues of loading stdlib dynamically at runtime + * If you want the old behavior, use include/chaiscript/chaiscript_basic.hpp +* Headers have been reorganized to fully separate stdlib/parser/engine from each other (some faster builds) +* Bootstrap functions no longer return a reference to the module added to (compile time savings) +* It's now no longer possible modify AST_Nodes (compile time, runtime efficiency) +* Function annotations no longer exist (simplifies code, reduces compile time, compile size) + +#### New Features Added + +* Modular optimization system; this can be accessed via the ChaiScript_Basic interface +* Execution tracing capability; also accessed via ChaiScript_Basic interface + +#### Improvements + +* Compile time improvements +* Compile size improvements +* Significant runtime improvements (see "Modular optimization system") + +#### Improvements Still Need To Be Made + +* File location tracking has been rewritten; this currently means error location reporting is not as good as it was +* Tracing capability needs to be tested and vetted + + + ### Changes since 5.8.2 * Add support for reference of pointer return types From 4b81a24a0a37da68bf1f55240e676e6ba5887a1f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 24 Sep 2016 17:15:17 -0600 Subject: [PATCH 085/108] Fix numeric mixed-convesion operations --- .../dispatchkit/proxy_functions.hpp | 5 ++--- include/chaiscript/dispatchkit/type_info.hpp | 10 ++++++++++ unittests/compiled_tests.cpp | 20 +++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 6128b33b..a5c25261 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -846,7 +846,8 @@ namespace chaiscript plist.begin(), std::back_inserter(newplist), [](const Type_Info &ti, const Boxed_Value ¶m) -> Boxed_Value { - if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()) { + if (ti.is_arithmetic() && param.get_type_info().is_arithmetic() + && param.get_type_info() != ti) { return Boxed_Number(param).get_as(ti).bv; } else { return param; @@ -854,8 +855,6 @@ namespace chaiscript } ); - - try { return (*(matching_func->second))(newplist, t_conversions); } catch (const exception::bad_boxed_cast &) { diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index c43767a3..eac984d4 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -60,6 +60,16 @@ namespace chaiscript return m_type_info < ti.m_type_info; } + CHAISCRIPT_CONSTEXPR bool operator!=(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + { + return !(operator==(ti)); + } + + CHAISCRIPT_CONSTEXPR bool operator!=(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + { + return !(operator==(ti)); + } + CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_type_info == m_type_info diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index edc62e2d..71fc59cb 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -950,4 +950,24 @@ TEST_CASE("Parse floats with non-posix locale") +bool FindBitmap(int &ox, int &oy, long) { + ox = 1; + oy = 2; + return true; +} + +TEST_CASE("Mismatched numeric types only convert necessary params") +{ + chaiscript::ChaiScript chai; + + chai.add(chaiscript::fun(&FindBitmap), "FindBitmap"); + int x = 0; + int y = 0; + chai.add(chaiscript::var(&x), "x"); + chai.add(chaiscript::var(&y), "y"); + chai.eval( "if ( FindBitmap ( x, y, 0) ) { print(\"found at \" + to_string(x) + \", \" + to_string(y))}" ); + CHECK(x == 1); + CHECK(y == 2); + +} From bec1b91b7beacbcaf672d77bfbe10ed57f02bdc0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 24 Sep 2016 17:17:40 -0600 Subject: [PATCH 086/108] Increment to 5.8.4 --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- releasenotes.md | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3fde8cd..ccab0041 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MINOR 8) -set(CPACK_PACKAGE_VERSION_PATCH 2) +set(CPACK_PACKAGE_VERSION_PATCH 4) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 9184f50e..ea8b1db9 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -99,7 +99,7 @@ namespace chaiscript { static const int version_major = 5; static const int version_minor = 8; - static const int version_patch = 2; + static const int version_patch = 4; static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; static const char *compiler_name = CHAISCRIPT_COMPILER_NAME; diff --git a/releasenotes.md b/releasenotes.md index 2ff69476..d2698ae8 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,9 @@ Notes: ======= -Current Version: 5.8.3 +Current Version: 5.8.4 + +### Changes since 5.8.3 +* Fix case with some numeric conversions mixed with numerics that do not need conversion ### Changes since 5.8.2 * Add support for reference of pointer return types From 21495ebb40adc6890140ee8399500409a7e407ae Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Oct 2016 09:09:50 -0600 Subject: [PATCH 087/108] Make sure atomics are initialized --- .../chaiscript/dispatchkit/dispatchkit.hpp | 2 +- .../dispatchkit/type_conversions.hpp | 3 +-- .../chaiscript/language/chaiscript_eval.hpp | 24 +++++++++---------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a272a07b..465e951a 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1503,7 +1503,7 @@ namespace chaiscript Type_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; - mutable std::atomic_uint_fast32_t m_method_missing_loc; + mutable std::atomic_uint_fast32_t m_method_missing_loc = {0}; State m_state; }; diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3a4d2392..d302a4ff 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -337,7 +337,6 @@ namespace chaiscript : m_mutex(), m_conversions(), m_convertableTypes(), - m_num_types(0), m_thread_cache(this), m_conversion_saves(this) { @@ -498,7 +497,7 @@ namespace chaiscript mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; std::set m_convertableTypes; - std::atomic_size_t m_num_types; + std::atomic_size_t m_num_types = {0}; mutable chaiscript::detail::threading::Thread_Storage> m_thread_cache; mutable chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 60474b4a..1495c9b8 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -128,7 +128,7 @@ namespace chaiscript private: Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Int_AST_Node : public AST_Node { @@ -203,7 +203,7 @@ namespace chaiscript Boxed_Value m_value; - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Char_AST_Node : public AST_Node { @@ -397,8 +397,8 @@ namespace chaiscript { assert(children.size() == 3); } Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc; - mutable std::atomic_uint_fast32_t m_clone_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_clone_loc = {0}; virtual ~Equation_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { @@ -567,7 +567,7 @@ namespace chaiscript return oss.str(); } - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Dot_Access_AST_Node : public AST_Node { @@ -624,8 +624,8 @@ namespace chaiscript } private: - mutable std::atomic_uint_fast32_t m_loc; - mutable std::atomic_uint_fast32_t m_array_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_array_loc = {0}; std::string m_fun_name; }; @@ -961,7 +961,7 @@ namespace chaiscript return Boxed_Value(); } - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Case_AST_Node : public AST_Node { @@ -1027,7 +1027,7 @@ namespace chaiscript return "[" + AST_Node::pretty_print() + "]"; } - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Inline_Map_AST_Node : public AST_Node { @@ -1055,7 +1055,7 @@ namespace chaiscript } } - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Return_AST_Node : public AST_Node { @@ -1147,7 +1147,7 @@ namespace chaiscript private: Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Break_AST_Node : public AST_Node { @@ -1217,7 +1217,7 @@ namespace chaiscript } } - mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc = {0}; }; struct Annotation_AST_Node : public AST_Node { From 7cc100e3d7019c4e113238c37388dc11ce047480 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Oct 2016 09:36:43 -0600 Subject: [PATCH 088/108] Make ChaiScript constructor public... --- include/chaiscript/chaiscript.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 2df9535c..076a2af0 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -825,14 +825,15 @@ namespace chaiscript { class ChaiScript : public ChaiScript_Basic { - ChaiScript(std::vector t_modulepaths = {}, - std::vector t_usepaths = {}) - : ChaiScript_Basic( - chaiscript::Std_Lib::library(), - std::make_unique>(), - t_modulepaths, t_usepaths) - { - } + public: + ChaiScript(std::vector t_modulepaths = {}, + std::vector t_usepaths = {}) + : ChaiScript_Basic( + chaiscript::Std_Lib::library(), + std::make_unique>(), + t_modulepaths, t_usepaths) + { + } }; } From 8b7fe33bf15ce205a726e6b2244d6c770cf1d66e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Oct 2016 14:41:45 -0600 Subject: [PATCH 089/108] Fix order of operations for prefix and '*', '/' The problem is that Prefix did not properly participate in operator precedence. I've fixed this, at least for the moment, by adding a final depth of precedence that can be called when the depth gets to the bottom. closes #285 --- include/chaiscript/language/chaiscript_parser.hpp | 9 ++++++--- unittests/precedence_4.chai | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 unittests/precedence_4.chai diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 8fc9827e..7653c7f0 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -219,6 +219,10 @@ namespace chaiscript m_operators.emplace_back(AST_Node_Type::Multiplication); m_operator_matches.emplace_back(std::initializer_list({"*", "/", "%"})); + // Prefix placeholder + m_operators.emplace_back(AST_Node_Type::Prefix); + m_operator_matches.emplace_back(std::initializer_list({})); + for (auto & elem : m_alphabet) { std::fill(std::begin(elem), std::end(elem), false); } @@ -2197,7 +2201,7 @@ namespace chaiscript bool retval = false; const auto prev_stack_top = m_match_stack.size(); - if (t_precedence < m_operators.size()) { + if (m_operators[t_precedence] != AST_Node_Type::Prefix) { if (Operator(t_precedence+1)) { retval = true; if (Operator_Helper(t_precedence)) { @@ -2257,8 +2261,7 @@ namespace chaiscript } while (Operator_Helper(t_precedence)); } } - } - else { + } else { return Value(); } diff --git a/unittests/precedence_4.chai b/unittests/precedence_4.chai new file mode 100644 index 00000000..b55c83d1 --- /dev/null +++ b/unittests/precedence_4.chai @@ -0,0 +1,4 @@ + +var i = 2; + +assert_equal(++i * i, 9) From 58faea1cf250c1f876e849c3f9aaa12d0688f317 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Oct 2016 14:52:34 -0600 Subject: [PATCH 090/108] Add conversion to bool compile test Re: #275 --- unittests/compiled_tests.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 71fc59cb..b95adb9e 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -971,3 +971,13 @@ TEST_CASE("Mismatched numeric types only convert necessary params") } +TEST_CASE("type_conversion to bool") +{ + auto module = std::make_shared(); + struct T { + operator bool() const { return true; } + }; + module->add(chaiscript::type_conversion()); +} + + From d1c7645a4eb4437f9b0e3e902ca4a1116171c445 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Oct 2016 15:19:47 -0600 Subject: [PATCH 091/108] Backport inits for g++4.6 --- .../chaiscript/dispatchkit/dispatchkit.hpp | 5 +- .../dispatchkit/type_conversions.hpp | 3 +- .../chaiscript/language/chaiscript_eval.hpp | 52 +++++++++++-------- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 465e951a..f9d34850 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -430,7 +430,8 @@ namespace chaiscript }; Dispatch_Engine() - : m_stack_holder(this) + : m_stack_holder(this), + m_method_missing_loc(0) { } @@ -1503,7 +1504,7 @@ namespace chaiscript Type_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; - mutable std::atomic_uint_fast32_t m_method_missing_loc = {0}; + mutable std::atomic_uint_fast32_t m_method_missing_loc; State m_state; }; diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index d302a4ff..3a4d2392 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -337,6 +337,7 @@ namespace chaiscript : m_mutex(), m_conversions(), m_convertableTypes(), + m_num_types(0), m_thread_cache(this), m_conversion_saves(this) { @@ -497,7 +498,7 @@ namespace chaiscript mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; std::set m_convertableTypes; - std::atomic_size_t m_num_types = {0}; + std::atomic_size_t m_num_types; mutable chaiscript::detail::threading::Thread_Storage> m_thread_cache; mutable chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 1495c9b8..000257ec 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -85,7 +85,8 @@ namespace chaiscript public: Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector t_children) : AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), - m_oper(Operators::to_operator(t_oper)) + m_oper(Operators::to_operator(t_oper)), + m_loc(0) { } virtual ~Binary_Operator_AST_Node() {} @@ -128,7 +129,7 @@ namespace chaiscript private: Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Int_AST_Node : public AST_Node { @@ -166,7 +167,7 @@ namespace chaiscript 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) - { } + { } virtual ~Id_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { @@ -203,7 +204,7 @@ namespace chaiscript Boxed_Value m_value; - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Char_AST_Node : public AST_Node { @@ -393,12 +394,15 @@ namespace chaiscript public: 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)) + m_oper(Operators::to_operator(children[1]->text)), + m_loc(0), + m_clone_loc(0) + { assert(children.size() == 3); } Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc = {0}; - mutable std::atomic_uint_fast32_t m_clone_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_clone_loc; virtual ~Equation_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { @@ -535,7 +539,7 @@ namespace chaiscript struct Array_Call_AST_Node : public AST_Node { public: Array_Call_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::Array_Call, std::move(t_loc), std::move(t_children)) { } + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)), m_loc(0) { } virtual ~Array_Call_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); @@ -567,13 +571,15 @@ namespace chaiscript return oss.str(); } - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Dot_Access_AST_Node : public AST_Node { public: 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_loc(0), + m_array_loc(0), 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) { } @@ -624,8 +630,8 @@ namespace chaiscript } private: - mutable std::atomic_uint_fast32_t m_loc = {0}; - mutable std::atomic_uint_fast32_t m_array_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_array_loc; std::string m_fun_name; }; @@ -923,7 +929,7 @@ namespace chaiscript struct Switch_AST_Node : public AST_Node { public: Switch_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::Switch, std::move(t_loc), std::move(t_children)) { } + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)), m_loc(0) { } virtual ~Switch_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { bool breaking = false; @@ -961,7 +967,7 @@ namespace chaiscript return Boxed_Value(); } - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Case_AST_Node : public AST_Node { @@ -999,7 +1005,10 @@ namespace chaiscript struct Inline_Array_AST_Node : public AST_Node { public: Inline_Array_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::Inline_Array, std::move(t_loc), std::move(t_children)) { } + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)), + m_loc(0) + { } + virtual ~Inline_Array_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { try { @@ -1027,13 +1036,13 @@ namespace chaiscript return "[" + AST_Node::pretty_print() + "]"; } - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Inline_Map_AST_Node : public AST_Node { public: Inline_Map_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::Inline_Map, std::move(t_loc), std::move(t_children)) { } + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)), m_loc(0) { } virtual ~Inline_Map_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ try { @@ -1055,7 +1064,7 @@ namespace chaiscript } } - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Return_AST_Node : public AST_Node { @@ -1123,7 +1132,8 @@ namespace chaiscript public: 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(children[0]->text, true)), + m_loc(0) { } virtual ~Prefix_AST_Node() {} @@ -1147,7 +1157,7 @@ namespace chaiscript private: Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Break_AST_Node : public AST_Node { @@ -1204,7 +1214,7 @@ namespace chaiscript struct Inline_Range_AST_Node : public AST_Node { public: Inline_Range_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::Inline_Range, std::move(t_loc), std::move(t_children)) { } + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)), m_loc(0) { } virtual ~Inline_Range_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ try { @@ -1217,7 +1227,7 @@ namespace chaiscript } } - mutable std::atomic_uint_fast32_t m_loc = {0}; + mutable std::atomic_uint_fast32_t m_loc; }; struct Annotation_AST_Node : public AST_Node { From 665125665a7ae95e9a2ad8d45303e1c39cb52568 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Oct 2016 22:32:55 -0600 Subject: [PATCH 092/108] Bump to 5.8.5 - remove parsing of unary &, it was unused --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- .../chaiscript/language/chaiscript_parser.hpp | 2 +- releasenotes.md | 6 +++++- unittests/fuzzy_tests-2015-07-16.tar.bz2 | Bin 85787 -> 86537 bytes 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ccab0041..944a8caf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MINOR 8) -set(CPACK_PACKAGE_VERSION_PATCH 4) +set(CPACK_PACKAGE_VERSION_PATCH 5) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index ea8b1db9..f5588476 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -99,7 +99,7 @@ namespace chaiscript { static const int version_major = 5; static const int version_minor = 8; - static const int version_patch = 4; + static const int version_patch = 5; static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; static const char *compiler_name = CHAISCRIPT_COMPILER_NAME; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 7653c7f0..fa161282 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2164,7 +2164,7 @@ namespace chaiscript /// Reads a unary prefixed expression from input bool Prefix() { const auto prev_stack_top = m_match_stack.size(); - const std::vector prefix_opers{"++", "--", "-", "+", "!", "~", "&"}; + const std::vector prefix_opers{"++", "--", "-", "+", "!", "~"}; for (const auto &oper : prefix_opers) { diff --git a/releasenotes.md b/releasenotes.md index d2698ae8..b415a8e8 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,10 @@ Notes: ======= -Current Version: 5.8.4 +Current Version: 5.8.5 + +### Changes since 5.8.4 +* Fix order of operations for prefix operators +* Make sure atomics are initialized properly ### Changes since 5.8.3 * Fix case with some numeric conversions mixed with numerics that do not need conversion diff --git a/unittests/fuzzy_tests-2015-07-16.tar.bz2 b/unittests/fuzzy_tests-2015-07-16.tar.bz2 index 9768b8e44cf430b648631185558eafa1c3cb0e86..7aadb7655278a529603e9bd9f82559a0c9da476e 100644 GIT binary patch literal 86537 zcmaHSWlS6n%=ZC@yBrRK!w+{EZo~BshvCEBWy9r=;qK01!=2&IhP%5D-(YNe|L^-I z&&Q`9+NMpKHfhrI*HqTXPLx;1kXhHTNSbp6=x+V#-~UQ~|NYye{3qHEK-C1GZ)54N z^Z@_>ocj*sYH6+RBG4{1`moz0i=(puN6t*fD)o$D{XkBmOSkPrsL5N(B5Xgr0G-6A z0|yj(Sttyt$XW%2sx7@BpKc@xK>co16bXfZhfX|g&- z?6$I`SVlPAkwG%nA>UP4(pAnij~37l^@%#bo;3tSeG0&rDVjyMLI6;~yZ>bcKnel) zybrE1o}MpKR)(Ti^(|S`;Ye!lSDUqoNvFW-F<-J&Mjs@P@2P z_|jeP6#;05crUv8g`NNaUt82K3z~*N2!D>xY5g-6D)L@5>B_1> zFfD|(Mk6#m1c0+x64|U$&?3u*3Pixmv91th$0HjUM3;h$%0w!0sQ@EEN|X?+asXhC zSegI;oGVp61P<_7@LAedMCCY`Q>yc!S0tIU?dDKW@Ub0^%H}SxwbG_K1fW$Hq%PV> zFlZ|0Fi*5fDCQ(Yuq3^!NDvf?&nik64}qq|YA(@MR)paKXe*@WijXRzLT~|=|5bqt z0NA00OaG^#(E$Jg|49IVk%&${RbHJ>cT!3v;9b?YUlLMVh1UOb0Vr_+l>cA*AD+6T zjKy4`2$Fc$@>vC!wn9QXwj$@h!1hIR$rbA43=E5NMJUq$wL}pGE((y3l0smjA{#)7 zR7ClItvO{e1ffO51OUP!=B#*<_3B?(PIAzH$|cr{>y>Ak0g+O=v)R0YQqWt?C85-J zCAJld0r4TUMG|xMK?)jT!3CZVtkB_ml?`Ns-^&QHda+2OoT z5inhw7^j&uVh`;mnz-Rw_Y*F-Mov#3lMAtgfrt#`oLRW{s^$f6Gi+pQk1>V@mK- zNSbTr%H~>5$}027V-lHpl#}*z*}f8$gL8?95MJHMBmMo`(b&)IJACC~d)w4CC66Xgo zi&Z#~Mv#w*XwO8|-TemMaV5AVDHq10txHHC@iYB4Rws{1Wn+grR!OmCojeZ(7Gu&h zwwV8$8B*9|pI_f}+u_FQWNB~ovB#>@R~TK>I7SRion5eHBW@wErcpF+FrEUz_ULv^%uOj873 zmS+2zgv@&glghL{IXZCB#!)YTIbANxl~0mMwRd5Aprf+q)-+v9OxQXpg?Vc#L(;XLBWR0Bgkmny|W#G|r(yHdhNo3SaNmaA2MNvi!xKNTIFu%BXFBv<=Q)4hn~j&c)>&W37+@37tW;i(H}z zj*7{!Ii+z&A%S(HX7Z4VOL%SzaAztff{( zJY28UY|cjVFX7b@lYbNO_t-b@No=*nweY`(IxR*kLeRtLm*`Lr^Z4Ji@=-zxJOtfqF>%NuCrM+W3&d;YF7<}Lx(oj{?5sE0O7Ga=YFCRNp<}IoB~gBp z>G+^I@;mzAPvL028sabPuVhE=GI4^5o2TRs`S*=7xmVgWIL39o_{?WDQn!r9dF6& zWG2?wluZ{V6Hrfw5vvp;oLjxI^~`Me>ex8KZplOi2?=uGJ&#R!1{KW5Y>3H0Fx^*C zN2VnfZ|A8FdKSi`jhtH7HJBo-(r$c;`AFEInV)B>otp*6boa3#_P$#qtD zhcj1@a-^tCc-lOh=_yknN5=MO3lu>7lZlhkHAJG_3J9)AhO-5eZV%Fv4Yi7=x(Aju zNS6X^7rcr(##{CgT64a5=OsF|IkDObEqS$k9AW&FF*fnJy8M?ESt@a(B_@;H7|fRL z$53wY(lVol`gBi6mS+N6lksGBYifKu$vFdvk6zo~Zo=2yA($*XQv*tLT-F|8(uo+a zg^>|@HQgY}{t#oD%uI%JS-L4yMY^SBGn*`_D8J1@z&&{P3s(rKn|=I}V)GLuo$Whh6cp$K#vSK%!QQ)a>@vFPQL zeoU6noPc_(&hY{DTOatK1D9JI*9ogTa*d4!m`Rwq6giJA04rZ zY{&z=6JIpu5Kn9~#LT1#NL@QRU3=(SvpqA1WB#_yk*gv3!zyOk{a4-gk_03sWtJ)a zg~RMaNfKFII%+nv1(Tk&M&;ATVB;6>vje!^FJ*2G`AljR?3)+-{$11xuMIxI34NlR zR2Cuj5>7$eqa`oKtFkeov(2MP`(l&Mbl$}Jilf6BX4YF=sR~`wHX|{Csp0XhlMIDIAqbGFl~%S(RSATY*drdK zO=z9QLJT&@DrR-qOpa7#Q|acS%NUmRyWSrzW76&5ozhib6sfL_>CI;SnT^}(vK^1z znHoQgkFAuquNcTOG0DOlhj3&W_p2FxHu;j3VFF>D;m9*D?GM}vvh1ua>xkpmb1$bK z7G#{Ffem2CSs>u&Q_Hf=>Vg5eIfvuDp$Ru5BLMpn+F@7S!` z<2&l@gt6-=jk~sMm(N;AihR**O`#)WMd=jQCQB(WZS@Uq=89#b@fvU=$pt6lR=^_3 zYt>{2$SNl6(BB5Nipv2_Sy;{cGi#Hr`^##*tzAwyO}F3vk+PTRmWDPzRL#uR6itXJ zCKt@Y!obCMM{slB%|s(O>S+6v9Vbiq$Va(svKH!M2NIvn<4td_t^PT{YaoTBFAEt8PHk-21cNm$P9gxe;f)iJeiB_*H#KDA&7M z`RkooHzVO70Dzyp(O0A?)eg_oCkkn}UM1Fk>@oP7d%LKZivBx7^4Q!s@5K(~Uzvc) z0Nd2x=xVq3PW?$QZwghLGpW#Pl-iMlwzn`46#(TK^kVUUmn(9m3DK+IfIKmD?sDl8 zi_9(GIuDFgR+9AJQxGJ(lD8ptl8j$f+RVddA6n*pZc7kP5(ajtA-rTMg%3hz1N-4^ z0nLw0oqdUB)nBK^a#vefqi>$Qouv9EVO*Ql?`MZWQa9F`XV&+_Bo|Ic3tV);N|_-T z^gEI}WceSZ;@&Nsw7+JGH-E!o1%J)l={6z}(01QB*wUMk z#6TWjD2fUFz$r*b{~>T(WYRBmsW!ZochoNwARWOEhzTL}CB;s9aFCP=-XhJ8e+m4) zkp0|zk`4#4dUq%p z{gC(%OOsT!JX-6xx%W?@N2clC`{m`qjgm$EqVgr_?^bk}uwTLUx<5>*U3XgVsp-hy zdq~7l^GK5bJ`(`Ix56orQ>wMFih A|0+Gb#O@_ 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 n$ZLREy8yaq%41OjY32~E#On*ykSPuIM)}#^` z9ak&UJi}*)IUt5quZIltY7fG~da)<@ zS?=Wzb%iJDVMp{BFY5ey>&0DJMML=*k9R3wxX2=&%frxs?M4OX0|+-Xa-N00U=l)J z!Tc+m9&RQ~xA3Ev4J=A8N4{(cNZxN+MqElxHoSv7^4=RR>loWj9oAF+C)Vd|U{|Lr z@H~jC?a(8Y)ue^wvP+ajF|WME)t8uQfNl4a|}@>(_nSI{qu@`mPS=YyCZk2j+O3Tv(-TOr!vjk(-uh z9(g#gv6t+<>+vCTD`9;onYM@oK1|%onM+H8psY)FhFqdLb1#={f|NaJcJAMX-lU@;>BajuRQN^Mt>=USe5+pcRy zh@!QlS}Q-3&Pzs>-ci}Qn+g0^Mr#p?I^3PP*Ic85<9X$4jiRo($|~&BoYi?nx@~UH zC6cEhYAZ|&>M9A3IhLhOwU7PNlcF_m@z0*-= zv1goz6j}W|gT#;@m4rzvYB*$T;?ZjAdE=?bkSA_ zxlEG9EtFc4){XQQV(?|$+oeTzwcWbv#fx=qGSzWy5vba}$7<_qZuZ(xS~hv@t?s;d zoFB>l0&8kcjL2ly4!D~n$e2wC{M$l55){_O{iUM2w7YBt=}#m-zZG;FNI(Y8R- z^H@uKbF-BtmBK3`*^xAfmiVzWZzi_X$~K9)OjA|9649(?CNVAIWIOp+2*quL%2_S( ztS1Kg%UXiy#B<7QVJz@_26mqKOrl$E#@NW}``Q1sVj;Iq!Y-p-M3;I?z2d0-g6d1kg-$sHoAgv@X%%EUa zgb>7exWlLUERHbVWt|bvV-_$lx?3r>I*uCVWqS5fcetspVRFRTOh(jlC91yc$-JF; z?elMXDm;S4M{Z@B!k2heyn{s)ajSC?0;3ZnGGCyln3^W}jrDU%#zl;!=?H>Hia;@q z`?%5&Rs>+!hBn5}8;7$?7~dwuj|l}f388@A_Q@@l*zJ>tTIHW#4P#j09B~%vuC;%W zkee#E#XI6SBYmH3Ea1vVd#4RJ_q8s}zg;UR=)}c~D==SQMbC=uqb9PMkm|^mEE49! zGccvL48czEz~5z6;AJuxt{F1}a>VPk66+QU%x&w@lyJexJ7nZ8HMUDa%MjBly5hlX zEu!0JNV2(D-lsyECJ;fKhr3OJZ26WTT%;|w7;zn;(kTvjS&88qh`1s&c-@#eCX*FE zeBz@ZgCPXjGY=;m@;>XtZ{Fi;IZSFNJj_PvGG;dL%|!7mqI>p#$;sKpa#4?M)8Nl% zeipp)#DY^5BU}9|hccoUbJLo>A>x5&3f&G6-6$9RUVx5=3!WXoAanM%}bLdajsz_o7Nqf#cdnPzIy zw!yWd6js}ntF3EICS`=y%(F8)o7N}%+cA+X^L+`RZI!lDSyO5)w59PIQ?j^j%vp%q#@k~;J6c6j1ZlhgSdGCT z3ylDqNE-}f8%WyR%T~d@R@9p?&{-Fc24zcB-xRcDo5a$MRi;AQDrO?tEuh-VO`>E> zn`M|INjc<nzvN8CaSVpMmNS|3|dCe)nyq*rbN=!T0x>)U^m#UKyIAdQEjl{ zt*)z9*sR3bNt(*0U^ND4%*l*A7PF_HCmOCRItp1!n3zqL7-eqDfacATLZt@W-xUjJ z8V0Zq9`j-LMfXC{pWpJ8r!VQ|a-gCF2iQC0Y=L=9LOu*^vnaC(tldphPP|Ao$hNCy z*1XlrdVF}OoN_KVGn;Q5x|^Wc7@Hv^VTv=$is8ymc8o@sp9-lz)n)K&ddR7R937 z{|dad+M5=|pto(=+wY=_`1iVq(;E=REr=^^0ri+qgK#FY8IWrRvA8&61}HR5voO@P ziZ+RYI*bg(w)4ReQdNQ$kVXl48YTR*s6}9#2Gk_Aide{Rmb>|y+ZUmOe68I&!B`n# zezR+<6xxh0Lk6VdYcjJ4C)nso8CQRmf$sj1`s#ljaJ%QP*b$g>#s`)r(cIPq#z z#i;dQZf#9Xu+tT508IeFzFT;Lh)iUtOCWh6l@Htlo3xCC?Ww#YRCDX$&HVS=U)_HX z(c4m&sRNnHN5wty@pEo-r2o4+o4lL3HGOAc=U@|4Keo@jrRGxXdfOf9*4B@yrAKJ# zOa$)-S09(XsXwmVAD+p2uM^zIqfdFz>L0+PN6ytXW8<>WZ)Ll2d24v}`6@ZG{AQLM zW<5g&)BNsjysqu9a{Mq>7b6XSH7}d^E(giacj)mAUf;H#I6cDw^8G|3)aAc@7umZq zt}dBJgUi=m_z_}cH`Bx8U3kW_g_HreWPv0Fc0iAu$1AOJNGUG3!{NYNFWa;Gox4PY zk4;(L^9|mP#^=Op4c*2?f2)TG&0#M+@B+6b-FFK4;0XreLE1T4-lvI2PKoo4mnxSd zbb48N(9E!sQa)#)BudEugcWQ#B!rIbfgiS*(_1xtr6jU;l zT=_-$TL_I6I`J>#Op=#YMcIq`Jp1$2x<#Pc4Q?d>Nf)%VR<=r6k|kY|j4ZYB{9Hnn z{DP$Q^q{(S%_o--wpmp9IZ-;D*w-AR>ESr|yn90X&b*0I3QjB6|7Y`n^WJT|o0Us6ry>E(tj*Ts|!0#g_DSSFz7toYyt; ze}w49Y+SVq!JSUb%(GEWtSPop!{7Fz^Q?apQ+(y>)W0<@0YDJImIfsV(K84L-q`bh zCL+gpT0qDFp04Rn=f#{|7IY3dri@eecpjXOP7f!&sP-}D&9L=n^;|jZ%p;{wa|Opg z8v)NKT=qvQM^sFlSq#f=7VT)V`AiPUc9(kLm_cQwTG-uQxA61WsWI(|qU4aWMmRLy zkoGUQ+joPGclt^nAWwNNJ%1zJ6XZ20x&nMEGQEukpaLK|n?(FJQ!rw^?9UTe#UD=4 zC%wX5o*T4IhfXn_9K_AU@Ye2pdG&E6!|8jzZeJ$i*KgPPwI4IUCcA~|ct)i2=+e48 zZx*?UzsyBL#h8yzclqJ4(G3=Bc_PGy)+sn-uceCrVa1})A${Wm%QJm!j%d_dNy4d^ zm0FuxrlQTHqgR5fuDi!yLfOH-I&t;5sd9GvyD9itLzgP+U3~2qRK#3)l^e}4|^s!IV%knVqtenYa49M|#vo8+q%r_T{9pz8% zGNkk(ape{{qOzk2nAzy)yp_OD<0Fjpczq5pvE6lZ+w*D4d$(mx3hz|KzY1kqYV5&` z%xjjc*L`>WC)qo-+g@Fns_rbMNwA0G$`HBvu8d8>q0WuP#Jqa+Lwo0=k%u%6N zn-JFo*M^_X#I?OgW@bA+d&$}LPDRC)m{&2+D(U3m3*zlczE(uBPo;!w1h{iWt+~1? zgg}*;HKsh-QYO}_gU~r35q8@?@YYkl#WJ4B56lJn0Kt~?C6_k7jY+ce=lx|3=*t%TdHWX4~8gU=RctfzZ{HO6M*ZPK}OPM%0ywB1i>j&SK|Q(9%=UecVVmsb?IQqxWaX{oM(JMlcF zF?CdScfBPzQf4~`f2OvH$FApgw9;Um>lJ3YuP@Jasd!1V&QH9PmCp3MJYG8TbSqbs zksr4cu0{Lc6oY;<|cyAKQJW zm!H$UqS13QdwVFc?*s^eN)Qmq3zqk-CkPQ<%w{HcW6>3ALF;F^=;^>thBPrzc#PG!G zcGfs-rM}jmfAStTY>w%8R*Bt`eOmHdW4AX;q;%HXcMK~gxOn{zK1<248|5xZ1{}>A zG-%UJ8t0SRiO9X}{dP!Ck&;Zxk;a70V>|WDHf2_oZhKoBOO71<_?~efrJQ;SC z-|&vUH*G6E1o7FwdFppMuGFrDYEOmF^l{R#%hckfg+B*vd4B^{0Z3 z=;B)sXVz}>Menaw`03?|!V|Nf&Q6%SisKfQX){G?V&TDg+T4$0Nvz%DAGP7itEFOt zE7`?nW}#_k$zN-hp6$2gecyxD*BjmQ>!M`xXpLA$VDQC}>3DoT7cZt-iNN7YgUJ(z zDmLm*vie-Q9}nv~`nqVdwkH>_M0tt_g`O&Yd|)2=Pnx1VT_ zrPCu}wX06JVshIPpt1TGw`Xs%_Oh<^=+T(1Wh`sB5L2js z&GV*|^6EafekQ-s#hO2^$gUT|JY7S* zyDW3)oop-!G44Q@8TGW{7_16Y%eB$TEfest09YJ~QjeJE6 z5l42ygtpudglH4GCqzvmcj9-VY9|sr;&T&INn9t&#@l>f;q~tvqJ6dE*=-Z3@#TE2 zl(lSI&bIuQ2P>p^yYs-U=bqqJGrwOK0i`aU&RI#`?DX8TeqW`I*ye*hc#V)fk@ndJ zWko(Ls_zquryh&X?DPxE6Gg#y$#5+&%*+v}n>f*U)WtSa_1!w^^2F5YoSeu=MPNYT zAp*3(i6p1$V(_sn(k9ytSzy3|g=}r?2wt%Gi?Qm>pm2vItkF!8RBTyDMW75Ux*5!) z+riZ0@*NbLPIX~fY@^xfQObC@rLNSyQD%MSqIX2zC$gP8(d%W54pBHn=5g>+=NDMZ zic5y}HEB`qWV05=)8O#Ula;AzTO_u*#dACtx|=w+CnCKF<7JJwNg0={VVSan+@;WM z;*G_c$ryMtH^XfD0)9ZBvGR2b-blsISswmE_WU=&OQ_E4!*MFUyNi5h3f3d!8#b{;BBs}GX9R9zgCX#O%m`R1y6OximmL=YE7qxAqcvV&Bske0@xyEN(Nx2vRivW@y3|G;DpHSn>C8t@Ss@>#k-e&UtN}PLO-Ded-4ecwP&5e!<}Q@8MP6tkb`@oSmi7_>^2QRualD zx4Tr{=RIFZwpT0D;`C>MF1$>^n2f^AOvIZd@?w4MO>@n7{U2MOt^FMrqJ-gnmR*m7 z_pg}9d075_8I{Hi9XaKmygh+%7g)K&!*^5hF$v`F!gsO`o}JVkPK-?P!O2t5%Ys$5 zwT#yV$ft=W_g(LP$7+`OoIRhy%fZ&o-HIQ_^+TTavgpOvG{=89e6%hpRm>&^Q2paN zcBL6f;+>^6De)I--POAns;ygd zDDmz}YxxV4(I4TSmfLz_?r73X4YhmCHEY7=yl)|T6}t8#X+a}lzo~<^bsak89U#4*~3^`{bruLeGehx-)Yq#%B&({rb|ugCt;0SYLj`Rw=*_{n(iJfnT5SA>Q4e%7GtYyxw&f5q;yvFljf{IAhie$c|-^xc@}&RU$65% z%Yrl}&`gdIHKLhS&b1Sk@i&Iibo#+;+r;A&3u#TFbk!#)nIP1rP#w|@MC}omMVvJp zQ^6Y6o6zTM;caU*6C^VklnF2p&?1SXSR93EzH?30>@HV4e9oe^5ym4TWQ?4!vl)pk z6C|^JI*Xi_OPyRMX6)QoY6E?S4Z1r{9Mp8E(xXFdPSJLynT=H|l%F0v6t^pwPHK%I z9Pk?rNZRt&{tH9bzPzRTTV5Igu%LZBeqKk{&-?i6;oIg{YCa4n8RbCIlPa9JcWe}R zzp>;TD9z}ZanMxbl#9Vj#URvlD8(3zs&K+}TbZFZLn|9Rg*3n7VEbpB$m!X^ z>JF(oL{~+Y85EtIO=Zih^-$Wq(y`M=PH{P9GK%P!7x~zOWc3x7BI(I)U1~9+@0FK9 zGpOW4!;m<_>c#AIZ(Ar^;?ldejK|vk@4Vxz0OMkl%hv3K>ONj~dU|=m-!<3ZDZMKF z2%KI_?{8G>Jw-IxvsE1;@cqBn+O8e<5Vkok?R4);Ss0Y;!Zk?RCrX1wPbdw?pCYXo zbX6a#rx_=9RWw2U_tBs0^unL5#~BA0Qz{Q%zE@Y5gvAewDr}5mv0=2z{)A9%&&t8U(mZrTWVGeusk>;FczzNecmRkg=IzwtnBGC7tWtgwXVaaV~%LYj^U9+;GH04p#<> z`r`pq!)FZ>gp^Z0LIbE-YBVK_&5EhsqeZ-Z%w{^xHJ1A-X(lAa6IJc*8NKga+7IlGF}L@eY&{i*R|~Q<0RuJqE9v8Rru7~e$rrK3A6hn zZH~nl+hW)Y;E$9NKIBL*dhGE_$u@o#vK-Bi#b)+ugP{->@<@9EA2fAlec7*pJibkl(uLlU_)-g~FwZUlLys z{=!&p-M!>1!5QE2Ys1})#h7MUmj+g{x9f)vBN&Y0;N0iW=xep=yZum4r`OCllvY|_ zf0v|lt{jHG|Lc5Df1M;~M?slvKm!5*#Yg~lzA4~Rt4+-3GYsl%RjXdteUyG)3h-@+ znRM{D__ZgeBh*&1zqL`iji4d_g2ulS9#F3iDAv9*P8pR%->4{0T6`}6H9bWk>?QP_?Wi6Io~`ucXaM=bm}If zB4RZgdwZUB)5DK{pC7W|QY1bqlyg~1EfPv40Eija%(9Z4wwjP*xMgM)n9R;vYj2yj z-#0&liPb!*HC>-r84d&T2L*Bw}V}DL!Ruy<|=M|5vCU z=3F`VH0`jqW24^XwNE}bXGw~ur7VY!1l8)vNvN4JRGoGO9;F6IHk8R4GEwrgW-Jq$ z281*wRYpQ$vjoI6l06I)kqM?Tw+0HZ+36ue+LY=e_Oy0U%Y!p4#$lQ9qrc9ps}wu2 zWK4v5@_P!JB4Va`2HmA{H)hwE+xV1$m~z&QwUa-}@O~C}6697a@ii}7DA}fClO|`E zL7#;f1V(}YM$bk<#8xUPC%i%@+l|Ncr9GyYt89bDiXRbdZHPZH(gC(s5O@wAdf5|e zr1(>5+LtJ}(aRSO5j+2tJrOlsuAW>}9u!vSe;rp&cl6S;6lN)mW>v{Y7@icK9Y{7& z?{5A8)mri&bGEr z=<~&o1C)j6ogNNmfB4kpk1vp#JT}=1S}%K=6Hjj0Tr3qWsisoenps>k78r7ksZnolEcS@Ee`~jF@Q*OAvu=$khK|GVo%rPevfvf#xoSR$bP0$ZI?WUx&9`V zHpTf^qW!i-4)%K)BER|0oW#gT7afjv*AH5@*cv+GCm8Z&v`jhiIw+n*q8$`SVpy@u zeCMd+&m8?}U&O+lN;^@G1?}S1H-gH%827uvuj_sN55qC}9`mT$`AQ~Vhi1Ny3J=r7 zt;E8oqrcC0#fSSZo5o!K)_l#q*E^r^eAa8#+cg{kU05aZl(s6Ek?Ua|lQ^EW!k)UO z2;8iWt0z5iiOi=PgUqjh4AAh;pw0s}EY2iv{&^6RWEi<9Q|OT5E}qDmM97}~ zzR`2Yvmkkl;)>Zz8Ihz6^l_oUmzPzYp_SaX-4k~&ZzS-pOS!f76-TmK6K>w0XLSYY z^Kj+5BJb+PW(<;l_cj)?%+BM*kts^14dfb_QPH9yJt}*QC%2woN;M$LQ>ue+Ubkg& zO?=1B^7dT^rLNwC*ErmHg?e(YS^F-c1t~&Z@jd8}22U5Z(80*3S`5Zc1FR7lJX^Ij z!4u!dYF0i7_*3%ljMzRb^H_dKgt^$<5oFxb?n- zx+=xzUJNs#)|wTk2H!_#V{LR{b3bqcvM~w}klBOEXmqZfv}< z-r(Zv+;kUVbO z8yTqqISivw7}-K0$p)irk4%8;ZO9nN%OE=vZB_-55w{yiXb3A5XsLs00NCLQP%A}o zkjDz($dJYiVFE=VFkn$tUQ%N)X0c;3BP<<-ww4mHwp(J9XsM<&;X_o7h|CjCP|TGO zVF8R-Qdu&Qgtp~UfWW3;s>bjrtkVi7Lt3?CV=Afx zlxYwiG_4sP3WZHJvny*cWfl!2+O!}xs3r_fClwlv4G^-S+Eh}IK_Qhq%u*>bD+a#Q z`jC?WpdDysD>r5x8+OILTb-qO46_q#8+&SQP;>75&QmwQCqF74lCt$m<%z-xCwnX*PH zjXG4dcP{o?+Rf~{9o^`AK=l)7?One0mE6;LI{Tv}-FJ1c z-Q7xQW^VPX#g^<$~XKp^!%6*e+s)pWHIGHgxj6FS_texJ?*>Y{Y&ECAO)JnUxn)2_Z zV`jrbR7(fJK0_Hw%2WKU2bh;c>7vAx#d;n?5(i+Z!0VwTWid% z?OmR=w%ef^xd(^K@p-vNRd}9e3)e|U=2u5;JHq=-We(Qn;EHzZx7zI0)wcH-&gr=3 z%~?eD29{T9Wo~uKD&)+)S2puIeKQwz-)kk?b<{gh%bnEjn#h!`Sx*Trw+-&Ccei_% zXggzZ=8ZFNy7tDbU95`w%}h>>V((hjn(r&AV#ls^O6uCZ76BuNgq{F+Kx1U0qMKzl zl-n^DtZ78Fn<8QuOhSpG%#vnUksy|76C*^W63m8FQWVex%|s~53ZQC)QLxz5l8sG8 zVkH#B%F#*@5sb*0tr(%DF%;G%D_ad>vP8w0!qq6W&4{H;O;QZDHbRX>vS`%VXxNJ) zO$wvoTD^Brd)* z=7ZlPP9|oK>kOiV7i=NC<^X0Tx02lK+!WO(lY}d zw_d1DS#FGWqb`iiBj~E@!+rA-zIGGQiC@lQ9P+6K5?eL_8rB!#Z&_``<&hz9bX3na2e0J&#;;=aXuC8}!t>6z0lSMLMz^2x6l^W@d2PZVTv(A~@2v6J)li%|zR2EhKtz zS@+u0YL^A@Wi1N9b1ryQnMP&xu^kaODARr$CDB{~!#W(3%QAhL_y(P`OT}?nXDQF7 znw8?*E3rdh+?QRizn*_X*XTpi+LP}rRq5|}*R!tnYrk|B+-k~C_Ho!^dXLxRGR(^% z#^Z9np1sdh?8#WCW(>)uwWeW=+b^Z1Q^1#BDvf)F^6BrXI7Gyr9nwvrZDfX`e4%Mb zR#ikKQz&IU01!C?lE5g+fV-qPe^uiJuSJ?fSDY zzT#_4QQf4P$`O$;gU$6HWygK?yjyGdlU8P{Oo@r}Em>l$T-a6%V~Zx`HpQ40u%((B zJ)cIaB!qya9=V>YII7QJMZMO~VAqVV7}FvcK9cs( zeVH%bzHcj-gM|7U8`^qNXixFL(q~DgHKfE5`vMX`cge>4`LnHPXI@_!DhsqhB3ibn zD^A^6FO5=KZtXDXnz{8^S{W?0P!&aFOnS(0!~@?8_R?sRmK z!nnoQR)T4qULE_K++P+)O>C($RfR4U2K|2qAzvM}zpe54ZZ9$qUB8x`^B*sPp3j#; zy)+x@s@bND$OUbNLUP3R?)aMPP|U>gZ(WC$arE_w_YDq%c{84S2x$n`tx6KZ zhPKm$$fjg0;#_h~IU7T1mN{&Vs7OJlOKwSHXK4!R%Q8R1`^^EiRXnuHN4AQFAvVO( z6%2)5K&WJtx@%Xf_jrCzw_>zaOS_fDB+^DxOvJ4erKm?a$g)YOlX0$EOEyxCm?T#g z;xDRrN(JCWnz+Zo0rzXua+c*b;%1pqWT}}21b2 z1L>psx#N2Jr(lvjnn@U%KrOT*#exy8B1s!yB#?qG@hux3b0J{_5vg)zC=V7Otjxn1 z4w`bgfdB_N49r6s)edEh0>(v5Wm|0}t68fxtea?=q_YwP#Ka6hkaE%yOcUA97ni3r z8gZ?FB!Jf5Vr{n|Ge-=|HN)K2o9f!^M=pqI7^*g6GazrjJ+LF|xt&b7Q$ z&b4{BlT8hgn!V5t*}%p*H*?NBxO3MjnI>5qVZKiqLul3_<%w-&Vwd@u6`_+k>(zzE z{theJ{hsZ;{p30S2TEUO^Ry^$iG2=k6;cZ60XrlEUGo-J{!)QA9)4At*T?MnlWv{vanr=OX39PP?bkiA|xChN~@`x=zA) zth08^NVZ}W!sLx59UPAlP~X<@JH@ubu|*vfXX}w zn2MxBhhf`meK-1Dh55b@vBkW$F&SJ3$^C8+egjW88On!!8J_0SPbfYtnq537)J_W$ zR@M@%u>SuCcMjcnE^mzsB^?5KWvYWok}xI`FQd_MwyE)@#w$i-gDv$O`aJ$#zKwaf zaqsfs=iWjt_C6|G3bSM2st#`S=SNm;v^MVywlKrQdzK#1VqJ0`_BCG)IlwqIUUe?U z^GUwtwVC9pNDa5%)a^DqcyD``mw2->?`iILcE!89&x;*#NS60j(^zeJidUCemUic@ z@cdgV24VUoT7KXT{OS zM@Fh)S}cFMM_glt36K}OR|-}Un1-MT3s|>JH1MSpnW(sokEf3>Hu=G~2Xg1*dLP$& zF*pvU?e?u);ZRbGHXIu>NrhPPViIi&6}6 z`TqmT_2}|^GvL;04^+pkG|Fg~=QQDs2ms-s91|8*i|bR`P$rUjoe)C81R+|3?OGU4 zmpd@fkj?eLJ;Y)(3~3=6GrTYWW*XAu!$>u748b(V28f!buox6Hp#+E~kF9XBv(HIT~UjSf+|0tS1vjn~H1aH4Q^ax|VXTZa3IXs@(?o;4^ z7=r@*c*70r?X{zXKXD-Yyhhp(#+yyHgf=CHxm@V*AV~qNGicKi_tLC1Bn&zi)&;XS z@9xIqIxRj0iyzIdFqfeuXVyIvT+VsUw|nD+xbk}pXh&K!g-E@s9)xj$ak26m-p!j> zuI&qnC^4;MS;R^j<)c_*7qUv5#jcS~BaoJOcQ*8~mNU_QD~ykRxqFx6Gp+5g8JAV_>#vYkB~<^Kk?wxbKg4m&zpMA4fpU85}pIv zQ)zsDd!2@nSG)jPwU67suphJP14HoszF*jasC!7*ByF zpa5||j=zsj<2R?q+3&{3zo0;P5O_def#cv99q7`-GSDr`l`oRhAP7kTA(W8O)-4S* zF!+4}2R;kOM?&FpoAQ;Ekmd*YqeJdXQIFgmku z?fSN+(gY_|NfM-M7+H)N^%2rhNp7ePMGfPTOQ)Wnu!>rMi$I92mzQH*z<9vLqU@IA z;RPfIx$y<$j^!oK7Q>!d)=bJ%6GDMuo_uC7aPl5$qDTU1dz{xEhKr?F&wA#if#>#5w>FP$2aHQ?@%V>A^Dc;$2brrd(2LW>~GI2)DmePOa zVQyqTj$=4kCba9L7|hMic+TXSkl3u8@kHT9MBweCQ!TD7lh^cjdi_1OVJ@j$z->XX zRX56|g0TVzC+h$bwFNER-03vbAot$K73)PCMX!M)RALv*WK(s}^4EO5s~c6OkV4=( zAkKJ|g9Gr;XPm>qB@uLDy3D^8u}_#+&H&)v%KDcqVh3?^lh#J+7Z?++SUve9{DehQu$V zU>_#~@G>U(N8RGC7%R(rV!gY~6KLINOgtV-q_rLG=n;^Eiw_7(ED;ZUT6);-M zHKvuDHp*+B7cR7`DTR!xGRRCZCKybzESXB!bm_ARFkpI0wLMwPFcL z9pJ|pdTsnYR;%NTdFw%Sho33}NP>&OQV>Cj1ZCC~Mj@UwZ%a!xpx%vm5F~(R^>bzn zAVJD#A(8Fz4LDfX>RmX~+(Th9YoW`og1u0T*b z=p(eB0VIS;*v}7@zT08tdSnV2Q(ffS={-KuEM5g+0u|7(rGv&b3qvr#p-3-ubr!VZ zNiSu}5y-`%h@JUk&ud0EVA%ODoU?r(6D$C2HX?Tj&>iI_GmA&wL}% zj_@F;faomnTu^plOT*CoULn~_nOfztU4P`` zmy%x9TnyA38pRL!c@}<{sYJLnkQnEDVZ=PHeYPO-?);x0dvo3b-<;vMwsd?70 z?)WHo&m?vwSS?sxy7O+C^G(d;7&eyMkA~4p|=L~Zp%x_^XJr? zFd+g5VNME)CDRWkhl7D5MaDaZ&cuM$>OG3?$fvP=W}6JnR?yn`Wjq2q5PSOWds{~K z{1f3i&pH>sU8?qt@VM(rjzTuZW0`?t4^)XoJylO^kJ)L&HuU&z+aDag=np~Y@kYgY#9Ux|QUYyh zD4>YZ42Y)YG{&h2F(d9oxZ3ER25omxS8#8 zVHOlzn%dZ=^AvVQ(>t7)=^#H_Hg=fIyD={NJ8F#*E4)Pp!Mp}wz2ZVOy_9>4c}tCu zAtI0=C%L_OOlwK8s4~x8-7GvKOfcBwI>Nx^}0Pl&5emrd?8nHIFq2a@5*D`t{dqo_m*(bS{CYw`yZR%9p5? z{L9BIxZH1B#*P(YQc={PNPY@X_C@2M^p6*dYp)jPq%V_{_`WY|*HQK8^r-ODuc^;{ z7JT0gUT2KFeg8Ad#h!*>gYR?Ta2)8bl5Hdzty>AsjUDA?Q6P*MCiF9$43I|I+5wz& zx5V15nv$=Rx0VL;E78)So19flu^1UV4?Fm zltrAiy8{G+l`Ua;f(@rB0zoHI1O#}97)*w;8@i}8)}C>ctO(ZwM&w&)w)0BINt=&a zIC_(gccrEgv^563z0iHg#Jo%cI`N;_aNNZ6D8*XEFtGaDT2OQr^&O1m)at{xhNFdF zPZQwFSeHO0*I#+x$Q~uA`qFt*UU{583ia~utoidf@1sl3)w9-R;HBnlhz#>~aT_Cm zX>b|ZBD*Sx$^mKtb5}?szEjSNFXFg2aOb7pJCdTI>u5Y4x^DxWp0@?Kp_J9{m@&Jo z*Ef1A!qbhtoz}HWjgi3Mz@{p_TyC2C5MQ16tOb65#=~RtbheE^I0uS&>9vur+=ge4>!AM0y>ueFe(t z_SzRVHj&uU8pu|KSSE%88iPsBkQiNo1;EJ(jdUe@cBRqcZuTM zwOI!!J06-*fHuY(`0D(FoF1;|{khqmSZyxhBnfAgiUbHm)d{9MBU-B#6SjAwdIk~l zFml|nuHEnBx4W(`vc5R)XgqgHi%L{lS_&~ZprFJyDoXg}an_f8zYZS=98|G|@s<;+ zr$=DB8P5w>wzO9I)STRXIV#r+gu{*AuyGLfNFWEnB!2mpxR8i1s6u}M3&4jEf%-h2 z4%)Ghp6kC{dOh+pQhVNw^@!v+4Q$>BdEVyXIV$3y;Pyo$Cie-wjuB{}q4uQL39`^P zbn>nFb0yHBHyo;*hcPv15{B}qwjnS+o++fkF+foee?9C&| zTq#S$efN{2%i`^3`yUB|+wRK0cX__%3mKzKoB{+ma(CqWb9N5qQtsp52W0a1X5_ynS9`SUr=w}g?cUpOamk&JvUyqKeOu1S zCG~j8FQ?AoH2Kw=mT2PVdLUWbNM8UGXiK&rUo##7%PKXAJ&F@9{@Sx9CW|8Ux$^jy z`vL@z9t_l1>Qe_C!JA@Sn`k|qSeV)M@(5{&h$KT_ECFK&#svYQFy-Oe(rvcXF@3wG zkZgPLj^(Rw36jr_;q$QJrqdc;63)heNde(tj0}rSwHj1{fmp{%K~bjFMI~*h4J$Oo ztnYA&Grhk3PnXH^zDA?pIX2f;ThPGrg}*g$G9iiiQjJnX-jS?S#zi5;wHnuYUw5$M zj#VEShq)A@gBXhY^{0J$A%|S!;HELJ4D>|_2+su3aq7v;3eFlgj5U$A>hRPoNbAEw zxt!I-p4IDPEXTdxjWM&d(_?-ZbCY!F&@Eh?S>h)6(HYx@>U;0Y@3W7WetZXpX#kP| z)>ez}1=BF_%^g_P^vcZ%kB9BOUuM`}49A$Uo|(^icpN;awXEl69v${iy3_TXuDaBR zaD)P3+RVbzH1(d}Al@HnyEndp-qL{!9UTme)Er!d2Kkyd&k_div0igi4CNadSovZx z0zN?t^Ik6xi+p%~cKoQ!&J`Lhb9j-YWSvnpL!NHz+ipuZeTTKni-k+>GL~fJi^Gt* z@~eDN?BP#)5yv6p&(g(h{tlYQd>=>9eL(&p@Okdy@$+XphPAC3H}vUr`s1TWqtu{{ zyQBxe7=@NcDB#-K9}jfAQWOg10->IUHFHZ1X3Q^`Rot_eU}iS(T8)~$!C6^F?hC6F z?I+E`*n@3iLE3e4lu6KS{7e{g5xUGZi=69R<`6Ly3_(E_?lrjcc*mIF_bs+<$IBrZ zKXCh0eXq&(>95e*=_#_FwQIxC*6{XrcXYryBMy#-cMWPfb-#R9VG**Ail?ProFF#C z@*g9dPjTqaE<#S2`#2zV2x>vSL`QwZX=%|x^?JW4c#|ZNb3K)?Vk5<#duU*^7XvK- zmUWt3MyohRG>ZmB<@RzhX|uJ&=bI+bq+V~W-(2E3ar2x{&>-`GRcVYqXowK56ARdm zhJ>pZdWgE-JD1mQ#5CCn^MYM<v3I zD}yLBcfIm+*@q7}?8k4P1|HemNG;gRVddj|E^x~0X_YyL&eE@3U138vc^0;L_1(Z{ zgO6RcqsBLp-N)m;ju%kX2;EAZ`s>GjEPgoap5>5G3cw};n`~GEBI?p9A(3A?X#*rx zs@A3oyU&jwHDeE!MWX?Hrw2&txI7i>K49Zr%{ckfTF9qVRk81~uBk5^2Nex4T{W3? zc#w(*wux|>vrw2e)QHouT$gx842aNy#SAr-37E!Z5{_7^wn!u55LicUUe_{H3W#>@ z;LD|)D%gaP4+&jdBqAx@!cYxW)F+oLq%4O^iruv(*h_$4xB$M?M|}M$d-dE3pr!_ZdhYJ4=zN0?0w3%9uz`17>pXnp9%GtSMSU8Tbl@WQ_eZLTN)Vzjv>azPzZVcZvgwP>#%MDQtoU}9GE2iE-Y4yf7 z)qdXtJBI1alel6-JRQMcbm5F>oI%ud~|$U6hMoQ zi*KVAiqswe#;%|tN~*}tnB;VsW6oyVk^Ow&-+grW{Kv(J2_%jJ2LU|i0LSYM;alHh z_Iozfx|uIJJlD2c7b^2>!L41M+f}>UkSglT&loq?-pr|Ivg^jhE}6AgI-I(i0wdyi zz&2OwXT>GqG@3vEYEbXX(nY7s3c!mx)KeblZ1`i0j|;qI7i+M zcz(T^Y4P|hpBsqz4O)CP@?+psQ|AwFYXM66!aKDCAXLGG1_g?gJ^u3%fYceMaZ#Gk z2<$d{L%PU}0QlHxB{fR5TE&Kahl-R9$UW7TWA|iE&Q*_pcduv`P$E_5Y!1Rp>3x$< z)^_rnb+{MGDVy5qcsIMRZ_U#4E>>4#r`-;=$(m;Aeg$^a^I5*AhMxBlvMWw$zbZ+L zpa_SD>AyPqM@0A>&d5FwI+=TRdk=s^5pS6yg|;uh!@Ty{*xB-E z`4=JW?3Zj$#4fqkxWh5Pp@V)FjNmmkczD@^@-*Dj>w7rHxg-4fozo6?%e@`EydCXu zc=>!So+M3;o;-KV0+_NFx!zcP{of>U^f8<860e5(eaX(x9eU3`Ce1$re9FqTi>%GTt=^XTi= z{_^X9;Wg~gj1&&e9Gpv3&uhKA%fZI$Gcht7tSh)XExvrT0)O3f)tWU6YE zWwNnmY_?RInMIRk+e(vZN|MTDHCahEN|`Mz+Lekm8p(<^GB(D|nu=+vHiZ&Oi8C~o zqPDSZwl>jiNo}?(Z5f7SrdW)^S!EfSNhf_0p6ZXs%HacKC6YE_l*S_j!ILG5ERVdl%8=hQkue#$TF)IL{}zMR~U`S?!~I^#NhG7;zhMtHV;;6M>4To zIBN!9vdV@T^i~Of68&yWpap1#rZxF$aAxJy< zwbvnawmBEi?-zuF*}ugEedl|#n@RgF#|?`1a;B`s!@`%8TgvO4a%b7vxQ|9b*|A<+ zM{6W)Q#-RPx;wCFSr;q^elJRSFttm=TdEM}qG3E$%rdL-gmgzzD3p?x0@?Js2qqTL zLl<9b$;0|}HiUG1!$}@Bsw5vP6H;bDAzNgL%JL5sX`~t;vN`REfZ^~W4ILvOo=a6w z{6=Li={M=l%wrkGs=LfZ=NZ?DUuH)pqJC~7aN#|8`YB*}IBSl8Bf4Oi1UV*FNuB^9 z>?DPkr$Zi>4tmVa(&)$6etr{d%vtudqvYX71tu0ATtYD#2Z!(SV8qGbO)Bow{o(awhh1-%W>9TptH+di=jE z;nU`G+cFe=HdS9)k6KFo9Xy|s+iw(sL9JcN)N9ebHt%?g(DTwfPfpvW!_AL(FD68s zYBA#Z|Mqs=OjyK2>C*|b=NVxXl200;3g&`Uk%C^Rh?5YYIt(#IIN_)YA~;Tw8G;)@ zic4-*Rh5Y~k>53<&Cxtv)$~tnnkRji0vfZ8Lhc4EIhLIqr@|yXmP{0IW2R+$pUH=M zZ>sln_g9pJ^ikownwz9(-0h!a?TO|_|AWrY>M{8Xc`t=EHyOVJac!fBEuI-cAwXqz zfKFXWg9U_MYYMCjmwm(%nMX|3krs0=25R_GXcn#A#iM?f7lSBxCw?AO!ezE^v8l9fgWb z+jn#Xgr!Lw_AH?t2XSI7rc4VDfRV6F1D+$plJ{EeR#qWt!UEAm8c2;`+6rn`ijvTp5jKsB7=}zTkHmXYym))r z{dy#WPo$?bf;5jjNM*Y5nvR*tGnYvD3TLzMvG;$#)}MoG1hj{fAM zyPuwgdcfO0RZF@KxXL2~3gO>GfTjXOT2BC8Wv*pBp^^~Is?R$AV|g6ed2OGV0I?YZ zFp~@eGYljhWVdq3UjIG^hqj-&&%WPHB4mFDIo`KQ*%v%}8N(~OWqfsY#r;4xNqT4K zVoY5q}du;{A%3 zP0G8!Aqkoxsx%|6c$(;k;kMhV;O%5J@u4AsGYN44A;6HplVV_}!mTCSsZ1;{QP8zX znJ9d`lJo@291DZl%Kk<+>95S`KF%WAGR9qrmUI?}9I4edbmWsFva;dB@f)df1BxbTXl&R+dUzpe&z+zqWCqEEssWSLxidds*3J1ksrI*F>rQ?J{o||N z>!{V`(8pu*;mNpdA3sa!pGgRXr*%40$GSI;4-KkoC;%dUk}uBUYp`#o?R}^9{vKuw zl>7Ril2`}FaD19%2ZpE0tewP&oERxdX!wf>~_@+g?{0ZsPFXmym!${*}Q}tqHQq~Q880ZX|>TcGG(cZ zGR#b?7~yrzplGP3)H;0$^ z_CBj}a?^{m*gbV)AVxY!a4g0f$@!Kkc14PeX2;%F^m2b253{c>GdC}#TCE1yb@ z$ljHi6HsKyYG5~RFsv_!Bz`VtwH2(C*%K~WD?w!^2P-w)e7;@c$lgcIGGY)UfTm$Z zJXH*7CQ8BgUyG?J`JyfzPo=KvJrskVUxR~ss_3~{69oE|(c7Fp zZxJ}-PsHcXKgQ!ZG1}@<&Oae;4gxAZ5>vDmavz^qg{H&~fbZZ?h5IiJ1#b zlkS`z#~oEi+u);z6I2YrCp>0r2rnK548>7fWGY&~AC-_M^ej|d*tfGYETt^K4s1$q zBO;NuRTeB&F_A2?Dl*AA6KGBFQ`*T<{ny}YjeQ){s`Ts3rCq0oOWF~BLnXfIo~4DD zD1Qk#k#pW4OV7)hPW}XLDeE`ut0?|Q_WCRKc&N;%?Z6-1WP_P}$q(MB+WyIUqF z2fdO|;QvEj`q@b`OOxehklGS-U>>fx^3mftwq*ORQRtd_hi*JiR* zNJh3aXaI^+M3F)y^)Sptz1#(vN>*a2H^8-(W!!=CO>2*~+?@efw?;Y+092_q}#yx1|T%Z3?9bw#G3)c6@a1?xt4uZaKZ< ziRmE-9L&OGAqT;cqNSD=Spu?FN?6!TlFC_X)q7g8f?hGZRG3Q^Lcy4*GYq3tYOjYB z%#^m2$V_H9U$Ef41rzeWnd|g$*MaBp^6{PTI|njIu|_p8X)E@|LK%|`kRw5X2Ux(M z)3L*rsYaCySY?=d`NJpSVo#y?zdvhamLke77K7_yU6_t^s>+XEL8}Ng(nFps!I($v za@J4N{+AT?qn!gTtM}UuoHd4~8A@T8Wc6^;Z2nK-?Ok{c-F*k4>EYt)Aup?#qlGcb(4rD19LX}y{>zsG~J>`26 z_jBbJoXuVQ+WUlzk^sujK#f$r!kJ`KHqUL5X+eba^`(4#UdA6$>^!Me*|@V@we@`& zRkjs=W-k>9%XANR&gv7l>D4G~IA%Og7lxM7eKRWYeJryhGVI~D%)-o5@bjY*$qnX8 zKH^Jb`OiOco-_%vFRu^6czq-)V1|Sq!qjSJ?kcrYo!uOY}TxI-LyYWk*cw z`E_ybPk$A9_*YuMkDtR*t0OU!o~C0!Xvn<;*YW=arMg$p?t8LWrN5=DVtQE&!dlp) z+liZV*H(Ydhnr$|rc}&@zDaS<3+iC!>GklJ#QNP9`0BlFZI$k2A>2XJR-OnjkLG5i zS8=Mor!PL;1J|a^RcJM8Fk$R)pSVgvyhImBV!Ogk*>^Rbwi?mLAqeE?=GL<>h`iH?!^jKSR&$^L}^GalUU3 z)ST5aXVK2~+R&w}y-Y;3P8;T8epXrml{fbyY;88-^CD`KVmbW#>}|YriO##wn*edeLPA;jBI~~=m{T@n@b4McpwnFMFMLz$M_S73|+?upx2S#;&f&S}n#%NI2(4p!jh% zC_0ZF)nFuwz_QI0^dfcvdY6%j3A((G{~AO9)6Kh;yV}-R+N$Yl2(+nI83fTXmPwIo z5jBFfO%| z8BKY~-q*dqyTXpn8>0R@FIturwnZ;=n zy1w7eabHJmE@g$1uU@0mvvlH_w+;K*!XsX@N(~9AJE|}@Y-@SNU!J0H=IuHv=2`QW z%c!rf(EXlC{0xTCiPO%syK|YJvE1FXEp<3oMZ8X$TqU8})@Zvi;fce=_#51_LUcsl zCweAvF8#?gN(#ESP491AJ-+q5%Jh>e*`#wGv#`qsP%C(oLSXXC~ zrs=R5ftD54F;dKHl+tGMN{%t!6eX3$|r#WtU>qT2gtjCXq2u%j%6%Joq=O z5inTD86q*1nG-HO+C0E@(f8D1ouq$WrwR`eEM{G1V(Dd$&A*A_zpVAYE&Ko2a_aN7+1t3A;lE*da<@s_ zq39*bsq?ZycrJbkF6?wK4lKaEgvmmfMkGSH*YN_!SY#~DtkF6HBDPJI$GEvYu@_dmU3k0f#C>f{mnHgHcxw@2#s`g|g~ z*%5bOtJ26EJwBY)zq9O7>nV2f8uoC^LEgnttO-quVunNTH4e@G+M76f{sWP{#@{wp z!nN)nb*{D~9b{NHwnu|7B$9hC_h$(qkHLIjQ0%3QYw-O~2f&m2jx==7DJ-y4+h?68 z$%&x*Za-J%adK~0OXd7Roh4?{Fu7B{BJakG{*Z2ahUJ^{@o9B1QLDNm{^) z%!AAWcxWV9XYz+Trnr^SjF(8{3t842dVq+Z5BQs;t^;L0xsT`R$- zUd1%x+TUpZTQ3q#j&xPjQzU)@iNN@a6}1X=tfZZFN*t{9Z7EN+-(n{w-2J+bjq!Bt z_WE3&Rtr{&E4L|~b>}+$MO$j!Hb|M=Q1Ef_Y<*9cqL`EMe~qN}{_|Q{_ZeGZne1Tw zjyBF@yMBh-4E;Yg&AvR8Qvc1PNIp`j?&VWUgIDsoDBM{n-fCm^*%kXt5%n;sc(9@J zy18fGd%l0a%K5Y`O8F$huHQON>}>ho()shrru^{5SY7N=Z!op|k`fMl z&!8FUZ*OY06nYSD|A~3n)tN}SGT8>DtE^4%j<=tiqWaHoCYt#ez5M+`+L5a?t{C8_ z!A5=06mN+f{yn{keqVcu2k!8sxMVA<6tZ!zO6#>HyeACLv*)`vCI&(>eQOxUDIh0$ zN{<~DW=SDtx|Ulw47O6t&PhLUty0WcJ)K%upL@2@elAK4;$CT5M+T5*^*jC^ zd?D$6@1ef#h;@qa!rY$uER|iDljU+wY1p2`#v3_`U*fea23bmJ<>)hKZ`f zDaZ6Q_O?HHjt}T#_fHQm&baCE>O1kW(55^VG3VnO{f{Q!k7yoTMa?0VTQs`yT(CS# z2*y$S9dS~o)s(9s?WMGyJ^1+Yzcqt^~R0n_qqH_#U&TCMUe2!DZ=+5xCEt=S@oN$CJC|@UI!<1!^mjk2l}_@G^C{U_ zGvrfsJj}^{mzL}dKiJ3bqWhJ8eGJN9hwEu=H#)ce_waU@J9)Nzz6bbV)@<*^+HrnW z_eQ2xyVrGIpE6xf!0$hc_x;wp`J*k~)T0OT+TXn2)zgxXGdpK{mH$~?M4HcI-hbEo z-FF+E{_eHy^j+4k`RD3UmRs*@+uYXRch_zq#q9X}3;j>I@_L=$ef>XAuc_F`{-5k^ zaep6U%J6tuRIvOCAJ37EB!3$#S0}aQWAHzF-p|uluGuiPHgsM`*xbCQfBtQwo#DS1 z*xJ4GbSk&2z52HHU7xV@yZ`CEyUNJR<7adHOO46D?l|T~hl|!?`8DL@^LbrAy6^Jj z>3Ymu_Qj-WbT^sX9-ICoCd6lC=eqy1i}&*Wp6j;E+2-ssFghMoU0yD_IA{~Pmh<U5 z!qKCroeSt?^0KMK|AQ#~XPxUjNu&Q;{Jswg`W#>!R^(f36p>p82)#);;%F zxEpJ{>i;v}{5v0C^y%#2ab9(g*U3^UTECrJkvuoHWwC|ie^fmt?R9w1zO_D&M+1W= z4o&x=uJU$r40nDOBv==C9%o(b`+vg~I(w$Ctn*F&CEoY2mn!Mk*je5^JWNM&_1-s= z(eU<9-(rkTgZE=jaj^0@mUZ60;NtTzBIWV_ z=jGNsp5tZMU*zpNT7P?^+uVhl?{QbH*!Nv*HGB;2hk+JuhY!K8foGR4JwK68 z*K}^=G+KnVb~pHb7XJ%3x|+=&UtZmiSa)Q{z{WlkJI|6vhxv|i{2wxtzL3Yo zVSg(bktZB83abA{Afv5{PCw#5)9DDSe!IcL^mi4#w!d5ZJyWXR5`U$q?l7-?Yx=Fc z`&)b3+(oO%_03whO<2^Cjf+>yt-G45@w>Ti%3aH+fZhY9;T&J`a}a5y25upA(nyR- zu@Ru*g>>4equdq6wu05uY**&>amwX7+_083E59>g8XxzrQYFrmrRcSL>d?SSfS+S)a3jP z53_9(&yeygh(2xyRuXtW@h)w$CX!(q{_`Xr3=^Itk@lGh0{bZm`KeZfzFVlU*>Zt2 zBZ%=Dg}KceTd4hO5A|MexYBG=UWVvbJMIYPjdv7`uE}9->^Yf`JRP5Q6=0fB4n0Y zcp_yy^qo!yT%-IPr(b(~BclWL{DM9E6+6lJ84KIPgeY&6ILyvlc1W+kf$M&~@Nw+d zcl2A{3fP-jrL=r`YM&HNNjWZ6%6NaU;T#;LI;5~!mKhHAv`_l_7k>)asddrd%}7VJ zldQH5IBbyU{l2_Wark0*&V4^O3(t}BvcASu#|=#TTGKFVG|J3esWap$op1ATb?3^; zFHFh~%;K}3JbPR9YU?PDu)YneqIt(WX9i}IO#8^wY|nRjZI)H==sIqirk!hpR{mkC z?APjgq@M4mlVq*26U4A3WWu7%ps$z(y`o~0?o{-j7n`drBPzuH%PlFHB{^he*N@~;)!%lCJ7)!A6uHo*qn{|BGF^<;4P&GM(xgXP5eYZ7<(BK_7arrsyw`|4<_ z!mAawq#G8(DU|rJs-@GPB57%DGT;2NlsZ;90r8SNqMnKHpIpPvk5)J11y9sGLSOFj59Ff zol$hq^0p>P%LsSKnH@41;EYMcVI%9ZK!I0KckHSbAHif=gNQh#$x?0mWSc+n{*3n` zu~fpuumfyL@o8ny(_ZCiT^fLax z4PttIx^{YQjqQbIVT_|HDU5>d(@y;r)5a$Jw+qO@C(h4UcU=g%)BXpk(K48!nE~@S zc7H#8`*?Z3OI$Zot?;Sn?GK@f)=|gV`~HdAOP=DVJY4i2bCNo83uP}(286tM2KciP zn6n&8a@1Tb45vr0v?}Y0U#ZH4_MQ#Mz3uTUl=BCh3x^GFs(0Ga9e9&tDVB9e_-uXC zoK8r-Hi?zt#$_~Fl(WYgap8VWw)1c9^vH07rz?!tTz_ZDY0o3Kx*y}?XRD7-hpJWi zUVTLGCHN%DJjrqE&8y9n9`&>5oo{tzMIR=z5F~(wjMk+DC#y*Uas)ff9SywfRMoO4 zg|sb3Wkk+IWHVIOvS_KHq%~Ly+N(s>10rFW^1ZF2;(xy3`aKmyi8CupW+rkl}rcF+(8wr^Q z*!lY?udJUB!_~@@q*gA9T%cmg?|qFN`BLe^PlG6P>;-hFiZIq1S&W?>c{IceT=Gm8AH&of8ku<>5H;56dy&eu1=6+UfX^`!5_tnKVSIeJxUiQH*J6w6`TqN8OPriM z6W7^(PYYjLymFs=?B!MI;O?Ef(uH0B9#sdRtOR|0*0l#3Q297x%vI)$WhNY*d)3B8 zTxoi^m(RfLxZsw&7=*dLcZR~e!+r@vi@@GfX!kzq5%m%VSmQEau_BQ|bwcJpw@jg_N|7#7-zPH(i_MMf>dH;9HR16I ze!C?vCFG%lV(y3uCyRtcV$ko7zB~D8fGAU4F4jWTVIxZ7B) zrJLwY4r^F4%LTS{?^;!sIO}}a%6kE2n<_uK&P8QzTj^T|qP*F)L$?1L)wL(0@$2?j z1GB9lO;UG=Pk^Y+ELKkC7S@zL)`=C2fRWjzmwJ+IOB$qEDgWiD3m^Y}dDk z=l&b$)hK_G>`?~-#yj)+-H!NM@2YffNiR>`i7qSWqrWdr1Fe){WQ&oNRf`PEGQL6U zc@X11(I9LcWFf7|ed}T7LIm!P-}MuDYt9lxB(WVNF!R#4qF$ zikydz>>~OZM+{sZh?AS& zDSy-HUKQARb87i)L5u)WdqI`w<*hBMhoj(vB^hEf{>ck%g zPc9@}o(Dd<`FnS>0{$Z^xO-Wr9syU62(Ph`Lx$}NxEI@AEqhy}_S?GuhsINe9I*Bb zl3jR_;K?c_>*P^)*uMK6>?zji(`<~!3OX|^r{7{l_jw{fWH2OPFkuk0?(nAsijYzy zfhsXLc=p=IiQ{bRLRM5*yB|AeRJzYta->EiCAS$GY3N9D1aQb``8Lz1^Y#DR)!y5d zf9L4ft+b}1eA~4qYJrpWD_jfJizZfL%vy=jr7q~0*W|KGa-Tm^)Q^@wlay?_&i@G| zvCWG1R^N@2vzG&@OY%Hz=UK^qVwX)DZ~ZTK9l={B!_@Ov29^qEo^4u5J0f^#7oUh!H=?1{^S$DQaf#C5 zuLJmc3*pxP2V(84?v(JB)|7Ao6AUy%&MVX{Ddd9nUsz+ znMk?fFSyLcm?HR@RJVK?6IbeITRdN<XR5rx&RT%YE zD0e4Ya`!U1Z6-{YpR}{2f_-mS2scrjb@w~-^!5=@;8*E^&$g*UdbOOeWL5@PFSf}i z@OT?xJNXq~OBo=^8;p`B+d?BkZ2}1zffzh%EW}gOl92kjC{eyl$`tHiN?)IqLGR#2 z-^Du>)s-|=*M-+y*k%cQoL*ZiWqoy}tZ+(hOl4YmY|$9Zii_?L1F1qTT_G02HjX(Q_-`U0+s0@_1Mi>MK`BN;O{ne8hI68R4`#cZVq{LM zWA+?JN={VYLf&#~NqUIJX#BbaLIw!}8qe7pO`PGsQu|z|CAmy=*g98CZ_P&z^w)tp zac#}|%zTeamkhnmZx3ph{QL*%aFujI-qmaAMw z`Bw~``Mfu>_;Meq;A%222CDxT(aCmkE3dStEd|$<)vb5gA9ap0aGG3u(Kp-Xb4y<5 zgO=L4^HG~>W1LOuIVGM`wq$&fg`chZr>?Jm6Q**>IqaSh2gPZ1VV}_BM{R|3*(4$e zC=!)xMDDb{AN0ESO^N`v4!P5{O3*CJoa!;~{LjDFe?6F5eoaZGR5pY!U- zOxdKPuS-~6{3TWFWl0b2vY<|RR6VQ-KF(Dq5tOi*C~?H7Y9>@r%&*7e|LurOOmc+{vm>6jhTQvsb2M#!hfJTHcO?y7q})O4SR7 z6Ndy;I`OiTp1;K5*cK99guyPKk*aLPE3233Zd0jOUUAoMQfC;Q0gImzgX6{7_?EIp zMEB5{QH)VD5?KXX{XRLmg~q5=j$!yHzb9)O66dL-5mn4xU6w!*$Xktc2C5{s-t<5sxYujVwEvQNSEs{Q2Nca z;qrQYAIJQUTi;$2NHHU)EDV*DV0`Q*k%-DNjrBqEF=isnGZ3c?vjcoz+1HuLvi z6E2G{GAm_A0(28+7nkn37T#}*$m^u#MhDCEDC<<_4%|@MF^nu?Sxm`C9(5@MbjUh^erf3j;F}%;Tbm?_y;T z^5sc3-i~<8CNUOdrw=|oeTDGH<=DD16Kb0^jcKMcQmgIx{8v7E-Qi!2h^y^Ilfq}j zHVWvwE@m^e-V5G`E+1i1|}6_~>( zMdZO$-w<&0Xx}0-{M?p{i}^TGeUh_im_|WNPc9)l_}V5F8^w_{CbL4je7rdDZDu&T zw_e?3=|duqHhllhPWIYa$#u@1_pfw1z`JE5R7pq7{UQbyC$Zj;p?nWasB~aH1C?q% z4=L~}G<037dBJ#@f|CM;^75#4Nh3 zg-~M!Rqtcz{JmeR%|see#~tB2-miLx_U!8NUcV1W^1P;0vu#UNHI=4{RwVUgign@& zYZVsQ#}$^KvlTk=n-tS)F~i;QcBa++&ztP#`TLldnho=~aqplijbVkfW%MokxgZ&Z zR{Kv4rcjYaxLe2?}r*npUU9-YzH+HEKxC1tb-JX!zY)mHu9x2-DTq1B7EPSzIxs;z4~lY zuLqFt&SE2Pv(6Pj3TRmg%i*vngeF2|tHm-Nfl7+tzlHJM9aHrYP{(fGPWDrr`@Fr$ zz9=SsNwNXv$klARe853hnz_}GBtx*sc~e2!b~)4TkKiv6nib9@ZF z+@3s?01`lBOMjawRaPX{d>a@$A-!H3k`?SxWlJ$$j&xx!p0QxEk6mUf*yDWO6M>Y; z!S=DQoBkIs(()eVLCA#VkE*I`TTs!Iv(CVSR$-dF6Q%sf)1!`jqV@+*V z$Zb;udnC-02P_q{C0@q?w3|?goFw3SK+&=v;NDgNA^CT`BkB|=R?0wxaN&8@?dZOt ze`}L+pYMDZBI@=3N!3Dk*Qdig`UOV2@F_eJ^{fdkwYNx;2GV0tN#a3D*>rr*a#scF zER=gW_St;Sr1)9brs@Ws51uEgZ%bmEie7I%-*(_9%8#?AAD{1hbvIMOR#BL${g>@D zY{FhF66(a;y0yy5_{JDtSyc>JL$tg`{NIO^=eFDG5+kBQbCP==6Yl@td@!Ab3kz$)puFX`8rHtg! zi|{C1?S72LqF`kc_@Pk!e!Tp>kK%ZuVqg6Ha(XiQ9eme;236qNPx#n^yHSx<9$r3k zm!F3}$9H%9y5&c#vR9Zadmgl!r*1v}57U(ot(6qqy8FAd=Xt7yUe!>m@$NrY_guOE zGYR?Lx|*RsKN42~woN9a!zi%7Ws=pIl2p|-QAe`#;Cj~$Y^|27vofPpz6@zIGL~f- zGQz9?!fle8lOpk;)S@;+ua;`Ow+}kXiv83tMc)#t@ z-mvGvdtXVdu5B{*FzdFhFm>ZnQ>wCLV=QK4GaB!5*T0o(6whbx@*G6>v;xIFXR3Ti z5gi^801mm9|78#p4^qWKB~}J8qBuwtL4gtzjbY>u;Ax{A~wX3{%D7~ zsrc*eua0qlF5lShkBqm_g<2Z4?^|Pl?d=Aos&XG>!>&jIEHv8xb+4LITdQ+rteA&p zu@A=S{-$I^iXoYsjLW%vD0S4zT~w#XyyYMKAwC&|`d_Hz=A-v8Vev2>y~4_+16v_O zTXdYVy}fy|=Tovh+i)#n{-vy{cI96|w|G~VkkZ~w_9FEX$;o1q7zDf)Ke`t>M+HcS z4a>qQ#fyDvKK5T|+*Ud`$I>P^l>qtK8=QS^MlPFdN&Y_rj`Ef(Y~4A&_gH%j?$-O$ z6e*+R{D8-TY=?o{`B3ZTz_7SeqXzwzGrYR>WgHytZ0c_ZCNrmO$(Wof|1YD-D2rNs z*xne4iSqCq_5Db-snlxsMeK3|3G5C(tC=g|l)DBhRf#H4{>Bz1$0KRK?j_st$b4uB zxZ?PjZs^-Z8^hEQe*uda4i0?}(2H$*A}_C7GMOo`{XM#sE#r}`+2_p* z&a4Sglh`)+(cM7W*?IAx#{Ib*5*pomkjb=edc1q% zlM*s)Jh$aUFj_mD`*;^}2#ey4g=~Un9$ohOxxSO{eWc_JhVJtEnrMPRk^-|hN7n9H zd{}*!47)p5pk`i@<~on%<}m+dbT}`tyBG(he^;F`r?PGw#T4zKIx&M+MJ=($Zu&wo5H1LFuy%4 zHM(dcYUT6Uakd>M(*9OCu0Jz8_}ElNfNlS;ym$?e;5wARfeB;cE8lCt`XrPbcg#PE z-qwe5#yc1-IZmrTL6mNX1iG)4E^R9hBw)zXb-lxl zd54fw^b|o+h(+6RJ-k&~Co`ti?iu<`?g)Z5dH#>;ZRim}i0ZfP4E**7e7ODo!Y)b6 zp2P{04#3bKzc8J#9Opv{p9+JgTJm4oXbkxAv`duO2MwwbY!+n?W;>QR@aY)GB3^4$Nb=PU;uBij-7%bR^jK=Qod i_iUC0bJ?-alcEg~5{9VZu;X*^-qD(~44}MMn literal 85787 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

liu&@TP{c7cs8itvBEn#x8XyqG*e06l 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 LML1B9&Hfv}kIA*K From d638d87a0f781bb9285778eea7491ada3efb7e6e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 7 Oct 2016 09:36:38 -0600 Subject: [PATCH 093/108] Fix function reassignment --- include/chaiscript/dispatchkit/bootstrap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 553ff768..45143636 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -156,7 +156,7 @@ namespace chaiscript /// Specific version of shared_ptr_clone just for Proxy_Functions template - std::shared_ptr::type> shared_ptr_unconst_clone(const std::shared_ptr::type> &p) + std::shared_ptr::type> shared_ptr_unconst_clone(const std::shared_ptr::type> &p) { return std::const_pointer_cast::type>(p); } From 690b96d9ee90960f06245d0d78d7665941c0860c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 7 Oct 2016 11:26:30 -0600 Subject: [PATCH 094/108] Change fuzzy tests to account for prefix & changes --- unittests/fuzzy_tests-2016-06-29.tar.bz2 | Bin 85071 -> 84871 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/unittests/fuzzy_tests-2016-06-29.tar.bz2 b/unittests/fuzzy_tests-2016-06-29.tar.bz2 index 88c873062b694c95872909390cd303fbb429bab6..95fd20ae03b75b4446c7d9108652d70ab788a428 100644 GIT binary patch literal 84871 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 a#n@+c`R7lYuI!Khi@744C`d3a_(K4rF{6V3 literal 85071 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 y#N#RfDdq(3epHbpz4xHf<+>KlbsOb zl*y@adHi~t#oLOSGFIYVEUd(qU~6WTO|lx4%BA7a8l)@3kQ19KkFA1Lvm~dxl$78G zMP9QvWP>qMW)&THBY3k|Lu{1`CIqorQCL_`q-OM?kK=wu+h0pGLFn=!?_iG%$*B~6 zX<{6GK4lM9Axr%c)RXDR9bD=S6>aOA^~*2W%B9mEosVk*e;Ww8Rr=L0>R{RI{HZ;< zOp@6Q<30Qyhh^kMs<1p6KEn}m#R=!-*Wae6rIIX?Uq6W}lA$@P&V)8CI9|U$uuCXU zk%)_b=5qNaNEuaPO7Fxof8ODVywlPm?qeQxnz`WibgW1 zZpayxTVQ5FABm8gVkTsy;7OEzeic8HfXq~_>{XUP%1kDiS&^kOL*r!2378`ARdK4- z23SySjIwakLs-n544A^0jFTyp!!ruqFomlMvneU8y0xoVI5yCNstEv7v^JY+*sX$q zfEqvKVvy8EQ!AU*ciW$NlIwBOJei&O#U)LR#Wh)`Caw~7AxSV_c zTU@@K@No2SFE5Lc@Rze*XWMmcYZR+l6;|VG1z3wz!x>Z=P{J5>LdqFNYfBX#32f3# z1}g%=23Z&_2lo3Hxq+A?daOw_Ea8)>CC7~utl2^Y8tA5q>Z)CIxRzkPExSLdn8529 z^)j1cUW`U!IAp%=7rl-QIPd;K*wuF-H!Lj1_wT`2Be*#N#rQ%rRQpBWlEIYt#D{tKIchS+*>zetwl1BKNY{ zC4XNn9l=i1Dg1%p|pRu^y z%H*q>Tx*m@(X`T9<$zmJf$Sm>tE8GqVj3Vciin7!kTlTBp)#OGD}c5ZWDu9%d}cI6 z!$j$OMYokC96)4?la|LJge)1HgcY9TwJeU@$C3S?qkmt&kF|bo`Rw>N%2P3e!$E?1 z7?pa|n8hYZxh4bK!{}xDk8*fupPAdjUhXE}6&+YhKO6?p2q{MyC= z#13k;{vw>A>sUjE1-m#w&b}HdX`u#6plP1AD8FhE^?ce$>ku*`lApQq` z&HaBOAaS^!zI7_5%sSEHWNkhB;(ScfqndC#n?`G8duwh>#Y* zL{vaUUxi0knqU*eY0jjP@tSBK9Z#pP!rBc=dkV>Shlt4#Mh2`}>1DiHVG#)4UnLk2h%t#GK&t07sF z;!u3dl%B&DF)(DgRSw#$lruP-eUeR6?Br~joW9LZ<|+27Xjvwz85fWoRW2oz#Ia*6 zX<{A5TQfZV6J$++UYtWp7>~Q#O$zkoy;&iMnFwORF$_HZT^8BtMcY&Jl)-n^KaW$7 zke%T5{FM#rCh*spR#j8G_j}wwfA?y2iP%%WhoVC@=*sgvwzmjo885cU38Ktq4&xSA zW?k>={MYRH+`YG}s*`T2xGKTAj@3x+ryauM3+Nb$#OJ#H|4aYgE97URt|>9&@A(jP zuD{IQnx*oP-A`{yi%y@gsM*uVFG~wNH*ps=d6ucu)hhzFlJ@QiYrO^i+n(ZWrRvYI zyj<9-yKxuX!k(+&$;xk^^gNzO5`Mg!ylELC1dBhtJN{m3UX?v> ziPhwZ(GvEus}&cw^>BIdQ8N;Z$`wzkkXEr$8D#}dSqNQWk9RG|_~U~8rbp9M-};P! z!16;W@nqVoS1EX{UZ%W4(Q&Q8w-j4$y6Ww^OApJ2+Vvs!DfqqeQp4KNkk)l5z z_4JN zKLhA?{?{rUfMj0*GDY!`XP?|YsoB2Ej=yeEW~gMH+3d1W#$Y{Z@v|{wApP6~{a;7P z@2QpV?c{y`!S|cdaVjDhy}Vfbi#1%a9N{xL&Xvy$ZW1{xjj(`Bh}(%ix~$|avV*_* zdu;THgrDK%DmKEpu%o6SmB8v{4TU&g!QI!rRw~GK;$7d_5= zW)>z{@o>2()=J4DMRGCegr0rz6WiHCZFNxyf z18ke>wG_%a(XyIxc`{oqrYxjzLj{PS!U2!~n4N&#>(Ds^Br+2>W$ERAZuiIYelJVt zf7|6_fAhrr9&376_cKoOrklCZ@_z^L^pO4CZ$@njA8yCJ^uK5Rd|x}|_kNF$V*mL1 zU;1Evs+|Aw%*4a@ZPAX`$kNyR3-5#XqQ$TC8ipUzq51P6y#8lsdTznNeF`=!cwDG| zFFV1COuw@K#pBuB`4z2XTf6>0ZTIi9zu~y;{I5^%czY~tUi-Q2v_1`g$!6uc+zc;L z-FtqX=kMwGx7!|9`&!z`+mHWreSE*!sQ3JS<8{lOsE2#T^Q}osVatDS4s86NkMZH!+*zSw zFF)S!jqiUSHI@9QD z=HSn)cr8OwmjA7?;MK+FbrfzOm#lWP8o$HqE^{WQ*mToQxxVaV=y$$XO#frLua!Oj zN7-4iPr&N2D??*>hoPA}hgVzp;P%tw?`UtW?fRJRs9DCy?RFM$_grbdEs56n)$7!? z`srV8JWY+vH1$-s*HpD1%cZ{E^QwKXW5niVdHkMl58Zp;u1RtF9qTja%4ScNeVr*L zJYK2CCI@?*I$xR!(E0IEsNc~aq4TU)g00h!(Ja+CKEmXTg0E#h3Ef0IPoX_twezkZV6}fFdb# z>Ioty6ao%%zzO#BY|hjb>ALuGuka7Wm%@m}W~cj8iaLBxz5G0Ty3C<7ei~NNf0uzDOCo=Pkgw=vJFxza zL3MD@s_JISU)EufEKzg)Fh4}#UWIztGYJ`jxQWK9c(9#W4f>=X^+7nhU*Y5Vnf-S4 zO=|xe`1_Y_OA&u3D!5t4=yrD@`TyzFTvwmNL%x{vL`!XQ_0CT(k#8%rC@l!*@|iEP z=Z1VeM{!{;%%q&&%G8f7%7#$NO#U9iPFYls{NKD*&vi$a33)j9HrF5Xb?@h&&)=kc z?5xJVZm1YoLAFsDhL7tOmRhSVamYV#^V-o()sg53#Kp ztz!czg?;6NZj@kiNZ6( zPE*CPaX4fh7{M}(WHSkn?Z#v^L^?~knxvOCq~V#3g&eTcmY0T$-9x;*KKELmPb)D3 z7>(o@tBqa8t$xpy>v#Re-P_3;(Rr+r>*-vxtnu`9vkYOD{3}0=#lwR!c;8;>bn4}C zrbXxax#C?dfI)dG_3_ViyPc9X#lv2hYex_Ay=0HT^?#-2*6N0)B^FGSsqi3SIS_fm z_1=7Pb%skNl^^+ar4yDGvYJ-gzT0_|SBqP~>2q6x#TeQwW*L)*{p5VUSw>$m9~}>i zF(>}c{uEzRi*>hm+Imv73k5K+CaPLOtWV3$5^?^JuF7j~E6{{Gcs#s+6Xg3m9nV&L zXC+d6?1Fq*^$OCM3`elUFSbU5RaK^5!_u_%^m9KQ-HHeINADd>^3uFW#RS zK3hxnf19)WOuhT_f~Zu++Zfw$83tziR5dncvsmpRwDc8_^QFPV89wwGyE#(t#ihe6 z=i=hwicg0kud2lkSd`2I{TR99B3#)lVt~eGR7NaO*Mv#KB1idIBtPx4kvO503B{3F zkr{-aDP);|hx&L_wq_tig$voK|nJrf`ruqAkMykt&$n5$7dY@|L$d9P*37ZKCb+djsrs3i9Pq1))f zyD!=$sSdwyg*yo1;8zl`SL5Or;KX4DvYCcsFtZJ*H_=1P8xZgtRB3Az9D`!DQI)K;l+?6~ zMk-rNMA0T8lV8c#)ZDoIhIHWl9i=P9gVm9lautf{iD?W^=i^h$sSoLGjRUJ-X$+#o zGKQH3K*bt^DOp1x%9WVz*2c|d7ftz77pj;$*kNaU%L`qIJ=E8^;axDy6R%=;TkkkUsY(_+2zB z^?#|2}cPrl1)*WweO=T8sQtbx-VuRI%J(#b((w~u1?53FZ{r=QDC}I;S z_-xXpVh3rZO)gkFV8r^lQMORvlO`m=GRRI6tjv{na8L`$nIlhLrp-x>`R=qD#)kQh3K>*1l$qDw{sm^8l~L%N_v_=`Z@NzF2>X!NR7a=ewIy>? z!DN4_*G^O9!TSGVti^e~^N#|MJU#?Rv5+UAvZcoXOh~=FyvY~hVLbH1B4th21XAEr ztGg9mErA>5Q?u&Q)eVVP5TM#b#Q z;wbOlo(^!HP?u~fv=f1HSWAb_a7Q(j2^XwE10gwr{mBUg5RSi*)ClnKr$W!I6gwd( zO(x82K>)(Ox0x8ch!7#bkyVQqPRK(#xPUa`iDS%&AHvhNMUrsaghJ#g)q=Y@z1L%nrVN zln&KJ+OKcFs`F$^YHnu>!Q<86`**qDyWwK^m_&TsB!1s1CFH`W)=8`o#!#a4Fe|%? z4YHAjNU*SmG97r3FYEc5hGV~4e;LEy?cdt-`!?BGtz=L-YLS2EVy(BmSSBm&ajn~$ zjq=*e$+Q1nXv00YME(MjM z+eX9U-?;e5f&DjJDqJOucA9rpJlM3UA5JMh4~f*5c%Cv>S&FVp3S`4F_ZQ;)dRH0k z$ht%2qF)Ej{at+gsqt~$>s>;9ri0wdjg-Nd!7u6kJx7n{-Fq_>IF*TkkgTPInUgWU z?)9s|$-`7O^3ULBb{`uE%#{nCBA?UEqz`t1u3q&f68z`%uxUyhbFy%M5}C( zYZtTZE|qd4%~gMAl;y=l_bP+$M4pyFw&3P`obLVi`Ten&lS~s5v0ZF#Mc~S!v|D_3 z)I1KHDK^2rPdh64*cAHt6+C#7RkjI1?qrmnEJQpEKKBm}Qgz^H&mM(NyfYa!79uvR zVyj!nHr1-$Dz>wQCdF5q5#N=VA$X^Ygz+}^czeBlUnBMWe`~FCQEJqtg=Bi0ns}SL z_V3}W_qc40wMLNY21z~J>)PNuv0?HxO_0G~Nenvbwxsx)Ekn@1;^5kL9sD92LF`Yr zvTR*Qc$|)>+s7IFgg5O5`ttqnP2f2hQ|@wAm~T?Iie-#L3656A$c&Y?t!f-P_P?&j z#JBZYy}pFl;M3AQ7hSZEMpSxj?dY!5J5fyGBn_pkW*Eg9u|;CY5&>AXVwn~-MzB?} zi&zmPMnsV)B-w(3#iJ5v%*Y#PWfhHPMoeQt0HR}Jpuq_lh9t2tB!g8ZqA?q2+91+I zV%8J@NUa#v7RJ_*GK|>U7J@5A#i^AROHh`SX{@HAne72B(E8m?_KNs4^z^!}z;~@_ zR|!L9ln=*oyg3DQ3eUdlHBrUw*h9hRg}Rrm!dqy=LTDNTjw@8H)SH?$yl;k@Dh=u{ zpuo(9t^L-5R~^6Ks-u=l@C)MK4@#qFDD?56tdjC!6HiShOqgHC#8)hwGNbkJP)Ezc zOY<^PPZkg-vzd~vkuoUj#Y3J~EK;Wb6@qG>FCC@aVUmryf01ivvrD}t+DR`BQTM2U z)@qKT;W2vKb5AM|_BejVP~wc`o{yCWVMrOmPl$_$Y9Mfzu$EB6Af9})C|^$(xA-gFKdk2v3}t6%HaciDo6H=q_x5fL+Z5? zR!N*a&$4>_ycdEhM>N??@$990t-6@0;q}B37tDnAmtv%U%Trfpw+>k~l&Uz23O>VA z>2^8vWRGIfp!@*#dtt6GMmcfz^KY%J;jmwM9`-IcRm6v5ZP3ylX6H(BBe6M6aW1Xn zZ2vPKJq~;%96uu?oNd%{KF2C=Nrd#kPDH{)5+Dj`6AUU*_^d~Pbq!34%5^~lv;A$0 z>fuoA2TeF>V`ef}5i*#jd6jGFY#NZ;HJnPgyQON^B{*d9O_1Va+Q~dtEK5I2CB8qg z^>y!EoRx9&(r0KpGV|c}_qXxJ;~CE%jnFu@uAOLe;KH}|{7zh8%EiAFHx5|t&Shxy zua8(W=X}?+eY{uA$=L>PiRFnhTT8nX{STR{Cuwr;+n1@|;oZy7qt|$Se@B(ao9lk% z!nvTb_h8Xdt|E81Xc718DK0AjvS+2Lb>OOWjD0(DWXM0}58IDT0dida3(vH3<7i!c~d`9Ad zl8yLz>R*!KwGnm7!czI%1<#VV+>ZJkS)JIEH$$o!HLdF9S9jku$ykTCAi!mcixn%_ zxNL;sBn)_YOXFXml(X33=IYZi$=*x&-bSLE)VNq9n-{^a0cpw@FQLU(49q9HlSMEw zS&JcLGKZI;aSH-=tHoaF$7`CkSGV7}#kv;uHNZ74?~AB&R~rYClyKj(Uy0)Gr>c2{ z%);^%ymZZ9(!p1g-xcd+T1Yvmg3=nP0RsyB^=S=Z4ONv3SVN{}24y7CMUJ9%b#~WZ zcjEN)W5L$d)1OYvgSg06=2TURvME^xQj6x`i%&brpLzYSwsySbScT1&C5l)qg@VCg zuv<{nPk#lOOk}FJ$v4BG+Qs7ayN`+IDB7XOIiqJE?0M5(E_EJyVE8)ml<2Cs$<>86 zv6!sEV=yi!<>cAehb2$)@f9vPRLIBrIh*i4*Ht~^6#RUs{%+b=6~}Yp8}71ZZ$($= zV8w;Bt72s)W>JA_*zIYnYS$}kw^U#%3>c)=sikdb*4Ix=yr-pWxA6lGrIfu0$yeiG z-xg&HfM)IuHLYycDy#ax3aHcL6Gx==v(;{eyo3N$h8Uo!b~%KF?8ZvyB(&fJk?HO> zFHj9M9|%3HF_ln%2jDH<4EwlvCOb?r_wZZb24I{$8mQc`xDvlQOwt$_K*;jsOSPLJ zh=l?WzypK>0z=@_AV$(yVkzf4y10$`Upn5dea!@MM#{N!_(^ftikcIQ0H=SW*69al zc0kik9?OMA)0zX|z^LqERc1v}%nB^9lz6aEYZWUnN%8VTn!-}dJ-;r$+2sFUoGMxl zIrrXG9KH`e18%Pq?sxK;iImBPDTQH(WSW(vN=i*?)p&NbTHX2-+kneZlQ5@SXnahI zeelY(v{ER0S_uzGNWgV50gUu23@=kbz(E@?=Y4keh2rVf73E$naQ}^ETPxUdhh#F5 zl`pGHrXy^dcW2DmM_y(^o(zxoV|+vJKPOcD$EP$!JDF0S8x(ROnIOq2V6sJf$$GDU z&)j*cS8TbRn*~?7^f|l8yxO)9zPH%U;JVQq{H8tCSzUjX;eoB+SS$zOI=n-lpNCsJTf{F+Jkd>xGCr#puG zMvW<>xlLJRt)-x8Sy1;PV&#cjG6wOaYLk%~mYW9~Q*We{`JZX>cju`G*A?rX>YrMz zQg?4o00d07Uyk_u6&LVKF42H|&PV}WvUq@FMFMILzVo`<)D`{a6HCoZs=4sO_K~$I zd`LXCqI-0lAf4~L{5J_+>b}PL|1yoq+f0UJJ~s_nN1cg1Ewp9iYU7K>WVfuvpCc)l zZDnkY+ECy&t@gL3(8;VT2{M#^zEuzJzhhOo!I7FoYmCZrb?8kjmg_X2dGX`RQ%z8w zzxeuqo(G@G=k+=YyX?BrW#ZB=TU;hsU6-m_4^c45PcBn1riB&B)8{&n|n~g#UD(P zs^j8$UzGEuSr1z)pA)(&vRVZ{iB?c6(aX0y+(Xl4SYhE&?0KQF=+53yLsal@cw~X^ z$pgE8=5bT^-jcN`KfuZ(g0^O>MPn3YTFA^F)nvBB$Zb5jEpWQ{PCO6ugb^=KIo`QI1Y zZTk%13?HMN+1{KVT;uLymEdJ}RP_4Z0sW@`kH^S~j6wXYLB|VaF4$_S_i#fp%#pSf z$}py|k>^8ZvN1}`+gcN3F(sheYg=Md0~<9O9I{qqvne;r8|L*RY+7hogG5a*%2l>i zKJWUv4i;3hGcVQXpU%a#lHb_Pj2iW6N5#ZeF!_8PhS?frm(%lku*|6Z?09qh>@}0? z;(K_UahV+9JNQ$ksndyh*{Zl}4q06CmrN@8_`9)tn7+nmgC}Mw==~i!vBMO7ee~N0 zEQfE;%KesKr<^ma@@llJIci#DgvhWd29L@@N%RO^o4f z2#k(@Wj*~qiGRSDab-w-&+6!rCCWc_X&yjUzN|e!zr~M7%Y$Iin}-4DDW|qF9m^z{eQA_Uc-MX3-eAWti zE)crLG3rl$r8CbMjh1^C7+(qe0j3rq3%B3DMeZxRQrpX3W6_@DgJE~s%@?HrrxoaP z;t!_4$BpB>KH~yE2QAJxu0fK?dzMH=1mgqdkRV{~I_!lWzvspT0pl|IJ4gIaeG(HU z5j0c|!f6iYL zZ0DOAgM(46cO|`7)Or_OziwjYnup&UO%n&g;>R5b)J4l& zw}jC~!;YDb#k;H?KFSW4K-KqHpDNsRLwx0Md^F>4*g8|i%)Ef+S|-&%E{raQ7w1O= vE^hhmdy20;lnn*FcDRZyrrWL{6^VT&_;~YPVQ*cSf3UlfDZ+$>h4@l{-to(r From c37c901a0c409dea77e8d68cc875c2051ab36ec5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 7 Oct 2016 21:39:19 -0600 Subject: [PATCH 095/108] Fix MSVC build closes #287 --- include/chaiscript/language/chaiscript_optimizer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 9b406338..e8710596 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -24,7 +24,7 @@ namespace chaiscript { template auto optimize(eval::AST_Node_Impl_Ptr p) { - (void)std::initializer_list{ (p = T::optimize(p), 0)... }; + (void)std::initializer_list{ (p = static_cast(*this).optimize(p), 0)... }; return p; } }; From 21ccb1d1d0d9d16c92b75c497721435f269b7afd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 7 Oct 2016 21:54:40 -0600 Subject: [PATCH 096/108] Fix module loading --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 4e73389b..61ca7c11 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,7 +128,7 @@ std::vector default_search_paths() size_t secondtolastslash = exepath.rfind('/', lastslash - 1); if (lastslash != std::string::npos) { - paths.push_back(exepath.substr(0, lastslash)); + paths.push_back(exepath.substr(0, lastslash+1)); } if (secondtolastslash != std::string::npos) From 1efcddd33583b61f9d635a18fd5cdf49e39cac62 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 8 Oct 2016 07:38:49 -0600 Subject: [PATCH 097/108] Update releasenotes.md --- releasenotes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/releasenotes.md b/releasenotes.md index b433579c..eb4b08dd 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -26,6 +26,7 @@ Current Version: 6.0.0 * Modular optimization system; this can be accessed via the ChaiScript_Basic interface * Execution tracing capability; also accessed via ChaiScript_Basic interface +* range-based for loops `for( id : container ) { }` #### Improvements From 7339ff2c2f7c0d6f3adf2d0dcc7649c5624e9a6e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 9 Oct 2016 19:59:48 -0600 Subject: [PATCH 098/108] Update release notes for 5.8.5 --- releasenotes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/releasenotes.md b/releasenotes.md index b415a8e8..d85cdce4 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -5,6 +5,7 @@ Current Version: 5.8.5 ### Changes since 5.8.4 * Fix order of operations for prefix operators * Make sure atomics are initialized properly +* Remove parsing of unused prefix `&` operator ### Changes since 5.8.3 * Fix case with some numeric conversions mixed with numerics that do not need conversion From 23c13e65707216a155b1781ae33f811f1a88a893 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 10 Oct 2016 18:52:54 -0600 Subject: [PATCH 099/108] Apply return optimization to lambdas closes #289 --- include/chaiscript/language/chaiscript_parser.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index fa161282..769c6318 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -347,7 +347,7 @@ namespace chaiscript { for (auto &c : p->children) { - if (c->identifier == AST_Node_Type::Def && c->children.size() > 0) { + if ( (c->identifier == AST_Node_Type::Def || c->identifier == AST_Node_Type::Lambda) && c->children.size() > 0) { auto &last_child = c->children.back(); if (last_child->identifier == AST_Node_Type::Block) { auto &block_last_child = last_child->children.back(); From ab078728570a2f0e51507d57f8a821ffddea4fdf Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 10 Oct 2016 19:46:29 -0600 Subject: [PATCH 100/108] Update to 5.8.6 --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- releasenotes.md | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 944a8caf..0f6513bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MINOR 8) -set(CPACK_PACKAGE_VERSION_PATCH 5) +set(CPACK_PACKAGE_VERSION_PATCH 6) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index f5588476..3e2aff72 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -99,7 +99,7 @@ namespace chaiscript { static const int version_major = 5; static const int version_minor = 8; - static const int version_patch = 5; + static const int version_patch = 6; static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; static const char *compiler_name = CHAISCRIPT_COMPILER_NAME; diff --git a/releasenotes.md b/releasenotes.md index d85cdce4..8e1d6864 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,10 @@ Notes: ======= -Current Version: 5.8.5 + +Current Version: 5.8.6 + +### Changes since 5.8.5 +* Optimize away `return` statements in lambdas also ### Changes since 5.8.4 * Fix order of operations for prefix operators From c97a69537da038ddb1a18c8f1c8b2075b7392cd3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 13 Oct 2016 20:42:09 -0600 Subject: [PATCH 101/108] Add ability to get current script context closes #277 --- cheatsheet.md | 7 +++ .../chaiscript/language/chaiscript_common.hpp | 3 +- .../chaiscript/language/chaiscript_eval.hpp | 32 +++++----- .../chaiscript/language/chaiscript_parser.hpp | 58 ++++++++++++++++--- unittests/execution_context.chai | 42 ++++++++++++++ 5 files changed, 114 insertions(+), 28 deletions(-) create mode 100644 unittests/execution_context.chai diff --git a/cheatsheet.md b/cheatsheet.md index ab85c167..c220dfd8 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -455,6 +455,13 @@ the contained function. If both a 2 parameter and a 3 parameter signature match, the 3 parameter function always wins. +## Context + + * `__LINE__` Current file line number + * `__FILE__` Full path of current file + * `__CLASS__` Name of current class + * `__FUNC__` Mame of current function + # Built In Functions diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index ea42206e..2e8e05c5 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -31,7 +31,8 @@ namespace chaiscript { static const std::set m_reserved_words = {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto", - "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"}; + "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_", + "__LINE__", "__FILE__", "__FUNC__", "__CLASS__"}; return m_reserved_words.count(name) > 0; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 4ad24bb9..58be8a0b 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1368,30 +1368,27 @@ namespace chaiscript AST_Node_Impl_Ptr guardnode; - const auto d = t_ss->get_parent_locals(); - const auto itr = d.find("_current_class_name"); - const auto class_offset = (itr != d.end())?-1:0; - const std::string & class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; + const std::string & class_name = this->children[0]->text; //The first param of a method is always the implied this ptr. std::vector t_param_names{"this"}; dispatch::Param_Types param_types; - if ((this->children.size() > static_cast(3 + class_offset)) - && (this->children[static_cast(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { - auto args = Arg_List_AST_Node::get_arg_names(this->children[static_cast(2 + class_offset)]); + if ((this->children.size() > 3) + && (this->children[2]->identifier == AST_Node_Type::Arg_List)) { + auto args = Arg_List_AST_Node::get_arg_names(this->children[2]); t_param_names.insert(t_param_names.end(), args.begin(), args.end()); - param_types = Arg_List_AST_Node::get_arg_types(this->children[static_cast(2 + class_offset)], t_ss); + param_types = Arg_List_AST_Node::get_arg_types(this->children[2], t_ss); - if (this->children.size() > static_cast(4 + class_offset)) { - guardnode = this->children[static_cast(3 + class_offset)]; + if (this->children.size() > 4) { + guardnode = this->children[3]; } } else { //no parameters - if (this->children.size() > static_cast(3 + class_offset)) { - guardnode = this->children[static_cast(2 + class_offset)]; + if (this->children.size() > 3) { + guardnode = this->children[2]; } } @@ -1408,7 +1405,7 @@ namespace chaiscript } try { - const std::string & function_name = this->children[static_cast(1 + class_offset)]->text; + const std::string & function_name = this->children[1]->text; auto node = this->children.back(); if (function_name == class_name) { @@ -1454,13 +1451,10 @@ namespace chaiscript Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { - const auto &d = t_ss->get_parent_locals(); - const auto itr = d.find("_current_class_name"); - const auto class_offset = (itr != d.end())?-1:0; - std::string class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; + std::string class_name = this->children[0]->text; try { - std::string attr_name = this->children[static_cast(1 + class_offset)]->text; + std::string attr_name = this->children[1]->text; t_ss->add( std::make_shared( @@ -1470,7 +1464,7 @@ namespace chaiscript }), true - ), this->children[static_cast(1 + class_offset)]->text); + ), this->children[1]->text); } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Attribute redefined '" + e.name() + "'"); } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 2b384c66..7c694efb 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -839,6 +839,41 @@ namespace chaiscript } 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 == "__LINE__") { + m_match_stack.push_back(make_node>(text, start.line, start.col, + const_var(start.line))); + } else if (text == "__FILE__") { + m_match_stack.push_back(make_node>(text, start.line, start.col, + const_var(m_filename))); + } else if (text == "__FUNC__") { + const std::string fun_name = [&]()->std::string{ + for (size_t idx = m_match_stack.size() - 1; idx > 0; --idx) + { + if (m_match_stack[idx-1]->identifier == AST_Node_Type::Id + && m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) { + return m_match_stack[idx-1]->text; + } + } + return "NOT_IN_FUNCTION"; + }(); + + m_match_stack.push_back(make_node>(text, start.line, start.col, + const_var(std::move(fun_name)))); + } else if (text == "__CLASS__") { + const std::string fun_name = [&]()->std::string{ + for (size_t idx = m_match_stack.size() - 1; idx > 1; --idx) + { + if (m_match_stack[idx-2]->identifier == AST_Node_Type::Id + && m_match_stack[idx-1]->identifier == AST_Node_Type::Id + && m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) { + return m_match_stack[idx-2]->text; + } + } + return "NOT_IN_CLASS"; + }(); + + m_match_stack.push_back(make_node>(text, start.line, start.col, + const_var(std::move(fun_name)))); } else if (text == "_") { m_match_stack.push_back(make_node>(text, start.line, start.col, Boxed_Value(std::make_shared()))); @@ -1517,7 +1552,7 @@ namespace chaiscript } /// Reads a function definition from input - bool Def(const bool t_class_context = false) { + bool Def(const bool t_class_context = false, const std::string &t_class_name = "") { bool retval = false; const auto prev_stack_top = m_match_stack.size(); @@ -1525,6 +1560,10 @@ namespace chaiscript if (Keyword("def")) { retval = true; + if (t_class_context) { + m_match_stack.push_back(make_node>(t_class_name, m_position.line, m_position.col)); + } + if (!Id(true)) { throw exception::eval_error("Missing function name in definition", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1708,10 +1747,11 @@ namespace chaiscript throw exception::eval_error("Missing class name in definition", File_Position(m_position.line, m_position.col), *m_filename); } + const auto class_name = m_match_stack.back()->text; while (Eol()) {} - if (!Class_Block()) { + if (!Class_Block(class_name)) { throw exception::eval_error("Incomplete 'class' block", File_Position(m_position.line, m_position.col), *m_filename); } @@ -1908,7 +1948,7 @@ namespace chaiscript /// Reads a curly-brace C-style class block from input - bool Class_Block() { + bool Class_Block(const std::string &t_class_name) { bool retval = false; const auto prev_stack_top = m_match_stack.size(); @@ -1916,7 +1956,7 @@ namespace chaiscript if (Char('{')) { retval = true; - Class_Statements(); + Class_Statements(t_class_name); if (!Char('}')) { throw exception::eval_error("Incomplete class block", File_Position(m_position.line, m_position.col), *m_filename); } @@ -2059,7 +2099,7 @@ namespace chaiscript } /// Reads a variable declaration from input - bool Var_Decl(const bool t_class_context = false) { + bool Var_Decl(const bool t_class_context = false, const std::string &t_class_name = "") { bool retval = false; const auto prev_stack_top = m_match_stack.size(); @@ -2067,6 +2107,8 @@ namespace chaiscript if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) { retval = true; + m_match_stack.push_back(make_node>(t_class_name, m_position.line, m_position.col)); + if (!Id(true)) { throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename); } @@ -2176,7 +2218,7 @@ namespace chaiscript /// Reads a unary prefixed expression from input bool Prefix() { const auto prev_stack_top = m_match_stack.size(); - constexpr const std::array prefix_opers{"++", "--", "-", "+", "!", "~"}; + constexpr const std::array prefix_opers{{"++", "--", "-", "+", "!", "~"}}; for (const auto &oper : prefix_opers) { @@ -2351,7 +2393,7 @@ namespace chaiscript } /// Parses statements allowed inside of a class block - bool Class_Statements() { + bool Class_Statements(const std::string &t_class_name) { bool retval = false; bool has_more = true; @@ -2359,7 +2401,7 @@ namespace chaiscript while (has_more) { const auto start = m_position; - if (Def(true) || Var_Decl(true)) { + if (Def(true, t_class_name) || Var_Decl(true, t_class_name)) { if (!saw_eol) { throw exception::eval_error("Two function definitions missing line separator", File_Position(start.line, start.col), *m_filename); } diff --git a/unittests/execution_context.chai b/unittests/execution_context.chai new file mode 100644 index 00000000..2944827d --- /dev/null +++ b/unittests/execution_context.chai @@ -0,0 +1,42 @@ + + +assert_equal(__LINE__, 3) + +def f() { + [__LINE__, __CLASS__, __FUNC__] +} + +var res = f() + +assert_equal(res[0], 6) +assert_equal(res[1], "NOT_IN_CLASS") +assert_equal(res[2], "f") + +assert_equal(__CLASS__, "NOT_IN_CLASS") +assert_equal(__FUNC__, "NOT_IN_FUNCTION") + +class C +{ + def C() {} + def member() { [__LINE__, __CLASS__, __FUNC__]; } +} + +var c = C(); + +var res2 = c.member(); + +assert_equal(res2[0], 21) +assert_equal(res2[1], "C") +assert_equal(res2[2], "member") + +def C::member2() { [__LINE__, __CLASS__, __FUNC__]; } + +var res3 = c.member2(); + +assert_equal(res3[0], 32) +assert_equal(res3[1], "C") +assert_equal(res3[2], "member2") + +assert_true(__FILE__.find("execution_context.chai") != -1) + + From b99ccafa079d4838e1a9070bfce915d1c17cbf37 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 16 Oct 2016 16:04:33 -0600 Subject: [PATCH 102/108] Fix some MSVC issues * Add error if you are using too low of an MSVC compiler * Fix some warnings --- include/chaiscript/chaiscript_defines.hpp | 5 ++++- include/chaiscript/dispatchkit/proxy_functions_detail.hpp | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 1002caff..65f69887 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -12,6 +12,9 @@ #define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER) #define CHAISCRIPT_MSVC _MSC_VER #define CHAISCRIPT_HAS_DECLSPEC + +static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later required"); + #else #define CHAISCRIPT_COMPILER_VERSION __VERSION__ #endif @@ -145,7 +148,7 @@ namespace chaiscript { auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type { T t = 0; - for (char c = *t_str; (c = *t_str); ++t_str) { + for (char c = *t_str; (c = *t_str) != 0; ++t_str) { if (c < '0' || c > '9') { return t; } diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 54a1c6e0..8258521d 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -115,7 +115,15 @@ namespace chaiscript const std::vector ¶ms, const Type_Conversions_State &t_conversions) { call_func(sig, std::index_sequence_for{}, f, params, t_conversions); +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4702) +#endif + // MSVC is reporting that this is unreachable code - and it's wrong. return Handle_Return::handle(); +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif } } From 7d9e1b3af7ce78e86a4f428edefa265090b5002c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 17 Oct 2016 20:51:15 -0600 Subject: [PATCH 103/108] Add ability to disable loading external files * Options are passed to ChaiScript constructor * load_module / eval_file / use can be disabled from script context --- cheatsheet.md | 20 + include/chaiscript/chaiscript.hpp | 5 +- include/chaiscript/chaiscript_defines.hpp | 12 + .../chaiscript/language/chaiscript_engine.hpp | 91 ++--- unittests/catch.hpp | 386 +++++++++++------- unittests/compiled_tests.cpp | 71 ++++ 6 files changed, 395 insertions(+), 190 deletions(-) diff --git a/cheatsheet.md b/cheatsheet.md index c220dfd8..b6c2fc45 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -465,6 +465,23 @@ If both a 2 parameter and a 3 parameter signature match, the 3 parameter functio # Built In Functions +## Disabling Built-Ins + +When constructing a ChaiScript object, a vector of parameters can be passed in to disable or enable various built-in methods. + +Current options: + +``` +enum class Options +{ + Load_Modules, + No_Load_Modules, + External_Scripts, + No_External_Scripts +}; +``` + + ## Evaluation ``` @@ -476,4 +493,7 @@ use("filename") // evals file exactly once and returns value of last statement Both `use` and `eval_file` search the 'usepaths' passed to the ChaiScript constructor +## JSON + * `from_json` converts a JSON string into its strongly typed (map, vector, int, double, string) representations + * `to_json` converts a ChaiScript object (either a `Object` or one of map, vector, int, double, string) tree into its JSON string representation diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 076a2af0..445cf598 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -827,11 +827,12 @@ namespace chaiscript { public: ChaiScript(std::vector t_modulepaths = {}, - std::vector t_usepaths = {}) + std::vector t_usepaths = {}, + const std::vector &t_opts) : ChaiScript_Basic( chaiscript::Std_Lib::library(), std::make_unique>(), - t_modulepaths, t_usepaths) + t_modulepaths, t_usepaths, t_opts) { } }; diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 1002caff..785b86e8 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -206,6 +206,18 @@ namespace chaiscript { return parse_num(t_str.c_str()); } + enum class Options + { + No_Load_Modules, + Load_Modules, + No_External_Scripts, + External_Scripts + }; + + static inline std::vector default_options() + { + return {Options::Load_Modules, Options::External_Scripts}; + }; } #endif diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 003af4e2..659014d0 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -124,7 +124,7 @@ 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) { + void build_eval_system(const ModulePtr &t_lib, const std::vector &t_opts) { if (t_lib) { add(t_lib); @@ -169,11 +169,20 @@ namespace chaiscript - m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module"); - m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module"); + if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end() + && std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end()) + { + m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module"); + m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module"); + } + + if (std::find(t_opts.begin(), t_opts.end(), Options::No_External_Scripts) == t_opts.end() + && std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end()) + { + m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use"); + 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_file){ return use(t_file); }), "use"); - 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"); @@ -210,58 +219,28 @@ namespace chaiscript } } + std::vector ensure_minimum_path_vec(std::vector paths) + { + if (paths.empty()) { return {""}; } + else { return paths; } + } + public: + /// \brief Constructor for ChaiScript /// \param[in] t_lib Standard library to apply to this ChaiScript instance /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file ChaiScript_Basic(const ModulePtr &t_lib, std::unique_ptr &&parser, - std::vector t_modulepaths = {}, - std::vector t_usepaths = {}) - : m_module_paths(std::move(t_modulepaths)), - m_use_paths(std::move(t_usepaths)), + std::vector t_module_paths = {}, + std::vector t_use_paths = {}, + const std::vector &t_opts = chaiscript::default_options()) + : m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))), + m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths))), m_parser(std::move(parser)), m_engine(*m_parser) { - if (m_module_paths.empty()) - { - m_module_paths.push_back(""); - } - - if (m_use_paths.empty()) - { - m_use_paths.push_back(""); - } - - build_eval_system(t_lib); - } - - /// \brief Constructor for ChaiScript. - /// - /// This version of the ChaiScript constructor attempts to find the stdlib module to load - /// at runtime generates an error if it cannot be found. - /// - /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module - /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file - ChaiScript_Basic(std::unique_ptr &&parser, - std::vector t_modulepaths = {}, - std::vector t_usepaths = {}) - : m_module_paths(std::move(t_modulepaths)), - m_use_paths(std::move(t_usepaths)), - m_parser(std::move(parser)), - m_engine(*m_parser) - { - if (m_module_paths.empty()) - { - m_module_paths.push_back(""); - } - - if (m_use_paths.empty()) - { - m_use_paths.push_back(""); - } - #if defined(_POSIX_VERSION) && !defined(__CYGWIN__) // If on Unix, add the path of the current executable to the module search path // as windows would do @@ -295,8 +274,22 @@ namespace chaiscript m_module_paths.insert(m_module_paths.begin(), dllpath+"/"); } #endif + build_eval_system(t_lib, t_opts); + } - + /// \brief Constructor for ChaiScript. + /// + /// This version of the ChaiScript constructor attempts to find the stdlib module to load + /// at runtime generates an error if it cannot be found. + /// + /// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module + /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file + ChaiScript_Basic(std::unique_ptr &&parser, + std::vector t_module_paths = {}, + std::vector t_use_paths = {}, + const std::vector &t_opts = chaiscript::default_options()) + : ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts) + { try { // attempt to load the stdlib load_module("chaiscript_stdlib-" + Build_Info::version()); @@ -312,8 +305,6 @@ namespace chaiscript << t_err.what(); throw; } - - build_eval_system(ModulePtr()); } diff --git a/unittests/catch.hpp b/unittests/catch.hpp index 2554d91b..a11ecce3 100644 --- a/unittests/catch.hpp +++ b/unittests/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.3.5 - * Generated: 2016-02-29 08:16:42.342094 + * Catch v1.5.7 + * Generated: 2016-09-27 10:45:46.824849 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -62,7 +62,11 @@ #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) @@ -89,7 +93,7 @@ // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? - +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too @@ -102,8 +106,16 @@ // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 -#if defined(__cplusplus) && __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER +#ifdef __cplusplus + +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + #endif #ifdef __clang__ @@ -185,6 +197,15 @@ #endif +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + //////////////////////////////////////////////////////////////////////////////// // C++ language feature support @@ -256,6 +277,9 @@ #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_UNIQUE_PTR #endif +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS @@ -686,24 +710,28 @@ void registerTestCaseFunction #ifdef CATCH_CONFIG_VARIADIC_MACROS /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + struct TestName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ @@ -711,24 +739,28 @@ void registerTestCaseFunction #else /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void TestName() #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + struct TestCaseName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ @@ -2041,7 +2073,7 @@ namespace Catch { __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ @@ -2578,10 +2610,12 @@ namespace Catch { } /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // #included from: internal/catch_approx.hpp #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED @@ -3189,10 +3223,11 @@ namespace Catch { bool matches( TestCaseInfo const& testCase ) const { // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { if( !(*it)->matches( testCase ) ) return false; - return true; + } + return true; } }; @@ -3424,7 +3459,7 @@ namespace Catch { }; class DebugOutStream : public IStream { - std::auto_ptr m_streamBuf; + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); @@ -3572,7 +3607,7 @@ namespace Catch { } ConfigData m_data; - std::auto_ptr m_stream; + CATCH_AUTO_PTR( IStream const ) m_stream; TestSpec m_testSpec; }; @@ -3592,7 +3627,7 @@ namespace Catch { #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { // #included from: ../external/clara.h -// Version 0.0.1.1 +// Version 0.0.2.4 // Only use header guard if we are not using an outer namespace #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) @@ -3908,6 +3943,10 @@ namespace Tbc { #include #include +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CLARA_PLATFORM_WINDOWS +#endif + // Use optional outer namespace #ifdef STITCH_CLARA_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE @@ -3931,9 +3970,6 @@ namespace Clara { const unsigned int consoleWidth = 80; #endif - // Use this to try and stop compiler from warning about unreachable code - inline bool isTrue( bool value ) { return value; } - using namespace Tbc; inline bool startsWith( std::string const& str, std::string const& prefix ) { @@ -3969,14 +4005,6 @@ namespace Clara { else throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); } - inline void convertInto( bool _source, bool& _dest ) { - _dest = _source; - } - template - inline void convertInto( bool, T& ) { - if( isTrue( true ) ) - throw std::runtime_error( "Invalid conversion" ); - } template struct IArgFunction { @@ -3986,7 +4014,6 @@ namespace Clara { IArgFunction( IArgFunction const& ) = default; #endif virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual void setFlag( ConfigT& config ) const = 0; virtual bool takesArg() const = 0; virtual IArgFunction* clone() const = 0; }; @@ -4008,9 +4035,6 @@ namespace Clara { void set( ConfigT& config, std::string const& value ) const { functionObj->set( config, value ); } - void setFlag( ConfigT& config ) const { - functionObj->setFlag( config ); - } bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { @@ -4023,7 +4047,6 @@ namespace Clara { template struct NullBinder : IArgFunction{ virtual void set( C&, std::string const& ) const {} - virtual void setFlag( C& ) const {} virtual bool takesArg() const { return true; } virtual IArgFunction* clone() const { return new NullBinder( *this ); } }; @@ -4034,9 +4057,6 @@ namespace Clara { virtual void set( C& p, std::string const& stringValue ) const { convertInto( stringValue, p.*member ); } - virtual void setFlag( C& p ) const { - convertInto( true, p.*member ); - } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } M C::* member; @@ -4049,11 +4069,6 @@ namespace Clara { convertInto( stringValue, value ); (p.*member)( value ); } - virtual void setFlag( C& p ) const { - typename RemoveConstRef::type value; - convertInto( true, value ); - (p.*member)( value ); - } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } void (C::*member)( M ); @@ -4067,9 +4082,6 @@ namespace Clara { if( value ) (p.*member)(); } - virtual void setFlag( C& p ) const { - (p.*member)(); - } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } void (C::*member)(); @@ -4084,9 +4096,6 @@ namespace Clara { if( value ) function( obj ); } - virtual void setFlag( C& p ) const { - function( p ); - } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } void (*function)( C& ); @@ -4100,11 +4109,6 @@ namespace Clara { convertInto( stringValue, value ); function( obj, value ); } - virtual void setFlag( C& obj ) const { - typename RemoveConstRef::type value; - convertInto( true, value ); - function( obj, value ); - } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } void (*function)( C&, T ); @@ -4112,8 +4116,20 @@ namespace Clara { } // namespace Detail - struct Parser { - Parser() : separators( " \t=:" ) {} + inline std::vector argsToVector( int argc, char const* const* const argv ) { + std::vector args( static_cast( argc ) ); + for( std::size_t i = 0; i < static_cast( argc ); ++i ) + args[i] = argv[i]; + + return args; + } + + class Parser { + enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; + Mode mode; + std::size_t from; + bool inQuotes; + public: struct Token { enum Type { Positional, ShortOpt, LongOpt }; @@ -4122,38 +4138,75 @@ namespace Clara { std::string data; }; - void parseIntoTokens( int argc, char const* const argv[], std::vector& tokens ) const { + Parser() : mode( None ), from( 0 ), inQuotes( false ){} + + void parseIntoTokens( std::vector const& args, std::vector& tokens ) { const std::string doubleDash = "--"; - for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) - parseIntoTokens( argv[i] , tokens); + for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) + parseIntoTokens( args[i], tokens); } - void parseIntoTokens( std::string arg, std::vector& tokens ) const { - while( !arg.empty() ) { - Parser::Token token( Parser::Token::Positional, arg ); - arg = ""; - if( token.data[0] == '-' ) { - if( token.data.size() > 1 && token.data[1] == '-' ) { - token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); - } - else { - token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); - if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { - arg = "-" + token.data.substr( 1 ); - token.data = token.data.substr( 0, 1 ); - } - } - } - if( token.type != Parser::Token::Positional ) { - std::size_t pos = token.data.find_first_of( separators ); - if( pos != std::string::npos ) { - arg = token.data.substr( pos+1 ); - token.data = token.data.substr( 0, pos ); - } - } - tokens.push_back( token ); + + void parseIntoTokens( std::string const& arg, std::vector& tokens ) { + for( std::size_t i = 0; i <= arg.size(); ++i ) { + char c = arg[i]; + if( c == '"' ) + inQuotes = !inQuotes; + mode = handleMode( i, c, arg, tokens ); } } - std::string separators; + Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + switch( mode ) { + case None: return handleNone( i, c ); + case MaybeShortOpt: return handleMaybeShortOpt( i, c ); + case ShortOpt: + case LongOpt: + case SlashOpt: return handleOpt( i, c, arg, tokens ); + case Positional: return handlePositional( i, c, arg, tokens ); + default: throw std::logic_error( "Unknown mode" ); + } + } + + Mode handleNone( std::size_t i, char c ) { + if( inQuotes ) { + from = i; + return Positional; + } + switch( c ) { + case '-': return MaybeShortOpt; +#ifdef CLARA_PLATFORM_WINDOWS + case '/': from = i+1; return SlashOpt; +#endif + default: from = i; return Positional; + } + } + Mode handleMaybeShortOpt( std::size_t i, char c ) { + switch( c ) { + case '-': from = i+1; return LongOpt; + default: from = i; return ShortOpt; + } + } + Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) + return mode; + + std::string optName = arg.substr( from, i-from ); + if( mode == ShortOpt ) + for( std::size_t j = 0; j < optName.size(); ++j ) + tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); + else if( mode == SlashOpt && optName.size() == 1 ) + tokens.push_back( Token( Token::ShortOpt, optName ) ); + else + tokens.push_back( Token( Token::LongOpt, optName ) ); + return None; + } + Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) + return mode; + + std::string data = arg.substr( from, i-from ); + tokens.push_back( Token( Token::Positional, data ) ); + return None; + } }; template @@ -4456,21 +4509,21 @@ namespace Clara { return oss.str(); } - ConfigT parse( int argc, char const* const argv[] ) const { + ConfigT parse( std::vector const& args ) const { ConfigT config; - parseInto( argc, argv, config ); + parseInto( args, config ); return config; } - std::vector parseInto( int argc, char const* argv[], ConfigT& config ) const { - std::string processName = argv[0]; + std::vector parseInto( std::vector const& args, ConfigT& config ) const { + std::string processName = args[0]; std::size_t lastSlash = processName.find_last_of( "/\\" ); if( lastSlash != std::string::npos ) processName = processName.substr( lastSlash+1 ); m_boundProcessName.set( config, processName ); std::vector tokens; Parser parser; - parser.parseIntoTokens( argc, argv, tokens ); + parser.parseIntoTokens( args, tokens ); return populate( tokens, config ); } @@ -4501,7 +4554,7 @@ namespace Clara { arg.boundField.set( config, tokens[++i].data ); } else { - arg.boundField.setFlag( config ); + arg.boundField.set( config, "true" ); } break; } @@ -4667,8 +4720,11 @@ namespace Catch { std::string line; while( std::getline( f, line ) ) { line = trim(line); - if( !line.empty() && !startsWith( line, "#" ) ) - addTestOrTags( config, "\"" + line + "\"," ); + if( !line.empty() && !startsWith( line, "#" ) ) { + if( !startsWith( line, "\"" ) ) + line = "\"" + line + "\""; + addTestOrTags( config, line + "," ); + } } } @@ -5209,6 +5265,8 @@ namespace Catch bool aborting; }; + class MultipleReporters; + struct IStreamingReporter : IShared { virtual ~IStreamingReporter(); @@ -5236,6 +5294,8 @@ namespace Catch virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } }; struct IReporterFactory : IShared { @@ -5312,7 +5372,10 @@ namespace Catch { ++it ) { matchedTests++; TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - Catch::cout() << testCaseInfo.name << std::endl; + if( startsWith( testCaseInfo.name, "#" ) ) + Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl; + else + Catch::cout() << testCaseInfo.name << std::endl; } return matchedTests; } @@ -5453,6 +5516,10 @@ namespace TestCaseTracking { virtual void addChild( Ptr const& child ) = 0; virtual ITracker* findChild( std::string const& name ) = 0; virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; }; class TrackerContext { @@ -5577,6 +5644,10 @@ namespace TestCaseTracking { m_parent->openChild(); } } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + void open() { m_runState = Executing; moveToThis(); @@ -5640,13 +5711,16 @@ namespace TestCaseTracking { {} virtual ~SectionTracker(); + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { SectionTracker* section = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( name ) ) { - section = dynamic_cast( childTracker ); - assert( section ); + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = static_cast( childTracker ); } else { section = new SectionTracker( name, ctx, ¤tTracker ); @@ -5671,13 +5745,16 @@ namespace TestCaseTracking { {} virtual ~IndexTracker(); + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { IndexTracker* tracker = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( name ) ) { - tracker = dynamic_cast( childTracker ); - assert( tracker ); + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = static_cast( childTracker ); } else { tracker = new IndexTracker( name, ctx, ¤tTracker, size ); @@ -5884,6 +5961,11 @@ namespace Catch { while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } m_totals.testCases += deltaTotals.testCases; m_reporter->testCaseEnded( TestCaseStats( testInfo, deltaTotals, @@ -6275,10 +6357,10 @@ namespace Catch { Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); if( m_configData.showHelp ) showHelp( m_configData.processName ); m_config.reset(); @@ -6302,16 +6384,13 @@ namespace Catch { m_config.reset(); } - int run( int argc, char const* argv[] ) { + int run( int argc, char const* const* const argv ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); return returnCode; } - int run( int argc, char* argv[] ) { - return run( argc, const_cast( argv ) ); - } int run() { if( m_configData.showHelp ) @@ -6375,13 +6454,31 @@ namespace Catch { #include #include +#ifdef CATCH_CPP14_OR_GREATER +#include +#endif + namespace Catch { - struct LexSort { - bool operator() (TestCase i,TestCase j) const { return (i + static void shuffle( V& vector ) { + RandomNumberGenerator rng; +#ifdef CATCH_CPP14_OR_GREATER + std::shuffle( vector.begin(), vector.end(), rng ); +#else + std::random_shuffle( vector.begin(), vector.end(), rng ); +#endif + } }; inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { @@ -6390,14 +6487,12 @@ namespace Catch { switch( config.runOrder() ) { case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end(), LexSort() ); + std::sort( sorted.begin(), sorted.end() ); break; case RunTests::InRandomOrder: { seedRng( config ); - - RandomNumberGenerator rng; - std::random_shuffle( sorted.begin(), sorted.end(), rng ); + RandomNumberGenerator::shuffle( sorted ); } break; case RunTests::InDeclarationOrder: @@ -6416,13 +6511,15 @@ namespace Catch { it != itEnd; ++it ) { std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); - if( !prev.second ){ - Catch::cerr() - << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; - exit(1); + if( !prev.second ) { + std::ostringstream ss; + + ss << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + + throw std::runtime_error(ss.str()); } } } @@ -7481,7 +7578,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 5, "", 0 ); + Version libraryVersion( 1, 5, 7, "", 0 ); } @@ -8460,13 +8557,18 @@ public: // IStreamingReporter ++it ) (*it)->skipTest( testInfo ); } + + virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + return this; + } + }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { Ptr resultingReporter; if( existingReporter ) { - MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + MultipleReporters* multi = existingReporter->tryAsMulti(); if( !multi ) { multi = new MultipleReporters; resultingReporter = Ptr( multi ); @@ -8646,7 +8748,7 @@ namespace Catch { virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& sectionNode = *m_sectionStack.back(); sectionNode.assertions.push_back( assertionStats ); @@ -8856,9 +8958,10 @@ namespace Catch { break; default: - // Escape control chars - based on contribution by @espenalb in PR #465 + // Escape control chars - based on contribution by @espenalb in PR #465 and + // by @mrpi PR #588 if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) - os << "&#x" << std::uppercase << std::hex << static_cast( c ); + os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast( c ) << ';'; else os << c; } @@ -8913,13 +9016,20 @@ namespace Catch { : m_tagIsOpen( false ), m_needsNewline( false ), m_os( &Catch::cout() ) - {} + { + // We encode control characters, which requires + // XML 1.1 + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + *m_os << "\n"; + } XmlWriter( std::ostream& os ) : m_tagIsOpen( false ), m_needsNewline( false ), m_os( &os ) - {} + { + *m_os << "\n"; + } ~XmlWriter() { while( !m_tags.empty() ) @@ -9086,7 +9196,7 @@ namespace Catch { virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name ); if ( m_config->showDurations() == ShowDurations::Always ) m_testCaseTimer.start(); @@ -9777,7 +9887,7 @@ namespace Catch { if( totals.testCases.total() == 0 ) { stream << Colour( Colour::Warning ) << "No tests ran\n"; } - else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { stream << Colour( Colour::ResultSuccess ) << "All tests passed"; stream << " (" << pluralise( totals.assertions.passed, "assertion" ) << " in " diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index f9ce4cf9..ba4d2fb8 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -982,4 +982,75 @@ TEST_CASE("type_conversion to bool") module->add(chaiscript::type_conversion()); } +TEST_CASE("Test stdlib options") +{ + const auto test_has_external_scripts = [](chaiscript::ChaiScript_Basic &chai) { + CHECK_NOTHROW(chai.eval("`use`")); + CHECK_NOTHROW(chai.eval("`eval_file`")); + }; + + const auto test_no_external_scripts = [](chaiscript::ChaiScript_Basic &chai) { + CHECK_THROWS(chai.eval("`use`")); + CHECK_THROWS(chai.eval("`eval_file`")); + }; + + const auto test_has_load_modules = [](chaiscript::ChaiScript_Basic &chai) { + CHECK_NOTHROW(chai.eval("`load_module`")); + }; + + const auto test_no_load_modules = [](chaiscript::ChaiScript_Basic &chai) { + CHECK_THROWS(chai.eval("`load_module`")); + }; + + SECTION( "Defaults" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + test_has_external_scripts(chai); + test_has_load_modules(chai); + } + + SECTION( "Load_Modules, External_Scripts" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {}, + {chaiscript::Options::Load_Modules, chaiscript::Options::External_Scripts} ); + test_has_external_scripts(chai); + test_has_load_modules(chai); + } + + SECTION( "No_Load_Modules, No_External_Scripts" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {}, + {chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts} ); + test_no_external_scripts(chai); + test_no_load_modules(chai); + } + + SECTION( "No_Load_Modules, Load_Modules" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {}, + {chaiscript::Options::No_Load_Modules, chaiscript::Options::Load_Modules} ); + test_no_external_scripts(chai); + test_no_load_modules(chai); + } + + SECTION( "No_External_Scripts, External_Scripts" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {}, + {chaiscript::Options::No_External_Scripts, chaiscript::Options::External_Scripts} ); + test_no_external_scripts(chai); + test_no_load_modules(chai); + } + + SECTION( "No_External_Scripts, Load_Modules" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {}, + {chaiscript::Options::No_External_Scripts, chaiscript::Options::Load_Modules} ); + test_no_external_scripts(chai); + test_has_load_modules(chai); + } + + SECTION( "External_Scripts, No_Load_Modules" ) { + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser(), {}, {}, + {chaiscript::Options::External_Scripts, chaiscript::Options::No_Load_Modules} ); + test_has_external_scripts(chai); + test_no_load_modules(chai); + } + + +} + From 4ad661475be86fb53c54b3f1fb6fbebbaf759b56 Mon Sep 17 00:00:00 2001 From: Daniel Guzman Date: Sat, 22 Oct 2016 16:49:53 +0200 Subject: [PATCH 104/108] Fix some GCC compiler errors. --- include/chaiscript/chaiscript.hpp | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 445cf598..f8e512e1 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -828,7 +828,7 @@ namespace chaiscript public: ChaiScript(std::vector t_modulepaths = {}, std::vector t_usepaths = {}, - const std::vector &t_opts) + const std::vector &t_opts = {}) : ChaiScript_Basic( chaiscript::Std_Lib::library(), std::make_unique>(), diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index e711cae7..0a76a822 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -220,7 +220,7 @@ namespace chaiscript { static inline std::vector default_options() { return {Options::Load_Modules, Options::External_Scripts}; - }; + } } #endif From 0fe78f7ba58492e10ee7d4ebb43effc1cbd1999a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Oct 2016 08:47:49 -0600 Subject: [PATCH 105/108] Make sure to not break non-basic interface --- unittests/compiled_tests.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index ba4d2fb8..a3f7220c 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -15,6 +15,7 @@ #endif +#include #include #include #include @@ -982,6 +983,11 @@ TEST_CASE("type_conversion to bool") module->add(chaiscript::type_conversion()); } +TEST_CASE("Make sure ChaiScript object still compiles / executes") +{ + chaiscript::ChaiScript chai; +} + TEST_CASE("Test stdlib options") { const auto test_has_external_scripts = [](chaiscript::ChaiScript_Basic &chai) { From 508729ec77949d801229a38f951c46985532bebc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Oct 2016 10:08:53 -0600 Subject: [PATCH 106/108] Properly handle error reporting with method_missing --- include/chaiscript/dispatchkit/dispatchkit.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index f9d34850..cb61a914 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -963,14 +963,20 @@ namespace chaiscript This_Foist fi(*this, l_params.front()); - auto func = boxed_cast>(bv); try { - return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions); + auto func = boxed_cast>(bv); + try { + return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions); + } catch (const chaiscript::exception::bad_boxed_cast &) { + } catch (const chaiscript::exception::arity_error &) { + } catch (const chaiscript::exception::guard_error &) { + } + throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector{func}); } catch (const chaiscript::exception::bad_boxed_cast &) { - } catch (const chaiscript::exception::arity_error &) { - } catch (const chaiscript::exception::guard_error &) { + // unable to convert bv into a Proxy_Function_Base + throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, + std::vector(l_funs.begin(), l_funs.end())); } - throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()}, std::vector{func}); } else { return bv; } From 9f30d84f3950a1d48de5abb02e6dede135462012 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Oct 2016 12:29:30 -0600 Subject: [PATCH 107/108] Add conversion to bool tests as conditionals --- unittests/conversion_to_bool.chai | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 unittests/conversion_to_bool.chai diff --git a/unittests/conversion_to_bool.chai b/unittests/conversion_to_bool.chai new file mode 100644 index 00000000..d5512bf1 --- /dev/null +++ b/unittests/conversion_to_bool.chai @@ -0,0 +1,17 @@ + +// all we care is that this executes, really + +add_type_conversion(type("int"), type("bool"), fun(int i) { return i != 0; }); + +if (0) { + assert_true(false); +} + +while (0) { + assert_true(false); +} + +for (; 0; ) { + assert_true(false); +} + From 0d4a99af82d8cb077ed71a0fbbe703d027affa3e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Oct 2016 13:41:15 -0600 Subject: [PATCH 108/108] Enable conversion to bool in conditionals closes #295 --- cheatsheet.md | 28 +++++++++++++++++++ .../chaiscript/language/chaiscript_common.hpp | 4 +-- .../chaiscript/language/chaiscript_eval.hpp | 18 ++++++------ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/cheatsheet.md b/cheatsheet.md index c37045f7..6314728e 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -84,6 +84,33 @@ chai.add(chaiscript::user_type(), "MyClass"); User defined type conversions are possible, defined in either script or in C++. + +### ChaiScript Defined Conversions + +Function objects (including lambdas) can be used to add type conversions +from inside of ChaiScript: + +``` +add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); }); +``` + +### C++ Defined Conversions + +Invoking a C++ type conversion possible with `static_cast` + +``` +chai.add(chaiscript::type_conversion()); +``` + +Calling a user defined type conversion that takes a lambda + +``` +chai.add(chaiscript::type_conversion([](const TestBaseType &t_bt) { /* return converted thing */ })); +``` + + +### Helpers + A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition: ``` @@ -97,6 +124,7 @@ chai.add(chaiscript::map_conversion>()); ``` + This allows you to pass a ChaiScript function to a function requiring `std::vector` ## Adding Objects diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index b44a5a3b..65629382 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -489,9 +489,9 @@ namespace chaiscript } } - static bool get_bool_condition(const Boxed_Value &t_bv) { + static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) { try { - return boxed_cast(t_bv); + return t_ss->boxed_cast(t_bv); } catch (const exception::bad_boxed_cast &) { throw exception::eval_error("Condition not boolean"); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 000257ec..ae26fec7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -809,7 +809,7 @@ namespace chaiscript chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { - while (get_bool_condition(this->children[0]->eval(t_ss))) { + while (get_bool_condition(this->children[0]->eval(t_ss), t_ss)) { try { this->children[1]->eval(t_ss); } catch (detail::Continue_Loop &) { @@ -851,7 +851,7 @@ namespace chaiscript { assert(children.size() == 3); } virtual ~Ternary_Cond_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { - if (get_bool_condition(children[0]->eval(t_ss))) { + if (get_bool_condition(children[0]->eval(t_ss), t_ss)) { return children[1]->eval(t_ss); } else { @@ -868,7 +868,7 @@ namespace chaiscript virtual ~If_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ - if (get_bool_condition(children[0]->eval(t_ss))) { + if (get_bool_condition(children[0]->eval(t_ss), t_ss)) { return children[1]->eval(t_ss); } else { if (children.size() > 2) { @@ -878,7 +878,7 @@ namespace chaiscript return children[i+1]->eval(t_ss); } else if (children[i]->text == "else if") { - if (get_bool_condition(children[i+1]->eval(t_ss))) { + if (get_bool_condition(children[i+1]->eval(t_ss), t_ss)) { return children[i+2]->eval(t_ss); } } @@ -905,7 +905,7 @@ namespace chaiscript try { for ( children[0]->eval(t_ss); - get_bool_condition(children[1]->eval(t_ss)); + get_bool_condition(children[1]->eval(t_ss), t_ss); children[2]->eval(t_ss) ) { try { @@ -1498,8 +1498,8 @@ namespace chaiscript virtual ~Logical_And_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ - return const_var(get_bool_condition(children[0]->eval(t_ss)) - && get_bool_condition(children[2]->eval(t_ss))); + return const_var(get_bool_condition(children[0]->eval(t_ss), t_ss) + && get_bool_condition(children[2]->eval(t_ss), t_ss)); } virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE @@ -1515,8 +1515,8 @@ namespace chaiscript { assert(children.size() == 3); } virtual ~Logical_Or_AST_Node() {} virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ - return const_var(get_bool_condition(children[0]->eval(t_ss)) - || get_bool_condition(children[2]->eval(t_ss))); + return const_var(get_bool_condition(children[0]->eval(t_ss), t_ss) + || get_bool_condition(children[2]->eval(t_ss), t_ss)); } virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE

liu&@TP{c7cs8itvBEn#x8XyqG*e06l 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 LML1B9&Hfv}kIA*K diff --git a/unittests/fuzzy_tests-2016-06-29.tar.bz2 b/unittests/fuzzy_tests-2016-06-29.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..88c873062b694c95872909390cd303fbb429bab6 GIT binary patch literal 85071 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