2 translator-def.cc -- implement Translator_def
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "lily-proto.hh"
11 #include "translator-def.hh"
12 #include "translator-group.hh"
14 #include "music-output-def.hh"
15 #include "ly-smobs.icc"
18 Translator_def::print_smob (SCM smob
, SCM port
, scm_print_state
*)
20 Translator_def
* me
= (Translator_def
*) SCM_CELL_WORD_1 (smob
);
22 scm_puts ("#<Translator_def ", port
);
23 scm_display (me
->type_name_
, port
);
30 Translator_def::mark_smob (SCM smob
)
32 Translator_def
* me
= (Translator_def
*) SCM_CELL_WORD_1 (smob
);
34 scm_gc_mark (me
->description_
);
35 scm_gc_mark (me
->type_aliases_
);
36 scm_gc_mark (me
->consists_name_list_
);
37 scm_gc_mark (me
->accepts_name_list_
);
38 scm_gc_mark (me
->end_consists_name_list_
);
39 scm_gc_mark (me
->property_ops_
);
40 scm_gc_mark (me
->translator_group_type_
);
41 return me
->type_name_
;
45 Translator_def::Translator_def ()
47 type_aliases_
= SCM_EOL
;
48 translator_group_type_
= SCM_EOL
;
49 accepts_name_list_
= SCM_EOL
;
50 consists_name_list_
= SCM_EOL
;
51 end_consists_name_list_
= SCM_EOL
;
52 property_ops_
= SCM_EOL
;
54 description_
= SCM_EOL
;
60 Translator_def::~Translator_def ()
64 Translator_def::Translator_def (Translator_def
const & s
)
67 type_aliases_
= SCM_EOL
;
68 translator_group_type_
= SCM_EOL
;
69 accepts_name_list_
= SCM_EOL
;
70 consists_name_list_
= SCM_EOL
;
71 end_consists_name_list_
= SCM_EOL
;
72 property_ops_
= SCM_EOL
;
74 description_
= SCM_EOL
;
77 description_
= s
.description_
;
79 consists_name_list_
= scm_list_copy (s
.consists_name_list_
);
80 end_consists_name_list_
= scm_list_copy (s
.end_consists_name_list_
);
81 accepts_name_list_
= scm_list_copy (s
.accepts_name_list_
);
82 property_ops_
= scm_list_copy (s
.property_ops_
);
83 type_aliases_
= scm_list_copy (s
.type_aliases_
);
84 translator_group_type_
= s
.translator_group_type_
;
85 type_name_
= s
.type_name_
;
91 Translator_def::set_acceptor (SCM name
, bool add
)
94 this->accepts_name_list_
= gh_cons (name
, this->accepts_name_list_
);
96 this->accepts_name_list_
= scm_delete_x (name
, this->accepts_name_list_
);
101 Translator_def::modify_definition (SCM list
, SCM str
, bool add
)
103 String s
= ly_scm2string (str
);
104 if (!get_translator (s
))
105 error (_ ("Program has no such type"));
109 if (scm_memq (str
, list
) != SCM_BOOL_F
)
111 warning (_f ("Already contains: `%s'", s
));
112 warning (_f ("Not adding translator: `%s'", s
));
115 list
= gh_cons (str
, list
);
119 list
= scm_delete_x (str
, list
);
127 Translator_def::remove_element (SCM s
)
129 this->end_consists_name_list_
= modify_definition (this->end_consists_name_list_
, s
, false);
130 this->consists_name_list_
= modify_definition (this->consists_name_list_
, s
, false);
134 Translator_def::add_element (SCM s
)
136 this->consists_name_list_
= modify_definition (this->consists_name_list_
, s
, true);
140 Translator_def::add_last_element (SCM s
)
142 this->end_consists_name_list_
= modify_definition (this->end_consists_name_list_
, s
, true);
145 Translator_def::add_push_property (SCM props
, SCM syms
, SCM vals
)
147 this->property_ops_
= gh_cons (scm_list_n (ly_symbol2scm ("push"), props
, syms
, vals
, SCM_UNDEFINED
),
148 this->property_ops_
);
152 Translator_def::add_pop_property (SCM props
, SCM syms
)
154 this->property_ops_
= gh_cons (scm_list_n (ly_symbol2scm ("push"), props
, syms
, SCM_UNDEFINED
),
155 this->property_ops_
);
161 Do it. SYM is single symbol. VAL is SCM_UNDEFINED in case of a pop
164 Translator_def::apply_pushpop_property (Translator_group
* me
,SCM sym
, SCM eprop
, SCM val
)
166 dynamic_cast<Translator_group
*> (me
)
167 ->execute_single_pushpop_property (sym
, eprop
, val
);
172 Link_array
<Translator_def
>
173 Translator_def::path_to_acceptable_translator (SCM type_string
, Music_output_def
* odef
) const
175 assert (gh_string_p (type_string
));
177 Link_array
<Translator_def
> accepteds
;
178 for (SCM s
= accepts_name_list_
; gh_pair_p (s
); s
= ly_cdr (s
))
180 Translator_def
*t
= unsmob_translator_def (odef
->find_translator (ly_car (s
)));
186 Link_array
<Translator_def
> best_result
;
187 for (int i
=0; i
< accepteds
.size (); i
++)
191 don't check aliases, because \context Staff should not create RhythmicStaff.
193 if (gh_equal_p (accepteds
[i
]->type_name_
, type_string
))
195 best_result
.push (accepteds
[i
]);
200 int best_depth
= INT_MAX
;
201 for (int i
=0; i
< accepteds
.size (); i
++)
203 Translator_def
* g
= accepteds
[i
];
205 Link_array
<Translator_def
> result
206 = g
->path_to_acceptable_translator (type_string
, odef
);
207 if (result
.size () && result
.size () < best_depth
)
210 best_result
= result
;
217 IMPLEMENT_SMOBS (Translator_def
);
218 IMPLEMENT_DEFAULT_EQUAL_P (Translator_def
);
222 trans_list (SCM namelist
, Translator_group
*tg
)
225 for (SCM s
= namelist
; gh_pair_p (s
) ; s
= ly_cdr (s
))
227 Translator
* t
= get_translator (ly_scm2string (ly_car (s
)));
229 warning (_f ("can't find: `%s'", s
));
232 Translator
* tr
= t
->clone ();
233 SCM str
= tr
->self_scm ();
234 l
= gh_cons (str
, l
);
236 tr
->daddy_trans_
= tg
;
237 tr
->output_def_
= tg
->output_def_
;
239 scm_gc_unprotect_object (str
);
247 Translator_def::instantiate (Music_output_def
* md
)
249 Translator
* g
= get_translator (ly_scm2string (translator_group_type_
));
252 Translator_group
*tg
= dynamic_cast<Translator_group
*> (g
);
253 tg
->output_def_
= md
;
254 tg
->definition_
= self_scm ();
255 tg
->type_string_
= ly_scm2string (type_name_
);
258 TODO: ugh. we're reversing CONSISTS_NAME_LIST_ here
260 SCM l1
= trans_list (consists_name_list_
, tg
);
261 SCM l2
=trans_list (end_consists_name_list_
,tg
);
262 l1
= scm_reverse_x (l1
, l2
);
264 tg
->simple_trans_list_
= l1
;
271 Translator_def::apply_property_operations (Translator_group
*tg
)
273 SCM correct_order
= scm_reverse (property_ops_
); // pity of the mem.
274 for (SCM s
= correct_order
; gh_pair_p (s
); s
= ly_cdr (s
))
276 SCM entry
= ly_car (s
);
277 SCM type
= ly_car (entry
);
278 entry
= ly_cdr (entry
);
280 if (type
== ly_symbol2scm ("push"))
282 SCM val
= ly_cddr (entry
);
283 val
= gh_pair_p (val
) ? ly_car (val
) : SCM_UNDEFINED
;
285 apply_pushpop_property (tg
, ly_car (entry
), ly_cadr (entry
), val
);
287 else if (type
== ly_symbol2scm ("assign"))
289 tg
->internal_set_property (ly_car (entry
), ly_cadr (entry
));
295 Translator_def::clone_scm () const
297 Translator_def
* t
= new Translator_def (*this);
298 scm_gc_unprotect_object (t
->self_scm());
299 return t
->self_scm();
303 Translator_def::make_scm ()
305 Translator_def
* t
= new Translator_def
;
306 scm_gc_unprotect_object (t
->self_scm());
307 return t
->self_scm();
311 Translator_def::add_property_assign (SCM nm
, SCM val
)
313 this->property_ops_
= gh_cons (scm_list_n (ly_symbol2scm ("assign"), scm_string_to_symbol (nm
), val
, SCM_UNDEFINED
),
314 this->property_ops_
);
318 Default child context as a SCM string, or something else if there is
322 Translator_def::default_child_context_name ()
324 SCM d
= accepts_name_list_
;
325 return gh_pair_p (d
) ? ly_car (scm_last_pair (d
)) : SCM_EOL
;
329 Translator_def::to_alist () const
333 l
= gh_cons (gh_cons (ly_symbol2scm ("consists"), consists_name_list_
), l
);
334 l
= gh_cons (gh_cons (ly_symbol2scm ("description"), description_
), l
);
335 l
= gh_cons (gh_cons (ly_symbol2scm ("end-consists"),
336 end_consists_name_list_
), l
);
337 l
= gh_cons (gh_cons (ly_symbol2scm ("accepts"), accepts_name_list_
), l
);
338 l
= gh_cons (gh_cons (ly_symbol2scm ("property-ops"), property_ops_
), l
);
343 l
= gh_cons (gh_cons (ly_symbol2scm ("type-name"), type_name_
), l
);
345 l
= gh_cons (gh_cons (ly_symbol2scm ("group-type"), translator_group_type_
), l
);