2002->2003
[lilypond.git] / lily / translator-def.cc
blobf6add24b23326bb97fb3e4a2e69f2e016782f834
1 /*
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>
8 */
10 #include "lily-proto.hh"
11 #include "translator-def.hh"
12 #include "translator-group.hh"
13 #include "warn.hh"
14 #include "music-output-def.hh"
15 #include "ly-smobs.icc"
17 int
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);
24 scm_puts (">", port);
25 return 1;
29 SCM
30 Translator_def::mark_smob (SCM smob)
32 Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
34 scm_gc_mark (me->type_aliases_);
35 scm_gc_mark (me->consists_name_list_);
36 scm_gc_mark (me->accepts_name_list_);
37 scm_gc_mark (me->end_consists_name_list_);
38 scm_gc_mark (me->property_ops_);
39 scm_gc_mark (me->translator_group_type_);
40 return me->type_name_;
44 Translator_def::Translator_def ()
46 type_aliases_ = SCM_EOL;
47 translator_group_type_ = SCM_EOL;
48 accepts_name_list_ = SCM_EOL;
49 consists_name_list_ = SCM_EOL;
50 end_consists_name_list_ = SCM_EOL;
51 property_ops_ = SCM_EOL;
52 type_name_ = SCM_EOL;
54 smobify_self();
58 Translator_def::~Translator_def ()
62 Translator_def::Translator_def (Translator_def const & s)
63 : Input (s)
65 type_aliases_ = SCM_EOL;
66 translator_group_type_ = SCM_EOL;
67 accepts_name_list_ = SCM_EOL;
68 consists_name_list_ = SCM_EOL;
69 end_consists_name_list_ = SCM_EOL;
70 property_ops_ = SCM_EOL;
71 type_name_ = SCM_EOL;
74 smobify_self();
75 consists_name_list_ = scm_list_copy (s.consists_name_list_);
76 end_consists_name_list_ = scm_list_copy (s.end_consists_name_list_);
77 accepts_name_list_ = scm_list_copy (s.accepts_name_list_);
78 property_ops_ = scm_list_copy (s.property_ops_);
79 type_aliases_ = scm_list_copy (s.type_aliases_);
80 translator_group_type_ = s.translator_group_type_;
81 type_name_ = s.type_name_;
86 void
87 Translator_def::set_acceptor (SCM name, bool add)
89 if (add)
90 this->accepts_name_list_ = gh_cons (name, this->accepts_name_list_);
91 else
92 this->accepts_name_list_ = scm_delete_x (name, this->accepts_name_list_);
96 SCM
97 Translator_def::modify_definition (SCM list, SCM str, bool add)
99 String s = ly_scm2string (str);
100 if (!get_translator (s))
101 error (_ ("Program has no such type"));
103 if (add)
105 if (scm_memq (str, list) != SCM_BOOL_F)
107 warning (_f ("Already contains: `%s'", s));
108 warning (_f ("Not adding translator: `%s'", s));
110 else
111 list= gh_cons (str, list);
113 else
115 list = scm_delete_x (str, list);
117 return list;
122 void
123 Translator_def::remove_element (SCM s)
125 this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, false);
126 this->consists_name_list_ = modify_definition (this->consists_name_list_, s, false);
129 void
130 Translator_def::add_element (SCM s)
132 this->consists_name_list_ = modify_definition (this->consists_name_list_, s, true);
135 void
136 Translator_def::add_last_element (SCM s)
138 this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, true);
140 void
141 Translator_def::add_push_property (SCM props, SCM syms, SCM vals)
143 this->property_ops_ = gh_cons (scm_list_n (ly_symbol2scm ("push"), props, syms, vals, SCM_UNDEFINED),
144 this->property_ops_);
147 void
148 Translator_def::add_pop_property (SCM props, SCM syms)
150 this->property_ops_ = gh_cons (scm_list_n (ly_symbol2scm ("push"), props, syms, SCM_UNDEFINED),
151 this->property_ops_);
155 Do it. SYM is single symbol. VAL is SCM_UNDEFINED in case of a pop
157 void
158 Translator_def::apply_pushpop_property (Translator_group* me,SCM sym, SCM eprop, SCM val)
160 dynamic_cast<Translator_group*> (me)
161 ->execute_single_pushpop_property (sym, eprop, val);
166 Link_array<Translator_def>
167 Translator_def::path_to_acceptable_translator (SCM type_string, Music_output_def* odef) const
169 assert (gh_string_p (type_string));
171 Link_array<Translator_def> accepteds;
172 for (SCM s = accepts_name_list_; gh_pair_p (s); s = ly_cdr (s))
174 Translator_def *t = unsmob_translator_def (odef->find_translator (ly_car (s)));
175 if (!t)
176 continue;
177 accepteds.push (t);
180 Link_array<Translator_def> best_result;
181 for (int i=0; i < accepteds.size (); i++)
185 don't check aliases, because \context Staff should not create RhythmicStaff.
187 if (gh_equal_p (accepteds[i]->type_name_, type_string))
189 best_result.push (accepteds[i]);
190 return best_result;
194 int best_depth= INT_MAX;
195 for (int i=0; i < accepteds.size (); i++)
197 Translator_def * g = accepteds[i];
199 Link_array<Translator_def> result
200 = g->path_to_acceptable_translator (type_string, odef);
201 if (result.size () && result.size () < best_depth)
203 result.insert (g,0);
204 best_result = result;
208 return best_result;
211 IMPLEMENT_SMOBS (Translator_def);
212 IMPLEMENT_DEFAULT_EQUAL_P (Translator_def);
215 static SCM
216 trans_list (SCM namelist, Translator_group*tg)
218 SCM l = SCM_EOL;
219 for (SCM s = namelist; gh_pair_p (s) ; s = ly_cdr (s))
221 Translator * t = get_translator (ly_scm2string (ly_car (s)));
222 if (!t)
223 warning (_f ("can't find: `%s'", s));
224 else
226 Translator * tr = t->clone ();
227 SCM str = tr->self_scm ();
228 l = gh_cons (str, l);
230 tr->daddy_trans_ = tg;
231 tr->output_def_ = tg->output_def_;
233 scm_gc_unprotect_object (str);
236 return l;
240 Translator_group *
241 Translator_def::instantiate (Music_output_def* md)
243 Translator * g = get_translator (ly_scm2string (translator_group_type_));
244 g = g->clone ();
246 Translator_group *tg = dynamic_cast<Translator_group*> (g);
247 tg->output_def_ = md;
248 tg->definition_ = self_scm ();
249 tg->type_string_ = ly_scm2string (type_name_);
252 TODO: ugh. we're reversing CONSISTS_NAME_LIST_ here
254 SCM l1 = trans_list (consists_name_list_, tg);
255 SCM l2 =trans_list (end_consists_name_list_,tg);
256 l1 = scm_reverse_x (l1, l2);
258 tg->simple_trans_list_ = l1;
260 return tg;
264 void
265 Translator_def::apply_property_operations (Translator_group*tg)
267 SCM correct_order = scm_reverse (property_ops_); // pity of the mem.
268 for (SCM s = correct_order; gh_pair_p (s); s = ly_cdr (s))
270 SCM entry = ly_car (s);
271 SCM type = ly_car (entry);
272 entry = ly_cdr (entry);
274 if (type == ly_symbol2scm ("push"))
276 SCM val = ly_cddr (entry);
277 val = gh_pair_p (val) ? ly_car (val) : SCM_UNDEFINED;
279 apply_pushpop_property (tg, ly_car (entry), ly_cadr (entry), val);
281 else if (type == ly_symbol2scm ("assign"))
283 tg->internal_set_property (ly_car (entry), ly_cadr (entry));
289 Translator_def::clone_scm () const
291 Translator_def * t = new Translator_def (*this);
292 scm_gc_unprotect_object (t->self_scm());
293 return t->self_scm();
297 Translator_def::make_scm ()
299 Translator_def* t = new Translator_def;
300 scm_gc_unprotect_object (t->self_scm());
301 return t->self_scm();
304 void
305 Translator_def::add_property_assign (SCM nm, SCM val)
307 this->property_ops_ = gh_cons (scm_list_n (ly_symbol2scm ("assign"), scm_string_to_symbol (nm), val, SCM_UNDEFINED),
308 this->property_ops_);
312 Default child context as a SCM string, or something else if there is
313 none.
316 Translator_def::default_child_context_name ()
318 SCM d = accepts_name_list_;
319 return gh_pair_p (d) ? ly_car (scm_last_pair (d)) : SCM_EOL;
323 Translator_def::to_alist () const
325 SCM l = SCM_EOL;
327 l = gh_cons (gh_cons (ly_symbol2scm ("consists"), consists_name_list_), l);
328 l = gh_cons (gh_cons (ly_symbol2scm ("end-consists"), end_consists_name_list_), l);
329 l = gh_cons (gh_cons (ly_symbol2scm ("accepts"), accepts_name_list_), l);
330 l = gh_cons (gh_cons (ly_symbol2scm ("property-ops"), property_ops_), l);
331 l = gh_cons (gh_cons (ly_symbol2scm ("type-name"), type_name_), l); // junkme.
332 l = gh_cons (gh_cons (ly_symbol2scm ("group-type"), translator_group_type_), l);
334 return l;