]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/translator-group.cc
Imported Upstream version 2.14.2
[lilypond.git] / lily / translator-group.cc
index da3fda5ed5bbeb12cca478346fec0f5239662ceb..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,7 +54,7 @@ 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;
@@ -79,13 +86,22 @@ Translator_group::finalize ()
 {
 }
 
+/*
+  Both filter_performers and filter_engravers used to use a direct dynamic_cast
+  on the unsmobbed translator to be filtered, i.e.,
+
+  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);
@@ -99,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);
@@ -147,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);
+
+         SCM str = instance->self_scm ();
 
-         if (tr->must_be_last ())
+         if (instance->must_be_last ())
            {
              SCM cons = scm_cons (str, SCM_EOL);
              if (scm_is_pair (trans_list))
@@ -166,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))
@@ -202,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);
@@ -212,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);
@@ -220,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);
@@ -235,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);