2 Translator_group.cc -- implement Translator_group
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 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
);
298 Translator_group::set_property (SCM sym
, SCM val
)
300 properties_dict ()->set (sym
, val
);
304 Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
305 entry from a translator property list by name of PROP
308 Translator_group::execute_single_pushpop_property (SCM prop
, SCM eltprop
, SCM val
)
310 if (gh_symbol_p(prop
))
312 if (val
!= SCM_UNDEFINED
)
314 SCM prev
= get_property (prop
);
316 if (gh_pair_p (prev
) || prev
== SCM_EOL
)
318 bool ok
= type_check_assignment (val
, eltprop
, ly_symbol2scm ("backend-type?"));
324 prev
= gh_cons (gh_cons (eltprop
, val
), prev
);
325 set_property (prop
, prev
);
336 SCM prev
= get_property (prop
);
338 SCM newprops
= SCM_EOL
;
339 while (gh_pair_p (prev
) && gh_caar (prev
) != eltprop
)
341 newprops
= gh_cons (gh_car (prev
), newprops
);
342 prev
= gh_cdr (prev
);
345 if (gh_pair_p (prev
))
347 newprops
= scm_reverse_x (newprops
, gh_cdr (prev
));
348 set_property (prop
, newprops
);
362 Translator_group::stop_translation_timestep ()
364 each (&Translator::pre_move_processing
);
368 Translator_group::start_translation_timestep ()
370 each (&Translator::post_move_processing
);
374 Translator_group::do_announces ()
376 each (&Translator::announces
);
380 Translator_group::initialize ()
382 each (&Translator::initialize
);
386 Translator_group::finalize ()
388 each (&Translator::removal_processing
);
393 type_check_assignment (SCM val
, SCM sym
, SCM type_symbol
)
396 SCM type_p
= SCM_EOL
;
398 if (gh_symbol_p(sym
))
399 type_p
= scm_object_property (sym
, type_symbol
);
401 if (type_p
!= SCM_EOL
&& !gh_procedure_p (type_p
))
403 warning (_f ("Can't find property type-check for `%s'. Perhaps you made a typing error?",
404 ly_symbol2string (sym
).ch_C ()));
409 && gh_procedure_p (type_p
)
410 && gh_call1 (type_p
, val
) == SCM_BOOL_F
)
412 SCM errport
= scm_current_error_port ();
414 SCM typefunc
= scm_eval2 (ly_symbol2scm ("type-name"), SCM_EOL
);
415 SCM type_name
= gh_call1 (typefunc
, type_p
);
417 scm_puts (_f ("Failed typecheck for `%s', value `%s' must be of type `%s'",
418 ly_symbol2string (sym
).ch_C (),
419 ly_scm2string (ly_write2scm( val
)).ch_C (),
420 ly_scm2string (type_name
).ch_C ()).ch_C (),
422 scm_puts ("\n", errport
);
429 ly_get_trans_property (SCM context
, SCM name
)
431 Translator
*t
= unsmob_translator (context
);
432 Translator_group
* tr
= dynamic_cast<Translator_group
*> (t
);
435 /* programming_error? */
436 warning (_ ("ly-get-trans-property: expecting a Translator_group argument"));
439 return tr
->get_property (name
);
443 ly_set_trans_property (SCM context
, SCM name
, SCM val
)
446 Translator
*t
= unsmob_translator (context
);
447 Translator_group
* tr
= dynamic_cast<Translator_group
*> (t
);
450 tr
->set_property (name
, val
);
452 return SCM_UNSPECIFIED
;
459 add_trans_scm_funcs ()
461 scm_make_gsubr ("ly-get-trans-property", 2, 0, 0, (Scheme_function_unknown
)ly_get_trans_property
);
462 scm_make_gsubr ("ly-set-trans-property", 3, 0, 0, (Scheme_function_unknown
)ly_set_trans_property
);
465 ADD_SCM_INIT_FUNC(trans_scm
, add_trans_scm_funcs
);