lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: music macros?


From: Han-Wen Nienhuys
Subject: Re: music macros?
Date: Sat, 04 Feb 2006 14:43:10 +0100
User-agent: Mozilla Thunderbird 1.0.7-1.1.fc4 (X11/20050929)

Nicolas Sceaux wrote:
How about this: The parser spits out a big evaluatable Scheme expression, which simply is eval:ed after parsing. A bit like the return value of music->make-music, but with music functions & macros written as real Scheme functions.

The good thing about this solution, is the simplicity and the powerfulness (I suppose that lots of things would be handled automatically by Scheme, perhaps we will even get local variables for free). The bad thing, is that the \relative macro will be rather ugly (it will need to traverse (make-music ..) calls and modify pitches).


When using raw sexpr instead of music objects, you lose semantics.
Making the \relative macro deal with the sexpr:
  (make-music 'NoteEvent 'origin <location object> 'pitch <pitch object>
  ...)
instead of an actual NoteEvent object is a step backward in
expressiveness.

Wait a minute, I should not be the one argumenting against a LilyPond
code -> scheme code compiler!!

:-)

But I agree - I think that the parser should handle music expression arities, and assemble the right tree structures. I have the feeling we'll get into hairiness if we don't, and we would loose error handling and recovery that is now provided by bison. This means that we have to do the identifier lookup directly, otherwise we can't discover the arity of a music function, and generate the right tree. What we want to postpone is the application of said music function (ie. running the appropriate Scheme fragment).

More seriously.
  \relativeMacro c'' { c \someUnaryFunction { d \someMusicVariable } }
The parser would read the macro's arguments as unexpanded music objects:

(relativeMacro
  <Unexpanded music object for "c''">
  <Unexpanded music object for the 2nd argument>)
Where the two unexpanded music objects looks like:

 <EventChord elements: (<NoteEvent duration: <duration 2 0 1 1>
                                   pitch: <pitch 1 0 0>)>

just as an aside, changing relative to a macro has some compatibility caveats: currently we allow both

  \relative { STUFF }

and

  \relative c'' { STUFF }

if we make \relative generic, then this is no longer possible.

 <SequentialMusic
   elements: (<EventChord elements: (<NoteEvent duration: <duration 2 0 1 1>
                                                pitch: <pitch -1 0 0>)>
              <MusicFunction procedure: someUnaryFunction
                arguments: (<SequentialMusic
                             elements: (<EventChord
                                          elements: (<NoteEvent duration: 
<duration 2 0 1 1>
                                                                pitch: <pitch -1 1 
0>)>
                                        <MusicIdentifier symbol: 
'someMusicVariable>)>)>)>

Then, the relativeMacro is called and generate another unexpanded music
object (modifying octaves):

 <SequentialMusic
   elements: (<EventChord elements: (<NoteEvent duration: <duration 2 0 1 1>
                                                pitch: <pitch 1 0 0>)>
              <MusicFunction procedure: someUnaryFunction
                arguments: (<SequentialMusic
                             elements: (<EventChord
                                          elements: (<NoteEvent duration: 
<duration 2 0 1 1>
                                                                pitch: <pitch 1 1 
0>)>
                                        <MusicIdentifier symbol: 
'someMusicVariable>)>)>)>

The top-level music handler finally returns an expanded music object, by
applying music functions and replacing music identifier by their value,
using ly:parser-lookup.

Hmmm, wouldn't it be better to do the "expansion" when we start iterating the expressions? Then we can have the unfold repeats for MIDI for free.

I'm not sure when the #(scheme forms) found in music expressions would
be evaluated, maybe when they are read by the parser (iso when the top
level music handler expand music objects)...

As #( .. ) is handled in the lexer, not the parser, I think they will
have to be done directly.

BTW, looking at the parser, I see another option for deconstructing it further. It might be possible to add lexer-mode switches to the annotation of a music function. Then we could also soft-code the definition of \lyrics, \lyricsto, \figures, etc.


--
 Han-Wen Nienhuys - address@hidden - http://www.xs4all.nl/~hanwen




reply via email to

[Prev in Thread] Current Thread [Next in Thread]