2 translator-def.cc -- implement Context_def
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 /* TODO: should junk this class an replace by
10 a single list of context modifications? */
12 #include "context-def.hh"
15 #include "international.hh"
16 #include "output-def.hh"
17 #include "translator.hh"
20 Context_def::Context_def ()
22 context_aliases_ = SCM_EOL;
23 translator_group_type_ = SCM_EOL;
24 accept_mods_ = SCM_EOL;
25 translator_mods_ = SCM_EOL;
26 property_ops_ = SCM_EOL;
27 context_name_ = SCM_EOL;
28 default_child_ = 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;
46 default_child_ = SCM_EOL;
49 description_ = s.description_;
51 default_child_ = s.default_child_;
52 accept_mods_ = s.accept_mods_;
53 property_ops_ = s.property_ops_;
54 translator_mods_ = s.translator_mods_;
55 context_aliases_ = s.context_aliases_;
56 translator_group_type_ = s.translator_group_type_;
57 context_name_ = s.context_name_;
60 Context_def::~Context_def ()
64 #include "ly-smobs.icc"
65 IMPLEMENT_SMOBS (Context_def);
66 IMPLEMENT_DEFAULT_EQUAL_P (Context_def);
69 Context_def::print_smob (SCM smob, SCM port, scm_print_state*)
71 Context_def *me = (Context_def *) SCM_CELL_WORD_1 (smob);
73 scm_puts ("#<Context_def ", port);
74 scm_display (me->context_name_, port);
80 Context_def::mark_smob (SCM smob)
82 Context_def *me = (Context_def *) SCM_CELL_WORD_1 (smob);
84 scm_gc_mark (me->description_);
85 scm_gc_mark (me->context_aliases_);
86 scm_gc_mark (me->accept_mods_);
87 scm_gc_mark (me->translator_mods_);
88 scm_gc_mark (me->property_ops_);
89 scm_gc_mark (me->translator_group_type_);
90 scm_gc_mark (me->default_child_);
92 return me->context_name_;
96 Context_def::add_context_mod (SCM mod)
98 SCM tag = scm_car (mod);
99 if (ly_symbol2scm ("description") == tag)
101 description_ = scm_cadr (mod);
106 other modifiers take symbols as argument.
108 SCM sym = scm_cadr (mod);
109 if (scm_is_string (sym))
110 sym = scm_string_to_symbol (sym);
112 if (ly_symbol2scm ("default-child") == tag)
113 default_child_ = sym;
114 else if (ly_symbol2scm ("consists") == tag
115 || ly_symbol2scm ("consists-end") == tag
116 || ly_symbol2scm ("remove") == tag)
118 if (!get_translator (sym))
119 error (_f ("program has no such type: `%s'",
120 ly_symbol2string (sym).c_str ()));
122 translator_mods_ = scm_cons (scm_list_2 (tag, sym), translator_mods_);
124 else if (ly_symbol2scm ("accepts") == tag
125 || ly_symbol2scm ("denies") == tag)
126 accept_mods_ = scm_cons (scm_list_2 (tag, sym), accept_mods_);
127 else if (ly_symbol2scm ("pop") == tag
128 || ly_symbol2scm ("push") == tag
129 || ly_symbol2scm ("assign") == tag
130 || ly_symbol2scm ("unset") == tag)
131 property_ops_ = scm_cons (mod, property_ops_);
132 else if (ly_symbol2scm ("alias") == tag)
133 context_aliases_ = scm_cons (sym, context_aliases_);
134 else if (ly_symbol2scm ("translator-type") == tag)
135 translator_group_type_ = sym;
136 else if (ly_symbol2scm ("context-name") == tag)
139 programming_error ("unknown context mod tag");
143 Context_def::get_accepted (SCM user_mod) const
145 SCM mods = scm_reverse_x (scm_list_copy (accept_mods_), user_mod);
147 for (SCM s = mods; scm_is_pair (s); s = scm_cdr (s))
149 SCM tag = scm_caar (s);
150 SCM sym = scm_cadar (s);
151 if (tag == ly_symbol2scm ("accepts"))
152 acc = scm_cons (sym, acc);
153 else if (tag == ly_symbol2scm ("denies"))
154 acc = scm_delete_x (sym, acc);
157 SCM def = get_default_child (user_mod);
158 if (scm_is_symbol (def))
160 if (scm_memq (def, acc))
161 acc = scm_delete_x (def, acc);
162 acc = scm_cons (def, acc);
169 Context_def::get_default_child (SCM user_mod) const
171 SCM name = default_child_;
172 for (SCM s = user_mod; scm_is_pair (s); s = scm_cdr (s))
174 SCM entry = scm_car (s);
175 if (scm_car (entry) == ly_symbol2scm ("default-child"))
177 name = scm_cadr (entry);
186 Context_def::path_to_acceptable_context (SCM type_sym, Output_def *odef) const
188 assert (scm_is_symbol (type_sym));
190 SCM accepted = get_accepted (SCM_EOL);
192 vector<Context_def*> accepteds;
193 for (SCM s = accepted; scm_is_pair (s); s = scm_cdr (s))
194 if (Context_def *t = unsmob_context_def (find_context_def (odef,
196 accepteds.push_back (t);
198 vector<Context_def*> best_result;
199 for (vsize i = 0; i < accepteds.size (); i++)
201 /* do not check aliases, because \context Staff should not
202 create RhythmicStaff. */
203 if (ly_is_equal (accepteds[i]->get_context_name (), type_sym))
205 best_result.push_back (accepteds[i]);
210 vsize best_depth = INT_MAX;
211 for (vsize i = 0; i < accepteds.size (); i++)
213 Context_def *g = accepteds[i];
215 vector<Context_def*> result
216 = g->path_to_acceptable_context (type_sym, odef);
217 if (result.size () && result.size () < best_depth)
219 best_depth = result.size ();
220 result.insert (result.begin (), g);
221 best_result = result;
229 Context_def::get_translator_names (SCM user_mod) const
233 SCM mods = scm_reverse_x (scm_list_copy (translator_mods_), user_mod);
235 for (SCM s = mods; scm_is_pair (s); s = scm_cdr (s))
237 SCM tag = scm_caar (s);
238 SCM arg = scm_cadar (s);
240 if (scm_is_string (arg))
241 arg = scm_string_to_symbol (arg);
243 if (ly_symbol2scm ("consists") == tag)
244 l1 = scm_cons (arg, l1);
245 else if (ly_symbol2scm ("remove") == tag)
246 l1 = scm_delete_x (arg, l1);
253 Context_def::instantiate (SCM ops, Object_key const *key)
255 Context *context = new Context (key);
257 context->definition_ = self_scm ();
258 context->definition_mods_ = ops;
259 context->aliases_ = context_aliases_;
260 context->accepts_list_ = get_accepted (ops);
266 Context_def::clone_scm () const
268 Context_def *t = new Context_def (*this);
269 return t->unprotect ();
273 Context_def::make_scm ()
275 Context_def *t = new Context_def;
276 return t->unprotect ();
280 Context_def::apply_default_property_operations (Context *tg)
282 apply_property_operations (tg, property_ops_);
286 Context_def::to_alist () const
290 ell = scm_cons (scm_cons (ly_symbol2scm ("consists"),
291 get_translator_names (SCM_EOL)), ell);
292 ell = scm_cons (scm_cons (ly_symbol2scm ("description"), description_), ell);
293 ell = scm_cons (scm_cons (ly_symbol2scm ("aliases"), context_aliases_), ell);
294 ell = scm_cons (scm_cons (ly_symbol2scm ("accepts"), get_accepted (SCM_EOL)),
296 ell = scm_cons (scm_cons (ly_symbol2scm ("property-ops"), property_ops_),
298 ell = scm_cons (scm_cons (ly_symbol2scm ("context-name"), context_name_),
301 if (scm_is_symbol (translator_group_type_))
302 ell = scm_cons (scm_cons (ly_symbol2scm ("group-type"),
303 translator_group_type_), ell);