Erik Sandberg <[EMAIL PROTECTED]> writes:

> On Thursday 02 February 2006 02.35, Han-Wen Nienhuys wrote:
>> Erik Sandberg wrote:
>> > Yes, just represent those commands as music functions internally. E.g.,
>> > \transpose creates a MusicFunction expression, with a list of two pitches
>> > and one Music as its 'elements (or 'arguments, I haven't decided yet),
>> > and 'to-music-callback is set to ly:music-transpose (or rather, to a
>> > wrapper around that function).
>>
>> OK, so we create all music expressions/events as "Music promises", which
>> expand into Music objects via some function as soon as they are
>> inspected, but have \relative deal with music-promises directly?
>
> 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!!

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>)>

and:

 <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.

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)...

nicolas


_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to