+2006-10-13 Erik Sandberg <mandolaerik@gmail.com>
+
+ * lily/input-smob.cc: add equal_p for Input
+
+ * lily/music-scheme.cc (ly_camel_case_to_lisp_identifier): new
+ function
+
+ * lily/parser.yy: MY_MAKE_MUSIC sets music origin
+
+ * lily/prob.cc: Add equal_p predicate for Prob
+
+ * lily/translator.cc: small cleanup
+
+ * scm/document-music.cc: use data from translator listener
+ registration to generate documentation for event classes
+
2006-10-13 Jan Nieuwenhuizen <janneke@gnu.org>
* GNUmakefile.in (SCRIPTS): Remove lexer-gcc-3.1.sh.
Music *unsmob_music (SCM);
Music *make_music_by_name (SCM sym);
SCM ly_music_deep_copy (SCM);
+SCM ly_camel_case_to_lisp_identifier (SCM name_sym);
+
extern SCM ly_music_p_proc;
/* common transposition function for music and event */
void protect_event (SCM ev);
virtual void derived_mark () const;
static void add_translator_listener (translator_listener_record **listener_list, translator_listener_record *r, Listener (*get_listener) (void *), const char *ev_class);
- SCM get_listened_class_list (const translator_listener_record *listeners) const;
+ SCM static_translator_description (const char *grobs,
+ const char *desc,
+ translator_listener_record *listener_list,
+ const char *read,
+ const char *write) const;
friend class Translator_group;
};
SCM \
classname::static_translator_description () const \
{ \
- SCM static_properties = SCM_EOL; \
- /* static_properties = acons (name , gh_str02scm (Translator::name (self_scm ())), \
- static_properties_); \
- */ \
- static_properties = scm_acons (ly_symbol2scm ("grobs-created"), \
- parse_symbol_list (grobs), static_properties); \
- \
- static_properties = scm_acons (ly_symbol2scm ("description"), \
- scm_makfrom0str (desc), static_properties); \
- \
- static_properties = scm_acons (ly_symbol2scm ("events-accepted"), \
- get_listened_class_list (listener_list_), static_properties); \
- \
- static_properties = scm_acons (ly_symbol2scm ("properties-read"), \
- parse_symbol_list (read), static_properties); \
- \
- static_properties = scm_acons (ly_symbol2scm ("properties-written"), \
- parse_symbol_list (write), static_properties); \
- \
- return static_properties; \
+ return Translator::static_translator_description (grobs, desc, listener_list_, read, write); \
}
#define IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS(T) \
static long input_tag;
-static
-SCM mark_smob (SCM s)
+static SCM
+mark_smob (SCM s)
{
Input *sc = (Input *) SCM_CELL_WORD_1 (s);
return 0;
}
+static SCM
+equal_smob (SCM sa, SCM sb)
+{
+ Input *a = (Input *) SCM_CELL_WORD_1 (sa);
+ Input *b = (Input *) SCM_CELL_WORD_1 (sb);
+ if (a->get_source_file () == b->get_source_file () &&
+ a->start () == b->start () &&
+ a->end () == b->end ())
+ return SCM_BOOL_T;
+ else
+ return SCM_BOOL_F;
+}
+
static void
start_input_smobs ()
{
scm_set_smob_mark (input_tag, mark_smob);
scm_set_smob_free (input_tag, free_smob);
scm_set_smob_print (input_tag, print_smob);
- scm_set_smob_equalp (input_tag, 0);
+ scm_set_smob_equalp (input_tag, equal_smob);
}
SCM
return scm_reverse_x (newlist, SCM_EOL);
}
+/*
+ TODO: does this belong here?
+*/
+LY_DEFINE (ly_camel_case_to_lisp_identifier, "ly:camel-case->lisp-identifier",
+ 1, 0, 0, (SCM name_sym),
+ "Convert music name to corresponding event class name.")
+{
+ /* UGH. There should be a better way. */
+ const string in = ly_symbol2string (name_sym);
+ /* this should be sufficient */
+ char out[in.size() * 2 + 2];
+ /* don't add '-' before first character */
+ out[0] = tolower (in[0]);
+ size_t outpos = 1;
+ for (size_t inpos = 1; inpos < in.size (); inpos++)
+ {
+ if (isupper (in[inpos]))
+ out[outpos++] = '-';
+ out[outpos++] = tolower (in[inpos]);
+ }
+ out[outpos] = 0;
+
+ return ly_symbol2scm (out);
+}
Stream_event *
Music::to_event () const
{
- /* UGH. Temp hack */
- SCM orig_sym = get_property ("name");
- char out[200];
- string in = ly_symbol2string (orig_sym);
- /* don't add '-' before first character */
- out[0] = tolower (in[0]);
- size_t outpos = 1;
- for (size_t inpos = 1; inpos < in.size () && outpos < 190; inpos++)
- {
- if (isupper (in[inpos]))
- out[outpos++] = '-';
- out[outpos++] = tolower (in[inpos]);
- }
- out[outpos] = 0;
- SCM class_name = ly_symbol2scm (out);
+ SCM class_name = ly_camel_case_to_lisp_identifier (get_property ("name"));
// catch programming mistakes.
if (!internal_is_music_type (class_name))
%{
-#define MY_MAKE_MUSIC(x) make_music_by_name (ly_symbol2scm (x))
+#define MY_MAKE_MUSIC(x, spot) make_music_with_input (ly_symbol2scm (x), spot)
/* ES TODO:
- Don't use lily module, create a new module instead.
#endif
-
-SCM make_music_relative (Pitch start, SCM music);
+static Music *make_music_with_input (SCM name, Input where);
+SCM make_music_relative (Pitch start, SCM music, Input loc);
SCM run_music_function (Lily_parser *, SCM expr);
SCM get_first_context_id (SCM type, Music *m);
SCM make_chord_elements (SCM pitch, SCM dur, SCM modification_list);
}
| music_list error {
- Music *m = MY_MAKE_MUSIC("Music");
+ Music *m = MY_MAKE_MUSIC("Music", @$);
// ugh. code dup
m->set_property ("error-found", SCM_BOOL_T);
SCM s = $$;
relative_music:
RELATIVE absolute_pitch music {
Pitch start = *unsmob_pitch ($2);
- $$ = make_music_relative (start, $3);
+ $$ = make_music_relative (start, $3, @$);
}
| RELATIVE composite_music {
Pitch middle_c (0, 0, 0);
- $$ = make_music_relative (middle_c, $2);
+ $$ = make_music_relative (middle_c, $2, @$);
}
;
SCM check = $4;
SCM post = $5;
- Music *n = MY_MAKE_MUSIC ("NoteEvent");
+ Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
n->set_property ("pitch", $1);
- n->set_spot (@$);
if (q % 2)
n->set_property ("cautionary", SCM_BOOL_T);
if (ex % 2 || q % 2)
$$ = n->unprotect ();
}
| DRUM_PITCH post_events {
- Music *n = MY_MAKE_MUSIC ("NoteEvent");
+ Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
n->set_property ("duration", $2);
n->set_property ("drum-type", $1);
- n->set_spot (@$);
if (scm_is_pair ($2)) {
SCM arts = scm_reverse_x ($2, SCM_EOL);
$$ = MAKE_SYNTAX ("skip-music", @$, $2);
}
| E_BRACKET_OPEN {
- Music *m = MY_MAKE_MUSIC ("LigatureEvent");
+ Music *m = MY_MAKE_MUSIC ("LigatureEvent", @$);
m->set_property ("span-direction", scm_from_int (START));
- m->set_spot (@$);
$$ = m->unprotect();
}
| E_BRACKET_CLOSE {
- Music *m = MY_MAKE_MUSIC ("LigatureEvent");
+ Music *m = MY_MAKE_MUSIC ("LigatureEvent", @$);
m->set_property ("span-direction", scm_from_int (STOP));
- m->set_spot (@$);
$$ = m->unprotect ();
}
| E_BACKSLASH {
command_event:
E_TILDE {
- $$ = MY_MAKE_MUSIC ("PesOrFlexaEvent")->unprotect ();
+ $$ = MY_MAKE_MUSIC ("PesOrFlexaEvent", @$)->unprotect ();
}
| MARK DEFAULT {
- Music *m = MY_MAKE_MUSIC ("MarkEvent");
+ Music *m = MY_MAKE_MUSIC ("MarkEvent", @$);
$$ = m->unprotect ();
+ scm_display($$, SCM_UNDEFINED);
}
| tempo_event {
$$ = $1;
}
| KEY DEFAULT {
- Music *key = MY_MAKE_MUSIC ("KeyChangeEvent");
+ Music *key = MY_MAKE_MUSIC ("KeyChangeEvent", @$);
$$ = key->unprotect ();
}
| KEY NOTENAME_PITCH SCM_IDENTIFIER {
- Music *key = MY_MAKE_MUSIC ("KeyChangeEvent");
+ Music *key = MY_MAKE_MUSIC ("KeyChangeEvent", @$);
if (scm_ilength ($3) > 0)
{
key->set_property ("pitch-alist", $3);
| HYPHEN {
if (!PARSER->lexer_->is_lyric_state ())
PARSER->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
- $$ = MY_MAKE_MUSIC ("HyphenEvent")->unprotect ();
+ $$ = MY_MAKE_MUSIC ("HyphenEvent", @$)->unprotect ();
}
| EXTENDER {
if (!PARSER->lexer_->is_lyric_state ())
PARSER->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
- $$ = MY_MAKE_MUSIC ("ExtenderEvent")->unprotect ();
+ $$ = MY_MAKE_MUSIC ("ExtenderEvent", @$)->unprotect ();
}
| script_dir direction_reqd_event {
if ($1)
string_number_event:
E_UNSIGNED {
- Music *s = MY_MAKE_MUSIC ("StringNumberEvent");
+ Music *s = MY_MAKE_MUSIC ("StringNumberEvent", @$);
s->set_property ("string-number", scm_from_int ($1));
- s->set_spot (@$);
$$ = s->unprotect ();
}
;
if (unsmob_music (predefd))
{
m = unsmob_music (predefd)->clone ();
+ m->set_spot (@$);
}
else
{
- m = MY_MAKE_MUSIC ("Music");
+ m = MY_MAKE_MUSIC ("Music", @$);
}
- m->set_spot (@$);
$$ = m->unprotect ();
}
| EVENT_IDENTIFIER {
$$ = $1;
}
| tremolo_type {
- Music *a = MY_MAKE_MUSIC ("TremoloEvent");
- a->set_spot (@$);
+ Music *a = MY_MAKE_MUSIC ("TremoloEvent", @$);
a->set_property ("tremolo-type", scm_from_int ($1));
$$ = a->unprotect ();
}
}
| script_abbreviation {
SCM s = PARSER->lexer_->lookup_identifier ("dash" + ly_scm2string ($1));
- Music *a = MY_MAKE_MUSIC ("ArticulationEvent");
+ Music *a = MY_MAKE_MUSIC ("ArticulationEvent", @$);
if (scm_is_string (s))
a->set_property ("articulation-type", s);
else PARSER->parser_error (@1, _ ("expecting string as script definition"));
gen_text_def:
full_markup {
- Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
+ Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
t->set_property ("text", $1);
- t->set_spot (@$);
$$ = t->unprotect ();
}
| string {
- Music *t = MY_MAKE_MUSIC ("TextScriptEvent");
+ Music *t = MY_MAKE_MUSIC ("TextScriptEvent", @$);
t->set_property ("text",
make_simple_markup ($1));
- t->set_spot (@$);
$$ = t->unprotect ();
}
| DIGIT {
- Music *t = MY_MAKE_MUSIC ("FingeringEvent");
+ Music *t = MY_MAKE_MUSIC ("FingeringEvent", @$);
t->set_property ("digit", scm_from_int ($1));
- t->set_spot (@$);
$$ = t->unprotect ();
}
;
bass_figure:
FIGURE_SPACE {
- Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent");
- $$ = bfr->self_scm ();
- bfr->unprotect ();
- bfr->set_spot (@1);
+ Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent", @$);
+ $$ = bfr->unprotect ();
}
| bass_number {
- Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent");
+ Music *bfr = MY_MAKE_MUSIC ("BassFigureEvent", @$);
$$ = bfr->self_scm ();
if (scm_is_number ($1))
bfr->set_property ("text", $1);
bfr->unprotect ();
- bfr->set_spot (@1);
}
| bass_figure ']' {
$$ = $1;
Music *n = 0;
if ($6)
- n = MY_MAKE_MUSIC ("RestEvent");
+ n = MY_MAKE_MUSIC ("RestEvent", @$);
else
- n = MY_MAKE_MUSIC ("NoteEvent");
+ n = MY_MAKE_MUSIC ("NoteEvent", @$);
n->set_property ("pitch", $1);
n->set_property ("duration", $5);
if ($2 % 2 || $3 % 2)
n->set_property ("force-accidental", SCM_BOOL_T);
- n->set_spot (@$);
$$ = n->unprotect ();
}
| DRUM_PITCH optional_notemode_duration {
- Music *n = MY_MAKE_MUSIC ("NoteEvent");
+ Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
n->set_property ("duration", $2);
n->set_property ("drum-type", $1);
Music *ev = 0;
if (ly_scm2string ($1) == "s") {
/* Space */
- ev = MY_MAKE_MUSIC ("SkipEvent");
+ ev = MY_MAKE_MUSIC ("SkipEvent", @$);
}
else {
- ev = MY_MAKE_MUSIC ("RestEvent");
+ ev = MY_MAKE_MUSIC ("RestEvent", @$);
}
ev->set_property ("duration", $2);
- ev->set_spot (@$);
$$ = ev->unprotect ();
}
| lyric_element optional_notemode_duration {
if (!PARSER->lexer_->is_lyric_state ())
PARSER->parser_error (@1, _ ("have to be in Lyric mode for lyrics"));
- Music *levent = MY_MAKE_MUSIC ("LyricEvent");
+ Music *levent = MY_MAKE_MUSIC ("LyricEvent", @$);
levent->set_property ("text", $1);
levent->set_property ("duration",$2);
- levent->set_spot (@$);
$$= levent->unprotect ();
}
;
return v;
}
+Music *
+make_music_with_input (SCM name, Input where)
+{
+ Music *m = make_music_by_name (name);
+ m->set_spot (where);
+ return m;
+}
SCM
get_first_context_id (SCM type, Music *m)
}
SCM
-make_music_relative (Pitch start, SCM music)
+make_music_relative (Pitch start, SCM music, Input loc)
{
- Music *relative = MY_MAKE_MUSIC ("RelativeOctaveMusic");
+ Music *relative = MY_MAKE_MUSIC ("RelativeOctaveMusic", loc);
relative->set_property ("element", music);
Music *m = unsmob_music (music);
IMPLEMENT_SMOBS (Prob);
IMPLEMENT_TYPE_P (Prob, "ly:prob?");
-IMPLEMENT_DEFAULT_EQUAL_P (Prob);
+
+SCM
+Prob::equal_p (SCM sa, SCM sb)
+{
+ /* This comparison function is only designed to make the copy
+ constructor preserve equality.
+
+ Perhaps it would be better to use a more strict definition of
+ equality; e.g., that that two probs are equal iff they can be
+ distinguished by calls to ly:prob-property.
+ */
+ Prob *probs[2] = {unsmob_prob (sa), unsmob_prob (sb)};
+ SCM props[2][2];
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ props[i][0] = probs[i]->immutable_property_alist_;
+ props[i][1] = probs[i]->mutable_property_alist_;
+ }
+
+ if (strcmp (probs[0]->class_name (), probs[1]->class_name ()))
+ return SCM_BOOL_F;
+
+ /* Compare mutable and immutable lists, element by element. */
+ for (i = 0; i < 2; i++)
+ {
+ SCM aprop = props[0][i], bprop = props[1][i];
+
+ for (; scm_is_pair (aprop) && scm_is_pair(bprop); aprop = scm_cdr (aprop), bprop = scm_cdr (bprop))
+ {
+ if (scm_caar (aprop) != scm_caar (bprop) ||
+ !to_boolean (scm_equal_p (scm_cdar (aprop), scm_cdar (bprop))))
+ return SCM_BOOL_F;
+ }
+
+ /* is one list shorter? */
+ if (aprop != SCM_EOL || bprop != SCM_EOL)
+ return SCM_BOOL_F;
+ }
+
+ return SCM_BOOL_T;
+}
Prob::Prob (SCM type, SCM immutable_init)
{
}
/*
- Used by ADD_THIS_TRANSLATOR to extract a list of event-class names
- for each translator. This list is used by the internals
- documentation.
+ Helps the individual static_translator_description methods of translators.
*/
SCM
-Translator::get_listened_class_list (const translator_listener_record *listeners) const
+Translator::static_translator_description (const char *grobs,
+ const char *desc,
+ translator_listener_record *listener_list,
+ const char *read,
+ const char *write) const
{
+ SCM static_properties = SCM_EOL;
+
+ static_properties = scm_acons (ly_symbol2scm ("grobs-created"),
+ parse_symbol_list (grobs), static_properties);
+
+ static_properties = scm_acons (ly_symbol2scm ("description"),
+ scm_makfrom0str (desc), static_properties);
+
SCM list = SCM_EOL;
- for (; listeners; listeners = listeners->next_)
- list = scm_cons (listeners->event_class_, list);
- return list;
+ for (; listener_list; listener_list = listener_list->next_)
+ list = scm_cons (listener_list->event_class_, list);
+ static_properties = scm_acons (ly_symbol2scm ("events-accepted"),
+ list, static_properties);
+
+ static_properties = scm_acons (ly_symbol2scm ("properties-read"),
+ parse_symbol_list (read), static_properties);
+
+ static_properties = scm_acons (ly_symbol2scm ("properties-written"),
+ parse_symbol_list (write), static_properties);
+
+ return static_properties;
}
-
+
/*
SMOBS
*/
bool
internal_event_assignment (Stream_event **old_ev, Stream_event *new_ev, const char *function)
{
- if (*old_ev)
+ if (*old_ev &&
+ !to_boolean (scm_equal_p ((*old_ev)->self_scm (),
+ new_ev->self_scm ())))
{
/* extract event class from function name */
const char *prefix = "listen_";
texi)))
(define music-types->names (make-vector 61 '()))
-(map (lambda (entry)
- (let* ((types (cdr (assoc 'types (cdr entry)))))
- (map (lambda (type)
- (hashq-set! music-types->names type
- (cons (car entry)
- (hashq-ref music-types->names type '()))))
- types)))
- music-descriptions)
+(filter-map (lambda (entry)
+ (let* ((class (ly:camel-case->lisp-identifier (car entry)))
+ (classes (ly:make-event-class class)))
+ (if classes
+ (map (lambda (cl)
+ (hashq-set! music-types->names cl
+ (cons (car entry)
+ (hashq-ref music-types->names cl '()))))
+ classes)
+ #f)))
+
+ music-descriptions)
(define (strip-description x)
(cons (symbol->string (car x))
(define (music-doc-str obj)
(let* ((namesym (car obj))
(props (cdr obj))
- (types (cdr (assoc 'types props))))
-
+ (class (ly:camel-case->lisp-identifier namesym))
+ (classes (ly:make-event-class class))
+ (event-texi (if classes
+ (string-append
+ "\n\nEvent classes:\n"
+ (human-listify (map ref-ify (map symbol->string classes)))
+ "\n\n"
+ "\n\nAccepted by: "
+ (human-listify
+ (map ref-ify
+ (map symbol->string (map ly:translator-name
+ (filter
+ (lambda (x) (engraver-accepts-music-types? classes x)) all-engravers-list))))))
+ "")))
+
(string-append
(object-property namesym 'music-description)
- "\n\nMusic types:\n"
- (human-listify (map ref-ify (map symbol->string types)))
- "\n\n"
- "\n\nAccepted by: "
- (human-listify
- (map ref-ify
- (map symbol->string (map ly:translator-name
- (filter
- (lambda (x) (engraver-accepts-music-types? types x)) all-engravers-list)))))
+ event-texi
"\n\nProperties: \n"
(description-list->texi
(map