2 translator-def.cc -- implement Translator_def
4 source file of the GNU LilyPond music typesetter
6 (c) 2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
10 #include "lily-proto.hh"
11 #include "translator-def.hh"
12 #include "translator-group.hh"
14 #include "music-output-def.hh"
16 #include "ly-smobs.icc"
19 Translator_def::print_smob (SCM smob
, SCM port
, scm_print_state
*)
21 Translator_def
* me
= (Translator_def
*) SCM_CELL_WORD_1 (smob
);
23 scm_puts("#<Translator_def ", port
);
24 scm_display (me
->type_name_
, port
);
31 Translator_def::mark_smob (SCM smob
)
33 Translator_def
* me
= (Translator_def
*) SCM_CELL_WORD_1 (smob
);
34 scm_gc_mark (me
->consists_name_list_
);
35 scm_gc_mark (me
->accepts_name_list_
);
36 scm_gc_mark (me
->end_consists_name_list_
);
37 scm_gc_mark (me
->property_ops_
);
38 scm_gc_mark (me
->translator_group_type_
);
39 return me
->type_name_
;
48 push_sym
= scm_permanent_object (ly_symbol2scm ("push"));
49 assign_sym
= scm_permanent_object (ly_symbol2scm ("assign"));
52 ADD_SCM_INIT_FUNC(transdef
, foo_init
);
54 Translator_def::Translator_def ()
56 translator_group_type_
= SCM_EOL
;
57 accepts_name_list_
= SCM_EOL
;
58 consists_name_list_
= SCM_EOL
;
59 end_consists_name_list_
= SCM_EOL
;
60 property_ops_
= SCM_EOL
;
63 Translator_def::~Translator_def ()
67 Translator_def::Translator_def (Translator_def
const & s
)
70 consists_name_list_
= scm_list_copy (s
.consists_name_list_
);
71 end_consists_name_list_
= scm_list_copy (s
.end_consists_name_list_
);
72 accepts_name_list_
= scm_list_copy (s
.accepts_name_list_
);
73 property_ops_
= scm_list_copy (s
.property_ops_
);
75 translator_group_type_
= s
.translator_group_type_
;
76 type_name_
= s
.type_name_
;
82 Translator_def::set_acceptor (SCM name
, bool add
)
85 this->accepts_name_list_
= gh_cons (name
, this->accepts_name_list_
);
87 this->accepts_name_list_
= scm_delete_x (name
, this->accepts_name_list_
);
92 Translator_def::modify_definition (SCM list
, SCM str
, bool add
)
94 String s
= ly_scm2string (str
);
95 if (!get_translator_l (s
))
96 error (_ ("Program has no such type"));
100 if (scm_memq (str
, list
) != SCM_BOOL_F
)
102 warning (_f("Already contains: `%s'", s
));
103 warning (_f("Not adding translator: `%s'", s
));
106 list
= gh_cons (str
, list
);
110 list
= scm_delete_x (str
, list
);
118 Translator_def::remove_element (SCM s
)
120 this->end_consists_name_list_
= modify_definition (this->end_consists_name_list_
, s
, false);
121 this->consists_name_list_
= modify_definition (this->consists_name_list_
, s
, false);
125 Translator_def::add_element (SCM s
)
127 this->consists_name_list_
= modify_definition (this->consists_name_list_
, s
, true);
131 Translator_def::add_last_element (SCM s
)
133 this->end_consists_name_list_
= modify_definition (this->end_consists_name_list_
, s
, true);
136 Translator_def::add_push_property (SCM props
, SCM syms
, SCM vals
)
138 this->property_ops_
= gh_cons (gh_list (push_sym
, props
, syms
, vals
, SCM_UNDEFINED
),
139 this->property_ops_
);
143 Translator_def::add_pop_property (SCM props
, SCM syms
)
145 this->property_ops_
= gh_cons (gh_list (push_sym
, props
, syms
, SCM_UNDEFINED
),
146 this->property_ops_
);
150 Do it. SYMS maybe a symbol or a list of symbols. VAL is
151 SCM_UNDEFINED in case of a pop
154 Translator_def::apply_pushpop_property (Translator_group
* me
,SCM syms
, SCM eprop
, SCM val
)
156 if (gh_symbol_p (syms
))
157 dynamic_cast<Translator_group
*>(me
)->execute_single_pushpop_property (syms
, eprop
, val
);
158 else for (SCM s
= syms
; gh_pair_p (s
); s
= gh_cdr (s
))
159 dynamic_cast<Translator_group
*>(me
)->execute_single_pushpop_property (gh_car (s
), eprop
, val
);
164 Link_array
<Translator_def
>
165 Translator_def::path_to_acceptable_translator (SCM type_str
, Music_output_def
* odef
) const
167 assert (gh_string_p (type_str
));
169 Link_array
<Translator_def
> accepted_arr
;
170 for (SCM s
= accepts_name_list_
; gh_pair_p (s
); s
= gh_cdr (s
))
172 Translator_def
*t
= unsmob_translator_def (odef
->find_translator_l (gh_car (s
)));
175 accepted_arr
.push (t
);
178 Link_array
<Translator_def
> best_result
;
179 for (int i
=0; i
< accepted_arr
.size (); i
++)
180 if (scm_equal_p (accepted_arr
[i
]->type_name_
, type_str
) == SCM_BOOL_T
)
182 best_result
.push (accepted_arr
[i
]);
186 int best_depth
= INT_MAX
;
187 for (int i
=0; i
< accepted_arr
.size (); i
++)
189 Translator_def
* g
= accepted_arr
[i
];
191 Link_array
<Translator_def
> result
192 = g
->path_to_acceptable_translator (type_str
, odef
);
193 if (result
.size () && result
.size () < best_depth
)
196 best_result
= result
;
202 IMPLEMENT_UNSMOB(Translator_def
,translator_def
);
203 IMPLEMENT_SMOBS(Translator_def
);
204 IMPLEMENT_DEFAULT_EQUAL_P(Translator_def
);
208 trans_list (SCM namelist
, Translator_group
*tg
)
211 for (SCM s
= namelist
; gh_pair_p (s
) ; s
= gh_cdr (s
))
213 Translator
* t
= get_translator_l (ly_scm2string (gh_car (s
)));
215 warning (_f ("can't find: `%s'", s
));
218 Translator
* tr
= t
->clone ();
219 SCM str
= tr
->self_scm ();
220 l
= gh_cons (str
, l
);
222 tr
->daddy_trans_l_
= tg
;
223 tr
->output_def_l_
= tg
->output_def_l_
;
225 scm_unprotect_object (str
);
233 Translator_def::instantiate (Music_output_def
* md
)
235 Translator
* g
= get_translator_l (ly_scm2string (translator_group_type_
));
238 Translator_group
*tg
= dynamic_cast<Translator_group
*> (g
);
239 tg
->output_def_l_
= md
;
240 tg
->definition_
= self_scm ();
241 tg
->type_str_
= ly_scm2string (type_name_
);
242 SCM l1
= trans_list (consists_name_list_
, tg
);
243 SCM l2
=trans_list (end_consists_name_list_
,tg
);
244 l1
= scm_reverse_x (l1
, l2
);
246 tg
->simple_trans_list_
= l1
;
253 Translator_def::apply_property_operations (Translator_group
*tg
)
255 SCM correct_order
= scm_reverse (property_ops_
); // pity of the mem.
256 for (SCM s
= correct_order
; gh_pair_p (s
); s
= gh_cdr (s
))
258 SCM entry
= gh_car (s
);
259 SCM type
= gh_car (entry
);
260 entry
= gh_cdr (entry
);
262 if (type
== push_sym
)
264 SCM val
= gh_cddr (entry
);
265 val
= gh_pair_p (val
) ? gh_car (val
) : SCM_UNDEFINED
;
267 apply_pushpop_property (tg
, gh_car (entry
), gh_cadr (entry
), val
);
269 else if (type
== assign_sym
)
271 tg
->set_property (gh_car(entry
), gh_cadr (entry
));
277 Translator_def::clone_scm () const
279 Translator_def
* t
= new Translator_def (*this);
280 return t
->unprotected_smobify_self ();
284 Translator_def::make_scm ()
286 Translator_def
* t
= new Translator_def
;
287 return t
->unprotected_smobify_self ();
291 Translator_def::add_property_assign (SCM nm
, SCM val
)
293 this->property_ops_
= gh_cons (gh_list (assign_sym
, scm_string_to_symbol (nm
), val
, SCM_UNDEFINED
),
294 this->property_ops_
);
298 Default child context as a SCM string, or something else if there is
302 Translator_def::default_child_context_name ()
304 SCM d
= accepts_name_list_
;
305 return gh_pair_p (d
) ? gh_car (scm_last_pair (d
)) : SCM_EOL
;
309 Translator_def::to_alist ()const
313 l
= gh_cons (gh_cons (ly_symbol2scm ("consists"), consists_name_list_
), l
);
314 l
= gh_cons (gh_cons (ly_symbol2scm ("end-consists"), end_consists_name_list_
), l
);
315 l
= gh_cons (gh_cons (ly_symbol2scm ("accepts"), accepts_name_list_
), l
);
316 l
= gh_cons (gh_cons (ly_symbol2scm ("property-ops"), property_ops_
), l
);
317 l
= gh_cons (gh_cons (ly_symbol2scm ("type-name"), type_name_
), l
); // junkme.
318 l
= gh_cons (gh_cons (ly_symbol2scm ("group-type"), translator_group_type_
), l
);