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 "translator-def.hh"
17 Translator_group::Translator_group (Translator_group
const&s
)
22 Scheme_hash_table
* tab
= new Scheme_hash_table (*s
.properties_dict ());
23 properties_scm_
= tab
->self_scm ();
24 scm_gc_unprotect_object (tab
->self_scm ());
28 Translator_group::properties_dict () const
30 return Scheme_hash_table::unsmob (properties_scm_
);
33 Translator_group::~Translator_group ()
36 //assert (removable_b ());
40 Translator_group::Translator_group ()
43 Scheme_hash_table
*tab
= new Scheme_hash_table
;
44 properties_scm_
= tab
->self_scm ();
46 scm_gc_unprotect_object (tab
->self_scm ());
50 Translator_group::check_removal ()
53 for (SCM p
= trans_group_list_
; gh_pair_p (p
); p
= next
)
57 Translator_group
*trg
= dynamic_cast<Translator_group
*> (unsmob_translator (gh_car (p
)));
59 trg
->check_removal ();
60 if (trg
->removable_b ())
61 terminate_translator (trg
);
67 Translator_group::add_translator (SCM list
, Translator
*t
)
69 list
= gh_append2 (list
, gh_cons (t
->self_scm (), SCM_EOL
));
70 t
->daddy_trans_l_
= this;
71 t
->output_def_l_
= output_def_l_
;
72 if (Translator_group
*tg
= dynamic_cast<Translator_group
*> (t
))
74 unsmob_translator_def (tg
->definition_
)->apply_property_operations (tg
);
81 Translator_group::add_group_translator (Translator
*t
)
83 trans_group_list_
= add_translator (trans_group_list_
,t
);
89 Translator_group::removable_b () const
91 return trans_group_list_
== SCM_EOL
&& ! iterator_count_
;
95 Translator_group::find_existing_translator_l (String n
, String id
)
97 if (is_alias_b (n
) && (id_str_
== id
|| id
.empty_b ()))
100 Translator_group
* r
= 0;
101 for (SCM p
= trans_group_list_
; !r
&& gh_pair_p (p
); p
= gh_cdr (p
))
103 Translator
* t
= unsmob_translator (gh_car (p
));
105 r
= dynamic_cast<Translator_group
*> (t
)->find_existing_translator_l (n
, id
);
115 Translator_group::find_create_translator_l (String n
, String id
)
117 Translator_group
* existing
= find_existing_translator_l (n
,id
);
121 Link_array
<Translator_def
> path
122 = unsmob_translator_def (definition_
)->path_to_acceptable_translator (ly_str02scm ((char*)n
.ch_C ()), output_def_l ());
126 Translator_group
* current
= this;
128 // start at 1. The first one (index 0) will be us.
129 for (int i
=0; i
< path
.size (); i
++)
131 Translator_group
* new_group
= path
[i
]->instantiate (output_def_l_
);
133 current
->add_group_translator (new_group
);
136 current
->id_str_
= id
;
140 Translator_group
*ret
= 0;
142 ret
= daddy_trans_l_
->find_create_translator_l (n
,id
);
145 warning (_f ("can't find or create `%s' called `%s'", n
, id
));
152 Translator_group::try_music_on_nongroup_children (Music
*m
)
154 bool hebbes_b
=false;
156 for (SCM p
= simple_trans_list_
; !hebbes_b
&& gh_pair_p (p
); p
= gh_cdr (p
))
158 hebbes_b
= unsmob_translator (gh_car (p
))->try_music (m
);
164 Translator_group::try_music (Music
* m
)
166 bool hebbes_b
= try_music_on_nongroup_children (m
);
168 if (!hebbes_b
&& daddy_trans_l_
)
169 hebbes_b
= daddy_trans_l_
->try_music (m
);
174 Translator_group::depth_i () const
176 return (daddy_trans_l_
) ? daddy_trans_l_
->depth_i () + 1 : 0;
180 Translator_group::ancestor_l (int level
)
182 if (!level
|| !daddy_trans_l_
)
185 return daddy_trans_l_
->ancestor_l (level
-1);
189 Translator_group::terminate_translator (Translator
*r_l
)
191 r_l
->removal_processing ();
193 Return value ignored. GC does the rest.
195 remove_translator_p (r_l
);
200 Remove a translator from the hierarchy.
203 Translator_group::remove_translator_p (Translator
*trans_l
)
207 trans_group_list_
= scm_delq_x (trans_l
->self_scm (), trans_group_list_
);
208 trans_l
->daddy_trans_l_
= 0;
213 Translator_group::is_bottom_translator_b () const
215 return !gh_string_p (unsmob_translator_def (definition_
)->default_child_context_name ());
220 Translator_group::get_default_interpreter ()
222 if (!is_bottom_translator_b ())
224 SCM nm
= unsmob_translator_def (definition_
)->default_child_context_name ();
225 SCM st
= output_def_l ()->find_translator_l (nm
);
227 Translator_def
*t
= unsmob_translator_def (st
);
230 warning (_f ("can't find or create: `%s'", ly_scm2string (nm
).ch_C ()));
231 t
= unsmob_translator_def (this->definition_
);
233 Translator_group
*tg
= t
->instantiate (output_def_l_
);
234 add_group_translator (tg
);
236 if (!tg
->is_bottom_translator_b ())
237 return tg
->get_default_interpreter ();
245 static_each (SCM list
, Method_pointer method
)
247 for (SCM p
= list
; gh_pair_p (p
); p
= gh_cdr (p
))
248 (unsmob_translator (gh_car (p
))->*method
) ();
253 Translator_group::each (Method_pointer method
)
255 static_each (simple_trans_list_
, method
);
256 static_each (trans_group_list_
, method
);
264 Translator_group::where_defined (SCM sym
) const
266 if (properties_dict ()->elem_b (sym
))
268 return (Translator_group
*)this;
271 return (daddy_trans_l_
) ? daddy_trans_l_
->where_defined (sym
) : 0;
275 return SCM_EOL when not found.
278 Translator_group::get_property (SCM sym
) const
281 if (properties_dict ()->try_retrieve (sym
, &val
))
285 return daddy_trans_l_
->get_property (sym
);
291 Translator_group::set_property (String id
, SCM val
)
293 set_property (ly_symbol2scm (id
.ch_C ()), val
);
298 Translator_group::set_property (SCM sym
, SCM val
)
300 properties_dict ()->set (sym
, val
);
304 TODO: look up to check whether we have inherited var?
307 Translator_group::unset_property (SCM sym
)
309 properties_dict ()->remove (sym
);
314 Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
315 entry from a translator property list by name of PROP
318 Translator_group::execute_single_pushpop_property (SCM prop
, SCM eltprop
, SCM val
)
320 if (gh_symbol_p (prop
))
322 if (val
!= SCM_UNDEFINED
)
324 SCM prev
= get_property (prop
);
326 if (gh_pair_p (prev
) || prev
== SCM_EOL
)
328 bool ok
= type_check_assignment (val
, eltprop
, ly_symbol2scm ("backend-type?"));
334 prev
= gh_cons (gh_cons (eltprop
, val
), prev
);
335 set_property (prop
, prev
);
346 SCM prev
= get_property (prop
);
348 SCM newprops
= SCM_EOL
;
349 while (gh_pair_p (prev
) && gh_caar (prev
) != eltprop
)
351 newprops
= gh_cons (gh_car (prev
), newprops
);
352 prev
= gh_cdr (prev
);
355 if (gh_pair_p (prev
))
357 newprops
= scm_reverse_x (newprops
, gh_cdr (prev
));
358 set_property (prop
, newprops
);
372 Translator_group::stop_translation_timestep ()
374 each (&Translator::stop_translation_timestep
);
378 Translator_group::start_translation_timestep ()
380 each (&Translator::start_translation_timestep
);
384 Translator_group::do_announces ()
386 each (&Translator::announces
);
390 Translator_group::initialize ()
392 each (&Translator::initialize
);
396 Translator_group::finalize ()
398 each (&Translator::removal_processing
);
403 type_check_assignment (SCM val
, SCM sym
, SCM type_symbol
)
406 SCM type_p
= SCM_EOL
;
408 if (gh_symbol_p (sym
))
409 type_p
= scm_object_property (sym
, type_symbol
);
411 if (type_p
!= SCM_EOL
&& !gh_procedure_p (type_p
))
413 warning (_f ("Can't find property type-check for `%s'. Perhaps you made a typing error? Doing assignment anyway.",
414 ly_symbol2string (sym
).ch_C ()));
419 && gh_procedure_p (type_p
)
420 && gh_call1 (type_p
, val
) == SCM_BOOL_F
)
422 SCM errport
= scm_current_error_port ();
424 SCM typefunc
= scm_primitive_eval (ly_symbol2scm ("type-name"));
425 SCM type_name
= gh_call1 (typefunc
, type_p
);
427 scm_puts (_f ("Type check for `%s' failed; value `%s' must be of type `%s'",
428 ly_symbol2string (sym
).ch_C (),
429 ly_scm2string (ly_write2scm (val
)).ch_C (),
430 ly_scm2string (type_name
).ch_C ()).ch_C (),
432 scm_puts ("\n", errport
);
439 ly_get_trans_property (SCM context
, SCM name
)
441 Translator
*t
= unsmob_translator (context
);
442 Translator_group
* tr
= dynamic_cast<Translator_group
*> (t
);
445 /* programming_error? */
446 warning (_ ("ly-get-trans-property: expecting a Translator_group argument"));
449 return tr
->get_property (name
);
453 ly_set_trans_property (SCM context
, SCM name
, SCM val
)
456 Translator
*t
= unsmob_translator (context
);
457 Translator_group
* tr
= dynamic_cast<Translator_group
*> (t
);
460 tr
->set_property (name
, val
);
462 return SCM_UNSPECIFIED
;
469 add_trans_scm_funcs ()
471 scm_c_define_gsubr ("ly-get-trans-property", 2, 0, 0, (Scheme_function_unknown
)ly_get_trans_property
);
472 scm_c_define_gsubr ("ly-set-trans-property", 3, 0, 0, (Scheme_function_unknown
)ly_set_trans_property
);
475 ADD_SCM_INIT_FUNC (trans_scm
, add_trans_scm_funcs
);