From: David Kastrup Date: Fri, 20 Jan 2012 11:01:03 +0000 (+0100) Subject: Make inherited stream event properties immutable. X-Git-Tag: release/2.15.27-1~20 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=e8f544af29c93145d122efa8dcfc0548d9b84f0b;p=lilypond.git Make inherited stream event properties immutable. Previously, the initialization of stream events from the (mutable) part of music event properties was done by just taking the mutable property list. That had the effect that any changes to the inherited properties were reflected in the originating music event, making a mockery of the mutable/immutable distinction intended to provide copy-on-write semantics. As an example, the conversion of the articulations property to events might or might not already have happened if the music event got reported more than once, like it is done in \repeat unfold. The change had the unexpected side effect of making quoted transposed music fail since the transposition worked exclusively on the mutable property list part. This has been fixed by adding a make_transposable member function to Stream_event that copies affected properties from the immutable to the mutable part before one attempts transposition. The source code has not yet been combed through for instances where stream events have been manually cloned to avoid the bad side effects of the original code. --- diff --git a/lily/include/stream-event.hh b/lily/include/stream-event.hh index 613b9294fb..f255ab5353 100644 --- a/lily/include/stream-event.hh +++ b/lily/include/stream-event.hh @@ -30,12 +30,13 @@ public: Stream_event (); VIRTUAL_COPY_CONSTRUCTOR (Stream_event, Stream_event); - Stream_event (SCM event_class, SCM mutable_props = SCM_EOL); + Stream_event (SCM event_class, SCM immutable_props = SCM_EOL); Stream_event (SCM class_name, Input *); Input *origin () const; void set_spot (Input *i); bool internal_in_event_class (SCM class_name); + void make_transposable (); virtual SCM copy_mutable_properties () const; diff --git a/lily/music.cc b/lily/music.cc index d8609ace96..02dbe41499 100644 --- a/lily/music.cc +++ b/lily/music.cc @@ -290,8 +290,7 @@ Music::to_event () const for (; scm_is_pair (art_mus); art_mus = scm_cdr (art_mus)) { Music *m = unsmob_music (scm_car (art_mus)); - SCM ev = m ? m->to_event ()->unprotect () : scm_car (art_mus); - art_ev = scm_cons (ev, art_ev); + art_ev = scm_cons (m->to_event ()->unprotect (), art_ev); } e->set_property ("articulations", scm_reverse_x (art_ev, SCM_EOL)); } diff --git a/lily/quote-iterator.cc b/lily/quote-iterator.cc index 9c5ea78e22..efb9c132e8 100644 --- a/lily/quote-iterator.cc +++ b/lily/quote-iterator.cc @@ -265,6 +265,7 @@ Quote_iterator::process (Moment m) Pitch diff = pitch_interval (qp, mp); ev = ev->clone (); + ev->make_transposable (); transpose_mutable (ev->get_property_alist (true), diff); transposed_musics_ = scm_cons (ev->unprotect (), transposed_musics_); diff --git a/lily/stream-event.cc b/lily/stream-event.cc index 4b8ff7fa1e..117559b87c 100644 --- a/lily/stream-event.cc +++ b/lily/stream-event.cc @@ -22,7 +22,8 @@ #include "ly-smobs.icc" #include "context.hh" #include "input.hh" -#include "input.hh" +#include "music.hh" +#include "pitch.hh" /* TODO: Rename Stream_event -> Event */ @@ -31,11 +32,10 @@ Stream_event::Stream_event () { } -Stream_event::Stream_event (SCM event_class, SCM mutable_props) +Stream_event::Stream_event (SCM event_class, SCM immutable_props) : Prob (ly_symbol2scm ("Stream_event"), - scm_list_1 (scm_cons (ly_symbol2scm ("class"), event_class))) + scm_acons (ly_symbol2scm ("class"), event_class, immutable_props)) { - mutable_property_alist_ = mutable_props; } Stream_event::Stream_event (SCM class_name, Input *origin) @@ -76,6 +76,29 @@ Stream_event::internal_in_event_class (SCM class_name) MAKE_SCHEME_CALLBACK (Stream_event, undump, 1); MAKE_SCHEME_CALLBACK (Stream_event, dump, 1); +void +Stream_event::make_transposable () +{ + /* This is in preparation for transposing stuff + that may be defined in the immutable part */ + + for (SCM s = immutable_property_alist_; scm_is_pair (s); s = scm_cdr (s)) + { + SCM entry = scm_car (s); + SCM prop = scm_car (entry); + SCM val = scm_cdr (entry); + + if ((unsmob_pitch (val) + || (prop == ly_symbol2scm ("element") && unsmob_music (val)) + || (prop == ly_symbol2scm ("elements") && scm_is_pair (val)) + || (prop == ly_symbol2scm ("pitch-alist") && scm_is_pair (val))) + && scm_is_false (scm_assq (prop, mutable_property_alist_))) + mutable_property_alist_ = + scm_acons (prop, ly_music_deep_copy (val), mutable_property_alist_); + } +} + + SCM Stream_event::dump (SCM self) {