From 7ba7b81a5cd6ded8788d94040d9d66322aecb109 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 16 Oct 2015 21:41:54 -0600 Subject: [PATCH] Implement option explicit for dynamic objects. Closes #218 --- cheatsheet.md | 12 ++++++++++++ include/chaiscript/dispatchkit/dispatchkit.hpp | 17 +++++++++++------ .../chaiscript/dispatchkit/dynamic_object.hpp | 18 ++++++++++++++++++ .../chaiscript/dispatchkit/proxy_functions.hpp | 8 ++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/cheatsheet.md b/cheatsheet.md index 9ff4ad4..841cb92 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -354,6 +354,18 @@ o.f = fun(y) { print(this.x + y); } o.f(10); // prints 13 ``` +### Option Explicit + +If you want to disable dynamic parameter definitions, you can `set_explicit`. + +``` +class My_Class { + def My_Class() { + this.set_explicit(true); + this.x = 2; // this would fail with explicit set to true + } +}; + ## method_missing A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 305de99..aa09486 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1002,12 +1002,17 @@ namespace chaiscript }(); if (!functions.empty()) { - if (is_no_param) { - std::vector tmp_params(params); - tmp_params.insert(tmp_params.begin() + 1, var(t_name)); - return do_attribute_call(2, tmp_params, functions, m_conversions); - } else { - return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector(params.begin()+1, params.end()))}, m_conversions); + try { + if (is_no_param) { + std::vector tmp_params(params); + tmp_params.insert(tmp_params.begin() + 1, var(t_name)); + return do_attribute_call(2, tmp_params, functions, m_conversions); + } else { + return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector(params.begin()+1, params.end()))}, m_conversions); + } + } catch (const dispatch::option_explicit_set &e) { + throw chaiscript::exception::dispatch_error(params, std::vector(funs.second->begin(), funs.second->end()), + e.what()); } } diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 7df1abf..eaabf9b 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -24,6 +24,16 @@ namespace chaiscript { namespace dispatch { + struct option_explicit_set : std::runtime_error { + option_explicit_set(const std::string &t_param_name) + : std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist") + { + + } + + virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {} + }; + class Dynamic_Object { public: @@ -79,11 +89,19 @@ namespace chaiscript Boxed_Value &method_missing(const std::string &t_method_name) { + if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) { + throw option_explicit_set(t_method_name); + } + return get_attr(t_method_name); } const Boxed_Value &method_missing(const std::string &t_method_name) const { + if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) { + throw option_explicit_set(t_method_name); + } + return get_attr(t_method_name); } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index d9da2e6..6214b4d 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -760,6 +760,14 @@ namespace chaiscript { } + dispatch_error(std::vector t_parameters, + std::vector t_functions, + const std::string &t_desc) + : std::runtime_error(t_desc), parameters(std::move(t_parameters)), functions(std::move(t_functions)) + { + } + + dispatch_error(const dispatch_error &) = default; virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}