]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
release commit
[lilypond.git] / lily / translator-group.cc
1 /*
2   translator-group.cc -- implement Translator_group
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "translator-group.hh"
10
11 #include "output-def.hh"
12 #include "warn.hh"
13 #include "scm-hash.hh"
14 #include "context-def.hh"
15 #include "context.hh"
16 #include "main.hh"
17 #include "music.hh"
18
19 Translator_group *
20 Translator_group::get_daddy_translator () const
21 {
22   return context ()->get_parent_context ()->implementation ();
23 }
24
25 void
26 translator_each (SCM list, Translator_method method)
27 {
28   for (SCM p = list; scm_is_pair (p); p = scm_cdr (p))
29     (unsmob_translator (scm_car (p))->*method) ();
30 }
31
32 void
33 Translator_group::initialize ()
34 {
35   precompute_method_bindings ();
36 }
37
38 void
39 Translator_group::finalize ()
40 {
41 }
42
43 bool
44 translator_accepts_any_of (Translator *tr, SCM ifaces)
45 {
46   SCM ack_ifs = scm_assoc (ly_symbol2scm ("events-accepted"),
47                            tr->translator_description ());
48   ack_ifs = scm_cdr (ack_ifs);
49   for (SCM s = ifaces; scm_is_pair (s); s = scm_cdr (s))
50     if (scm_c_memq (scm_car (s), ack_ifs) != SCM_BOOL_F)
51       return true;
52   return false;
53 }
54
55 SCM
56 find_accept_translators (SCM gravlist, SCM ifaces)
57 {
58   SCM l = SCM_EOL;
59   for (SCM s = gravlist; scm_is_pair (s); s = scm_cdr (s))
60     {
61       Translator *tr = unsmob_translator (scm_car (s));
62       if (translator_accepts_any_of (tr, ifaces))
63         l = scm_cons (tr->self_scm (), l);
64     }
65   l = scm_reverse_x (l, SCM_EOL);
66
67   return l;
68 }
69
70 bool
71 Translator_group::try_music (Music *m)
72 {
73   SCM name = scm_sloppy_assq (ly_symbol2scm ("name"),
74                               m->get_property_alist (false));
75
76   if (!scm_is_pair (name))
77     return false;
78
79   name = scm_cdr (name);
80   SCM accept_list = scm_hashq_ref (accept_hash_table_, name, SCM_UNDEFINED);
81   if (accept_list == SCM_BOOL_F)
82     {
83       accept_list = find_accept_translators (get_simple_trans_list (),
84                                              m->get_property ("types"));
85       scm_hashq_set_x (accept_hash_table_, name, accept_list);
86     }
87
88   for (SCM p = accept_list; scm_is_pair (p); p = scm_cdr (p))
89     {
90       Translator *t = unsmob_translator (scm_car (p));
91       if (t && t->try_music (m))
92         return true;
93     }
94   return false;
95 }
96
97 SCM
98 Translator_group::get_simple_trans_list ()
99 {
100   return simple_trans_list_;
101 }
102
103 void
104 precomputed_recurse_over_translators (Context *c, Translator_precompute_index idx, Direction dir)
105 {
106   Translator_group *tg
107     = dynamic_cast<Translator_group *> (c->implementation ());
108
109   if (dir == DOWN)
110     {
111       tg->precomputed_translator_foreach (idx);
112       tg->call_precomputed_self_method (idx);
113     }
114
115   for (SCM s = c->children_contexts (); scm_is_pair (s);
116        s = scm_cdr (s))
117     precomputed_recurse_over_translators (unsmob_context (scm_car (s)), idx, dir);
118
119   if (dir == UP)
120     {
121       tg->precomputed_translator_foreach (idx);
122       tg->call_precomputed_self_method (idx);
123     }
124 }
125
126 void
127 recurse_over_translators (Context *c, Translator_method ptr, Translator_group_method tg_ptr, Direction dir)
128 {
129   Translator_group *tg
130     = dynamic_cast<Translator_group *> (c->implementation ());
131
132   if (dir == DOWN)
133     {
134       (tg->*tg_ptr) ();
135       translator_each (tg->get_simple_trans_list (), ptr);
136     }
137
138   for (SCM s = c->children_contexts (); scm_is_pair (s);
139        s = scm_cdr (s))
140     recurse_over_translators (unsmob_context (scm_car (s)), ptr, tg_ptr, dir);
141
142   if (dir == UP)
143     {
144       translator_each (tg->get_simple_trans_list (),
145                        ptr);
146
147       (tg->*tg_ptr) ();
148     }
149 }
150
151 Translator_group::Translator_group ()
152 {
153   simple_trans_list_ = SCM_EOL;
154   accept_hash_table_ = SCM_EOL;
155   context_ = 0;
156   smobify_self ();
157
158   accept_hash_table_ = scm_c_make_hash_table (19);
159 }
160
161 void
162 Translator_group::derived_mark () const
163 {
164 }
165
166 void
167 Translator_group::precompute_method_bindings ()
168 {
169   for (SCM s = simple_trans_list_; scm_is_pair (s); s = scm_cdr (s))
170     {
171       Translator *tr = unsmob_translator (scm_car (s));
172       Translator_void_method_ptr ptrs[TRANSLATOR_METHOD_PRECOMPUTE_COUNT];
173       tr->fetch_precomputable_methods (ptrs);
174
175       assert (tr);
176       for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
177         {
178           if (ptrs[i])
179             precomputed_method_bindings_[i].push (Translator_method_binding (tr, ptrs[i]));
180         }
181     }
182
183   fetch_precomputable_methods (precomputed_self_method_bindings_);
184 }
185
186 void
187 Translator_group::precomputed_translator_foreach (Translator_precompute_index idx)
188 {
189   Array<Translator_method_binding> &bindings (precomputed_method_bindings_[idx]);
190   for (int i = 0; i < bindings.size (); i++)
191     bindings[i].invoke ();
192 }
193
194 void
195 Translator_group::fetch_precomputable_methods (Translator_group_void_method ptrs[])
196 {
197   for (int i = 0; i < TRANSLATOR_METHOD_PRECOMPUTE_COUNT; i++)
198     ptrs[i] = 0;
199 }
200
201 void
202 Translator_group::call_precomputed_self_method (Translator_precompute_index idx)
203 {
204   if (precomputed_self_method_bindings_[idx])
205     (*precomputed_self_method_bindings_[idx]) (this);
206 }
207
208 Translator_group::~Translator_group ()
209 {
210 }
211
212 #include "ly-smobs.icc"
213
214 IMPLEMENT_SMOBS (Translator_group);
215 IMPLEMENT_DEFAULT_EQUAL_P (Translator_group);
216 IMPLEMENT_TYPE_P (Translator_group, "ly:translator-group?");
217
218 int
219 Translator_group::print_smob (SCM s, SCM port, scm_print_state *)
220 {
221   Translator_group *me = (Translator_group *) SCM_CELL_WORD_1 (s);
222   scm_puts ("#<Translator_group ", port);
223   scm_puts (me->class_name (), port);
224   scm_display (me->simple_trans_list_, port);
225   scm_puts (" >", port);
226   return 1;
227 }
228
229 SCM
230 Translator_group::mark_smob (SCM smob)
231 {
232   Translator_group *me = (Translator_group *)SCM_CELL_WORD_1 (smob);
233
234   me->derived_mark ();
235   scm_gc_mark (me->accept_hash_table_);
236   return me->simple_trans_list_;
237 }
238