2004-05-06 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * ly/music-functions-init.ly (TODO): new file.
+
* lily/parser.yy (Generic_prefix_music_scm): add more
music_function symbols.
+ (Prefix_composite_music): change \apply to music-function
* lily/include/music-function.hh: rename to music-function
+@c -*-texinfo-*-
@node Interfaces for programmers
@appendix Interfaces for programmers
@menu
* Programmer interfaces for input ::
-* Markup programmer interface::
-* Contexts for programmers::
+* Markup programmer interface::
+* Contexts for programmers::
@end menu
@node Programmer interfaces for input
@appendixsec Programmer interfaces for input
@menu
-* Input variables and Scheme::
+* Input variables and Scheme::
* Internal music representation::
+* Extending music syntax::
* Manipulating music expressions::
@end menu
\apply #@var{func} @var{music}
@end example
-A music function is created with @code{ly:make-music-function}.
+A music function is created with @code{ly:make-music-function},
+@example
+ (ly:make-music-function
+@end example
+
+@code{\apply} takes a Scheme function and a Music expression as
+argument. This is encoded in its first argument,
+
+@example
+ (list procedure? ly:music?)
+@end example
+
+The function itself takes another argument, an Input location
+object. That object is used to provide error messages with file names
+and line numbers. The definition is the second argument of
+@code{ly:make-music-function}. The body is function simply calls the
+function
+
+@example
+ (lambda (where func music)
+ (func music))
+@end example
+
+The above Scheme code only defines the functionality. The tag
+@code{\apply} is selected by defining
+
+@example
+ apply = #(ly:make-music-function
+ (list procedure? ly:music?)
+ (lambda (where func music)
+ (func music)))
+@end example
+
+Examples of the use of @code{\apply} are in the next section.
@node Manipulating music expressions
@menu
* Markup construction in scheme::
-* Markup command definition::
+* Markup command definition::
@end menu
@node Markup construction in scheme
@menu
-* Context evaluation::
+* Context evaluation::
* Running a function on all layout objects::
@end menu
--- /dev/null
+\header
+{
+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-function
+ (list string?)
+ (lambda (where type)
+ (context-spec-music
+ (context-spec-music (make-property-set 'whichBar type) 'Timing)
+ 'Score))
+
+ ))
+
+\score{
+ \notes {
+ d4 \myBar #"|:" d4
+
+ }
+}
+
+++ /dev/null
-\header
-{
-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-function
- (list string?)
- (lambda (where type)
- (context-spec-music
- (context-spec-music (make-property-set 'whichBar type) 'Timing)
- 'Score))
-
- ))
-
-\score{
- \notes {
- d4 \myBar #"|:" d4
-
- }
-}
-
void strip_trailing_white (String&);
void strip_leading_white (String&);
String lyric_fudge (String s);
-int music_head_type (SCM);
+int music_function_type (SCM);
SCM lookup_markup_command (String s);
bool is_valid_version (String s);
int
music_function_type (SCM func)
{
- SCM type= scm_object_property (func, ly_symbol2scm ("music-head-signature-keyword"));
+ SCM type= scm_object_property (func, ly_symbol2scm ("music-function-signature-keyword"));
if (type == ly_symbol2scm ("scm"))
{
return MUSIC_FUNCTION_SCM;
return MUSIC_FUNCTION_SCM_SCM_MUSIC;
}
else
- assert (false);
+ {
+ /* TODO: print location */
+ error ("Can not find sigature for music function.");
+ }
- return MUSIC_FUNCTION_SCM_MUSIC_MUSIC;
+ return MUSIC_FUNCTION_SCM;
}
--- /dev/null
+/*
+ music-function.cc -- implement music_function
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+#include "music-function.hh"
+#include "string.hh"
+#include "music.hh"
+
+static scm_t_bits music_function_tag;
+
+/* Print a textual represenation of the smob to a given port. */
+static int
+print_music_function (SCM b, SCM port, scm_print_state *)
+{
+ SCM value = SCM_CELL_OBJECT_1 (b);
+
+ scm_puts ("#<packaged object ", port);
+ scm_write (value, port);
+ scm_puts (">", port);
+
+ /* Non-zero means success. */
+ return 1;
+}
+
+
+LY_DEFINE (ly_make_music_function, "ly:make-music-function", 2, 0, 0,
+ (SCM signature, SCM func),
+ "Make a function to process music, to be used for the "
+ "parser. @code{func} is the function, and @code{signature} describes "
+ "Its arguments. @code{signature} is a list containing either "
+ "@code{ly:music?} predicates or other type predicates.")
+{
+ String str = "";
+ for (SCM s = signature; ly_c_pair_p (s); s = ly_cdr (s))
+ {
+ if (str != "")
+ str += "-";
+
+ if (ly_car (s) == Music_type_p_proc)
+ str += "music";
+ else if (ly_c_procedure_p (ly_car (s)))
+ str += "scm";
+ }
+
+ scm_set_object_property_x (func, ly_symbol2scm ("music-function-signature"),
+ signature);
+
+ scm_set_object_property_x (func, ly_symbol2scm ("music-function-signature-keyword"),
+ ly_symbol2scm (str.to_str0 ()));
+
+ SCM_RETURN_NEWSMOB (music_function_tag, func);
+}
+
+bool
+is_music_function (SCM music_function)
+{
+ return (SCM_NIMP (music_function) && SCM_CELL_TYPE (music_function) == music_function_tag);
+}
+
+
+SCM
+get_music_function_transform (SCM music_function)
+{
+ if (!is_music_function (music_function))
+ return SCM_UNDEFINED;
+
+ return SCM_CELL_OBJECT_1 (music_function);
+}
+
+static void
+init_music_function (void)
+{
+ music_function_tag = scm_make_smob_type ("music-function", 0);
+ scm_set_smob_mark (music_function_tag, scm_markcdr);
+ scm_set_smob_print (music_function_tag, print_music_function);
+}
+ADD_SCM_INIT_FUNC (music_function_tag, init_music_function);
+++ /dev/null
-/*
- music-head.cc -- implement Music_head
-
- source file of the GNU LilyPond music typesetter
-
- (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
-
-*/
-#include "music-head.hh"
-#include "string.hh"
-#include "music.hh"
-
-static scm_t_bits music_head_tag;
-
-/* Print a textual represenation of the smob to a given port. */
-static int
-print_music_head (SCM b, SCM port, scm_print_state *)
-{
- SCM value = SCM_CELL_OBJECT_1 (b);
-
- scm_puts ("#<packaged object ", port);
- scm_write (value, port);
- scm_puts (">", port);
-
- /* Non-zero means success. */
- return 1;
-}
-
-
-LY_DEFINE (ly_make_music_head, "ly:make-music-head", 2, 0, 0,
- (SCM signature, SCM func),
- "Make a function to process music, to be used for the "
- "parser. @code{func} is the function, and @code{signature} describes "
- "Its arguments. @code{signature} is a list containing either "
- "@code{ly:music?} predicates or other type predicates.")
-{
- String str = "";
- for (SCM s = signature; ly_c_pair_p (s); s = ly_cdr (s))
- {
- if (str != "")
- str += "-";
-
- if (ly_car (s) == Music_type_p_proc)
- str += "music";
- else if (ly_c_procedure_p (ly_car (s)))
- str += "scm";
- }
-
- scm_set_object_property_x (func, ly_symbol2scm ("music-head-signature"),
- signature);
-
- scm_set_object_property_x (func, ly_symbol2scm ("music-head-signature-keyword"),
- ly_symbol2scm (str.to_str0 ()));
-
- SCM_RETURN_NEWSMOB (music_head_tag, func);
-}
-
-bool
-is_music_head (SCM music_head)
-{
- return (SCM_NIMP (music_head) && SCM_CELL_TYPE (music_head) == music_head_tag);
-}
-
-
-SCM
-get_music_head_transform (SCM music_head)
-{
- if (!is_music_head (music_head))
- return SCM_UNDEFINED;
-
- return SCM_CELL_OBJECT_1 (music_head);
-}
-
-static void
-init_music_head (void)
-{
- music_head_tag = scm_make_smob_type ("music-head", 0);
- scm_set_smob_mark (music_head_tag, scm_markcdr);
- scm_set_smob_print (music_head_tag, print_music_head);
-}
-ADD_SCM_INIT_FUNC (music_head_tag, init_music_head);
{"addquote", ADDQUOTE},
{"alias", ALIAS},
{"alternative", ALTERNATIVE},
- {"apply", APPLY},
{"applycontext", APPLYCONTEXT},
{"applyoutput", APPLYOUTPUT},
{"appoggiatura", APPOGGIATURA},
%token LYRICSTO
%token ALIAS
%token ALTERNATIVE
-%token APPLY
%token APPLYCONTEXT
%token APPLYOUTPUT
%token AUTOCHANGE
$$->set_property ("element", p->self_scm ());
scm_gc_unprotect_object (p->self_scm ());
}
- | APPLY embedded_scm Music {
- if (!ly_input_procedure_p ($2))
- {
- THIS->parser_error (_ ("\\apply takes function argument"));
- $$ = $3;
- }
- else
- {
- SCM ret = scm_call_1 ($2, $3->self_scm ());
- Music *m = unsmob_music (ret);
- if (!m) {
- THIS->parser_error ("\\apply must return a Music");
- m = MY_MAKE_MUSIC ("Music");
- }
- $$ = m;
- }
- }
| NOTES
{
SCM nn = THIS->lexer_->lookup_identifier ("pitchnames");
longa = #(ly:make-duration -2 0 )
maxima = #(ly:make-duration -3 0)
+\include "music-functions-init.ly"
\include "nederlands.ly" % dutch
\include "drumpitch-init.ly"
\include "chord-modifiers-init.ly"