attributes / members holding functions works fully now

Issue #155
This commit is contained in:
Jason Turner 2015-04-17 16:32:59 -06:00
parent d2ed8fdcf1
commit ecd2e523f7
6 changed files with 69 additions and 11 deletions

View File

@ -793,6 +793,42 @@ namespace chaiscript
return m_conversions;
}
bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
bool t_has_params) const
{
if (!t_has_params || t_params.empty()) {
return false;
}
for (const auto &fun : t_funs) {
if (fun->is_attribute_function()) {
if (fun->compare_first_type(t_params[0], m_conversions)) {
return true;
}
}
}
return false;
}
Boxed_Value call_member(const std::string &t_name, const std::vector<Boxed_Value> &params, bool t_has_params) const
{
auto funs = get_function(t_name);
if (is_attribute_call(funs, params, t_has_params)) {
std::vector<Boxed_Value> attr_params{params[0]};
std::vector<Boxed_Value> remaining_params{params.begin() + 1, params.end()};
Boxed_Value bv = dispatch::dispatch(funs, attr_params, m_conversions);
if (!remaining_params.empty() || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
return (*boxed_cast<const dispatch::Proxy_Function_Base *>(bv))(remaining_params, m_conversions);
} else {
return bv;
}
} else {
return dispatch::dispatch(funs, params, m_conversions);
}
}
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const
{
Boxed_Value bv = dispatch::dispatch(get_function(t_name), params, m_conversions);

View File

@ -44,9 +44,11 @@ namespace chaiscript
public:
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func)
const Proxy_Function &t_func,
bool t_is_attribute = false)
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>())
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>()),
m_is_attribute(t_is_attribute)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
@ -55,9 +57,11 @@ namespace chaiscript
Dynamic_Object_Function(
std::string t_type_name,
const Proxy_Function &t_func,
const Type_Info &t_ti)
const Type_Info &t_ti,
bool t_is_attribute = false)
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>()),
m_is_attribute(t_is_attribute)
{
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
@ -78,6 +82,8 @@ namespace chaiscript
}
}
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
@ -164,6 +170,7 @@ namespace chaiscript
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
bool m_is_attribute;
};

View File

@ -162,6 +162,8 @@ namespace chaiscript
virtual bool operator==(const Proxy_Function_Base &) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
virtual bool is_attribute_function() const { return false; }
bool has_arithmetic_param() const
{
return m_has_arithmetic_param;
@ -219,6 +221,12 @@ namespace chaiscript
return false;
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
{
return compare_type_to_param(m_types[1], bv, t_conversions);
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const = 0;
@ -236,10 +244,6 @@ namespace chaiscript
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
{
return compare_type_to_param(m_types[1], bv, t_conversions);
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
{
@ -654,6 +658,8 @@ namespace chaiscript
virtual ~Attribute_Access() {}
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; }
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
{
const Attribute_Access<T, Class> * aa

View File

@ -704,7 +704,10 @@ namespace chaiscript
for (size_t i = 2; i < this->children.size(); i+=2) {
std::vector<Boxed_Value> params{retval};
bool has_function_params = false;
if (this->children[i]->children.size() > 1) {
has_function_params = true;
for (const auto &child : this->children[i]->children[1]->children) {
params.push_back(child->eval(t_ss));
}
@ -723,7 +726,7 @@ namespace chaiscript
try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
retval = t_ss.call_function(fun_name, std::move(params));
retval = t_ss.call_member(fun_name, std::move(params), has_function_params);
}
catch(const exception::dispatch_error &e){
if (e.functions.empty())
@ -1534,7 +1537,9 @@ namespace chaiscript
std::placeholders::_1,
this->children[static_cast<size_t>(1 + class_offset)]->text
))
)
),
true
), this->children[static_cast<size_t>(1 + class_offset)]->text);
}

View File

@ -1319,9 +1319,10 @@ namespace chaiscript
}
} while (Char(','));
}
build_match(std::make_shared<eval::Arg_List_AST_Node>(), prev_stack_top);
}
build_match(std::make_shared<eval::Arg_List_AST_Node>(), prev_stack_top);
SkipWS(true);
return retval;

View File

@ -18,3 +18,6 @@ assert_true(func_member(t0)(2) == 6)
assert_true((func_member(t0))(2) == 6)
assert_true(t0.func_member(2) == 6)
t0.func_member = fun() { 12; };
assert_true(t0.func_member() == 12);