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