From 3d1edbf38fa7fa85802abca4a6998144a12dedb8 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 13 Jan 2015 11:44:13 -0700 Subject: [PATCH] Add missing dynamic_object_detail --- .../dispatchkit/dynamic_object_detail.hpp | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 include/chaiscript/dispatchkit/dynamic_object_detail.hpp diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp new file mode 100644 index 0000000..5683404 --- /dev/null +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -0,0 +1,251 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2014, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +#ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_ +#define CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "../chaiscript_defines.hpp" +#include "boxed_cast.hpp" +#include "boxed_cast_helper.hpp" +#include "boxed_value.hpp" +#include "proxy_functions.hpp" +#include "type_info.hpp" +#include "dynamic_object.hpp" + +namespace chaiscript { +class Type_Conversions; +namespace dispatch { +class Proxy_Function_Base; +} // namespace dispatch +} // namespace chaiscript + +namespace chaiscript +{ + namespace dispatch + { + namespace detail + { + /// A Proxy_Function implementation designed for calling a function + /// that is automatically guarded based on the first param based on the + /// param's type name + class Dynamic_Object_Function : public Proxy_Function_Base + { + public: + Dynamic_Object_Function( + std::string t_type_name, + const Proxy_Function &t_func) + : 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()) + { + assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0) + && "Programming error, Dynamic_Object_Function must have at least one parameter (this)"); + } + + Dynamic_Object_Function( + std::string t_type_name, + const Proxy_Function &t_func, + const Type_Info &t_ti) + : 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(new Type_Info(t_ti)), m_doti(user_type()) + { + assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0) + && "Programming error, Dynamic_Object_Function must have at least one parameter (this)"); + } + + virtual ~Dynamic_Object_Function() {} + + Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete; + Dynamic_Object_Function(Dynamic_Object_Function &) = delete; + + virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE + { + if (const auto *df = dynamic_cast(&f)) + { + return df->m_type_name == m_type_name && (*df->m_func) == (*m_func); + } else { + return false; + } + } + + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) + { + return m_func->call_match(vals, t_conversions); + } else { + return false; + } + } + + virtual std::vector get_contained_functions() const CHAISCRIPT_OVERRIDE + { + return {m_func}; + } + + virtual std::string annotation() const CHAISCRIPT_OVERRIDE + { + return m_func->annotation(); + } + + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions)) + { + return (*m_func)(params, t_conversions); + } else { + throw exception::guard_error(); + } + } + + virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions); + } + + private: + static std::vector build_param_types( + const std::vector &t_inner_types, const Type_Info& t_objectti) + { + std::vector types(t_inner_types); + + assert(types.size() > 1); + //assert(types[1].bare_equal(user_type())); + types[1] = t_objectti; + return types; + } + + bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name, + const std::unique_ptr &ti, const Type_Conversions &t_conversions) const + { + if (bv.get_type_info().bare_equal(m_doti)) + { + try { + const Dynamic_Object &d = boxed_cast(bv, &t_conversions); + return name == "Dynamic_Object" || d.get_type_name() == name; + } catch (const std::bad_cast &) { + return false; + } + } else { + if (ti) + { + return bv.get_type_info().bare_equal(*ti); + } else { + return false; + } + } + + } + + bool dynamic_object_typename_match(const std::vector &bvs, const std::string &name, + const std::unique_ptr &ti, const Type_Conversions &t_conversions) const + { + if (bvs.size() > 0) + { + return dynamic_object_typename_match(bvs[0], name, ti, t_conversions); + } else { + return false; + } + } + + std::string m_type_name; + Proxy_Function m_func; + std::unique_ptr m_ti; + const Type_Info m_doti; + + + }; + + + /** + * A Proxy_Function implementation designed for creating a new + * Dynamic_Object + * that is automatically guarded based on the first param based on the + * param's type name + */ + class Dynamic_Object_Constructor : public Proxy_Function_Base + { + public: + Dynamic_Object_Constructor( + std::string t_type_name, + const Proxy_Function &t_func) + : Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1), + m_type_name(std::move(t_type_name)), m_func(t_func) + { + assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0) + && "Programming error, Dynamic_Object_Function must have at least one parameter (this)"); + } + + static std::vector build_type_list(const std::vector &tl) + { + auto begin = tl.begin(); + auto end = tl.end(); + + if (begin != end) + { + ++begin; + } + + return std::vector(begin, end); + } + + virtual ~Dynamic_Object_Constructor() {} + + virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE + { + const Dynamic_Object_Constructor *dc = dynamic_cast(&f); + if (dc) + { + return dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); + } else { + return false; + } + } + + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + std::vector new_vals{Boxed_Value(Dynamic_Object(m_type_name))}; + new_vals.insert(new_vals.end(), vals.begin(), vals.end()); + + return m_func->call_match(new_vals, t_conversions); + } + + virtual std::string annotation() const CHAISCRIPT_OVERRIDE + { + return m_func->annotation(); + } + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + auto bv = var(Dynamic_Object(m_type_name)); + std::vector new_params{bv}; + new_params.insert(new_params.end(), params.begin(), params.end()); + + (*m_func)(new_params, t_conversions); + + return bv; + } + + private: + std::string m_type_name; + Proxy_Function m_func; + + }; + } + } +} +#endif +