Implement option explicit for dynamic objects.

Closes #218
This commit is contained in:
Jason Turner
2015-10-16 21:41:54 -06:00
parent 882cbf2dfb
commit 7ba7b81a5c
4 changed files with 49 additions and 6 deletions

View File

@@ -354,6 +354,18 @@ o.f = fun(y) { print(this.x + y); }
o.f(10); // prints 13 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 ## method_missing
A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate A function of the signature `method_missing(object, name, param1, param2, param3)` will be called if an appropriate

View File

@@ -1002,6 +1002,7 @@ namespace chaiscript
}(); }();
if (!functions.empty()) { if (!functions.empty()) {
try {
if (is_no_param) { if (is_no_param) {
std::vector<Boxed_Value> tmp_params(params); std::vector<Boxed_Value> tmp_params(params);
tmp_params.insert(tmp_params.begin() + 1, var(t_name)); tmp_params.insert(tmp_params.begin() + 1, var(t_name));
@@ -1009,6 +1010,10 @@ namespace chaiscript
} else { } else {
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions); return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
} }
} catch (const dispatch::option_explicit_set &e) {
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
e.what());
}
} }
// If we get all the way down here we know there was no "method_missing" // If we get all the way down here we know there was no "method_missing"

View File

@@ -24,6 +24,16 @@ namespace chaiscript
{ {
namespace dispatch 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 class Dynamic_Object
{ {
public: public:
@@ -79,11 +89,19 @@ namespace chaiscript
Boxed_Value &method_missing(const std::string &t_method_name) 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); return get_attr(t_method_name);
} }
const Boxed_Value &method_missing(const std::string &t_method_name) const 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); return get_attr(t_method_name);
} }

View File

@@ -760,6 +760,14 @@ namespace chaiscript
{ {
} }
dispatch_error(std::vector<Boxed_Value> t_parameters,
std::vector<Const_Proxy_Function> 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; dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {} virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}