Bound_Function(const Const_Proxy_Function &t_f, 
     const std::vector<Boxed_Value> &t_args)
   : Proxy_Function_Base(build_param_type_info(t_f, t_args)),
     m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
 {
   assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
 }
        static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f, 
            const std::vector<Boxed_Value> &t_args)
        {
          assert(t_f->get_arity() < 0 || t_f->get_arity() == static_cast<int>(t_args.size()));

          if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }

          std::vector<Type_Info> types = t_f->get_param_types();
          assert(types.size() == t_args.size() + 1);

          std::vector<Type_Info> retval;
          retval.push_back(types[0]);
          for (size_t i = 0; i < types.size()-1; ++i)
          {
            if (t_args[i].get_type_info() == chaiscript::detail::Get_Type_Info<Placeholder_Object>::get())
            {
              retval.push_back(types[i+1]);
            }
          }

          return retval;
        }
      static std::string format_types(const Const_Proxy_Function &t_func,
          bool t_dot_notation,
          const chaiscript::detail::Dispatch_Engine &t_ss)
      {
        int arity = t_func->get_arity();
        std::vector<Type_Info> types = t_func->get_param_types();

        std::string retval;
        if (arity == -1)
        {
          retval = "(...)";
          if (t_dot_notation)
          {
            retval = "(Object)." + retval;
          }
        } else if (types.size() <= 1) {
          retval = "()";
        } else {
          std::stringstream ss;
          ss << "(";

          std::string paramstr;

          for (size_t index = 1;
               index != types.size();
               ++index)
          {
            paramstr += (types[index].is_const()?"const ":"");
            paramstr += t_ss.get_type_name(types[index]);

            if (index == 1 && t_dot_notation)
            {
              paramstr += ").(";
              if (types.size() == 2)
              {
                paramstr += ", ";
              }
            } else {
              paramstr += ", ";
            }
          }

          ss << paramstr.substr(0, paramstr.size() - 2);

          ss << ")";
          retval = ss.str();
        }


        std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun 
          = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);

        if (dynfun)
        {
          Proxy_Function f = dynfun->get_guard();

          if (f)
          {
            std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard 
              = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
            if (dynfunguard)
            {
              retval += " : " + format_guard(dynfunguard->get_parse_tree());
            }
          }

          retval += "\n          Defined at " + format_location(dynfun->get_parse_tree());        
        }

        return retval;
      }