From 61c40c765eea03bc1029b596a2d31ab70f26d82c Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Tue, 7 Jul 2015 21:44:59 +0200 Subject: [PATCH] Issue 4487/1: Implement partial function calls A partial function call acts as a function where the start of the argument list has already been supplied. For example: makeRed = \tweak color #red \etc Then one can use this as { c' \makeRed d' e'-\makeRed -. } --- lily/include/lily-imports.hh | 1 + lily/lily-imports.cc | 1 + lily/lily-lexer.cc | 1 + lily/parser.yy | 70 ++++++++++++++++++++++++++++++++++ scm/ly-syntax-constructors.scm | 10 +++++ 5 files changed, 83 insertions(+) diff --git a/lily/include/lily-imports.hh b/lily/include/lily-imports.hh index 120ff11cb7..535b40bea4 100644 --- a/lily/include/lily-imports.hh +++ b/lily/include/lily-imports.hh @@ -119,6 +119,7 @@ namespace Syntax { extern Variable multi_measure_rest; extern Variable music_function; extern Variable music_function_call_error; + extern Variable partial_music_function; extern Variable property_operation; extern Variable repeat; extern Variable repetition_chord; diff --git a/lily/lily-imports.cc b/lily/lily-imports.cc index 6f16c0ebc0..2a8ecf9e84 100644 --- a/lily/lily-imports.cc +++ b/lily/lily-imports.cc @@ -112,6 +112,7 @@ namespace Syntax { Variable multi_measure_rest ("multi-measure-rest"); Variable music_function ("music-function"); Variable music_function_call_error ("music-function-call-error"); + Variable partial_music_function ("partial-music-function"); Variable property_operation ("property-operation"); Variable repeat ("repeat"); Variable repetition_chord ("repetition-chord"); diff --git a/lily/lily-lexer.cc b/lily/lily-lexer.cc index 68b5578994..b6cbda7f97 100644 --- a/lily/lily-lexer.cc +++ b/lily/lily-lexer.cc @@ -57,6 +57,7 @@ static Keyword_ent the_key_tab[] {"description", DESCRIPTION}, {"drummode", DRUMMODE}, {"drums", DRUMS}, + {"etc", ETC}, {"figuremode", FIGUREMODE}, {"figures", FIGURES}, {"header", HEADER}, diff --git a/lily/parser.yy b/lily/parser.yy index 25b7cd86c3..581791d256 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -265,6 +265,7 @@ int yylex (YYSTYPE *s, YYLTYPE *loc, Lily_parser *parser); %token DESCRIPTION "\\description" %token DRUMMODE "\\drummode" %token DRUMS "\\drums" +%token ETC "\\etc" %token FIGUREMODE "\\figuremode" %token FIGURES "\\figures" %token HEADER "\\header" @@ -693,6 +694,25 @@ identifier_init_nonumber: | embedded_scm | full_markup_list | context_modification + | partial_function ETC + ; + +partial_function: + MUSIC_FUNCTION function_arglist_partial + { + $$ = MAKE_SYNTAX (partial_music_function, @$, + $1, $2); + } + | EVENT_FUNCTION function_arglist_partial + { + $$ = MAKE_SYNTAX (partial_music_function, @$, + $1, $2); + } + | SCM_FUNCTION function_arglist_partial + { + $$ = MAKE_SYNTAX (partial_music_function, @$, + $1, $2); + } ; context_def_spec_block: @@ -2004,6 +2024,56 @@ function_arglist_skip_nonbackup: } ; +// Partial function arglists are returned just in their incomplete +// state: when combined with the music function, the missing parts of +// the signature can be reconstructed +// +// To serve as a partial arglist, the argument list must absolutely +// _not_ be in "skipping optional arguments" mode since then there is +// some backup token that has nowhere to go before \etc. +// +// So we can skim off an arbitrary number of arguments from the end of +// the argument list. The argument list remaining afterwards has to +// be in not-skipping-optional-arguments mode. + +function_arglist_partial: + EXPECT_SCM function_arglist_optional + { + $$ = $2; + } + | EXPECT_SCM function_arglist_partial_optional + { + $$ = $2; + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_nonbackup + { + $$ = $3; + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_partial + { + $$ = $3; + } + ; + +function_arglist_partial_optional: + EXPECT_SCM function_arglist_optional + { + $$ = $2; + } + | EXPECT_SCM function_arglist_partial_optional + { + $$ = $2; + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_backup + { + $$ = $3; + } + | EXPECT_OPTIONAL EXPECT_SCM function_arglist_partial_optional + { + $$ = $3; + } + ; + function_arglist_common: EXPECT_NO_MORE_ARGS { $$ = SCM_EOL; diff --git a/scm/ly-syntax-constructors.scm b/scm/ly-syntax-constructors.scm index 04629bf655..b53e0cb34e 100644 --- a/scm/ly-syntax-constructors.scm +++ b/scm/ly-syntax-constructors.scm @@ -60,6 +60,16 @@ n (type-name pred) (music->make-music arg)) (*location*))) +(define-public (partial-music-function fun args) + (let* ((sig (ly:music-function-signature fun)) + (args (and (list args) (reverse! args)))) + (and args + (ly:make-music-function + (cons (car sig) (list-tail (cdr sig) (length args))) + (lambda rest + (apply (ly:music-function-extract fun) + (append args rest))))))) + (define-public (void-music) (ly:set-origin! (make-music 'Music))) -- 2.39.2