2 Translator_group.cc -- implement Translator_group
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "music-output-def.hh"
10 #include "translator-group.hh"
11 #include "translator.hh"
14 #include "scm-hash.hh"
15 #include "killing-cons.tcc"
16 #include "translator-def.hh"
18 Translator_group::Translator_group (Translator_group
const&s
)
23 Scheme_hash_table
* tab
= new Scheme_hash_table (*s
.properties_dict ());
24 properties_scm_
= tab
->self_scm ();
25 scm_unprotect_object (tab
->self_scm ());
29 Translator_group::properties_dict () const
31 return Scheme_hash_table::unsmob (properties_scm_
);
34 Translator_group::~Translator_group ()
37 //assert (removable_b ());
41 Translator_group::Translator_group ()
44 Scheme_hash_table
*tab
= new Scheme_hash_table
;
45 properties_scm_
= tab
->self_scm ();
47 scm_unprotect_object (tab
->self_scm ());
51 Translator_group::check_removal ()
54 for (SCM p
= trans_group_list_
; gh_pair_p (p
); p
= next
)
58 Translator_group
*trg
= dynamic_cast<Translator_group
*> (unsmob_translator (gh_car (p
)));
60 trg
->check_removal ();
61 if (trg
->removable_b ())
62 terminate_translator (trg
);
68 Translator_group::add_translator (SCM list
, Translator
*t
)
70 list
= gh_append2 (list
, gh_cons (t
->self_scm (), SCM_EOL
));
71 t
->daddy_trans_l_
= this;
72 t
->output_def_l_
= output_def_l_
;
73 if (Translator_group
*tg
= dynamic_cast<Translator_group
*> (t
))
75 unsmob_translator_def (tg
->definition_
)->apply_property_operations (tg
);
82 Translator_group::add_group_translator (Translator
*t
)
84 trans_group_list_
= add_translator (trans_group_list_
,t
);
90 Translator_group::removable_b () const
92 return trans_group_list_
== SCM_EOL
&& ! iterator_count_
;
96 Translator_group::find_existing_translator_l (String n
, String id
)
98 if (is_alias_b (n
) && (id_str_
== id
|| id
.empty_b ()))
101 Translator_group
* r
= 0;
102 for (SCM p
= trans_group_list_
; !r
&& gh_pair_p (p
); p
= gh_cdr (p
))
104 Translator
* t
= unsmob_translator (gh_car (p
));
106 r
= dynamic_cast<Translator_group
*> (t
)->find_existing_translator_l (n
, id
);
116 Translator_group::find_create_translator_l (String n
, String id
)
118 Translator_group
* existing
= find_existing_translator_l (n
,id
);
122 Link_array
<Translator_def
> path
123 = unsmob_translator_def (definition_
)->path_to_acceptable_translator (ly_str02scm ((char*)n
.ch_C ()), output_def_l ());
127 Translator_group
* current
= this;
129 // start at 1. The first one (index 0) will be us.
130 for (int i
=0; i
< path
.size (); i
++)
132 Translator_group
* new_group
= path
[i
]->instantiate (output_def_l_
);
134 current
->add_group_translator (new_group
);
137 current
->id_str_
= id
;
141 Translator_group
*ret
= 0;
143 ret
= daddy_trans_l_
->find_create_translator_l (n
,id
);
146 warning (_f ("can't find or create `%s' called `%s'", n
, id
));
153 Translator_group::try_music_on_nongroup_children (Music
*m
)
155 bool hebbes_b
=false;
157 for (SCM p
= simple_trans_list_
; !hebbes_b
&& gh_pair_p (p
); p
= gh_cdr (p
))
159 hebbes_b
= unsmob_translator (gh_car (p
))->try_music (m
);
165 Translator_group::try_music (Music
* m
)
167 bool hebbes_b
= try_music_on_nongroup_children (m
);
169 if (!hebbes_b
&& daddy_trans_l_
)
170 hebbes_b
= daddy_trans_l_
->try_music (m
);
175 Translator_group::depth_i () const
177 return (daddy_trans_l_
) ? daddy_trans_l_
->depth_i () + 1 : 0;
181 Translator_group::ancestor_l (int level
)
183 if (!level
|| !daddy_trans_l_
)
186 return daddy_trans_l_
->ancestor_l (level
-1);
190 Translator_group::terminate_translator (Translator
*r_l
)
192 r_l
->removal_processing ();
194 Return value ignored. GC does the rest.
196 remove_translator_p (r_l
);
201 Remove a translator from the hierarchy.
204 Translator_group::remove_translator_p (Translator
*trans_l
)
208 trans_group_list_
= scm_delq_x (trans_l
->self_scm (), trans_group_list_
);
209 trans_l
->daddy_trans_l_
= 0;
214 Translator_group::is_bottom_translator_b () const
216 return !gh_string_p (unsmob_translator_def (definition_
)->default_child_context_name ());
221 Translator_group::get_default_interpreter ()
223 if (!is_bottom_translator_b ())
225 SCM nm
= unsmob_translator_def (definition_
)->default_child_context_name ();
226 SCM st
= output_def_l ()->find_translator_l (nm
);
228 Translator_def
*t
= unsmob_translator_def (st
);
231 warning (_f ("can't find or create: `%s'", ly_scm2string (nm
).ch_C ()));
232 t
= unsmob_translator_def (this->definition_
);
234 Translator_group
*tg
= t
->instantiate (output_def_l_
);
235 add_group_translator (tg
);
237 if (!tg
->is_bottom_translator_b ())
238 return tg
->get_default_interpreter ();
246 static_each (SCM list
, Method_pointer method
)
248 for (SCM p
= list
; gh_pair_p (p
); p
= gh_cdr (p
))
249 (unsmob_translator (gh_car (p
))->*method
) ();
254 Translator_group::each (Method_pointer method
)
256 static_each (simple_trans_list_
, method
);
257 static_each (trans_group_list_
, method
);
265 Translator_group::where_defined (SCM sym
) const
267 if (properties_dict ()->elem_b (sym
))
269 return (Translator_group
*)this;
272 return (daddy_trans_l_
) ? daddy_trans_l_
->where_defined (sym
) : 0;
276 return SCM_EOL when not found.
279 Translator_group::get_property (SCM sym
) const
282 if (properties_dict ()->try_retrieve (sym
, &val
))
286 return daddy_trans_l_
->get_property (sym
);
292 Translator_group::set_property (String id
, SCM val
)
294 set_property (ly_symbol2scm (id
.ch_C ()), val
);
299 Translator_group::set_property (SCM sym
, SCM val
)
301 properties_dict ()->set (sym
, val
);
305 TODO: look up to check whether we have inherited var?
308 Translator_group::unset_property (SCM sym
)
310 properties_dict ()->remove (sym
);
315 Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
316 entry from a translator property list by name of PROP
319 Translator_group::execute_single_pushpop_property (SCM prop
, SCM eltprop
, SCM val
)
321 if (gh_symbol_p (prop
))
323 if (val
!= SCM_UNDEFINED
)
325 SCM prev
= get_property (prop
);
327 if (gh_pair_p (prev
) || prev
== SCM_EOL
)
329 bool ok
= type_check_assignment (val
, eltprop
, ly_symbol2scm ("backend-type?"));
335 prev
= gh_cons (gh_cons (eltprop
, val
), prev
);
336 set_property (prop
, prev
);
347 SCM prev
= get_property (prop
);
349 SCM newprops
= SCM_EOL
;
350 while (gh_pair_p (prev
) && gh_caar (prev
) != eltprop
)
352 newprops
= gh_cons (gh_car (prev
), newprops
);
353 prev
= gh_cdr (prev
);
356 if (gh_pair_p (prev
))
358 newprops
= scm_reverse_x (newprops
, gh_cdr (prev
));
359 set_property (prop
, newprops
);
373 Translator_group::stop_translation_timestep ()
375 each (&Translator::stop_translation_timestep
);
379 Translator_group::start_translation_timestep ()
381 each (&Translator::start_translation_timestep
);
385 Translator_group::do_announces ()
387 each (&Translator::announces
);
391 Translator_group::initialize ()
393 each (&Translator::initialize
);
397 Translator_group::finalize ()
399 each (&Translator::removal_processing
);
404 type_check_assignment (SCM val
, SCM sym
, SCM type_symbol
)
407 SCM type_p
= SCM_EOL
;
409 if (gh_symbol_p (sym
))
410 type_p
= scm_object_property (sym
, type_symbol
);
412 if (type_p
!= SCM_EOL
&& !gh_procedure_p (type_p
))
414 warning (_f ("Can't find property type-check for `%s'. Perhaps you made a typing error? Doing assignment anyway.",
415 ly_symbol2string (sym
).ch_C ()));
420 && gh_procedure_p (type_p
)
421 && gh_call1 (type_p
, val
) == SCM_BOOL_F
)
423 SCM errport
= scm_current_error_port ();
425 SCM typefunc
= scm_eval2 (ly_symbol2scm ("type-name"), SCM_EOL
);
426 SCM type_name
= gh_call1 (typefunc
, type_p
);
428 scm_puts (_f ("Type check for `%s' failed; value `%s' must be of type `%s'",
429 ly_symbol2string (sym
).ch_C (),
430 ly_scm2string (ly_write2scm (val
)).ch_C (),
431 ly_scm2string (type_name
).ch_C ()).ch_C (),
433 scm_puts ("\n", errport
);
440 ly_get_trans_property (SCM context
, SCM name
)
442 Translator
*t
= unsmob_translator (context
);
443 Translator_group
* tr
= dynamic_cast<Translator_group
*> (t
);
446 /* programming_error? */
447 warning (_ ("ly-get-trans-property: expecting a Translator_group argument"));
450 return tr
->get_property (name
);
454 ly_set_trans_property (SCM context
, SCM name
, SCM val
)
457 Translator
*t
= unsmob_translator (context
);
458 Translator_group
* tr
= dynamic_cast<Translator_group
*> (t
);
461 tr
->set_property (name
, val
);
463 return SCM_UNSPECIFIED
;
470 add_trans_scm_funcs ()
472 scm_make_gsubr ("ly-get-trans-property", 2, 0, 0, (Scheme_function_unknown
)ly_get_trans_property
);
473 scm_make_gsubr ("ly-set-trans-property", 3, 0, 0, (Scheme_function_unknown
)ly_set_trans_property
);
476 ADD_SCM_INIT_FUNC (trans_scm
, add_trans_scm_funcs
);