diff --git a/dispatchkit/bootstrap.hpp b/dispatchkit/bootstrap.hpp index 28cc4d0..396d031 100644 --- a/dispatchkit/bootstrap.hpp +++ b/dispatchkit/bootstrap.hpp @@ -431,6 +431,19 @@ namespace dispatchkit register_function(s, &multiply, "*"); } + static Boxed_Value bind_function(const std::vector ¶ms) + { + if (params.size() < 2) + { + throw arity_error(params.size(), 2); + } + + boost::shared_ptr f = boxed_cast >(params[0]); + + return Boxed_Value(boost::shared_ptr(new Bound_Function(f, + std::vector(params.begin() + 1, params.end())))); + } + static void bootstrap(Dispatch_Engine &s) { s.register_type("void"); @@ -441,6 +454,7 @@ namespace dispatchkit add_basic_constructors(s, "string"); add_oper_assign(s); + register_function(s, &to_string, "to_string"); register_function(s, &to_string, "to_string"); register_function(s, &unknown_assign, "="); @@ -466,6 +480,9 @@ namespace dispatchkit s.register_function(boost::function(boost::bind(&dump_system, boost::ref(s))), "dump_system"); s.register_function(boost::function(boost::bind(&dump_object, _1)), "dump_object"); + s.register_function(boost::shared_ptr(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))), + "bind"); + register_function(s, &bool_and, "&&"); register_function(s, &bool_or, "||"); } diff --git a/dispatchkit/boxed_value.hpp b/dispatchkit/boxed_value.hpp index be70cf7..e625580 100644 --- a/dispatchkit/boxed_value.hpp +++ b/dispatchkit/boxed_value.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace dispatchkit { diff --git a/dispatchkit/proxy_functions.hpp b/dispatchkit/proxy_functions.hpp index 00f4809..4e75185 100644 --- a/dispatchkit/proxy_functions.hpp +++ b/dispatchkit/proxy_functions.hpp @@ -158,6 +158,69 @@ namespace dispatchkit int m_arity; }; + class Bound_Function : public Proxy_Function + { + public: + Bound_Function(const boost::shared_ptr &t_f, + const std::vector &t_args) + : m_f(t_f), m_args(t_args) + { + } + + bool operator==(const Proxy_Function &f) const + { + return false; + } + + virtual ~Bound_Function() {} + + virtual Boxed_Value operator()(const std::vector ¶ms) + { + typedef std::vector::const_iterator pitr; + + pitr parg = params.begin(); + pitr barg = m_args.begin(); + + std::vector args; + + while (true) + { + while (barg != m_args.end() && !barg->is_unknown()) + { + args.push_back(*barg); + ++barg; + } + + if (parg != params.end()) + { + args.push_back(*parg); + ++parg; + } + + if (barg != m_args.end() && barg->is_unknown()) + { + ++barg; + } + + if (parg == params.end() && barg == m_args.end()) + { + break; + } + } + + return (*m_f)(args); + } + + virtual std::vector get_param_types() + { + return std::vector(); + } + + private: + boost::shared_ptr m_f; + std::vector m_args; + }; + template class Proxy_Function_Impl : public Proxy_Function { diff --git a/dispatchkit/type_info.hpp b/dispatchkit/type_info.hpp index 5841a56..e0651d0 100644 --- a/dispatchkit/type_info.hpp +++ b/dispatchkit/type_info.hpp @@ -1,7 +1,13 @@ #ifndef __type_info_hpp__ #define __type_info_hpp__ -#include +#include +#include +#include +#include +#include +#include +#include #include namespace dispatchkit diff --git a/samples/bind.chai b/samples/bind.chai new file mode 100644 index 0000000..71e699a --- /dev/null +++ b/samples/bind.chai @@ -0,0 +1,30 @@ + +//This is a cheater function. The entire point of it is to return a variable +// with an unspecified type. +// The bind function will substitute any unknown object with those passed in +def _() +{ + var i; + return i; +} + +def add(x, y) +{ + return x + y; +} + +var b = bind(add, 2, _()); +var c = bind(b, 3); + +print(b(4)); +print(c()); + + +def concat(a,b,c,d) +{ + return to_string(a) + to_string(b) + to_string(c) + to_string(d); +} + +var d = bind(concat, _(), " Hello ", _(), " World "); +print(d(1, 3)); +print(d(1, 3, 4));