From 3329732cebd3d12907da5218d5484275e652f3f5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 24 Sep 2011 15:21:15 -0600 Subject: [PATCH 1/5] Add scoping test --- unittests/scoping.chai | 1 + unittests/unit_test.inc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 unittests/scoping.chai diff --git a/unittests/scoping.chai b/unittests/scoping.chai new file mode 100644 index 0000000..e012100 --- /dev/null +++ b/unittests/scoping.chai @@ -0,0 +1 @@ +{ { { { assert_true(true); assert_true(true); } } } } diff --git a/unittests/unit_test.inc b/unittests/unit_test.inc index d746e7b..9d2fb91 100644 --- a/unittests/unit_test.inc +++ b/unittests/unit_test.inc @@ -23,7 +23,7 @@ def assert_true(f) { if (!f) { - print("assert_false failure"); + print("assert_true failure"); exit(-1); } } From 702b5fdba120a77f75cfd0d059a017e5d23458b8 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 25 Sep 2011 16:46:05 -0600 Subject: [PATCH 2/5] Enhance and correct error messages --- .../chaiscript/dispatchkit/dispatchkit.hpp | 7 +- .../dispatchkit/proxy_functions.hpp | 13 +- .../chaiscript/language/chaiscript_common.hpp | 111 +++++++++++++++++- .../chaiscript/language/chaiscript_eval.hpp | 42 +++---- .../chaiscript/language/chaiscript_parser.hpp | 4 +- 5 files changed, 137 insertions(+), 40 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 257379e..f6c68e2 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -688,10 +688,9 @@ namespace chaiscript /** * Dump object info to stdout */ - void dump_object(Boxed_Value o) const + void dump_object(const Boxed_Value &o) const { - Type_Info ti = o.get_type_info(); - std::cout << (ti.is_const()?"const ":"") << get_type_name(ti) << std::endl; + std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl; } /** @@ -783,7 +782,7 @@ namespace chaiscript return false; } - std::string type_name(Boxed_Value obj) const + std::string type_name(const Boxed_Value &obj) const { return get_type_name(obj.get_type_info()); } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index aa5ba0e..e04f000 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -587,17 +587,14 @@ namespace chaiscript class dispatch_error : public std::runtime_error { public: - dispatch_error() noexcept - : std::runtime_error("No matching function to dispatch to") + dispatch_error(const std::vector &t_bvs) + : std::runtime_error("Error with function dispatch"), parameters(t_bvs) { } - dispatch_error(bool is_const) noexcept - : std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":"")) - { - } - virtual ~dispatch_error() noexcept {} + + std::vector parameters; }; } @@ -631,7 +628,7 @@ namespace chaiscript ++begin; } - throw exception::dispatch_error(plist.empty()?false:plist[0].is_const()); + throw exception::dispatch_error(plist); } /** diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index f8af5e1..7b5e5ee 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -70,10 +70,23 @@ namespace chaiscript std::string filename; std::vector call_stack; + eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) noexcept : + std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_ss)), + reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname) + {} + + eval_error(const std::string &t_why, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) noexcept : + std::runtime_error(format(t_why, t_parameters, t_ss)), + reason(t_why) + {} + + eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept : std::runtime_error(format(t_why, t_where, t_fname)), reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname) - { } + {} eval_error(const std::string &t_why) noexcept : std::runtime_error("Error: \"" + t_why + "\" "), @@ -83,13 +96,101 @@ namespace chaiscript virtual ~eval_error() noexcept {} private: + static std::string format_why(const std::string &t_why) + { + return "Error: \"" + t_why + "\""; + } + + static std::string format_parameters(const std::vector &t_parameters, + const chaiscript::detail::Dispatch_Engine &t_ss) + { + std::stringstream ss; + ss << "With parameters: ("; + + if (!t_parameters.empty()) + { + std::string paramstr; + + for (const Boxed_Value &bv: t_parameters) + { + paramstr += (bv.is_const()?"const ":""); + paramstr += t_ss.type_name(bv); + paramstr += ", "; + } + + ss << paramstr.substr(0, paramstr.size() - 2); + } + ss << ")"; + + return ss.str(); + } + + static std::string format_filename(const std::string &t_fname) + { + std::stringstream ss; + + if (t_fname != "__EVAL__") + { + ss << "in '" << t_fname << "' "; + } else { + ss << "during evaluation "; + } + + return ss.str(); + } + + static std::string format_location(const File_Position &t_where) + { + std::stringstream ss; + ss << "at (" << t_where.line << ", " << t_where.column << ")"; + return ss.str(); + } + + static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) + { + std::stringstream ss; + + ss << format_why(t_why); + ss << " "; + + ss << format_parameters(t_parameters, t_ss); + ss << " "; + + ss << format_filename(t_fname); + ss << " "; + + ss << format_location(t_where); + + return ss.str(); + } + + static std::string format(const std::string &t_why, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) + { + std::stringstream ss; + + ss << format_why(t_why); + ss << " "; + + ss << format_parameters(t_parameters, t_ss); + ss << " "; + + return ss.str(); + } + static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) { std::stringstream ss; - ss << "Error: \"" << t_why << "\" " << - (t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") << - "at (" << t_where.line << ", " << - t_where.column + ")"; + + ss << format_why(t_why); + ss << " "; + + ss << format_filename(t_fname); + ss << " "; + + ss << format_location(t_where); + return ss.str(); } }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 3c7cd21..8e2b963 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -67,8 +67,8 @@ namespace chaiscript return t_ss.call_function(t_oper_string, t_lhs, t_rhs); } } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate '" + t_oper_string + "'"); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, t_ss); } } }; @@ -204,7 +204,7 @@ namespace chaiscript } catch(const exception::dispatch_error &e){ t_ss.set_stack(prev_stack); - throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss); } catch(detail::Return_Value &rv) { t_ss.set_stack(prev_stack); @@ -242,7 +242,7 @@ namespace chaiscript return (*boxed_cast(this->children[0]->eval(t_ss)))(plb); } catch(const exception::dispatch_error &e){ - throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss); } catch(detail::Return_Value &rv) { return rv.retval; @@ -312,19 +312,19 @@ namespace chaiscript try { retval = t_ss.call_function(this->children[1]->text, lhs, retval); } - catch(const exception::dispatch_error &){ - throw exception::eval_error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":".")); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, t_ss); } } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not clone right hand side of equation"); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, t_ss); } } else { try { retval = t_ss.call_function(this->children[1]->text, lhs, retval); - } catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate '" + this->children[1]->text + "'"); + } catch(const exception::dispatch_error &e){ + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, t_ss); } } } @@ -439,8 +439,8 @@ namespace chaiscript catch(std::out_of_range &) { throw exception::eval_error("Out of bounds exception"); } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate array lookup '[]' "); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, t_ss ); } } @@ -485,7 +485,7 @@ namespace chaiscript } catch(const exception::dispatch_error &e){ t_ss.set_stack(prev_stack); - throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name); + throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name, e.parameters, t_ss); } catch(detail::Return_Value &rv) { t_ss.set_stack(prev_stack); @@ -503,8 +503,8 @@ namespace chaiscript catch(std::out_of_range &) { throw exception::eval_error("Out of bounds exception"); } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate array lookup '[]' "); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, t_ss); } } } @@ -819,8 +819,8 @@ namespace chaiscript } return const_var(retval); } - catch (const exception::dispatch_error &) { - throw exception::eval_error("Can not find appropriate 'Map()'"); + catch (const exception::dispatch_error &e) { + throw exception::eval_error("Can not find appropriate copy constructor or clone while inserting into Map.", e.parameters, t_ss); } } @@ -896,8 +896,8 @@ namespace chaiscript } else { return t_ss.call_function(this->children[0]->text, bv); } - } catch (const exception::dispatch_error &) { - throw exception::eval_error("Error with prefix operator evaluation: " + children[0]->text); + } catch (const exception::dispatch_error &e) { + throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, t_ss); } } @@ -938,8 +938,8 @@ namespace chaiscript this->children[0]->children[0]->children[0]->eval(t_ss), this->children[0]->children[0]->children[1]->eval(t_ss)); } - catch (const exception::dispatch_error &) { - throw exception::eval_error("Unable to generate range vector"); + catch (const exception::dispatch_error &e) { + throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, t_ss); } } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index c176f6e..32aded3 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1587,7 +1587,7 @@ namespace chaiscript throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename); } if (!Char(')')) { - throw exception::eval_error("Missing closing parenthesis", File_Position(m_line, m_col), *m_filename); + throw exception::eval_error("Missing closing parenthesis ')'", File_Position(m_line, m_col), *m_filename); } } return retval; @@ -1605,7 +1605,7 @@ namespace chaiscript retval = true; Container_Arg_List(); if (!Char('}')) { - throw exception::eval_error("Missing closing square bracket", File_Position(m_line, m_col), *m_filename); + throw exception::eval_error("Missing closing brace '}' in container initializer", File_Position(m_line, m_col), *m_filename); } 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) { From db0e342a9632fa0e82be1f8002e1e8ac565d0fcd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 25 Sep 2011 18:34:02 -0600 Subject: [PATCH 3/5] Remove little used Param_List_Builder --- .../dispatchkit/proxy_functions.hpp | 31 ------------------- .../chaiscript/language/chaiscript_eval.hpp | 20 ++++++------ 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index e04f000..c14e1e7 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -28,37 +28,6 @@ namespace chaiscript namespace dispatch { - /** - * Helper for building a list of parameters for calling a Proxy_Function - * it does automatic conversion to Boxed_Value types via operator<< - * - * example usage: - * Boxed_Value retval = dispatch(dispatchengine.get_function("+"), - * chaiscript::Param_List_Builder() << 5 << 6); - */ - struct Param_List_Builder - { - Param_List_Builder &operator<<(const Boxed_Value &so) - { - objects.push_back(so); - return *this; - } - - template - Param_List_Builder &operator<<(T t) - { - objects.push_back(Boxed_Value(t)); - return *this; - } - - operator const std::vector &() const - { - return objects; - } - - std::vector objects; - }; - /** * Pure virtual base class for all Proxy_Function implementations * Proxy_Functions are a type erasure of type safe C++ diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 8e2b963..4337e69 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -182,11 +182,11 @@ namespace chaiscript AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Fun_Call_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ - dispatch::Param_List_Builder plb; + std::vector params; if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { for (size_t i = 0; i < this->children[1]->children.size(); ++i) { - plb << this->children[1]->children[i]->eval(t_ss); + params.push_back(this->children[1]->children[i]->eval(t_ss)); } } @@ -198,7 +198,7 @@ namespace chaiscript try { t_ss.set_stack(new_stack); - const Boxed_Value &retval = (*boxed_cast(fn))(plb); + const Boxed_Value &retval = (*boxed_cast(fn))(params); t_ss.set_stack(prev_stack); return retval; } @@ -230,16 +230,16 @@ namespace chaiscript AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inplace_Fun_Call_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ - dispatch::Param_List_Builder plb; + std::vector params; if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { for (size_t i = 0; i < this->children[1]->children.size(); ++i) { - plb << this->children[1]->children[i]->eval(t_ss); + params.push_back(this->children[1]->children[i]->eval(t_ss)); } } try { - return (*boxed_cast(this->children[0]->eval(t_ss)))(plb); + return (*boxed_cast(this->children[0]->eval(t_ss)))(params); } catch(const exception::dispatch_error &e){ throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss); @@ -458,12 +458,12 @@ namespace chaiscript if (this->children.size() > 1) { for (size_t i = 2; i < this->children.size(); i+=2) { - dispatch::Param_List_Builder plb; - plb << retval; + std::vector params; + params.push_back(retval); if (this->children[i]->children.size() > 1) { for (size_t j = 0; j < this->children[i]->children[1]->children.size(); ++j) { - plb << this->children[i]->children[1]->children[j]->eval(t_ss); + params.push_back(this->children[i]->children[1]->children[j]->eval(t_ss)); } } @@ -480,7 +480,7 @@ namespace chaiscript try { t_ss.set_stack(new_stack); - retval = t_ss.call_function(fun_name, plb); + retval = t_ss.call_function(fun_name, params); t_ss.set_stack(prev_stack); } catch(const exception::dispatch_error &e){ From 488f2ea39371f2036b6ea6a1d742f940a6410d84 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 26 Sep 2011 07:14:24 -0600 Subject: [PATCH 4/5] C++11 cleanups --- include/chaiscript/dispatchkit/bootstrap.hpp | 12 ++++------ .../chaiscript/dispatchkit/dynamic_object.hpp | 4 +--- .../dispatchkit/proxy_functions.hpp | 24 +++++++++---------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index f406780..f557aab 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -348,17 +348,13 @@ namespace chaiscript static std::vector do_return_boxed_value_vector(FunctionType f, const dispatch::Proxy_Function_Base *b) { - typedef decltype(std::mem_fn(f)) MemFunType; - typedef typename MemFunType::result_type Vector; - - Vector v = (b->*f)(); + auto v = (b->*f)(); std::vector vbv; - for (typename Vector::const_iterator itr = v.begin(); - itr != v.end(); - ++itr) + + for (const auto &o: v) { - vbv.push_back(const_var(*itr)); + vbv.push_back(const_var(o)); } return vbv; diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index e94e893..1126f28 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -111,9 +111,7 @@ namespace chaiscript virtual std::vector get_contained_functions() const { - std::vector fs; - fs.push_back(m_func); - return fs; + return {m_func}; } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index c14e1e7..e3ab3dc 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -51,7 +51,7 @@ namespace chaiscript /// if the function is variadic or takes no arguments (arity of 0 or -1), the returned /// value containes exactly 1 Type_Info object: the return type /// \returns the types of all parameters. - std::vector get_param_types() const { return m_types; } + const std::vector &get_param_types() const { return m_types; } virtual bool operator==(const Proxy_Function_Base &) const = 0; virtual bool call_match(const std::vector &vals) const = 0; @@ -262,7 +262,7 @@ namespace chaiscript // For the return type types.push_back(chaiscript::detail::Get_Type_Info::get()); - if (arity >= 0) + if (arity > 0) { for (int i = 0; i < arity; ++i) { @@ -378,6 +378,7 @@ namespace chaiscript const std::vector &t_args) { assert(t_f->get_arity() < 0 || t_f->get_arity() == static_cast(t_args.size())); + if (t_f->get_arity() < 0) { return std::vector(); } std::vector types = t_f->get_param_types(); @@ -419,8 +420,8 @@ namespace chaiscript Proxy_Function_Impl(const std::function &f) : Proxy_Function_Base(detail::build_param_type_list(static_cast(0))), m_f(f), m_dummy_func(0) - { - } + { + } virtual ~Proxy_Function_Impl() {} @@ -430,13 +431,11 @@ namespace chaiscript return pimpl != 0; } - virtual int get_arity() const { return static_cast(m_types.size()) - 1; } - virtual bool call_match(const std::vector &vals) const { if (int(vals.size()) != get_arity()) @@ -478,8 +477,8 @@ namespace chaiscript Attribute_Access(T Class::* t_attr) : Proxy_Function_Base(param_types()), m_attr(t_attr) - { - } + { + } virtual ~Attribute_Access() {} @@ -487,6 +486,7 @@ namespace chaiscript { const Attribute_Access * aa = dynamic_cast *>(&t_func); + if (aa) { return m_attr == aa->m_attr; } else { @@ -537,11 +537,9 @@ namespace chaiscript private: static std::vector param_types() { - std::vector v; - v.push_back(user_type()); - v.push_back(user_type()); - return v; + return {user_type(), user_type()}; } + T Class::* m_attr; }; } @@ -576,7 +574,7 @@ namespace chaiscript * function is found or throw dispatch_error if no matching function is found */ template - Boxed_Value dispatch(InItr begin, InItr end, + Boxed_Value dispatch(InItr begin, const InItr &end, const std::vector &plist) { while (begin != end) From b27aa50d6a8ad0d1cfa82decd2b8ee4062afc2af Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 26 Sep 2011 07:51:32 -0600 Subject: [PATCH 5/5] Minor cleanups in cv qualification removal --- include/chaiscript/dispatchkit/boxed_cast.hpp | 1 + include/chaiscript/dispatchkit/type_info.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index b75e06f..c4d820f 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -68,6 +68,7 @@ namespace chaiscript return detail::Cast_Helper::cast(bv); } catch (const chaiscript::detail::exception::bad_any_cast &) { + #ifdef CHAISCRIPT_MSVC //Thank you MSVC, yes we know that a constant value is being used in the if // statment in THIS VERSION of the template instantiation diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 87eddea..3c2fb20 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -20,7 +20,7 @@ namespace chaiscript template struct Bare_Type { - typedef typename std::remove_const::type>::type>::type type; + typedef typename std::remove_cv::type>::type>::type type; }; }