From: David Kastrup Date: Sun, 17 May 2015 10:04:32 +0000 (+0200) Subject: Issue 4400: Rework LY_DECLARE_SMOB_PROC to declare a member function X-Git-Tag: release/2.19.21-1~8 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=1a3796c7166c453fc1ef5d30858e6bbb88fdb59f;p=lilypond.git Issue 4400: Rework LY_DECLARE_SMOB_PROC to declare a member function 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::init into a separate routine smob_proc_init defined by LY_DECLARE_SMOB_PROC considerably simplifies the initialization. --- diff --git a/lily/include/listener.hh b/lily/include/listener.hh index 881b980e40..d9f8aea76e 100644 --- a/lily/include/listener.hh +++ b/lily/include/listener.hh @@ -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 (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 diff --git a/lily/include/smobs.hh b/lily/include/smobs.hh index 7097bb3d48..ee6af16162 100644 --- a/lily/include/smobs.hh +++ b/lily/include/smobs.hh @@ -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, \ + REQ, OPT, VAR); \ + } + + // Well, function template argument packs are a C++11 feature. So + // we just define a bunch of trampolines manually. + template + static SCM smob_trampoline (SCM self) + { + return (Super::unchecked_unsmob (self)->*pmf)(); + } + template + static SCM smob_trampoline (SCM self, SCM arg1) + { + return (Super::unchecked_unsmob (self)->*pmf)(arg1); + } + template + static SCM smob_trampoline (SCM self, SCM arg1, SCM arg2) + { + return (Super::unchecked_unsmob (self)->*pmf)(arg1, arg2); + } + template + 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) diff --git a/lily/include/smobs.tcc b/lily/include/smobs.tcc index 940f0032ae..fffe4c4892 100644 --- a/lily/include/smobs.tcc +++ b/lily/include/smobs.tcc @@ -151,11 +151,6 @@ void Smob_base::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 diff --git a/lily/unpure-pure-container.cc b/lily/unpure-pure-container.cc index ede75022c6..3a2ab1e52d 100644 --- a/lily/unpure-pure-container.cc +++ b/lily/unpure-pure-container.cc @@ -27,9 +27,10 @@ class Unpure_pure_call : public Smob1 { 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)));