]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 4357/7: Replace translator_listener_record mess with Scheme
authorDavid Kastrup <dak@gnu.org>
Thu, 30 Apr 2015 15:47:29 +0000 (17:47 +0200)
committerDavid Kastrup <dak@gnu.org>
Tue, 12 May 2015 12:30:29 +0000 (14:30 +0200)
lily/include/scheme-engraver.hh
lily/include/translator.hh
lily/include/translator.icc
lily/scheme-engraver.cc
lily/translator.cc

index 9b9db003175418054e28f79b2941d37da827c9d9..c7d16d76e9c10145d090472de46688384279f6dd 100644 (file)
@@ -30,8 +30,6 @@ public:
   void init_from_scheme (SCM definition);
   TRANSLATOR_DECLARATIONS_NO_LISTENER (Scheme_engraver);
 
-  static Listener tlr_get_listener (void *generic_arg, SCM event);
-
 protected:
   ~Scheme_engraver ();
 
@@ -43,7 +41,7 @@ protected:
   virtual void initialize ();
   virtual void finalize ();
   virtual void derived_mark () const;
-  virtual translator_listener_record *get_listener_list () const;
+  virtual SCM get_listener_list () const;
   virtual bool must_be_last () const;
 
 private:
@@ -71,8 +69,8 @@ private:
   SCM listeners_alist_;
 
   // We dont use this, but need it for the documentation boilerplate.
-  static translator_listener_record *listener_list_;
-  translator_listener_record *per_instance_listeners_;
+  static Protected_scm listener_list_;
+  SCM per_instance_listeners_;
 };
 
 #endif /* SCHEME_ENGRAVER_HH */
index 9abea3b64c93f4ae09c6c4c69c918612dcf5575c..22e656ceb842593774b7eb3ced8cf0537ee0e5ba 100644 (file)
 #include "std-vector.hh"
 #include "protected-scm.hh"
 
-/*
-  Each translator class has a static list of listener records. Each
-  record makes one explains how to register one of the class's stream event
-  listeners to a context.
-*/
-typedef struct translator_listener_record
-{
-  Listener (*get_listener_) (void *, SCM event_class);
-  SCM event_class_;
-  struct translator_listener_record *next_;
-
-  translator_listener_record ()
-  {
-    next_ = 0;
-    event_class_ = SCM_EOL;
-    get_listener_ = 0;
-  }
-
-} translator_listener_record;
-
 #define TRANSLATOR_DECLARATIONS_NO_LISTENER(NAME)                       \
   public:                                                               \
   NAME ();                                                              \
@@ -69,12 +49,19 @@ typedef struct translator_listener_record
   } \
   /* end #define */
 
+/*
+  Each translator class has a static alist of event class symbols
+  mapping to callbacks that are called with a translator instance and
+  a stream event when an event of the appropriate event class is
+  announced in a context.
+*/
+
 #define TRANSLATOR_DECLARATIONS(NAME)                                   \
   TRANSLATOR_DECLARATIONS_NO_LISTENER(NAME)                             \
 private:                                                                \
-  static translator_listener_record *listener_list_;                    \
+  static Protected_scm listener_list_;                                  \
 public:                                                                 \
-  virtual translator_listener_record *get_listener_list () const        \
+  virtual SCM get_listener_list () const                                \
   {                                                                     \
     return listener_list_;                                              \
   }                                                                     \
@@ -84,9 +71,7 @@ public:                                                                 \
 public:                                                 \
 inline void listen_ ## m (Stream_event *);              \
 /* Should be private */                                 \
-static void _internal_declare_ ## m ();                 \
-private:                                                \
- static Listener _get_ ## m ## _listener (void *, SCM);
+static void _internal_declare_ ## m ();
 
 #define DECLARE_ACKNOWLEDGER(x) public : void acknowledge_ ## x (Grob_info); protected:
 #define DECLARE_END_ACKNOWLEDGER(x) public : void acknowledge_end_ ## x (Grob_info); protected:
@@ -151,13 +136,10 @@ protected:                      // should be private.
   void protect_event (SCM ev);
   friend class Callback_wrapper;
   virtual void derived_mark () const;
-  static void add_translator_listener (translator_listener_record **listener_list,
-                                       translator_listener_record *r,
-                                       Listener (*get_listener) (void *, SCM),
-                                       const char *ev_class);
+  static SCM event_class_symbol (const char *ev_class);
   SCM static_translator_description (const char *grobs,
                                      const char *desc,
-                                     translator_listener_record *listener_list,
+                                     SCM listener_list,
                                      const char *read,
                                      const char *write) const;
 
index f583d32aad46f407d8422b349c64365f26fc6b0c..7fc128fe72f68d732fa448f9a42d4755fc17e7c3 100644 (file)
@@ -48,7 +48,7 @@
   /* end define */
 
 #define DEFINE_TRANSLATOR_LISTENER_LIST(T) \
-  translator_listener_record *T::listener_list_;        \
+  Protected_scm T::listener_list_ (SCM_EOL);    \
   /* end define */
 
 #define DEFINE_ACKNOWLEDGERS(classname) \
@@ -135,18 +135,12 @@ generic_get_acknowledger (SCM sym,
 void                                                    \
 cl :: _internal_declare_ ## m ()                        \
 {                                                       \
-  static translator_listener_record r;                  \
-  add_translator_listener (&listener_list_, &r, _get_ ## m ## _listener, #m); \
-}                                                       \
-                                                        \
-ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m);    \
-                                                        \
- Listener                                                               \
- cl :: _get_ ## m ## _listener (void *me, SCM)                          \
- {                                                                      \
-   cl *obj = (cl *) me;                                                 \
-   return obj->get_listener                                             \
-     (Callback_wrapper::make_smob<cl, Stream_event *, &cl::listen_ ## m> ());      \
- }
+  listener_list_ = scm_acons                                            \
+    (event_class_symbol (#m),                                           \
+     Callback_wrapper::make_smob<cl, Stream_event *, &cl::listen_ ## m> (), \
+     listener_list_);                                                   \
+}                                                                       \
+                                                                        \
+ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m);
 
 #endif /* TRANSLATOR_ICC */
index 6762c753c96bb6c29bcd86086f1b292ccadb1ac8..7e601f8db7563014ad81b18a02981f6bf811780e 100644 (file)
@@ -33,24 +33,16 @@ Scheme_engraver::Scheme_engraver ()
   process_acknowledged_function_ = SCM_EOL;
   initialize_function_ = SCM_EOL;
   finalize_function_ = SCM_EOL;
-  listeners_alist_ = SCM_EOL;
 
   interface_acknowledger_hash_ = SCM_EOL;
   interface_end_acknowledger_hash_ = SCM_EOL;
 
   must_be_last_ = false;
-  per_instance_listeners_ = 0;
+  per_instance_listeners_ = SCM_EOL;
 }
 
 Scheme_engraver::~Scheme_engraver ()
 {
-  translator_listener_record *next = 0;
-  for (translator_listener_record *r = per_instance_listeners_;
-       r; r = next)
-    {
-      next = r->next_;
-      delete r;
-    }
 }
 
 // Extracts the value if callable, if not return #f.
@@ -82,13 +74,12 @@ Scheme_engraver::init_from_scheme (SCM definition)
 
   SCM listeners = ly_assoc_get (ly_symbol2scm ("listeners"), definition, SCM_EOL);
 
-  listeners_alist_ = SCM_EOL;
+  per_instance_listeners_ = SCM_EOL;
 
   must_be_last_ = to_boolean (ly_assoc_get (ly_symbol2scm ("must-be-last"),
                                             definition,
                                             SCM_BOOL_F));
 
-  translator_listener_record **tail = &per_instance_listeners_;
   for (SCM p = listeners; scm_is_pair (p); p = scm_cdr (p))
     {
       SCM event_class = scm_caar (p);
@@ -100,13 +91,7 @@ Scheme_engraver::init_from_scheme (SCM definition)
       // We should check the arity of the function?
 
       // Record for later lookup.
-      listeners_alist_ = scm_acons (event_class, proc, listeners_alist_);
-
-      translator_listener_record *rec = new translator_listener_record;
-      *tail = rec;
-      rec->event_class_ = event_class;
-      rec->get_listener_ = &Scheme_engraver::tlr_get_listener;
-      tail = &rec->next_;
+      per_instance_listeners_ = scm_acons (event_class, proc, per_instance_listeners_);
     }
 
   init_acknowledgers (ly_assoc_get (ly_symbol2scm ("acknowledgers"),
@@ -171,18 +156,7 @@ Scheme_engraver::acknowledge_grob_by_hash (Grob_info info,
     }
 }
 
-/* static */
-Listener
-Scheme_engraver::tlr_get_listener (void *arg, SCM name)
-{
-  Scheme_engraver *me = (Scheme_engraver *) arg;
-  SCM func = ly_assoc_get (name, me->listeners_alist_, SCM_BOOL_F);
-  assert (ly_is_procedure (func));
-
-  return me->get_listener (func);
-}
-
-translator_listener_record *
+SCM
 Scheme_engraver::get_listener_list () const
 {
   return per_instance_listeners_;
@@ -212,7 +186,7 @@ Scheme_engraver::derived_mark () const
   scm_gc_mark (finalize_function_);
   scm_gc_mark (process_music_function_);
   scm_gc_mark (process_acknowledged_function_);
-  scm_gc_mark (listeners_alist_);
+  scm_gc_mark (per_instance_listeners_);
   scm_gc_mark (interface_acknowledger_hash_);
   scm_gc_mark (interface_end_acknowledger_hash_);
 }
index d6874ef78ca35d90a0e4a088405183961f17870c..87fc0a15a471104e482395b358b9049640c448a1 100644 (file)
@@ -118,48 +118,38 @@ Translator::finalize ()
 void
 Translator::connect_to_context (Context *c)
 {
-  for (translator_listener_record *r = get_listener_list (); r; r = r->next_)
-    c->events_below ()->add_listener (r->get_listener_ (this, r->event_class_),
-                                      r->event_class_);
+  for (SCM r = get_listener_list (); scm_is_pair (r); r = scm_cdr (r))
+    {
+      SCM event_class = scm_caar (r);
+      SCM callback = scm_cdar (r);
+
+      c->events_below ()->add_listener (get_listener (callback),
+                                        event_class);
+    }
 }
 
 void
 Translator::disconnect_from_context (Context *c)
 {
-  for (translator_listener_record *r = get_listener_list (); r; r = r->next_)
-    c->events_below ()->remove_listener (r->get_listener_ (this, r->event_class_),
-                                         r->event_class_);
-}
+  for (SCM r = get_listener_list (); scm_is_pair (r); r = scm_cdr (r))
+    {
+      SCM event_class = scm_caar (r);
+      SCM callback = scm_cdar (r);
 
-/*
-  internally called once, statically, for each translator
-  listener. Connects the name of an event class with a procedure that
-  fetches the corresponding listener.
+      c->events_below ()->remove_listener (get_listener (callback),
+                                           event_class);
+    }
+}
 
-  The method should only be called from the macro
-  IMPLEMENT_TRANSLATOR_LISTENER.
- */
-void
-Translator::add_translator_listener (translator_listener_record **listener_list,
-                                     translator_listener_record *r,
-                                     Listener (*get_listener) (void *, SCM),
-                                     const char *ev_class)
+SCM
+Translator::event_class_symbol (const char *ev_class)
 {
   /* ev_class is the C++ identifier name. Convert to scm symbol */
   string name = string (ev_class);
   name = replace_all (&name, '_', '-');
   name += "-event";
 
-  // we make the symbol permanent in order not to have to bother about
-  // the static translator_listener_record chains while garbage
-  // collecting.
-
-  SCM class_sym = scm_permanent_object (scm_from_ascii_symbol (name.c_str ()));
-
-  r->event_class_ = class_sym;
-  r->get_listener_ = get_listener;
-  r->next_ = *listener_list;
-  *listener_list = r;
+  return scm_from_ascii_symbol (name.c_str ());
 }
 
 /*
@@ -168,7 +158,7 @@ Translator::add_translator_listener (translator_listener_record **listener_list,
 SCM
 Translator::static_translator_description (const char *grobs,
                                            const char *desc,
-                                           translator_listener_record *listener_list,
+                                           SCM listener_list,
                                            const char *read,
                                            const char *write) const
 {
@@ -181,8 +171,8 @@ Translator::static_translator_description (const char *grobs,
                                  scm_from_utf8_string (desc), static_properties);
 
   SCM list = SCM_EOL;
-  for (; listener_list; listener_list = listener_list->next_)
-    list = scm_cons (listener_list->event_class_, list);
+  for (; scm_is_pair (listener_list); listener_list = scm_cdr (listener_list))
+    list = scm_cons (scm_caar (listener_list), list);
   static_properties = scm_acons (ly_symbol2scm ("events-accepted"),
                                  list, static_properties);