]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-def.cc
release: 1.5.19
[lilypond.git] / lily / translator-def.cc
1 /*   
2   translator-def.cc --  implement Translator_def
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
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
16 #include "ly-smobs.icc"
17
18 int
19 Translator_def::print_smob (SCM smob, SCM port, scm_print_state*)
20 {
21   Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
22
23   scm_puts ("#<Translator_def ", port);
24   scm_display (me->type_name_, port);
25   scm_puts (">", port);
26   return 1;
27 }
28
29
30 SCM
31 Translator_def::mark_smob (SCM smob)
32 {
33   Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
34
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_;
42 }
43
44 SCM push_sym;
45 SCM assign_sym;
46
47 static void
48 foo_init ()
49 {
50   push_sym = scm_permanent_object (ly_symbol2scm ("push"));
51   assign_sym = scm_permanent_object (ly_symbol2scm ("assign"));
52 }
53
54 ADD_SCM_INIT_FUNC (transdef, foo_init);
55
56 Translator_def::Translator_def ()
57 {
58   type_aliases_ = SCM_EOL;
59   translator_group_type_ = SCM_EOL;
60   accepts_name_list_ = SCM_EOL;   
61   consists_name_list_ = SCM_EOL;
62   end_consists_name_list_ = SCM_EOL;
63   property_ops_ = SCM_EOL;
64   type_name_ = SCM_EOL;
65 }
66 Translator_def::~Translator_def ()
67 {
68 }
69
70 Translator_def::Translator_def (Translator_def const & s)
71   : Input (s)
72 {
73   consists_name_list_ = scm_list_copy (s.consists_name_list_);
74   end_consists_name_list_ = scm_list_copy (s.end_consists_name_list_);
75   accepts_name_list_ = scm_list_copy (s.accepts_name_list_);
76   property_ops_ = scm_list_copy (s.property_ops_);
77   type_aliases_ = s.type_aliases_;
78   translator_group_type_ = s.translator_group_type_;
79   type_name_ = s.type_name_;
80 }
81
82
83
84 void
85 Translator_def::set_acceptor (SCM name, bool add)
86 {
87   if (add)
88     this->accepts_name_list_ = gh_cons (name, this->accepts_name_list_);
89   else
90     this->accepts_name_list_ = scm_delete_x (name, this->accepts_name_list_);
91 }
92
93
94 SCM
95 Translator_def::modify_definition (SCM list, SCM str, bool add)
96 {
97   String s = ly_scm2string (str);
98   if (!get_translator_l (s))
99     error (_ ("Program has no such type"));
100
101   if (add)
102     {
103       if (scm_memq (str, list) != SCM_BOOL_F)
104         {
105           warning (_f ("Already contains: `%s'", s));
106           warning (_f ("Not adding translator: `%s'", s));
107         }
108       else
109         list= gh_cons (str, list);
110     }
111   else
112     {
113       list = scm_delete_x (str, list);
114     }
115   return list;
116 }
117
118
119
120 void
121 Translator_def::remove_element (SCM s)
122 {
123   this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, false);
124   this->consists_name_list_ = modify_definition (this->consists_name_list_, s, false);
125 }
126
127 void
128 Translator_def::add_element (SCM s)
129 {
130   this->consists_name_list_ = modify_definition (this->consists_name_list_, s, true);
131 }
132
133 void
134 Translator_def::add_last_element (SCM s)
135 {
136   this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, true);
137 }
138 void
139 Translator_def::add_push_property (SCM props, SCM syms,  SCM vals)
140 {
141   this->property_ops_ = gh_cons (scm_list_n (push_sym, props, syms, vals, SCM_UNDEFINED),
142                                  this->property_ops_);
143 }
144
145 void
146 Translator_def::add_pop_property (SCM props, SCM syms)
147 {
148   this->property_ops_ = gh_cons (scm_list_n (push_sym, props, syms, SCM_UNDEFINED),
149                                  this->property_ops_);
150 }
151
152 /*
153   Do it. SYMS maybe a symbol or a list of symbols. VAL is
154   SCM_UNDEFINED in case of a pop
155 */
156 void
157 Translator_def::apply_pushpop_property (Translator_group* me,SCM syms, SCM eprop, SCM val)
158 {
159   if (gh_symbol_p (syms))
160     dynamic_cast<Translator_group*> (me)->execute_single_pushpop_property (syms, eprop, val);
161   else for (SCM s = syms; gh_pair_p (s); s = ly_cdr (s))
162     dynamic_cast<Translator_group*> (me)->execute_single_pushpop_property (ly_car (s), eprop, val);
163 }
164
165
166
167 Link_array<Translator_def>
168 Translator_def::path_to_acceptable_translator (SCM type_str, Music_output_def* odef) const
169 {
170   assert (gh_string_p (type_str));
171   
172   Link_array<Translator_def> accepted_arr;
173   for (SCM s = accepts_name_list_; gh_pair_p (s); s = ly_cdr (s))
174     {
175       Translator_def *t = unsmob_translator_def (odef->find_translator_l (ly_car (s)));
176       if (!t)
177         continue;
178       accepted_arr.push (t);
179     }
180
181   Link_array<Translator_def> best_result;
182   for (int i=0; i < accepted_arr.size (); i++)
183     {
184
185       /*
186         don't check aliases, because \context Staff should not create RhythmicStaff.
187       */
188       if (gh_equal_p (accepted_arr[i]->type_name_, type_str))
189         {
190           best_result.push (accepted_arr[i]);
191           return best_result;
192         }
193     }
194       
195   int best_depth= INT_MAX;
196   for (int i=0; i < accepted_arr.size (); i++)
197     {
198       Translator_def * g = accepted_arr[i];
199
200       Link_array<Translator_def> result
201         = g->path_to_acceptable_translator (type_str, odef);
202       if (result.size () && result.size () < best_depth)
203         {
204           result.insert (g,0);
205           best_result = result;
206         }
207     }
208
209   return best_result;
210 }
211
212 IMPLEMENT_SMOBS (Translator_def);
213 IMPLEMENT_DEFAULT_EQUAL_P (Translator_def);
214
215
216 static SCM
217 trans_list (SCM namelist, Translator_group*tg)
218 {
219   SCM l = SCM_EOL;
220   for (SCM s = namelist; gh_pair_p (s) ; s = ly_cdr (s))
221     {
222       Translator * t = get_translator_l (ly_scm2string (ly_car (s)));
223       if (!t)
224         warning (_f ("can't find: `%s'", s));
225       else
226         {
227           Translator * tr = t->clone ();
228           SCM str = tr->self_scm ();
229           l = gh_cons (str, l);
230
231           tr->daddy_trans_l_ = tg;
232           tr->output_def_l_  = tg->output_def_l_;
233
234           scm_gc_unprotect_object (str);
235         }
236     }
237   return l; 
238 }
239
240
241 Translator_group *
242 Translator_def::instantiate (Music_output_def* md)
243 {
244   Translator * g = get_translator_l (ly_scm2string (translator_group_type_));
245   g = g->clone (); 
246
247   Translator_group *tg = dynamic_cast<Translator_group*> (g);
248   tg->output_def_l_ = md;
249   tg->definition_ = self_scm ();
250   tg->type_str_ = ly_scm2string (type_name_);
251   SCM l1 = trans_list (consists_name_list_, tg);
252   SCM l2 =trans_list (end_consists_name_list_,tg);
253   l1 = scm_reverse_x (l1, l2);
254   
255   tg->simple_trans_list_ = l1;
256   
257   return tg;
258 }
259
260
261 void
262 Translator_def::apply_property_operations (Translator_group*tg)
263 {
264   SCM correct_order = scm_reverse (property_ops_); // pity of the mem.
265   for (SCM s = correct_order; gh_pair_p (s); s = ly_cdr (s))
266     {
267       SCM entry = ly_car (s);
268       SCM type = ly_car (entry);
269       entry = ly_cdr (entry); 
270       
271       if (type == push_sym)
272         {
273           SCM val = ly_cddr (entry);
274           val = gh_pair_p (val) ? ly_car (val) : SCM_UNDEFINED;
275
276           apply_pushpop_property (tg, ly_car (entry), ly_cadr (entry), val);
277         }
278       else if (type == assign_sym)
279         {
280           tg->internal_set_property (ly_car (entry), ly_cadr (entry));
281         }
282     }
283 }
284
285 SCM
286 Translator_def::clone_scm () const
287 {
288   Translator_def * t = new Translator_def (*this);
289   return t->unprotected_smobify_self ();
290 }
291
292 SCM
293 Translator_def::make_scm ()
294 {
295   Translator_def* t = new Translator_def;
296   return t->unprotected_smobify_self ();
297 }
298
299 void
300 Translator_def::add_property_assign (SCM nm, SCM val)
301 {
302   this->property_ops_ = gh_cons (scm_list_n (assign_sym, scm_string_to_symbol (nm), val, SCM_UNDEFINED),
303                                  this->property_ops_);
304 }
305
306 /*
307   Default child context as a SCM string, or something else if there is
308   none.
309 */
310 SCM
311 Translator_def::default_child_context_name ()
312 {
313   SCM d = accepts_name_list_;
314   return gh_pair_p (d) ? ly_car (scm_last_pair (d)) : SCM_EOL;
315 }
316
317 SCM
318 Translator_def::to_alist ()const
319 {
320   SCM l = SCM_EOL;
321   
322   l = gh_cons (gh_cons (ly_symbol2scm ("consists"),  consists_name_list_), l);
323   l = gh_cons (gh_cons (ly_symbol2scm ("end-consists"),  end_consists_name_list_), l);
324   l = gh_cons (gh_cons (ly_symbol2scm ("accepts"),  accepts_name_list_), l);
325   l = gh_cons (gh_cons (ly_symbol2scm ("property-ops"),  property_ops_), l);
326   l = gh_cons (gh_cons (ly_symbol2scm ("type-name"),  type_name_), l); // junkme.
327   l = gh_cons (gh_cons (ly_symbol2scm ("group-type"),  translator_group_type_), l);    
328
329   return l;  
330 }