]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/translator-group.cc
Imported Upstream version 2.14.2
[lilypond.git] / lily / translator-group.cc
index badd1b82e802da140b35901b97a953e4be1b2ecd..487037a2dc4e7ab815420daf353e5ba2e05624a4 100644 (file)
@@ -1,10 +1,21 @@
 /*
-  translator-group.cc -- implement Translator_group
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
-
-  (c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>,
+  Copyright (C) 1997--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>,
                  Erik Sandberg <mandolaerik@gmail.com>
+
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "translator-group.hh"
 #include "context-def.hh"
 #include "context.hh"
 #include "dispatcher.hh"
+#include "engraver.hh"
 #include "engraver-group.hh"
 #include "international.hh"
 #include "main.hh"
 #include "music.hh"
 #include "output-def.hh"
+#include "performer.hh"
 #include "performer-group.hh"
+#include "scheme-engraver.hh"
 #include "scm-hash.hh"
-#include "stream-event.hh"
 #include "warn.hh"
 
-Translator_group *
-Translator_group::get_daddy_translator () const
-{
-  return context ()->get_parent_context ()->implementation ();
-}
-
 void
 translator_each (SCM list, Translator_method method)
 {
@@ -47,12 +54,10 @@ Translator_group::connect_to_context (Context *c)
   if (context_)
     {
       programming_error ("translator group is already connected to context "
-                        +  context_->context_name ());
+                        + context_->context_name ());
     }
   
   context_ = c;
-  c->event_source ()->add_listener (GET_LISTENER (eat_event),
-                                   ly_symbol2scm ("OldMusicEvent"));
   c->event_source ()->add_listener (GET_LISTENER (create_child_translator),
                                    ly_symbol2scm ("AnnounceNewContext"));
   for (SCM tr_list = simple_trans_list_; scm_is_pair (tr_list); tr_list = scm_cdr (tr_list))
@@ -70,8 +75,6 @@ Translator_group::disconnect_from_context ()
       Translator *tr = unsmob_translator (scm_car (tr_list));
       tr->disconnect_from_context (context_);
     }
-  context_->event_source ()->remove_listener (GET_LISTENER (eat_event),
-                                             ly_symbol2scm ("OldMusicEvent"));
   context_->event_source ()->remove_listener (GET_LISTENER (create_child_translator),
                                              ly_symbol2scm ("AnnounceNewContext"));
   context_ = 0;
@@ -83,40 +86,22 @@ Translator_group::finalize ()
 {
 }
 
-bool
-translator_accepts_any_of (Translator *tr, SCM ifaces)
-{
-  SCM ack_ifs = scm_assoc (ly_symbol2scm ("events-accepted"),
-                          tr->translator_description ());
-  ack_ifs = scm_cdr (ack_ifs);
-  for (SCM s = ifaces; scm_is_pair (s); s = scm_cdr (s))
-    if (scm_c_memq (scm_car (s), ack_ifs) != SCM_BOOL_F)
-      return true;
-  return false;
-}
-
-SCM
-find_accept_translators (SCM gravlist, SCM ifaces)
-{
-  SCM l = SCM_EOL;
-  for (SCM s = gravlist; scm_is_pair (s); s = scm_cdr (s))
-    {
-      Translator *tr = unsmob_translator (scm_car (s));
-      if (translator_accepts_any_of (tr, ifaces))
-       l = scm_cons (tr->self_scm (), l);
-    }
-  l = scm_reverse_x (l, SCM_EOL);
+/*
+  Both filter_performers and filter_engravers used to use a direct dynamic_cast
+  on the unsmobbed translator to be filtered, i.e.,
 
-  return l;
-}
+  if (dynamic_cast<Performer *> (unsmob_translator (scm_car (*tail))))
 
+  but this caused mysterious optimisation issues in several GUB builds.  See
+  issue #818 for the background to this change.
+*/
 SCM
 filter_performers (SCM ell)
 {
   SCM *tail = &ell;
   for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p))
     {
-      if (dynamic_cast<Performer *> (unsmob_translator (scm_car (*tail))))
+      if (unsmob_performer (scm_car (*tail)))
        *tail = scm_cdr (*tail);
       else
        tail = SCM_CDRLOC (*tail);
@@ -130,7 +115,7 @@ filter_engravers (SCM ell)
   SCM *tail = &ell;
   for (SCM p = ell; scm_is_pair (p); p = scm_cdr (p))
     {
-      if (dynamic_cast<Engraver *> (unsmob_translator (scm_car (*tail))))
+      if (unsmob_engraver (scm_car (*tail)))
        *tail = scm_cdr (*tail);
       else
        tail = SCM_CDRLOC (*tail);
@@ -178,15 +163,38 @@ Translator_group::create_child_translator (SCM sev)
 
   for (SCM s = trans_names; scm_is_pair (s); s = scm_cdr (s))
     {
-      Translator *type = get_translator (scm_car (s));
+      SCM definition = scm_car (s);
+      bool is_scheme = false;
+
+      Translator *type = 0;
+      if (ly_is_symbol (definition))
+       type = get_translator (definition);
+      else if (ly_is_pair (definition))
+       {
+         type = get_translator (ly_symbol2scm ("Scheme_engraver"));
+         is_scheme = true;
+       }
+      else if (ly_is_procedure (definition))
+       {
+         // `definition' is a procedure, which takes the context as
+         // an argument and evaluates to an a-list scheme engraver
+         // definition.
+         definition = scm_call_1 (definition, cs);
+         type = get_translator (ly_symbol2scm ("Scheme_engraver"));
+         is_scheme = true;
+       }
+        
       if (!type)
-       warning (_f ("can't find: `%s'", ly_symbol2string (scm_car (s)).c_str ()));
+       warning (_f ("cannot find: `%s'", ly_symbol2string (scm_car (s)).c_str ()));
       else
        {
-         Translator *tr = type->clone ();
-         SCM str = tr->self_scm ();
+         Translator *instance = type->clone ();
+         if (is_scheme)
+           dynamic_cast<Scheme_engraver *> (instance)->init_from_scheme (definition);
 
-         if (tr->must_be_last ())
+         SCM str = instance->self_scm ();
+
+         if (instance->must_be_last ())
            {
              SCM cons = scm_cons (str, SCM_EOL);
              if (scm_is_pair (trans_list))
@@ -197,13 +205,13 @@ Translator_group::create_child_translator (SCM sev)
          else
            trans_list = scm_cons (str, trans_list);
 
-         tr->daddy_context_ = new_context;
-         tr->unprotect ();
+         instance->daddy_context_ = new_context;
+         instance->unprotect ();
        }
     }
 
   /* Filter unwanted translator types. Required to make
-     \with {\consists "..."} work. */
+     \with { \consists "..." } work. */
   if (dynamic_cast<Engraver_group *> (g))
     g->simple_trans_list_ = filter_performers (trans_list);
   else if (dynamic_cast<Performer_group *> (g))
@@ -221,56 +229,6 @@ Translator_group::create_child_translator (SCM sev)
                            DOWN);
 }
 
-IMPLEMENT_LISTENER (Translator_group, eat_event);
-void
-Translator_group::eat_event (SCM sev)
-{
-  Stream_event *ev = unsmob_stream_event (sev);
-  SCM sm = ev->get_property ("music");
-  Music *m = unsmob_music (sm);
-  try_music (m);
-}
-
-bool
-Translator_group::try_music (Music *m)
-{
-  SCM name = scm_sloppy_assq (ly_symbol2scm ("name"),
-                             m->get_property_alist (false));
-
-  if (!scm_is_pair (name))
-    return false;
-
-  name = scm_cdr (name);
-  SCM accept_list = scm_hashq_ref (accept_hash_table_, name, SCM_UNDEFINED);
-  if (accept_list == SCM_BOOL_F)
-    {
-      accept_list = find_accept_translators (get_simple_trans_list (),
-                                            m->get_property ("types"));
-      scm_hashq_set_x (accept_hash_table_, name, accept_list);
-    }
-
-  for (SCM p = accept_list; scm_is_pair (p); p = scm_cdr (p))
-    {
-      Translator *t = unsmob_translator (scm_car (p));
-      if (t && t->try_music (m))
-       return true;
-    }
-    
-  // We couldn't swallow the event in this context. Try parent.
-  Context *p = context ()->get_parent_context ();
-  // Global context's translator group is a dummy, so don't try it.
-  if (p->get_parent_context())
-    // ES todo: Make Translators listeners directly instead.
-    return p->implementation ()->try_music (m);
-  // 'junking event' warning is temporarily disabled during translator cleanup
-  /*
-  else
-    // We have tried all possible contexts. Give up.
-    m->origin ()->warning (_f ("junking event: `%s'", m->name ()));
-  */
-  return false;
-}
-
 SCM
 Translator_group::get_simple_trans_list ()
 {
@@ -283,7 +241,7 @@ precomputed_recurse_over_translators (Context *c, Translator_precompute_index id
   Translator_group *tg
     = dynamic_cast<Translator_group *> (c->implementation ());
 
-  if (dir == DOWN)
+  if (tg && dir == DOWN)
     {
       tg->precomputed_translator_foreach (idx);
       tg->call_precomputed_self_method (idx);
@@ -293,7 +251,7 @@ precomputed_recurse_over_translators (Context *c, Translator_precompute_index id
        s = scm_cdr (s))
     precomputed_recurse_over_translators (unsmob_context (scm_car (s)), idx, dir);
 
-  if (dir == UP)
+  if (tg && dir == UP)
     {
       tg->precomputed_translator_foreach (idx);
       tg->call_precomputed_self_method (idx);
@@ -301,12 +259,13 @@ precomputed_recurse_over_translators (Context *c, Translator_precompute_index id
 }
 
 void
-recurse_over_translators (Context *c, Translator_method ptr, Translator_group_method tg_ptr, Direction dir)
+recurse_over_translators (Context *c, Translator_method ptr,
+                         Translator_group_method tg_ptr, Direction dir)
 {
   Translator_group *tg
     = dynamic_cast<Translator_group *> (c->implementation ());
 
-  if (dir == DOWN)
+  if (tg && dir == DOWN)
     {
       (tg->*tg_ptr) ();
       translator_each (tg->get_simple_trans_list (), ptr);
@@ -316,7 +275,7 @@ recurse_over_translators (Context *c, Translator_method ptr, Translator_group_me
        s = scm_cdr (s))
     recurse_over_translators (unsmob_context (scm_car (s)), ptr, tg_ptr, dir);
 
-  if (dir == UP)
+  if (tg && dir == UP)
     {
       translator_each (tg->get_simple_trans_list (),
                       ptr);
@@ -328,12 +287,9 @@ recurse_over_translators (Context *c, Translator_method ptr, Translator_group_me
 Translator_group::Translator_group ()
 {
   simple_trans_list_ = SCM_EOL;
-  accept_hash_table_ = SCM_EOL;
   protected_events_ = SCM_EOL;
   context_ = 0;
   smobify_self ();
-
-  accept_hash_table_ = scm_c_make_hash_table (19);
 }
 
 void
@@ -410,7 +366,6 @@ Translator_group::mark_smob (SCM smob)
   Translator_group *me = (Translator_group *)SCM_CELL_WORD_1 (smob);
 
   me->derived_mark ();
-  scm_gc_mark (me->accept_hash_table_);
   scm_gc_mark (me->protected_events_);
   return me->simple_trans_list_;
 }