2 translator-def.cc -- implement Context_def
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 /* TODO: should junk this class an replace by
10 a single list of context modifications? */
12 #include "context-def.hh"
14 #include "engraver.hh"
15 #include "output-def.hh"
16 #include "performer.hh"
17 #include "score-context.hh"
18 #include "translator-group.hh"
21 Context_def::Context_def ()
23 context_aliases_
= SCM_EOL
;
24 translator_group_type_
= SCM_EOL
;
25 accept_mods_
= SCM_EOL
;
26 translator_mods_
= SCM_EOL
;
27 property_ops_
= SCM_EOL
;
28 context_name_
= SCM_EOL
;
29 description_
= SCM_EOL
;
33 context_name_
= ly_symbol2scm ("");
36 Context_def::Context_def (Context_def
const &s
)
39 context_aliases_
= SCM_EOL
;
40 translator_group_type_
= SCM_EOL
;
41 accept_mods_
= SCM_EOL
;
42 translator_mods_
= SCM_EOL
;
43 property_ops_
= SCM_EOL
;
44 context_name_
= SCM_EOL
;
45 description_
= SCM_EOL
;
48 description_
= s
.description_
;
50 accept_mods_
= s
.accept_mods_
;
51 property_ops_
= s
.property_ops_
;
52 translator_mods_
= s
.translator_mods_
;
53 context_aliases_
= s
.context_aliases_
;
54 translator_group_type_
= s
.translator_group_type_
;
55 context_name_
= s
.context_name_
;
58 Context_def::~Context_def ()
62 #include "ly-smobs.icc"
63 IMPLEMENT_SMOBS (Context_def
);
64 IMPLEMENT_DEFAULT_EQUAL_P (Context_def
);
67 Context_def::print_smob (SCM smob
, SCM port
, scm_print_state
*)
69 Context_def
*me
= (Context_def
*) SCM_CELL_WORD_1 (smob
);
71 scm_puts ("#<Context_def ", port
);
72 scm_display (me
->context_name_
, port
);
78 Context_def::mark_smob (SCM smob
)
80 Context_def
*me
= (Context_def
*) SCM_CELL_WORD_1 (smob
);
82 scm_gc_mark (me
->description_
);
83 scm_gc_mark (me
->context_aliases_
);
84 scm_gc_mark (me
->accept_mods_
);
85 scm_gc_mark (me
->translator_mods_
);
86 scm_gc_mark (me
->property_ops_
);
87 scm_gc_mark (me
->translator_group_type_
);
89 return me
->context_name_
;
93 Context_def::add_context_mod (SCM mod
)
95 SCM tag
= scm_car (mod
);
96 if (ly_symbol2scm ("description") == tag
)
98 description_
= scm_cadr (mod
);
102 SCM sym
= scm_cadr (mod
);
103 if (scm_is_string (sym
))
104 sym
= scm_string_to_symbol (sym
);
106 if (ly_symbol2scm ("consists") == tag
107 || ly_symbol2scm ("consists-end") == tag
108 || ly_symbol2scm ("remove") == tag
)
110 if (!get_translator (sym
))
111 error (_f ("program has no such type: `%s'",
112 ly_symbol2string (sym
).to_str0 ()));
114 translator_mods_
= scm_cons (scm_list_2 (tag
, sym
), translator_mods_
);
116 else if (ly_symbol2scm ("accepts") == tag
117 || ly_symbol2scm ("denies") == tag
)
118 accept_mods_
= scm_cons (scm_list_2 (tag
, sym
), accept_mods_
);
119 else if (ly_symbol2scm ("poppush") == tag
120 || ly_symbol2scm ("pop") == tag
121 || ly_symbol2scm ("push") == tag
122 || ly_symbol2scm ("assign") == tag
123 || ly_symbol2scm ("unset") == tag
)
124 property_ops_
= scm_cons (mod
, property_ops_
);
125 else if (ly_symbol2scm ("alias") == tag
)
126 context_aliases_
= scm_cons (sym
, context_aliases_
);
127 else if (ly_symbol2scm ("translator-type") == tag
)
128 translator_group_type_
= sym
;
129 else if (ly_symbol2scm ("context-name") == tag
)
132 programming_error ("unknown context mod tag");
136 Context_def::get_context_name () const
138 return context_name_
;
142 Context_def::get_accepted (SCM user_mod
) const
144 SCM mods
= scm_reverse_x (scm_list_copy (accept_mods_
), user_mod
);
146 for (SCM s
= mods
; scm_is_pair (s
); s
= scm_cdr (s
))
148 SCM tag
= scm_caar (s
);
149 SCM sym
= scm_cadar (s
);
150 if (tag
== ly_symbol2scm ("accepts"))
151 acc
= scm_cons (sym
, acc
);
152 else if (tag
== ly_symbol2scm ("denies"))
153 acc
= scm_delete_x (sym
, acc
);
158 Link_array
<Context_def
>
159 Context_def::path_to_acceptable_context (SCM type_sym
, Output_def
*odef
) const
161 assert (scm_is_symbol (type_sym
));
163 SCM accepted
= get_accepted (SCM_EOL
);
165 Link_array
<Context_def
> accepteds
;
166 for (SCM s
= accepted
; scm_is_pair (s
); s
= scm_cdr (s
))
167 if (Context_def
*t
= unsmob_context_def (find_context_def (odef
,
171 Link_array
<Context_def
> best_result
;
172 for (int i
= 0; i
< accepteds
.size (); i
++)
174 /* do not check aliases, because \context Staff should not
175 create RhythmicStaff. */
176 if (ly_c_equal_p (accepteds
[i
]->get_context_name (), type_sym
))
178 best_result
.push (accepteds
[i
]);
183 int best_depth
= INT_MAX
;
184 for (int i
= 0; i
< accepteds
.size (); i
++)
186 Context_def
*g
= accepteds
[i
];
188 Link_array
<Context_def
> result
189 = g
->path_to_acceptable_context (type_sym
, odef
);
190 if (result
.size () && result
.size () < best_depth
)
192 result
.insert (g
, 0);
193 best_result
= result
;
195 /* this following line was added in 1.9.3, but hsould've been
196 there all along... Let's hope it doesn't cause nightmares. */
197 best_depth
= result
.size ();
205 Context_def::get_translator_names (SCM user_mod
) const
209 SCM mods
= scm_reverse_x (scm_list_copy (translator_mods_
), user_mod
);
211 for (SCM s
= mods
; scm_is_pair (s
); s
= scm_cdr (s
))
213 SCM tag
= scm_caar (s
);
214 SCM arg
= scm_cadar (s
);
216 if (scm_is_string (arg
))
217 arg
= scm_string_to_symbol (arg
);
219 if (ly_symbol2scm ("consists") == tag
)
220 l1
= scm_cons (arg
, l1
);
221 else if (ly_symbol2scm ("remove") == tag
)
223 l1
= scm_delete_x (arg
, l1
);
231 filter_performers (SCM ell
)
233 for (SCM
*tail
= &ell
; scm_is_pair (*tail
); tail
= SCM_CDRLOC (*tail
))
235 if (dynamic_cast<Performer
*> (unsmob_translator (scm_car (*tail
))))
237 *tail
= scm_cdr (*tail
);
238 if (!scm_is_pair (*tail
))
246 filter_engravers (SCM ell
)
249 for (; scm_is_pair (*tail
); tail
= SCM_CDRLOC (*tail
))
251 if (dynamic_cast<Engraver
*> (unsmob_translator (scm_car (*tail
))))
253 *tail
= scm_cdr (*tail
);
254 if (!scm_is_pair (*tail
))
262 Context_def::instantiate (SCM ops
, Object_key
const *key
)
266 if (context_name_
== ly_symbol2scm ("Score"))
267 tg
= new Score_context (key
);
269 tg
= new Context (key
);
271 tg
->definition_
= self_scm ();
273 SCM trans_names
= get_translator_names (ops
);
275 Translator_group
*g
= dynamic_cast<Translator_group
*>
276 (get_translator (translator_group_type_
));
277 g
= dynamic_cast<Translator_group
*> (g
->clone ());
279 SCM trans_list
= SCM_EOL
;
281 for (SCM s
= trans_names
; scm_is_pair (s
); s
= scm_cdr (s
))
283 Translator
*t
= get_translator (scm_car (s
));
285 warning (_f ("can't find: `%s'", s
));
288 Translator
*tr
= t
->clone ();
289 SCM str
= tr
->self_scm ();
291 if (tr
->must_be_last ())
293 SCM cons
= scm_cons (str
, SCM_EOL
);
294 if (scm_is_pair (trans_list
))
295 scm_set_cdr_x (scm_last_pair (trans_list
), cons
);
301 trans_list
= scm_cons (str
, trans_list
);
304 tr
->daddy_context_
= tg
;
305 scm_gc_unprotect_object (str
);
309 g
->simple_trans_list_
= trans_list
;
311 tg
->implementation_
= g
->self_scm ();
312 if (dynamic_cast<Engraver
*> (g
))
313 g
->simple_trans_list_
= filter_performers (g
->simple_trans_list_
);
314 else if (dynamic_cast<Performer
*> (g
))
315 g
->simple_trans_list_
= filter_engravers (g
->simple_trans_list_
);
317 g
->daddy_context_
= tg
;
318 tg
->aliases_
= context_aliases_
;
320 scm_gc_unprotect_object (g
->self_scm ());
322 tg
->accepts_list_
= get_accepted (ops
);
328 Context_def::clone_scm () const
330 Context_def
*t
= new Context_def (*this);
331 SCM x
= t
->self_scm ();
332 scm_gc_unprotect_object (x
);
337 Context_def::make_scm ()
339 Context_def
*t
= new Context_def
;
340 SCM x
= t
->self_scm ();
341 scm_gc_unprotect_object (x
);
346 Context_def::apply_default_property_operations (Context
*tg
)
348 apply_property_operations (tg
, property_ops_
);
352 Context_def::to_alist () const
356 ell
= scm_cons (scm_cons (ly_symbol2scm ("consists"),
357 get_translator_names (SCM_EOL
)), ell
);
358 ell
= scm_cons (scm_cons (ly_symbol2scm ("description"), description_
), ell
);
359 ell
= scm_cons (scm_cons (ly_symbol2scm ("aliases"), context_aliases_
), ell
);
360 ell
= scm_cons (scm_cons (ly_symbol2scm ("accepts"), get_accepted (SCM_EOL
)),
362 ell
= scm_cons (scm_cons (ly_symbol2scm ("property-ops"), property_ops_
),
364 ell
= scm_cons (scm_cons (ly_symbol2scm ("context-name"), context_name_
),
367 if (scm_is_symbol (translator_group_type_
))
368 ell
= scm_cons (scm_cons (ly_symbol2scm ("group-type"),
369 translator_group_type_
), ell
);