diff --git a/CMakeLists.txt b/CMakeLists.txt index 09444f7..a8187a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp") list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt") -set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.txt") +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt") set(CPACK_PACKAGE_VERSION_MAJOR 5) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 1a45b5d..b7fdc04 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -443,6 +443,7 @@ namespace chaiscript bootstrap_pod_type("long_double", m); bootstrap_pod_type("float", m); bootstrap_pod_type("int", m); + bootstrap_pod_type("long", m); bootstrap_pod_type("unsigned_int", m); bootstrap_pod_type("unsigned_long", m); bootstrap_pod_type("size_t", m); diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index b26e9ca..40ff1df 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -148,6 +148,96 @@ namespace chaiscript }; namespace detail { + template + int return_int_impl(const std::function &t_func, const T *t_obj) + { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4267) +#endif + return t_func(t_obj); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + + template + std::function return_int(size_t (T::*t_func)() const) + { + return std::bind(&return_int_impl, std::function(std::mem_fn(t_func)), std::placeholders::_1); + } + + template + int return_int_impl(const std::function &t_func, const T *t_obj, P1 p1) + { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4267) +#endif + return t_func(t_obj, p1); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + + template + int return_int_impl_non_const(const std::function &t_func, T *t_obj, P1 p1) + { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4267) +#endif + return t_func(t_obj, p1); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + + template + std::function return_int(size_t (T::*t_func)(P1) const) + { + return std::bind(&return_int_impl, std::function(std::mem_fn(t_func)), std::placeholders::_1, std::placeholders::_2); + } + + template + std::function return_int(size_t (T::*t_func)(P1) ) + { + return std::bind(&return_int_impl_non_const, std::function(std::mem_fn(t_func)), std::placeholders::_1, std::placeholders::_2); + } + + + template + int return_int_impl(const std::function &t_func, const T *t_obj, P1 p1, P2 p2) + { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4267) +#endif + return t_func(t_obj, p1, p2); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + + template + std::function return_int(size_t (T::*t_func)(P1, P2) const) + { + return std::bind(&return_int_impl, std::function(std::mem_fn(t_func)), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + } + + template + void insert(T &t_target, const T &t_other) + { + t_target.insert(t_other.begin(), t_other.end()); + } + + template + void insert_ref(T &t_target, const typename T::value_type &t_val) + { + t_target.insert(t_val); + } + + /** * Add Bidir_Range support for the given ContainerType @@ -393,6 +483,23 @@ namespace chaiscript { m->add(fun(&ContainerType::count), "count"); + + typedef size_t (ContainerType::*erase)(const typename ContainerType::key_type &); + erase eraseptr(&ContainerType::erase); + + m->add(fun(std::function(detail::return_int(eraseptr))), "erase"); + + m->add(fun(&detail::insert), "insert"); + + std::string insert_name; + if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) + { + insert_name = "insert_ref"; + } else { + insert_name = "insert"; + } + + m->add(fun(&detail::insert_ref), insert_name); return m; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 2c3fd3f..0621a7f 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -104,6 +104,9 @@ namespace chaiscript Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(int(atoi(t_ast_node_text.c_str())))) { } + Int_AST_Node(const std::string &t_ast_node_text = "", const Boxed_Value &t_bv = const_var(0), int t_id = AST_Node_Type::Int, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(t_bv) { } virtual ~Int_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){ return m_value; @@ -119,6 +122,9 @@ namespace chaiscript Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(double(atof(t_ast_node_text.c_str())))) { } + Float_AST_Node(const std::string &t_ast_node_text = "", const Boxed_Value &t_bv = const_var(0), int t_id = AST_Node_Type::Float, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(t_bv) { } virtual ~Float_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){ return m_value; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 3172672..8f5c2b3 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -33,6 +33,8 @@ namespace chaiscript , bin_alphabet , id_alphabet , white_alphabet + , int_suffix_alphabet + , float_suffix_alphabet , max_alphabet , lengthof_alphabet = 256 }; @@ -175,6 +177,17 @@ namespace chaiscript m_alphabet[detail::white_alphabet][static_cast(' ')]=true; m_alphabet[detail::white_alphabet][static_cast('\t')]=true; + + m_alphabet[detail::int_suffix_alphabet][static_cast('l')] = true; + m_alphabet[detail::int_suffix_alphabet][static_cast('L')] = true; + m_alphabet[detail::int_suffix_alphabet][static_cast('u')] = true; + m_alphabet[detail::int_suffix_alphabet][static_cast('U')] = true; + + m_alphabet[detail::float_suffix_alphabet][static_cast('l')] = true; + m_alphabet[detail::float_suffix_alphabet][static_cast('L')] = true; + m_alphabet[detail::float_suffix_alphabet][static_cast('f')] = true; + m_alphabet[detail::float_suffix_alphabet][static_cast('F')] = true; + } /** @@ -343,6 +356,12 @@ namespace chaiscript ++m_input_pos; ++m_col; } + + while (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_suffix_alphabet)) + { + ++m_input_pos; + ++m_col; + } } else { --m_input_pos; @@ -371,6 +390,11 @@ namespace chaiscript ++m_input_pos; ++m_col; } + while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet)) + { + ++m_input_pos; + ++m_col; + } } else { --m_input_pos; @@ -386,6 +410,14 @@ namespace chaiscript return retval; } + void IntSuffix_() { + while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet)) + { + ++m_input_pos; + ++m_col; + } + } + /** * Reads a binary value from input, without skipping initial whitespace */ @@ -419,6 +451,110 @@ namespace chaiscript return retval; } + Boxed_Value buildFloat(const std::string &t_val) + { + bool float_ = false; + bool long_ = false; + + size_t i = t_val.size(); + + for (; i > 0; --i) + { + char val = t_val[i-1]; + + if (val == 'f' || val == 'F') + { + float_ = true; + } else if (val == 'l' || val == 'L') { + long_ = true; + } else { + break; + } + } + + std::stringstream ss(t_val.substr(0, i)); + + if (float_) + { + float f; + ss >> f; + return Boxed_Value(const_var(f)); + } else if (long_) { + long double f; + ss >> f; + return Boxed_Value(const_var(f)); + } else { + double f; + ss >> f; + return Boxed_Value(const_var(f)); + } + } + + template + Boxed_Value buildInt(const IntType &t_type, const std::string &t_val) + { + bool unsigned_ = false; + bool long_ = false; + bool longlong_ = false; + + size_t i = t_val.size(); + + for (; i > 0; --i) + { + char val = t_val[i-1]; + + if (val == 'u' || val == 'U') + { + unsigned_ = true; + } else if (val == 'l' || val == 'L') { + if (long_) + { + longlong_ = true; + } + + long_ = true; + } else { + break; + } + } + + std::stringstream ss(t_val.substr(0, i)); + ss >> t_type; + + if (unsigned_) + { + if (longlong_) + { + uint64_t val; + ss >> val; + return Boxed_Value(const_var(val)); + } else if (long_) { + unsigned long val; + ss >> val; + return Boxed_Value(const_var(val)); + } else { + unsigned int val; + ss >> val; + return Boxed_Value(const_var(val)); + } + } else { + if (longlong_) + { + int64_t val; + ss >> val; + return Boxed_Value(const_var(val)); + } else if (long_) { + long val; + ss >> val; + return Boxed_Value(const_var(val)); + } else { + int val; + ss >> val; + return Boxed_Value(const_var(val)); + } + } + } + /** * Reads a number from the input, detecting if it's an integer or floating point */ @@ -435,19 +571,14 @@ namespace chaiscript if (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_alphabet) ) { if (Hex_()) { std::string match(start, m_input_pos); - std::stringstream ss(match); - unsigned int temp_int; - ss >> std::hex >> temp_int; - - std::ostringstream out_int; - out_int << static_cast(temp_int); - AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); + Boxed_Value i = buildInt(std::hex, match); + AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); m_match_stack.push_back(t); return true; } if (Binary_()) { std::string match(start, m_input_pos); - int temp_int = 0; + int64_t temp_int = 0; size_t pos = 0, end = match.length(); while ((pos < end) && (pos < (2 + sizeof(int) * 8))) { @@ -458,32 +589,36 @@ namespace chaiscript ++pos; } - std::ostringstream out_int; - out_int << temp_int; - AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); + Boxed_Value i; + if (match.length() <= sizeof(int) * 8) + { + i = Boxed_Value(const_var(int(temp_int))); + } else { + i = Boxed_Value(const_var(temp_int)); + } + + AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); m_match_stack.push_back(t); return true; } if (Float_()) { std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Float_AST_Node(match, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col)); + Boxed_Value f = buildFloat(match); + AST_NodePtr t(new eval::Float_AST_Node(match, f, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col)); m_match_stack.push_back(t); return true; } else { + IntSuffix_(); std::string match(start, m_input_pos); if ((match.size() > 0) && (match[0] == '0')) { - std::stringstream ss(match); - unsigned int temp_int; - ss >> std::oct >> temp_int; - - std::ostringstream out_int; - out_int << int(temp_int); - AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); + Boxed_Value i = buildInt(std::oct, match); + AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); m_match_stack.push_back(t); } else { - AST_NodePtr t(new eval::Int_AST_Node(match, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); + Boxed_Value i = buildInt(std::dec, match); + AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col)); m_match_stack.push_back(t); } return true; diff --git a/unittests/map.chai b/unittests/map.chai index a0a31ee..b2901ce 100644 --- a/unittests/map.chai +++ b/unittests/map.chai @@ -1 +1,29 @@ assert_equal([true, false, true], map([1,2,3], odd)) + + + +var m = ["a":1, "b":2]; + +assert_equal(1, m.count("a")) +assert_equal(0, m.count("c")) +assert_equal(1, m.erase("a")) +assert_equal(1, m.size()) +assert_equal(0, m.erase("a")) + +assert_equal(1, m.size()); + +var m2 = ["c":3, "b":4] +m.insert(m2); + +assert_equal(3, m["c"]) +// The inserted values do not overwrite the existing ones +assert_equal(2, m["b"]) +assert_equal(2, m.size()) + +var v = "bob"; + +m.insert_ref(Map_Pair("d", v)) + +assert_equal("bob", m["d"]) +v = "bob2" +assert_equal("bob2", m["d"])