]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/sequential-iterator.cc
Doc-es: various updates.
[lilypond.git] / lily / sequential-iterator.cc
index 6817d3a0d5c71c7f95cd85f6d5d22683a8aa988d..b02e58c62d0c57ab8dd3f00a9fecad1002ede9b1 100644 (file)
 /*
-  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 <hanwen@xs4all.nl>
 
-  (c)  1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
+  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 <http://www.gnu.org/licenses/>.
+*/
 
-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.
-
 */
 
 /*
   Invariant for the data structure.
 
 
-  if (gh_pair_p (cursor_))
-    iter_->music_ == unsmob_music (ly_car (cursor_))
+  if (scm_is_pair (cursor_))
+  iter_->music_ == unsmob<Music> (scm_car (cursor_))
   else
-    iter_ == 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);
-  list_ = SCM_EOL;
-  cursor_ = SCM_EOL; 
+  cursor_ = SCM_EOL;
   grace_fixups_ = 0;
-  iter_ =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;
 }
 
 void
 Sequential_iterator::do_quit ()
 {
   if (iter_)
-    iter_->quit();
+    iter_->quit ();
 }
 
-
-Sequential_iterator::Sequential_iterator (Sequential_iterator const &src)
-  : Music_iterator (src)
+void
+Sequential_iterator::derived_mark () const
 {
-  grace_fixups_ = copy_grace_fixups (src.grace_fixups_);
-  cursor_ = src.cursor_;
-  list_ = src.cursor_;
-  here_mom_ = src.here_mom_;
-  iter_ = (src.iter_) ? src.iter_->clone () : 0;
-
   if (iter_)
-    scm_gc_unprotect_object (iter_->self_scm());
+    scm_gc_mark (iter_->self_scm ());
+  scm_gc_mark (cursor_);
 }
 
 void
-Sequential_iterator::derived_mark ()const
+Sequential_iterator::derived_substitute (Context *f, Context *t)
 {
   if (iter_)
-    scm_gc_mark (iter_->self_scm());
-  scm_gc_mark (list_);
-  scm_gc_mark (cursor_);
+    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<Music> (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,192 +129,108 @@ copy_grace_fixups (Grace_fixup* src)
 void
 Sequential_iterator::construct_children ()
 {
-  list_ = get_music_list ();
-  cursor_ = list_; 
+  cursor_ = get_music_list ();
 
   iter_ = 0;
-  if (gh_pair_p (cursor_))
+  if (scm_is_pair (cursor_))
     {
-      Music *m  =unsmob_music (ly_car (cursor_));
-      iter_ = unsmob_iterator (get_iterator (m));
+      Music *m = unsmob<Music> (scm_car (cursor_));
+      iter_ = unsmob<Music_iterator> (get_iterator (m));
     }
-  
+
   while (iter_ && !iter_->ok ())
-    {
-      next_element (true);
-    }
+    next_element (true);
 
+  last_mom_ = Moment (-1);
   here_mom_ = get_music ()->start_mom ();
-  grace_fixups_ = get_grace_fixups (cursor_);
+  grace_fixups_ = create_grace_fixup_list (cursor_);
 
   /*
     iter_->ok () is tautology, but what the heck.
-   */
-  if (iter_ && iter_->ok ()) 
-    descend_to_child ();
+  */
+  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_->music_length_mom () - iter_->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 ();
 
-      Grace_fixup * n =grace_fixups_->next_;
-      delete grace_fixups_;
-      grace_fixups_ = n;
+      last_mom_ = here_mom_;
+      here_mom_ += gf->length_;
+      here_mom_.grace_part_ += gf->grace_start_;
+
+      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;
     }
-  
-  cursor_ = ly_cdr (cursor_);
 
-  iter_->quit();
-  if (gh_pair_p (cursor_))
-    iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
+  cursor_ = scm_cdr (cursor_);
+
+  iter_->quit ();
+  if (scm_is_pair (cursor_))
+    iter_ = unsmob<Music_iterator> (get_iterator (unsmob<Music> (scm_car (cursor_))));
   else
     iter_ = 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_pending_events (Moment until)const
-{
-  SCM s = SCM_EOL;
-  if (until <  pending_moment ())
-    return s;
-
-  Sequential_iterator * me =
-    dynamic_cast<Sequential_iterator*> (clone ());
-  while (me->ok ())
-    {
-      SCM nm = me->iter_->get_pending_events (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);
-    }
-
-  scm_gc_unprotect_object (me->self_scm());
-  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
- */
-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_->skip (iter_->music_length_mom ());
-       }
-      else if (iter_->music_length_mom () >= until - here_mom_)
-       iter_->skip (until - here_mom_ + iter_->music_start_mom ());
-
-      if (iter_->ok ())
-       return ; 
-
-      next_element (false);
-    }
-}
-
 void
 Sequential_iterator::process (Moment until)
 {
   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_->process (iter_->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_->process (until - here_mom_ + iter_->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_->ok ())
-       return ;
+        return;
 
-      descend_to_child ();
+      descend_to_child (iter_->get_outlet ());
       next_element (true);
     }
 }
@@ -338,11 +243,10 @@ Sequential_iterator::pending_moment () const
   /*
     Fix-up a grace note halfway in the music.
   */
-  if (grace_fixups_ && here_mom_ == grace_fixups_->start_
-      && grace_fixups_->length_ + iter_->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.
@@ -350,17 +254,33 @@ Sequential_iterator::pending_moment () const
   return cp + here_mom_ - iter_->music_start_mom ();
 }
 
-
 bool
 Sequential_iterator::ok () const
 {
   return iter_;
 }
 
-Music_iterator*
-Sequential_iterator::try_music_in_children (Music *m) const
-{ 
-  return iter_ ? iter_->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;
+}