X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fsequential-iterator.cc;h=b02e58c62d0c57ab8dd3f00a9fecad1002ede9b1;hb=90e4d7057f3857da049dfda3d130017d4719bd6b;hp=de12d9362e33bf805e6799abfd96ae95de258106;hpb=c4c5bf6febe39f3e4d25f52e517e9b91addcbdc0;p=lilypond.git diff --git a/lily/sequential-iterator.cc b/lily/sequential-iterator.cc index de12d9362e..b02e58c62d 100644 --- a/lily/sequential-iterator.cc +++ b/lily/sequential-iterator.cc @@ -1,137 +1,126 @@ /* - Sequential_iterator.cc -- implement Sequential_iterator + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 1997--2015 Han-Wen Nienhuys - (c) 1997--2002 Han-Wen Nienhuys -*/ + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -#include "translator-group.hh" + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -#include "sequential-iterator.hh" -#include "music-list.hh" + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . +*/ -Grace_fixup *copy_grace_fixups (Grace_fixup* src); -Grace_fixup *get_grace_fixups (SCM cursor); +#include "sequential-iterator.hh" +#include "music.hh" +#include "translator-group.hh" +#include "context.hh" +#include "grace-fixup.hh" /* - TODO: handling of grace notes is exquisite pain. This handling should be formally specified and then the implementation verified. - */ -/* - - TODO: the grace note handling hasn't been done for skip() and - get_music(), meaning that staff-switching and partcombining will be - broken with grace notes. - - */ -/* - - TODO: the grace note handling hasn't been done for skip() and - get_music(), meaning that staff-switching and partcombining will be - broken with grace notes. - - */ /* Invariant for the data structure. - if (gh_pair_p (cursor_)) - iter_p_->music_l_ == unsmob_music (ly_car (cursor_)) + if (scm_is_pair (cursor_)) + iter_->music_ == unsmob (scm_car (cursor_)) else - iter_p_ == 0; + iter_ == 0; The length of musiclist from start to up to cursor_ (cursor_ not including), is summed - here_mom_ = sum (length (musiclist [start ... cursor>)) %) - - */ + here_mom_ = sum (length (musiclist [start ... cursor>)) %) +*/ Sequential_iterator::Sequential_iterator () { here_mom_ = Moment (0); + cursor_ = SCM_EOL; grace_fixups_ = 0; - iter_p_ =0; + iter_ = 0; } -SCM +SCM Sequential_iterator::get_music_list () const { - return SCM_EOL; + Music *m = get_music (); + SCM proc = m->get_property ("elements-callback"); + if (ly_is_procedure (proc)) + return scm_call_1 (proc, m->self_scm ()); + else + return SCM_EOL; } -Sequential_iterator::Sequential_iterator (Sequential_iterator const &src) - : Music_iterator (src) +void +Sequential_iterator::do_quit () { - grace_fixups_ = copy_grace_fixups (src.grace_fixups_); - cursor_ = src.cursor_; - list_ = src.cursor_; - here_mom_ = src.here_mom_; - if (src.iter_p_) - iter_p_ = src.iter_p_->clone (); - else - iter_p_ = 0; + if (iter_) + iter_->quit (); } -Sequential_iterator::~Sequential_iterator () +void +Sequential_iterator::derived_mark () const { - delete iter_p_; + if (iter_) + scm_gc_mark (iter_->self_scm ()); + scm_gc_mark (cursor_); } +void +Sequential_iterator::derived_substitute (Context *f, Context *t) +{ + if (iter_) + iter_->substitute_outlet (f, t); +} +/* + TODO: this should be made lazily. +*/ Grace_fixup * -get_grace_fixups (SCM cursor) +create_grace_fixup_list (SCM cursor) { Moment here; Moment last (-1); Grace_fixup *head = 0; Grace_fixup **tail = &head; - for (; gh_pair_p (cursor); cursor = ly_cdr (cursor)) + for (; scm_is_pair (cursor); cursor = scm_cdr (cursor)) { - Music * mus = unsmob_music (ly_car (cursor)); + Music *mus = unsmob (scm_car (cursor)); Moment s = mus->start_mom (); - Moment l =mus->length_mom () - s; + Moment l = mus->get_length () - s; if (s.grace_part_) - { - if (last != Moment (-1)) - { - Grace_fixup *p =new Grace_fixup; - p->start_ = last; - p->length_ = here - last; - p->grace_start_ = s.grace_part_; - p->next_ = 0; - *tail = p; - tail = &(*tail)->next_; - } - - here.grace_part_ = s.grace_part_; - } - - if (l.to_bool()) - { - last = here; - here += l; - } - } - return head; -} - -Grace_fixup * -copy_grace_fixups (Grace_fixup* src) -{ - Grace_fixup * head = 0; - Grace_fixup **dest = &head; - - while (src) - { - *dest = new Grace_fixup (*src); - dest = & (*dest)->next_; - src = src ->next_; + { + if (last != Moment (-1)) + { + Grace_fixup *p = new Grace_fixup; + p->start_ = last; + p->length_ = here - last; + p->grace_start_ = s.grace_part_; + p->next_ = 0; + *tail = p; + tail = &(*tail)->next_; + } + + here.grace_part_ = s.grace_part_; + } + + if (l.to_bool ()) + { + last = here; + here += l; + } } return head; @@ -140,188 +129,108 @@ copy_grace_fixups (Grace_fixup* src) void Sequential_iterator::construct_children () { - list_ = get_music_list (); - cursor_ = list_; + cursor_ = get_music_list (); - iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (ly_car (cursor_))) : 0; - while (iter_p_ && !iter_p_->ok ()) + iter_ = 0; + if (scm_is_pair (cursor_)) { - next_element (true); + Music *m = unsmob (scm_car (cursor_)); + iter_ = unsmob (get_iterator (m)); } - here_mom_ = music_l ()->start_mom (); - grace_fixups_ = get_grace_fixups (cursor_); + while (iter_ && !iter_->ok ()) + next_element (true); + + last_mom_ = Moment (-1); + here_mom_ = get_music ()->start_mom (); + grace_fixups_ = create_grace_fixup_list (cursor_); /* - iter_p_->ok () is tautology, but what the heck. - */ - if (iter_p_ && iter_p_->ok ()) - descend_to_child (); + iter_->ok () is tautology, but what the heck. + */ + if (iter_ && iter_->ok ()) + descend_to_child (iter_->get_outlet ()); } - /* maintain invariants: change cursor, iter and here_mom_ in one fell swoop. */ void -Sequential_iterator::next_element (bool side_effect) +Sequential_iterator::next_element (bool) { - Moment len =iter_p_->music_length_mom () - iter_p_->music_start_mom (); - assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_); - - if (len.main_part_ && grace_fixups_ && - grace_fixups_->start_ == here_mom_) + Moment len = iter_->music_get_length () - iter_->music_start_mom (); + assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_); + + if (len.main_part_ + && get_grace_fixup ()) { - here_mom_ += grace_fixups_->length_; - here_mom_.grace_part_ += grace_fixups_->grace_start_; + Grace_fixup *gf = get_grace_fixup (); + + last_mom_ = here_mom_; + here_mom_ += gf->length_; + here_mom_.grace_part_ += gf->grace_start_; - Grace_fixup * n =grace_fixups_->next_; - delete grace_fixups_; - grace_fixups_ = n; + next_grace_fixup (); } else if (len.grace_part_ && !len.main_part_) { - here_mom_.grace_part_ =0; + last_mom_ = here_mom_; + here_mom_.grace_part_ = 0; } else { /* - !len.grace_part_ || len.main_part_ + !len.grace_part_ || len.main_part_ - We skip over a big chunk (mainpart != 0). Any starting graces - in that chunk should be in len.grace_part_ + We skip over a big chunk (mainpart != 0). Any starting graces + in that chunk should be in len.grace_part_ */ + last_mom_ = here_mom_; here_mom_ += len; } - - delete iter_p_; - cursor_ = ly_cdr (cursor_); - - if (gh_pair_p (cursor_)) - iter_p_ = get_iterator_p (unsmob_music (ly_car (cursor_))); - else - iter_p_ = 0; -} - -/* - move to context of child iterator if it is deeper down in the - hierarchy. - */ -void -Sequential_iterator::descend_to_child () -{ -} - - -/* - Retrieve all music (starting at HERE), until a music with length L > - 0 is found. From the precondition, we know that UNTIL is later than - the earliest event. Hence we know - - L >= (UNTIL - HERE) - - so something that comes after this thing with L > 0 happens after - - HERE + L >= HERE + (UNTIL - HERE) = UNTIL - - Hence all events after the one with L>0 are uninteresting, so we - ignore them. - -*/ - -SCM -Sequential_iterator::get_music (Moment until)const -{ - SCM s = SCM_EOL; - if (until < pending_moment ()) - return s; - - Sequential_iterator * me = - dynamic_cast (clone ()); - while (me->ok ()) - { - SCM nm = me->iter_p_->get_music (until - me->here_mom_); - s = gh_append2 (nm, s); - - Moment m = 0; - for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i)) - { - Music *mus=unsmob_music (ly_car (i)); - m = m >? (mus->length_mom () - mus->start_mom ()); - } - if (m > Moment (0)) - break ; - else - me->next_element (false); - } - delete me; - - return s; -} - -/* - Skip events till UNTIL. We don't do any other side effects such as - descending to child iterator contexts, because they might depend on - \context specs and \translator changes being executed + cursor_ = scm_cdr (cursor_); - TODO: check support for grace notes here. - */ -void -Sequential_iterator::skip (Moment until) -{ - while (ok ()) - { - if (grace_fixups_ && - grace_fixups_->start_ == here_mom_ - && (grace_fixups_->start_ + grace_fixups_->length_ - + Moment (Rational (0), grace_fixups_->grace_start_) == until)) - { - /* - do the stuff/note/rest preceding a grace. - */ - iter_p_->skip (iter_p_->music_length_mom ()); - } - else if (iter_p_->music_length_mom () >= until - here_mom_) - iter_p_->skip (until - here_mom_ + iter_p_->music_start_mom ()); - - if (iter_p_->ok ()) - return ; - - next_element (false); - } + iter_->quit (); + if (scm_is_pair (cursor_)) + iter_ = unsmob (get_iterator (unsmob (scm_car (cursor_)))); + else + iter_ = 0; } void Sequential_iterator::process (Moment until) { - while (iter_p_) + while (iter_) { - if (grace_fixups_ && - grace_fixups_->start_ == here_mom_ - && (grace_fixups_->start_ + grace_fixups_->length_ - + Moment (Rational (0), grace_fixups_->grace_start_) == until)) - { - /* - do the stuff/note/rest preceding a grace. - */ - iter_p_->process (iter_p_->music_length_mom ()); - } + Grace_fixup *gf = get_grace_fixup (); + if (gf + && gf->start_ + gf->length_ + + Moment (Rational (0), gf->grace_start_) == until) + { + /* + do the stuff/note/rest preceding a grace. + */ + iter_->process (iter_->music_get_length ()); + } else - iter_p_->process (until - here_mom_ + iter_p_->music_start_mom ()); + { + Moment w = until - here_mom_ + iter_->music_start_mom (); + iter_->process (w); + } /* - if the iter is still OK, there must be events left that have - - TIME > LEFT - + if the iter is still OK, there must be events left that have + + TIME > LEFT + */ - if (iter_p_->ok ()) - return ; + if (iter_->ok ()) + return; - descend_to_child (); + descend_to_child (iter_->get_outlet ()); next_element (true); } } @@ -329,34 +238,49 @@ Sequential_iterator::process (Moment until) Moment Sequential_iterator::pending_moment () const { - Moment cp = iter_p_->pending_moment (); + Moment cp = iter_->pending_moment (); /* Fix-up a grace note halfway in the music. */ - if (grace_fixups_ && here_mom_ == grace_fixups_->start_ - && grace_fixups_->length_ + iter_p_->music_start_mom () == cp) - { - return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_); - } + Grace_fixup *gf = get_grace_fixup (); + if (gf + && gf->length_ + iter_->music_start_mom () == cp) + return here_mom_ + gf->length_ + Moment (0, gf->grace_start_); /* Fix-up a grace note at the start of the music. */ - return cp + here_mom_ - iter_p_->music_start_mom (); + return cp + here_mom_ - iter_->music_start_mom (); } - bool Sequential_iterator::ok () const { - return iter_p_; + return iter_; } -Music_iterator* -Sequential_iterator::try_music_in_children (Music *m) const -{ - return iter_p_ ? iter_p_->try_music (m) : 0; +IMPLEMENT_CTOR_CALLBACK (Sequential_iterator); + +bool +Sequential_iterator::run_always () const +{ + return iter_ ? iter_->run_always () : false; } -IMPLEMENT_CTOR_CALLBACK (Sequential_iterator); +void +Sequential_iterator::next_grace_fixup () +{ + Grace_fixup *n = grace_fixups_->next_; + delete grace_fixups_; + grace_fixups_ = n; +} + +Grace_fixup * +Sequential_iterator::get_grace_fixup () const +{ + if (grace_fixups_ && grace_fixups_->start_ == here_mom_) + return grace_fixups_; + else + return 0; +}