On Mon, Dec 15, 2008 at 2:09 PM, Han-Wen Nienhuys <hanw...@gmail.com> wrote:

> On Mon, Dec 15, 2008 at 5:25 PM, Carl D. Sorensen <c_soren...@byu.edu>
> wrote:
> >
> >
> >
> > On 12/15/08 7:18 AM, "Han-Wen Nienhuys" <hanw...@gmail.com> wrote:
> >
> >
> >> Try not to form mental models.  Use the source instead.
> >
> > Unfortunately, not very many of us understand the source completely, and
> so
> > we need mental models to work in LilyPond.  Of course, our mental models
> > will be incorrect in some detail, and we'll need to revise them from time
> to
> > time.
>
> sure, but if you spend a lot of time and effort on theorizing (like
> Trevor did), you might as well invest that time & effort into looking
> at the source code itself.
>

I think both are good: wanton speculation taken together with digging
through source.

:-)

I've been digging through source this morning ... and I'm understanding much
better ... but still unable to resolve at least one example, which I've
included at the end of this message.

What I've found so far:

* There are 22 -iterator.cc files with Music_iterator being the base class
from which the others all directly (or, more usually, indirectly) inherit.
(Simple_music_iterator, Music_wrapper_iterator and Sequential_iterator are
all popular choices to derive from, too, but all three inherit from
Music_iterator at base.) Concrete iterators exist to iterate over regular
stuff like EventChord and and 'simple music' (which parser.yy makes me think
means basically notes and rests). Iterators also exist to iterate over more
complex music expressions like grace music, time-scaled music, voltas, and
music expressions passed to the \unfold command. My understanding of this
flock of iterators available in the C++ source is as a type of realization
of the visitor pattern that separates traversal from other activities like
calculation and modification.

* Additionally, both the comments at the head of music-iterator.hh and
Erik's thesis make it clear that the object over which the different
iterators iterate is a (conceptual) queue of music events *that all happen
at the same moment*. That is, when it comes time to iterate, the first thing
that happens is that the entire context tree (starting from the Global
context and proceeding all the way to bottom-level voice contexts) are
*prepared* for Moment 0; then iterators iterate over all events that happen
at Moment 0 *no matter at which level of the context tree those different
events occur*. This helps because I was assuming (wrongly) earlier that
iteration would be a depth-first search starting from the root of the
expression tree; if that were the case then each context would be visited
before any of its children. But, in fact, section 9.4 of Erik's thesis says
"One of the consequences of a OneTimeStep stream event, is that all contexts
are visited in a post-order tree walk; i.e., each context is visited after
all its children have been visited." I haven't been able to verify this in
the code, however.

* I've also found that a pronouncement like "\new Voice { c'4 }" is actually
THREE expressions. The "\new Voice" is actually a music expression all by
itself (of type ContextSpeccedMusic). There is a
Context_specced_music_iterator defined in an eponymous .cc file and
inheriting from Music_wrapper_iterator. The purpose of the
Context_specced_music_iterator is to descend to the one (and only one) child
that each ContextSpeccedMusic like "\new Voice" music have: something like
Sequential is the usual option. So the parser (which I only understand
vaguely) decomposes "\new Voice { c'4 }" into three expressions with "\new
Voice" parsed as ContextSpeccedMusic, with "{ }" parsed as Sequential, with
"c'4" parsed as EventChord (I think). Further, the parser builds the
resulting music expression such that ContextSpeccedMusic is the parent of
Sequential which is, in turn, the parent of EventChord.

* Also, all parsing is done before any iteration is done.

* OK, so based on this understanding, can somebody please correct my
understanding of the parsing (not the iteration, just the parsing) of the
following expression (which is the same as my original example #2):

  {
    \new Voice {
      c'8 c'8 c'8 c'8
    }
    d'8 d'8 d'8 d'8
  }

If I'm understanding how the parser works, then what should result here is a
music expression that looks like this:

                 Global
                    V
               \new Score
                    V
               \new Staff
                    V
               \new Voice
                    V
                Sequential
                    V
    \new Voice, d'8, d'8, d'8, d'8
       V
    Sequential
       V
c'8, c'8, c'8, c'8


If I'm counting correctly, that's 15 total nodes in the expression tree.
Eight atomic nodes and seven internal nodes. The Global, \new Score, \new
Staff and the first \new Voice are all created implicitly.

I know that the next part in the process is iteration. But I want to stop
and check my understanding here: am I understanding the output of the parser
correctly at this point?


Trevor.

-- 
Trevor Bača
trevorb...@gmail.com
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to