SCM sid = lookup_identifier (str);
if (is_music_function (sid))
{
- int funtype = MUSIC_FUNCTION;
+ int funtype = SCM_FUNCTION;
yylval.scm = get_music_function_transform (sid);
SCM s = scm_object_property (yylval.scm, ly_symbol2scm ("music-function-signature"));
- if (scm_is_eq (scm_car (s), ly_lily_module_constant ("scheme-function")))
+ SCM cs = scm_car (s);
+
+ if (scm_is_eq (cs, ly_lily_module_constant ("ly:music?")))
+ funtype = MUSIC_FUNCTION;
+ else if (ly_is_procedure (cs))
funtype = SCM_FUNCTION;
-
+ else programming_error ("Bad syntax function predicate");
+
push_extra_token (EXPECT_NO_MORE_ARGS);
for (s = scm_cdr (s); scm_is_pair (s); s = scm_cdr (s))
{
- SCM cs = scm_car (s);
+ cs = scm_car (s);
if (cs == ly_music_p_proc)
push_extra_token (EXPECT_MUSIC);
return LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("void-music"), scm_list_2 (parser->self_scm (), make_input (loc)));
}
- SCM syntax_args = scm_list_4 (parser->self_scm (), make_input (loc), func, args);
- return LOWLEVEL_MAKE_SYNTAX (scm_car (sig), syntax_args);
+ SCM syntax_args = scm_list_5 (parser->self_scm (), make_input (loc), scm_car (sig), func, args);
+ return LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant ("music-function"), syntax_args);
}
bool
(doc (procedure-documentation func))
(sign (object-property func 'music-function-signature))
(type-names (map type-name sign))
-
(signature-str
(string-join
(map (lambda (x) (format #f "@var{~a} (~a)"
(car x)
(cadr x)))
- (zip arg-names type-names)))))
+ (zip arg-names (cdr type-names))))))
(format #f
- "@item @code{~a}~a~a
+ "@item @code{~a} (~a) ~a~a
@funindex ~a
~a
"
- name-sym (if (equal? "" signature-str) "" " - ") signature-str
+ name-sym (car type-names)
+ (if (equal? "" signature-str) "" " - ") signature-str
name-sym
- (if doc doc "(undocumented; fixme)"))))
+ (or doc "(undocumented; fixme)"))))
(define (document-object obj-pair)
(set! (ly:music-property m 'origin) location)
m)))
-;; Scheme function: Apply function, return value can be anything
-(define-ly-syntax (scheme-function parser loc fun args)
- (apply fun parser loc args))
-
;; Music function: Apply function and check return value.
-(define-ly-syntax-loc (music-function parser loc fun args)
+(define-ly-syntax-loc (music-function parser loc pred fun args)
(let ((m (apply fun parser loc args)))
- (if (ly:music? m)
+ (if (pred m)
m
- (begin
- (ly:parser-error parser (_ "Music head function must return Music object") loc)
- (make-music 'Music)))))
+ (cond ((eq? pred ly:music?)
+ (ly:parser-error parser (_ "Music syntax function must return Music object") loc)
+ (make-music 'Music))
+ (else
+ (ly:parser-error parser
+ (format #f (_ "Scheme function must return ~a object") (type-name pred))
+ loc)
+ #f)))))
(define-ly-syntax-simple (void-music)
(make-music 'Music))
music
(ly:music-deep-copy ,stop))))))
-(defmacro-public define-music-function (args signature . body)
+(defmacro-public define-syntax-function (type args signature . body)
"Helper macro for `ly:make-music-function'.
Syntax:
- (define-music-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
+ (define-syntax-function (result-type? parser location arg1 arg2 ...) (result-type? arg1-type? arg2-type? ...)
...function body...)
"
-(if (and (pair? body) (pair? (car body)) (eqv? '_i (caar body)))
+ (if (and (pair? body) (pair? (car body)) (eqv? '_i (caar body)))
;; When the music function definition contains a i10n doc string,
;; (_i "doc string"), keep the literal string only
(let ((docstring (cadar body))
(body (cdr body)))
- `(ly:make-music-function (list music-function ,@signature)
+ `(ly:make-music-function (list ,type ,@signature)
(lambda (,@args)
,docstring
,@body)))
- `(ly:make-music-function (list music-function ,@signature)
+ `(ly:make-music-function (list ,type ,@signature)
(lambda (,@args)
,@body))))
-(defmacro-public define-scheme-function (args signature . body)
+(defmacro-public define-music-function rest
+ "Helper macro for `ly:make-music-function'.
+Syntax:
+ (define-music-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
+ ...function body...)
+"
+ `(define-syntax-function ly:music? ,@rest))
+
+
+(defmacro-public define-scheme-function rest
"Helper macro for `ly:make-music-function'.
Syntax:
(define-scheme-function (parser location arg1 arg2 ...) (arg1-type? arg2-type? ...)
...function body...)
"
-(if (and (pair? body) (pair? (car body)) (eqv? '_i (caar body)))
- ;; When the music function definition contains a i10n doc string,
- ;; (_i "doc string"), keep the literal string only
- (let ((docstring (cadar body))
- (body (cdr body)))
- `(ly:make-music-function (list scheme-function ,@signature)
- (lambda (,@args)
- ,docstring
- ,@body)))
- `(ly:make-music-function (list scheme-function ,@signature)
- (lambda (,@args)
- ,@body))))
+ `(define-syntax-function ly:scheme? ,@rest))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;