/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>,
+ Copyright (C) 1997--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>,
Erik Sandberg <mandolaerik@gmail.com>
LilyPond is free software: you can redistribute it and/or modify
#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 "warn.hh"
-
void
translator_each (SCM list, Translator_method method)
{
if (context_)
{
programming_error ("translator group is already connected to context "
- + context_->context_name ());
+ + context_->context_name ());
}
context_ = c;
{
}
+/*
+ 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 = ℓ
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);
SCM *tail = ℓ
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);
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 ("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))
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))