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