]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
2002-07-31 Rune Zedeler <rune@zedeler.dk>
[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--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "music-output-def.hh"
10 #include "translator-group.hh"
11 #include "translator.hh"
12 #include "warn.hh"
13 #include "moment.hh"
14 #include "scm-hash.hh"
15 #include "translator-def.hh"
16 #include "main.hh"
17
18 Translator_group::Translator_group (Translator_group const&s)
19   : Translator (s)
20 {
21   iterator_count_ =0;
22   
23   Scheme_hash_table * tab =  new Scheme_hash_table (*s.properties_dict ());
24   properties_scm_ = tab->self_scm ();
25   scm_gc_unprotect_object (tab->self_scm ());
26 }
27
28 Scheme_hash_table*
29 Translator_group::properties_dict () const
30 {
31   return Scheme_hash_table::unsmob (properties_scm_);
32 }
33
34 Translator_group::~Translator_group ()
35 {
36   
37   //assert (removable_b ());
38 }
39
40
41 Translator_group::Translator_group ()
42 {
43   iterator_count_  = 0;
44   Scheme_hash_table *tab = new Scheme_hash_table ;
45   properties_scm_ = tab->self_scm ();
46
47   scm_gc_unprotect_object (tab->self_scm ());
48 }
49
50 void
51 Translator_group::check_removal ()
52 {
53   SCM next = SCM_EOL; 
54   for (SCM p = trans_group_list_; gh_pair_p (p); p = next)
55     {
56       next = ly_cdr (p);
57
58       Translator_group *trg =  dynamic_cast<Translator_group*> (unsmob_translator (ly_car (p)));
59
60       trg->check_removal ();
61       if (trg->removable_b ())
62         terminate_translator (trg);
63     }
64 }
65
66 SCM
67 Translator_group::add_translator (SCM list, Translator *t)
68 {
69   /*
70     Must append, since list ordering must be preserved.
71    */
72   list = gh_append2 (list, gh_cons (t->self_scm (), SCM_EOL));
73   t->daddy_trans_ = this;
74   t->output_def_ = output_def_;
75
76   return list;
77 }
78
79
80 void
81 Translator_group::add_used_group_translator (Translator *t)
82 {
83   trans_group_list_ = add_translator (trans_group_list_,t);
84 }
85
86
87 void
88 Translator_group::add_fresh_group_translator (Translator*t)
89 {
90   Translator_group*tg = dynamic_cast<Translator_group*> (t);
91   assert (tg);
92
93   trans_group_list_ = add_translator (trans_group_list_,t); 
94   unsmob_translator_def (tg->definition_)->apply_property_operations (tg);
95   t->initialize ();
96   
97 }
98
99
100 bool
101 Translator_group::removable_b () const
102 {
103   return trans_group_list_ == SCM_EOL && ! iterator_count_;
104 }
105
106 Translator_group *
107 Translator_group::find_existing_translator (String n, String id)
108 {
109   if ((is_alias_b (n) && (id_string_ == id || id.empty_b ())) || n == "Current")
110     return this;
111
112   Translator_group* r = 0;
113   for (SCM p = trans_group_list_; !r && gh_pair_p (p); p = ly_cdr (p))
114     {
115       Translator *  t = unsmob_translator (ly_car (p));
116       
117       r = dynamic_cast<Translator_group*> (t)->find_existing_translator (n, id);
118     }
119
120   return r;
121 }
122
123
124
125
126 Translator_group*
127 Translator_group::find_create_translator (String n, String id)
128 {
129   Translator_group * existing = find_existing_translator (n,id);
130   if (existing)
131     return existing;
132
133   Link_array<Translator_def> path
134     = unsmob_translator_def (definition_)->path_to_acceptable_translator (ly_str02scm ((char*)n.to_str0 ()), get_output_def ());
135
136   if (path.size ())
137     {
138       Translator_group * current = this;
139
140       // start at 1.  The first one (index 0) will be us.
141       for (int i=0; i < path.size (); i++)
142         {
143           Translator_group * new_group = path[i]->instantiate (output_def_);
144
145           if (i == path.size () -1)
146             new_group->id_string_ = id;   
147           current->add_fresh_group_translator (new_group);
148           current = new_group;
149         }
150
151       return current;
152     }
153
154   Translator_group *ret = 0;
155   if (daddy_trans_)
156     ret = daddy_trans_->find_create_translator (n,id);
157   else
158     {
159       warning (_f ("can't find or create `%s' called `%s'", n, id));
160       ret =0;
161     }
162   return ret;
163 }
164
165 bool
166 Translator_group::try_music_on_nongroup_children (Music *m)
167 {
168   bool hebbes_b =false;
169   
170   for (SCM p = simple_trans_list_; !hebbes_b && gh_pair_p (p); p = ly_cdr (p))
171     {
172       hebbes_b = unsmob_translator (ly_car (p))->try_music (m);
173     }
174   return hebbes_b;
175 }
176
177 bool
178 Translator_group::try_music (Music* m)
179 {
180   bool hebbes_b = try_music_on_nongroup_children (m);
181   
182   if (!hebbes_b && daddy_trans_)
183     hebbes_b = daddy_trans_->try_music (m);
184   return hebbes_b ;
185 }
186
187 int
188 Translator_group::get_depth () const
189 {
190   return (daddy_trans_) ? daddy_trans_->get_depth ()  + 1 : 0;
191 }
192
193 Translator_group*
194 Translator_group::get_ancestor (int level)
195 {
196   if (!level || !daddy_trans_)
197     return this;
198
199   return daddy_trans_->get_ancestor (level-1);
200 }
201
202 void
203 Translator_group::terminate_translator (Translator*r)
204 {
205   r->removal_processing ();
206   /*
207     Return value ignored. GC does the rest.
208    */
209   remove_translator (r);
210 }
211
212
213 /**
214    Remove a translator from the hierarchy.
215  */
216 Translator *
217 Translator_group::remove_translator (Translator*trans)
218 {
219   assert (trans);
220
221   trans_group_list_ = scm_delq_x (trans->self_scm (), trans_group_list_);
222   trans->daddy_trans_ = 0;
223   return trans;
224 }
225
226 bool
227 Translator_group::is_bottom_translator_b () const
228 {
229   return !gh_string_p (unsmob_translator_def (definition_)->default_child_context_name ());
230
231 }
232
233 Translator_group*
234 Translator_group::get_default_interpreter ()
235 {
236   if (!is_bottom_translator_b ())
237     {
238       SCM nm = unsmob_translator_def (definition_)->default_child_context_name ();
239       SCM st = get_output_def ()->find_translator (nm);
240
241       Translator_def *t = unsmob_translator_def (st);
242       if (!t)
243         {
244           warning (_f ("can't find or create: `%s'", ly_scm2string (nm).to_str0 ()));
245           t = unsmob_translator_def (this->definition_);
246         }
247       Translator_group *tg = t->instantiate (output_def_);
248       add_fresh_group_translator (tg);
249
250       if (!tg->is_bottom_translator_b ())
251         return tg->get_default_interpreter ();
252       else
253         return tg;
254     }
255   return this;
256 }
257
258 static void
259 static_each (SCM list, Method_pointer method)
260 {
261   for (SCM p = list; gh_pair_p (p); p = ly_cdr (p))
262     (unsmob_translator (ly_car (p))->*method) ();
263   
264 }
265
266 void
267 Translator_group::each (Method_pointer method) 
268 {
269   static_each (simple_trans_list_, method);
270   static_each (trans_group_list_, method);
271 }
272
273
274 /*
275   PROPERTIES
276  */
277 Translator_group*
278 Translator_group::where_defined (SCM sym) const
279 {
280   if (properties_dict ()->elem_b (sym))
281     {
282       return (Translator_group*)this;
283     }
284
285   return (daddy_trans_) ? daddy_trans_->where_defined (sym) : 0;
286 }
287
288 /*
289   return SCM_EOL when not found.
290 */
291 SCM
292 Translator_group::internal_get_property (SCM sym) const
293 {
294   SCM val =SCM_EOL;
295   if (properties_dict ()->try_retrieve (sym, &val))
296     return val;
297
298   if (daddy_trans_)
299     return daddy_trans_->internal_get_property (sym);
300   
301   return val;
302 }
303
304 void
305 Translator_group::internal_set_property (SCM sym, SCM val)
306 {
307 #ifndef NDEBUG
308   if (internal_type_checking_global_b)
309     assert (type_check_assignment (sym, val, ly_symbol2scm ("translation-type?")));
310 #endif
311   
312   properties_dict ()->set (sym, val);
313 }
314
315 /*
316   TODO: look up to check whether we have inherited var? 
317  */
318 void
319 Translator_group::unset_property (SCM sym)
320 {
321   properties_dict ()->remove (sym);
322 }
323
324
325 /*
326   Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
327   entry from a translator property list by name of PROP
328 */
329 void
330 Translator_group::execute_single_pushpop_property (SCM prop, SCM eltprop, SCM val)
331 {
332   if (gh_symbol_p (prop))
333     {
334       if (val != SCM_UNDEFINED)
335         {
336           SCM prev = internal_get_property (prop);
337
338           if (gh_pair_p (prev) || prev == SCM_EOL)
339             {
340               bool ok = type_check_assignment (eltprop, val, ly_symbol2scm ("backend-type?"));
341               
342               if (ok)
343                 {
344                   prev = gh_cons (gh_cons (eltprop, val), prev);
345                   internal_set_property (prop, prev);
346                 }
347             }
348           else
349             {
350               // warning here.
351             }
352           
353         }
354       else
355         {
356           SCM prev = internal_get_property (prop);
357
358           SCM newprops= SCM_EOL ;
359           while (gh_pair_p (prev) && ly_caar (prev) != eltprop)
360             {
361               newprops = gh_cons (ly_car (prev), newprops);
362               prev = ly_cdr (prev);
363             }
364           
365           if (gh_pair_p (prev))
366             {
367               newprops = scm_reverse_x (newprops, ly_cdr (prev));
368               internal_set_property (prop, newprops);
369             }
370         }
371     }
372 }
373
374
375
376
377
378 /*
379   STUBS
380 */
381 void
382 Translator_group::stop_translation_timestep ()
383 {
384   each (&Translator::stop_translation_timestep);
385 }
386
387 void
388 Translator_group::start_translation_timestep ()
389 {
390   each (&Translator::start_translation_timestep);
391 }
392
393 void
394 Translator_group::do_announces ()
395 {
396   each (&Translator::do_announces);
397 }
398
399 void
400 Translator_group::initialize ()
401 {
402   each (&Translator::initialize);
403 }
404
405 void
406 Translator_group::finalize ()
407 {
408   each (&Translator::removal_processing);
409 }
410
411 LY_DEFINE(ly_get_context_property,
412           "ly-get-context-property", 2, 0, 0,
413           (SCM context, SCM name),
414           "retrieve the value of @var{sym} from context @var{tr}")
415 {
416   Translator *t = unsmob_translator (context);
417   Translator_group* tr=   dynamic_cast<Translator_group*> (t);
418   SCM_ASSERT_TYPE(tr, context, SCM_ARG1, __FUNCTION__, "Translator group");
419   SCM_ASSERT_TYPE(gh_symbol_p (name), name, SCM_ARG2, __FUNCTION__, "symbol");
420
421   return tr->internal_get_property (name);
422   
423 }
424
425 LY_DEFINE(ly_set_context_property,
426           "ly-set-context-property", 3, 0, 0,
427           (SCM context, SCM name, SCM val),
428           "set value of property @var{sym} in context @var{tr} to @var{val}.
429 ")
430 {
431   Translator *t = unsmob_translator (context);
432   Translator_group* tr=   dynamic_cast<Translator_group*> (t);
433
434   SCM_ASSERT_TYPE(tr, context, SCM_ARG1, __FUNCTION__, "Context");
435   tr->internal_set_property (name, val);
436
437   return SCM_UNSPECIFIED;
438 }