]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 4400: Rework LY_DECLARE_SMOB_PROC to declare a member function
authorDavid Kastrup <dak@gnu.org>
Sun, 17 May 2015 10:04:32 +0000 (12:04 +0200)
committerDavid Kastrup <dak@gnu.org>
Fri, 22 May 2015 08:41:06 +0000 (10:41 +0200)
This is nicer to work with.  LY_DECLARE_SMOB_PROC now needs to
additionally get the class name for declaring the smob procedure: this
is astonishingly hard to avoid.  Moving the initialization out of
Smob_base<Super>::init into a separate routine smob_proc_init defined by
LY_DECLARE_SMOB_PROC considerably simplifies the initialization.

lily/include/listener.hh
lily/include/smobs.hh
lily/include/smobs.tcc
lily/unpure-pure-container.cc

index 881b980e4048421144bf7f075058ea781c933200..d9f8aea76ee020a89084dc3b6f9d018a1494f220 100644 (file)
@@ -101,11 +101,10 @@ public:
   Listener (SCM callback, SCM target)
     : callback_ (callback), target_ (target) { }
 
-  void listen (SCM ev) const { scm_call_2 (callback_, target_, ev); }
-
-  LY_DECLARE_SMOB_PROC (1, 0, 0, (SCM self, SCM ev))
+  LY_DECLARE_SMOB_PROC (&Listener::listen, 1, 0, 0)
+  SCM listen (SCM ev)
   {
-    Listener::unsmob (self)->listen (ev);
+    scm_call_2 (callback_, target_, ev);
     return SCM_UNSPECIFIED;
   }
 
@@ -180,9 +179,10 @@ class Callback_wrapper : public Simple_smob<Callback_wrapper>
   Callback_wrapper (void (*trampoline) (SCM, SCM)) : trampoline_ (trampoline)
   { } // Private constructor, use only in make_smob
 public:
-  LY_DECLARE_SMOB_PROC (2, 0, 0, (SCM self, SCM target, SCM ev))
+  LY_DECLARE_SMOB_PROC (&Callback_wrapper::call, 2, 0, 0)
+  SCM call (SCM target, SCM ev)
   {
-    unsmob (self)->trampoline_ (target, ev);
+    trampoline_ (target, ev);
     return SCM_UNSPECIFIED;
   }
   // Callback wrappers are for an unchanging entity, so we do the Lisp
index 7097bb3d48c6605b4a08ff769d54bc80be9e0651..ee6af16162be9da50d33da46753708a99d22718d 100644 (file)
@@ -185,6 +185,7 @@ private:
   static SCM equal_p (SCM, SCM);
   int print_smob (SCM, scm_print_state *);
   static int print_trampoline (SCM, SCM, scm_print_state *);
+  static void smob_proc_init (scm_t_bits) { };
 
   // type_p_name_ can be overriden in the Super class with a static
   // const char [] string.  This requires both a declaration in the
@@ -200,25 +201,41 @@ private:
   static const int type_p_name_ = 0;
 
   // LY_DECLARE_SMOB_PROC is used in the Super class definition for
-  // making a smob callable like a function.  Declaration has to be
-  // public.  It may be either be completed with a semicolon in which
-  // case a definition of the member function smob_proc has to be done
-  // outside of the class body, or the semicolon is left off and an
-  // inline function body is added immediately below.  It would be
-  // nice if this were a non-static member function but it would seem
-  // tricky to do the required trampolining for unsmobbing the first
-  // argument of the callback and using it as a this pointer.
-#define LY_DECLARE_SMOB_PROC(REQ, OPT, VAR, ARGLIST)                    \
-  static const int smob_proc_signature_ = ((REQ)<<8)|((OPT)<<4)|(VAR);  \
-  static SCM smob_proc ARGLIST
-
-  // a separate LY_DEFINE_SMOB_PROC seems sort of pointless as it
-  // would just result in SCM CLASS::smob_proc ARGLIST
-  //
-  // The default case without function functionality is recognized by
-  // smob_proc_signature being -1.
-  static const int smob_proc = 0;
-  static const int smob_proc_signature_ = -1;
+  // making a smob callable like a function.  Its first argument is a
+  // function member pointer constant, to a function taking the
+  // correct number of SCM arguments and returning SCM.  The function
+  // itself has to be defined separately.
+
+#define LY_DECLARE_SMOB_PROC(PMF, REQ, OPT, VAR)                        \
+  static void smob_proc_init (scm_t_bits smob_tag)                      \
+  {                                                                     \
+    scm_set_smob_apply (smob_tag,                                       \
+                        (scm_t_subr)smob_trampoline<PMF>,               \
+                        REQ, OPT, VAR);                                 \
+  }
+
+  // Well, function template argument packs are a C++11 feature.  So
+  // we just define a bunch of trampolines manually.
+  template <SCM (Super::*pmf)(void)>
+  static SCM smob_trampoline (SCM self)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)();
+  }
+  template <SCM (Super::*pmf)(SCM)>
+  static SCM smob_trampoline (SCM self, SCM arg1)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)(arg1);
+  }
+  template <SCM (Super::*pmf)(SCM, SCM)>
+  static SCM smob_trampoline (SCM self, SCM arg1, SCM arg2)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)(arg1, arg2);
+  }
+  template <SCM (Super::*pmf)(SCM, SCM, SCM)>
+  static SCM smob_trampoline (SCM self, SCM arg1, SCM arg2, SCM arg3)
+  {
+    return (Super::unchecked_unsmob (self)->*pmf)(arg1, arg2, arg3);
+  }
 
 public:
   static bool is_smob (SCM s)
index 940f0032ae975ee47d6f202951f55d30527df825..fffe4c4892c07e185b086d963e674065fc5404e6 100644 (file)
@@ -151,11 +151,6 @@ void Smob_base<Super>::init ()
       scm_c_export (Super::type_p_name_, NULL);
     }
   ly_add_type_predicate ((void *) is_smob, smob_name_.c_str ());
-  if (Super::smob_proc_signature_ >= 0)
-    scm_set_smob_apply (smob_tag_,
-                        (scm_t_subr)Super::smob_proc,
-                        Super::smob_proc_signature_ >> 8,
-                        (Super::smob_proc_signature_ >> 4)&0xf,
-                        Super::smob_proc_signature_ & 0xf);
+  Super::smob_proc_init (smob_tag_);
 }
 #endif
index ede75022c6d0c148857e19f01f22f1c2687138c5..3a2ab1e52de6ec64063b2c022a681cd3be900d03 100644 (file)
 class Unpure_pure_call : public Smob1<Unpure_pure_call>
 {
 public:
-  LY_DECLARE_SMOB_PROC (2, 0, 1, (SCM self, SCM arg1, SCM arg2, SCM rest))
+  LY_DECLARE_SMOB_PROC (&Unpure_pure_call::call, 2, 0, 1)
+  SCM call (SCM arg1, SCM arg2, SCM rest)
   {
-    return scm_apply_0 (Unpure_pure_call::unsmob (self)->scm1 (),
+    return scm_apply_0 (scm1 (),
                         scm_call_2 (ly_lily_module_constant ("drop-right"),
                                     scm_cons2 (arg1, arg2, rest),
                                     scm_from_int (2)));