From ed7bdfb17242702855b140c728af6b5086b99577 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Sep 2012 11:31:19 -0600 Subject: [PATCH 1/3] Add "erase" function to associative sets (maps) --- CMakeLists.txt | 2 +- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 25 +++++++++++++++++++ unittests/map.chai | 12 +++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44c8b6d..69aa2d0 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 4) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 40f9687..0a53201 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -176,6 +176,19 @@ namespace chaiscript return t_func(t_obj, p1); #ifdef BOOST_MSVC #pragma warning(pop) +#endif + } + + template + int return_int_impl_non_const(const boost::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 } @@ -185,6 +198,13 @@ namespace chaiscript return boost::bind(&return_int_impl, boost::function(boost::mem_fn(t_func)), _1, _2); } + template + boost::function return_int(size_t (T::*t_func)(P1) ) + { + return boost::bind(&return_int_impl_non_const, boost::function(boost::mem_fn(t_func)), _1, _2); + } + + template int return_int_impl(const boost::function &t_func, const T *t_obj, P1 p1, P2 p2) { @@ -452,6 +472,11 @@ namespace chaiscript { m->add(fun(boost::function(detail::return_int(&ContainerType::count))), "count"); + + typedef size_t (ContainerType::*erase)(const typename ContainerType::key_type &); + erase eraseptr(&ContainerType::erase); + + m->add(fun(boost::function(detail::return_int(eraseptr))), "erase"); return m; } diff --git a/unittests/map.chai b/unittests/map.chai index a0a31ee..3fe753a 100644 --- a/unittests/map.chai +++ b/unittests/map.chai @@ -1 +1,13 @@ 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")) + + From 9832d1ce39395970eaecd8f691bed5d1ab8267e3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Sep 2012 12:38:32 -0600 Subject: [PATCH 2/3] Add insert and insert_ref methods to "map" types --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 26 +++++++++++++++++++ unittests/map.chai | 16 ++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 0a53201..88fed35 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -224,6 +224,20 @@ namespace chaiscript return boost::bind(&return_int_impl, boost::function(boost::mem_fn(t_func)), _1, _2, _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 @@ -477,6 +491,18 @@ namespace chaiscript erase eraseptr(&ContainerType::erase); m->add(fun(boost::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/unittests/map.chai b/unittests/map.chai index 3fe753a..b2901ce 100644 --- a/unittests/map.chai +++ b/unittests/map.chai @@ -10,4 +10,20 @@ 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"]) From 623c64299ac5e98abaf08aa5a9f2c98290aa6f87 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 7 Nov 2012 12:05:34 -0700 Subject: [PATCH 3/3] Add ability to specify number prefixes for floating point and integers. --- include/chaiscript/dispatchkit/bootstrap.hpp | 1 + .../chaiscript/language/chaiscript_eval.hpp | 6 + .../chaiscript/language/chaiscript_parser.hpp | 175 ++++++++++++++++-- 3 files changed, 162 insertions(+), 20 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index fe57d70..6fcc11c 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -447,6 +447,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/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index ea7902f..c11b708 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -103,6 +103,9 @@ namespace chaiscript Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr &t_fname=boost::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 boost::shared_ptr &t_fname=boost::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; @@ -118,6 +121,9 @@ namespace chaiscript Float_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Float, const boost::shared_ptr &t_fname=boost::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 boost::shared_ptr &t_fname=boost::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 b1258e4..fee0717 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_) + { + boost::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_) + { + boost::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;