From ade7a425af75448ef0116928bceb65d339bf09ef Mon Sep 17 00:00:00 2001
From: Han-Wen Nienhuys <hanwen@xs4all.nl>
Date: Thu, 6 May 2004 21:37:32 +0000
Subject: [PATCH] rename to music-function

---
 ChangeLog                                     |  7 ++
 .../user/programming-interface.itely          | 27 ++++++
 input/regression/music-head.ly                |  4 +-
 lily/include/music-function.hh                | 20 +++++
 lily/include/music-head.hh                    | 20 -----
 lily/lexer.ll                                 | 27 +++---
 lily/music-wrapper.cc                         |  3 +-
 lily/parser.yy                                | 89 +++++++++++++++----
 8 files changed, 146 insertions(+), 51 deletions(-)
 create mode 100644 lily/include/music-function.hh
 delete mode 100644 lily/include/music-head.hh

diff --git a/ChangeLog b/ChangeLog
index 6b1f9dea61..7e6eac26e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-05-06  Han-Wen Nienhuys   <hanwen@xs4all.nl>
+
+	* lily/parser.yy (Generic_prefix_music_scm): add more
+	music_function symbols.
+
+	* lily/include/music-function.hh: rename to music-function
+
 2004-05-05  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
 	* lily/music-head.cc (LY_DEFINE): change order of args.
diff --git a/Documentation/user/programming-interface.itely b/Documentation/user/programming-interface.itely
index 1f840e55c7..75696a6f0e 100644
--- a/Documentation/user/programming-interface.itely
+++ b/Documentation/user/programming-interface.itely
@@ -133,6 +133,33 @@ and @internalsref{GraceMusic} has its single argument in
 @code{element}. The body of a repeat is in @code{element} property of
 @internalsref{RepeatedMusic}, and the alternatives in @code{elements}.
 
+
+
+
+@node Extending music syntax
+@appendixsubsec Extending music syntax
+
+The syntax of composite music expressions, like
+@code{\repeat}, @code{\transpose} and @code{\context}
+follows the general form of
+
+@example
+  \@code{keyword} @var{non-music-arguments} @var{music-arguments}
+@end example
+
+Such syntax can also be defined as user code. To do this, it is
+necessary to create a @em{music function}. This is a specially marked
+Scheme function. For example, the music function @code{\apply} applies
+a user-defined function to a music expression.  Its syntax is
+
+@example
+\apply #@var{func} @var{music}
+@end example
+
+A music function is created with @code{ly:make-music-function}.
+
+
+
 @node Manipulating music expressions
 @appendixsubsec Manipulating music expressions
 
diff --git a/input/regression/music-head.ly b/input/regression/music-head.ly
index 42a33c1553..0c538b655c 100644
--- a/input/regression/music-head.ly
+++ b/input/regression/music-head.ly
@@ -1,13 +1,13 @@
 \header
 {
-texidoc = "Music heads are generic music transformation functions,
+texidoc = "Music function are generic music transformation functions,
 which can be used to extend music syntax seamlessly."
 
 }
 \version "2.3.1"
 
 #(define myBar
-  (ly:make-music-head
+  (ly:make-music-function
    (list string?)
    (lambda (where type)
     (context-spec-music
diff --git a/lily/include/music-function.hh b/lily/include/music-function.hh
new file mode 100644
index 0000000000..cfc923f720
--- /dev/null
+++ b/lily/include/music-function.hh
@@ -0,0 +1,20 @@
+/* 
+  music-head.hh -- declare music_function
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  
+*/
+
+#ifndef MUSIC_FUNCTION_HH
+#define MUSIC_FUNCTION_HH
+
+#include "lily-guile.hh"
+
+SCM ly_make_music_function (SCM, SCM);
+SCM get_music_function_transform (SCM);
+bool is_music_function (SCM);
+
+#endif /* MUSIC_FUNCTION_HH */
+
diff --git a/lily/include/music-head.hh b/lily/include/music-head.hh
deleted file mode 100644
index b010c2278b..0000000000
--- a/lily/include/music-head.hh
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 
-  music-head.hh -- declare Music_head
-  
-  source file of the GNU LilyPond music typesetter
-  
-  (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
-  
-*/
-
-#ifndef MUSIC_HEAD_HH
-#define MUSIC_HEAD_HH
-
-#include "lily-guile.hh"
-
-SCM ly_make_music_head (SCM, SCM);
-SCM get_music_head_transform (SCM);
-bool is_music_head (SCM);
-
-#endif /* MUSIC_HEAD_HH */
-
diff --git a/lily/lexer.ll b/lily/lexer.ll
index 506c047dbf..aefd759995 100644
--- a/lily/lexer.ll
+++ b/lily/lexer.ll
@@ -32,7 +32,7 @@
 
 #include <iostream>
 using namespace std;
-#include "music-head.hh"
+#include "music-function.hh"
 #include "source-file.hh"
 #include "parse-scm.hh"
 #include "lily-guile.hh"
@@ -699,10 +699,11 @@ My_lily_lexer::scan_escaped_word (String str)
 		return l;
 	}
 	SCM sid = lookup_identifier (str);
-	if (is_music_head (sid))
+	if (is_music_function (sid))
 	{
-		yylval.scm = get_music_head_transform (sid); 
-		return music_head_type (yylval.scm);
+		yylval.scm = get_music_function_transform (sid);
+		
+		return music_function_type (yylval.scm);
 	}
 
 	if (sid != SCM_UNDEFINED)
@@ -889,31 +890,35 @@ lookup_markup_command (String s)
 
 
 int
-music_head_type (SCM func)
+music_function_type (SCM func)
 {
 	SCM type= scm_object_property (func, ly_symbol2scm ("music-head-signature-keyword"));
 	if (type == ly_symbol2scm ("scm"))
 	{
-		return MUSIC_HEAD_SCM;
+		return MUSIC_FUNCTION_SCM;
 	}
 	else if (type == ly_symbol2scm ("music"))
 	{
-		return MUSIC_HEAD_MUSIC;
+		return MUSIC_FUNCTION_MUSIC;
 	}
 	else if (type == ly_symbol2scm ("scm-music"))
 	{
-		return MUSIC_HEAD_SCM_MUSIC;
+		return MUSIC_FUNCTION_SCM_MUSIC;
+	}
+	else if (type == ly_symbol2scm ("music-music"))
+	{
+		return MUSIC_FUNCTION_MUSIC_MUSIC;
 	}
 	else if (type == ly_symbol2scm ("scm-music-music"))
 	{
-		return MUSIC_HEAD_SCM_MUSIC_MUSIC;
+		return MUSIC_FUNCTION_SCM_MUSIC_MUSIC;
 	}
 	else if (type == ly_symbol2scm ("scm-scm-music"))
 	{
-		return MUSIC_HEAD_SCM_SCM_MUSIC;
+		return MUSIC_FUNCTION_SCM_SCM_MUSIC;
 	}
 	else
 		assert (false);
 
-	return MUSIC_HEAD_SCM_MUSIC_MUSIC;
+	return MUSIC_FUNCTION_SCM_MUSIC_MUSIC;
 }
diff --git a/lily/music-wrapper.cc b/lily/music-wrapper.cc
index b13d7fac60..3eac65aec6 100644
--- a/lily/music-wrapper.cc
+++ b/lily/music-wrapper.cc
@@ -8,9 +8,8 @@
  */
 
 
-#include "music-wrapper.hh"
-
 
+#include "music-wrapper.hh"
 
 
 Music_wrapper::Music_wrapper ()
diff --git a/lily/parser.yy b/lily/parser.yy
index 14d509f027..898c2403cd 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -359,19 +359,19 @@ or
 %token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
 %token <scm> MARKUP_HEAD_SCM0_SCM1_MARKUP2
 
-%token <scm> MUSIC_HEAD_SCM 
-%token <scm> MUSIC_HEAD_MUSIC 
-%token <scm> MUSIC_HEAD_SCM_MUSIC 
-%token <scm> MUSIC_HEAD_MUSIC_MUSIC 
-%token <scm> MUSIC_HEAD_SCM_SCM_MUSIC 
-%token <scm> MUSIC_HEAD_SCM_MUSIC_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM 
+%token <scm> MUSIC_FUNCTION_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_MUSIC 
+%token <scm> MUSIC_FUNCTION_MUSIC_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_SCM_MUSIC 
+%token <scm> MUSIC_FUNCTION_SCM_MUSIC_MUSIC 
 
 %token <scm> MARKUP_IDENTIFIER MARKUP_HEAD_LIST0
 %type <scm> markup markup_line markup_list  markup_list_body full_markup
 
 %type <book>	book_block book_body
 %type <i>	exclamations questions dots optional_rest
-%type <i>  	 bass_mod
+%type <i>  	bass_mod
 %type <scm> 	grace_head
 %type <scm> 	oct_check
 %type <scm> 	context_mod_list
@@ -385,6 +385,7 @@ or
 %type <music>	toplevel_music
 %type <music>	simple_element event_chord command_element
 %type <music>	Composite_music Simple_music Prefix_composite_music Generic_prefix_music
+%type <scm>  	Generic_prefix_music_scm 
 %type <music>	Grouped_music_list
 %type <music>	Repeated_music
 %type <scm>     Alternative_music
@@ -953,22 +954,78 @@ Grouped_music_list:
 	| Sequential_music		{ $$ = $1; }
 	;
 
+Generic_prefix_music_scm:
+	MUSIC_FUNCTION_SCM {
+		THIS->push_spot ();
+	} embedded_scm {
+		$$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3);
+	}
+	| MUSIC_FUNCTION_MUSIC {
+		THIS->push_spot (); 
+	} Music {
+		$$ = scm_list_3 ($1, make_input (THIS->pop_spot ()), $3->self_scm ());
+		scm_gc_unprotect_object ($3->self_scm ());
+	}
+	| MUSIC_FUNCTION_SCM_MUSIC {
+		THIS->push_spot (); 
+	}  embedded_scm Music {
+		$$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3, $4->self_scm ());
+		scm_gc_unprotect_object ($4->self_scm ());
+	}
+	| MUSIC_FUNCTION_MUSIC_MUSIC {
+		THIS->push_spot (); 
+	}  Music  Music {
+		$$ = scm_list_4 ($1, make_input (THIS->pop_spot ()), $3->self_scm (), $4->self_scm ());
+		scm_gc_unprotect_object ($3->self_scm ());
+		scm_gc_unprotect_object ($4->self_scm ());
+	}
+	| MUSIC_FUNCTION_SCM_MUSIC_MUSIC {
+		THIS->push_spot (); 
+	} embedded_scm Music Music {
+		$$ = scm_list_5 ($1, make_input (THIS->pop_spot ()),
+			$3, $4->self_scm (), $5->self_scm ());
+		scm_gc_unprotect_object ($5->self_scm ());
+		scm_gc_unprotect_object ($4->self_scm ());
+	}
+	;
+
 Generic_prefix_music:
-	MUSIC_HEAD_SCM { THIS->push_spot (); } embedded_scm {
-		SCM m = scm_call_2 ($1, make_input (THIS->pop_spot ()),
-			$3);
+	Generic_prefix_music_scm {
+		SCM func = ly_car ($1);
+		Input *loc = unsmob_input (ly_cadr ($1));
+		SCM args = ly_cddr ($1);
+		SCM sig = scm_object_property (func, ly_symbol2scm ("music-head-signature"));
+		int k = 0;
+		bool ok  = true; 
+		for (SCM s = sig, t = args;
+			ok && ly_c_pair_p (s) && ly_c_pair_p (t);
+			s = ly_cdr (s), t = ly_cdr (t)) {
+			k++;
+			if (scm_call_1 (ly_car (s), ly_car (t)) != SCM_BOOL_T)
+			{
+				loc->error (_f ("Argument %d failed typecheck", k));
+				THIS->error_level_ = 1;
+				ok = false;
+			}
+		}
+		SCM m = SCM_EOL;
+		if (ok)
+			m = scm_apply_0 (func, ly_cdr  ($1));
 		if (unsmob_music (m))
-		{	$$ = unsmob_music (m);
+			{
+			$$ = unsmob_music (m);
 			scm_gc_protect_object (m);
-		}
+			}
 		else
-		{
-			THIS->parser_error ("MUSIC_HEAD should return Music");
-			$$ = MY_MAKE_MUSIC("Music");
-		}
+			{
+			loc->error (_ ("Music head function should return Music object.")); 
+			$$ = MY_MAKE_MUSIC ("Music");
+			}
+
 	}
 	;
 
+
 Prefix_composite_music:
 	Generic_prefix_music {
 		$$ = $1;
-- 
2.39.5