makecmd.h

Go to the documentation of this file.
00001 
00005 
00006 //
00007 // Copyright (c) 2001-2004 California Institute of Technology
00008 // Copyright (c) 2004-2007 University of Southern California
00009 // Rob Peters <rjpeters at usc dot edu>
00010 //
00011 // created: Fri Jun 22 09:07:27 2001
00012 // commit: $Id: makecmd.h 10065 2007-04-12 05:54:56Z rjpeters $
00013 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/tcl/makecmd.h $
00014 //
00015 // --------------------------------------------------------------------
00016 //
00017 // This file is part of GroovX.
00018 //   [http://ilab.usc.edu/rjpeters/groovx/]
00019 //
00020 // GroovX is free software; you can redistribute it and/or modify it
00021 // under the terms of the GNU General Public License as published by
00022 // the Free Software Foundation; either version 2 of the License, or
00023 // (at your option) any later version.
00024 //
00025 // GroovX is distributed in the hope that it will be useful, but
00026 // WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028 // General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU General Public License
00031 // along with GroovX; if not, write to the Free Software Foundation,
00032 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00033 //
00035 
00036 #ifndef GROOVX_TCL_MAKECMD_H_UTC20050628162421_DEFINED
00037 #define GROOVX_TCL_MAKECMD_H_UTC20050628162421_DEFINED
00038 
00039 #include "nub/ref.h"
00040 
00041 #include "tcl/argspec.h"
00042 #include "tcl/conversions.h"
00043 #include "tcl/command.h"
00044 #include "tcl/commandgroup.h"
00045 #include "tcl/vecdispatch.h"
00046 
00047 #include "rutz/functors.h"
00048 #include "rutz/shared_ptr.h"
00049 
00050 namespace rutz
00051 {
00052   struct file_pos;
00053 
00055   template <class MF>
00056   struct func_traits<mem_functor<MF> > : public func_traits<MF>
00057   {
00058     typedef nub::soft_ref<typename mem_functor<MF>::C> arg1_t;
00059   };
00060 }
00061 
00062 namespace tcl
00063 {
00065 
00067   template <class T>
00068   inline nub::ref<T> aux_convert_to(Tcl_Obj* obj, nub::ref<T>*)
00069   {
00070     nub::uid uid = tcl::convert_to<nub::uid>(obj);
00071     return nub::ref<T>(uid);
00072   }
00073 
00075 
00077   template <class T>
00078   inline tcl::obj aux_convert_from(nub::ref<T> obj)
00079   {
00080     return convert_from<nub::uid>(obj.id());
00081   }
00082 
00084 
00086   template <class T>
00087   inline nub::soft_ref<T> aux_convert_to(Tcl_Obj* obj, nub::soft_ref<T>*)
00088   {
00089     nub::uid uid = tcl::convert_to<nub::uid>(obj);
00090     return nub::soft_ref<T>(uid);
00091   }
00092 
00094 
00096   template <class T>
00097   inline tcl::obj aux_convert_from(nub::soft_ref<T> obj)
00098   {
00099     return convert_from<nub::uid>(obj.id());
00100   }
00101 
00102 
00104 //
00105 // func_wrapper<> template definitions. Each specialization takes a
00106 // C++-style functor (could be a free function, or struct with
00107 // operator()), and transforms it into a functor with an
00108 // operator()(tcl::call_context&) which can be called from a
00109 // tcl::command. This transformation requires extracting the
00110 // appropriate parameters from the tcl::call_context, passing them to
00111 // the C++ functor, and returning the result back to the
00112 // tcl::call_context.
00113 //
00115 
00116 #ifdef EXTRACT_PARAM
00117 #  error EXTRACT_PARAM macro already defined
00118 #endif
00119 
00120 #define EXTRACT_PARAM(N) \
00121   typename rutz::func_traits<Func>::arg##N##_t p##N = \
00122   ctx.template get_arg<typename rutz::func_traits<Func>::arg##N##_t>(N);
00123 
00125   template <unsigned int N, class R, class Func>
00126   class func_wrapper
00127   {};
00128 }
00129 
00130 namespace rutz
00131 {
00133   template <unsigned int N, class F, class Func>
00134   struct func_traits<tcl::func_wrapper<N, F, Func> >
00135   {
00136     typedef typename rutz::func_traits<Func>::retn_t retn_t;
00137   };
00138 }
00139 
00140 namespace tcl
00141 {
00142 
00143 
00144 // ########################################################
00146 
00147   template <class R, class Func>
00148   struct func_wrapper<0, R, Func>
00149   {
00150   private:
00151     Func m_held_func;
00152 
00153   public:
00154     func_wrapper<0, R, Func>(Func f) : m_held_func(f) {}
00155 
00156     ~func_wrapper() throw() {}
00157 
00158     R operator()(tcl::call_context& /*ctx*/)
00159     {
00160       return m_held_func();
00161     }
00162   };
00163 
00164 
00165 // ########################################################
00167 
00168   template <class R, class Func>
00169   struct func_wrapper<1, R, Func>
00170   {
00171   private:
00172     Func m_held_func;
00173 
00174   public:
00175     func_wrapper<1, R, Func>(Func f) : m_held_func(f) {}
00176 
00177     ~func_wrapper() throw() {}
00178 
00179     R operator()(tcl::call_context& ctx)
00180     {
00181       EXTRACT_PARAM(1);
00182       return m_held_func(p1);
00183     }
00184   };
00185 
00186 
00187 // ########################################################
00189 
00190   template <class R, class Func>
00191   struct func_wrapper<2, R, Func>
00192   {
00193   private:
00194     Func m_held_func;
00195 
00196   public:
00197     func_wrapper<2, R, Func>(Func f) : m_held_func(f) {}
00198 
00199     ~func_wrapper() throw() {}
00200 
00201     R operator()(tcl::call_context& ctx)
00202     {
00203       EXTRACT_PARAM(1); EXTRACT_PARAM(2);
00204       return m_held_func(p1, p2);
00205     }
00206   };
00207 
00208 
00209 // ########################################################
00211 
00212   template <class R, class Func>
00213   struct func_wrapper<3, R, Func>
00214   {
00215   private:
00216     Func m_held_func;
00217 
00218   public:
00219     func_wrapper<3, R, Func>(Func f) : m_held_func(f) {}
00220 
00221     ~func_wrapper() throw() {}
00222 
00223     R operator()(tcl::call_context& ctx)
00224     {
00225       EXTRACT_PARAM(1); EXTRACT_PARAM(2); EXTRACT_PARAM(3);
00226       return m_held_func(p1, p2, p3);
00227     }
00228   };
00229 
00230 
00231 // ########################################################
00233 
00234   template <class R, class Func>
00235   struct func_wrapper<4, R, Func>
00236   {
00237   private:
00238     Func m_held_func;
00239 
00240   public:
00241     func_wrapper<4, R, Func>(Func f) : m_held_func(f) {}
00242 
00243     ~func_wrapper() throw() {}
00244 
00245     R operator()(tcl::call_context& ctx)
00246     {
00247       EXTRACT_PARAM(1); EXTRACT_PARAM(2); EXTRACT_PARAM(3);
00248       EXTRACT_PARAM(4);
00249       return m_held_func(p1, p2, p3, p4);
00250     }
00251   };
00252 
00253 
00254 // ########################################################
00256 
00257   template <class R, class Func>
00258   struct func_wrapper<5, R, Func>
00259   {
00260   private:
00261     Func m_held_func;
00262 
00263   public:
00264     func_wrapper<5, R, Func>(Func f) : m_held_func(f) {}
00265 
00266     ~func_wrapper() throw() {}
00267 
00268     R operator()(tcl::call_context& ctx)
00269     {
00270       EXTRACT_PARAM(1); EXTRACT_PARAM(2); EXTRACT_PARAM(3);
00271       EXTRACT_PARAM(4); EXTRACT_PARAM(5);
00272       return m_held_func(p1, p2, p3, p4, p5);
00273     }
00274   };
00275 
00276 
00277 // ########################################################
00279 
00280   template <class R, class Func>
00281   struct func_wrapper<6, R, Func>
00282   {
00283   private:
00284     Func m_held_func;
00285 
00286   public:
00287     func_wrapper<6, R, Func>(Func f) : m_held_func(f) {}
00288 
00289     ~func_wrapper() throw() {}
00290 
00291     R operator()(tcl::call_context& ctx)
00292     {
00293       EXTRACT_PARAM(1); EXTRACT_PARAM(2); EXTRACT_PARAM(3);
00294       EXTRACT_PARAM(4); EXTRACT_PARAM(5); EXTRACT_PARAM(6);
00295       return m_held_func(p1, p2, p3, p4, p5, p6);
00296     }
00297   };
00298 
00299 // ########################################################
00301 
00302   template <class R, class Func>
00303   struct func_wrapper<7, R, Func>
00304   {
00305   private:
00306     Func m_held_func;
00307 
00308   public:
00309     func_wrapper<7, R, Func>(Func f) : m_held_func(f) {}
00310 
00311     ~func_wrapper() throw() {}
00312 
00313     R operator()(tcl::call_context& ctx)
00314     {
00315       EXTRACT_PARAM(1); EXTRACT_PARAM(2); EXTRACT_PARAM(3);
00316       EXTRACT_PARAM(4); EXTRACT_PARAM(5); EXTRACT_PARAM(6);
00317       EXTRACT_PARAM(7);
00318       return m_held_func(p1, p2, p3, p4, p5, p6, p7);
00319     }
00320   };
00321 
00322 // ########################################################
00324 
00325   template <class R, class Func>
00326   struct func_wrapper<8, R, Func>
00327   {
00328   private:
00329     Func m_held_func;
00330 
00331   public:
00332     func_wrapper<8, R, Func>(Func f) : m_held_func(f) {}
00333 
00334     ~func_wrapper() throw() {}
00335 
00336     R operator()(tcl::call_context& ctx)
00337     {
00338       EXTRACT_PARAM(1); EXTRACT_PARAM(2); EXTRACT_PARAM(3);
00339       EXTRACT_PARAM(4); EXTRACT_PARAM(5); EXTRACT_PARAM(6);
00340       EXTRACT_PARAM(7); EXTRACT_PARAM(8);
00341       return m_held_func(p1, p2, p3, p4, p5, p6, p7, p8);
00342     }
00343   };
00344 
00345 #undef EXTRACT_PARAM
00346 
00347 // ########################################################
00349 
00350   template <class Fptr>
00351   inline func_wrapper<rutz::func_traits<Fptr>::num_args,
00352                       typename rutz::func_traits<Fptr>::retn_t,
00353                       typename rutz::functor_of<Fptr>::type>
00354   build_func_wrapper(Fptr f)
00355   {
00356     return rutz::build_functor(f);
00357   }
00358 
00359 
00360 // ########################################################
00362 
00363   template <class R, class func_wrapper>
00364   class generic_function : public tcl::function
00365   {
00366   protected:
00367     generic_function<R, func_wrapper>(func_wrapper f) : m_held_func(f) {}
00368 
00369   public:
00370     static rutz::shared_ptr<tcl::function> make(func_wrapper f)
00371     {
00372       return rutz::shared_ptr<tcl::function>(new generic_function(f));
00373     }
00374 
00375     virtual ~generic_function() throw() {}
00376 
00377   protected:
00378     virtual void invoke(tcl::call_context& ctx)
00379     {
00380       R res(m_held_func(ctx)); ctx.set_result(res);
00381     }
00382 
00383   private:
00384     func_wrapper m_held_func;
00385   };
00386 
00387 // ########################################################
00389 
00390   template <class func_wrapper>
00391   class generic_function<void, func_wrapper> : public tcl::function
00392   {
00393   protected:
00394     generic_function<void, func_wrapper>(func_wrapper f) : m_held_func(f) {}
00395 
00396   public:
00397     static rutz::shared_ptr<tcl::function> make(func_wrapper f)
00398     {
00399       return rutz::shared_ptr<tcl::function>(new generic_function(f));
00400     }
00401 
00402     virtual ~generic_function() throw() {}
00403 
00404   protected:
00405     virtual void invoke(tcl::call_context& ctx)
00406     {
00407       m_held_func(ctx);
00408     }
00409 
00410   private:
00411     func_wrapper m_held_func;
00412   };
00413 
00414 
00415 // ########################################################
00417 
00418   template <class func_wrapper>
00419   inline void
00420   make_generic_command(tcl::interpreter& interp,
00421                        func_wrapper f,
00422                        const char* cmd_name,
00423                        const char* usage,
00424                        const arg_spec& spec,
00425                        const rutz::file_pos& src_pos)
00426   {
00427     typedef typename rutz::func_traits<func_wrapper>::retn_t retn_t;
00428     tcl::command_group::make(interp,
00429                        generic_function<retn_t, func_wrapper>::make(f),
00430                        cmd_name, usage, spec, src_pos);
00431   }
00432 
00433 
00434 // ########################################################
00436 
00437   template <class func_wrapper>
00438   inline void
00439   make_generic_vec_command(tcl::interpreter& interp,
00440                            func_wrapper f,
00441                            const char* cmd_name,
00442                            const char* usage,
00443                            const arg_spec& spec,
00444                            unsigned int keyarg,
00445                            const rutz::file_pos& src_pos)
00446   {
00447     typedef typename rutz::func_traits<func_wrapper>::retn_t retn_t;
00448     rutz::shared_ptr<tcl::command> cmd =
00449       tcl::command_group::make(interp,
00450                          generic_function<retn_t, func_wrapper>::make(f),
00451                          cmd_name, usage, spec, src_pos);
00452     tcl::use_vec_dispatch(*cmd, keyarg);
00453   }
00454 
00456 //
00457 // And finally... make_command
00458 //
00460 
00461 // ########################################################
00463 
00464   template <class Func>
00465   inline void
00466   make_command(tcl::interpreter& interp,
00467           Func f,
00468           const char* cmd_name,
00469           const char* usage,
00470           const rutz::file_pos& src_pos)
00471   {
00472     make_generic_command
00473       (interp, build_func_wrapper(f), cmd_name, usage,
00474        arg_spec(rutz::func_traits<Func>::num_args + 1, -1, true),
00475        src_pos);
00476   }
00477 
00478 // ########################################################
00480 
00481   template <class Func>
00482   inline void
00483   make_vec_command(tcl::interpreter& interp,
00484                    Func f,
00485                    const char* cmd_name,
00486                    const char* usage,
00487                    unsigned int keyarg /*default is 1*/,
00488                    const rutz::file_pos& src_pos)
00489   {
00490     make_generic_vec_command
00491       (interp, build_func_wrapper(f), cmd_name, usage,
00492        arg_spec(rutz::func_traits<Func>::num_args + 1, -1, true),
00493        keyarg, src_pos);
00494   }
00495 
00496 } // end namespace tcl
00497 
00498 static const char __attribute__((used)) vcid_groovx_tcl_makecmd_h_utc20050628162421[] = "$Id: makecmd.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00499 #endif // !GROOVX_TCL_MAKECMD_H_UTC20050628162421_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:41 2008 by Doxygen version 1.5.5.