bug-lilypond
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scheme parameters names lost with Lilypond 2.23.8


From: Stéphane SOPPERA
Subject: Re: Scheme parameters names lost with Lilypond 2.23.8
Date: Sun, 1 May 2022 23:43:09 +0200
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.8.1

Thanks Jean for the detailed answer!

Regarding having custom versions of functions & macros that defines functions & procedures, I would prefer avoiding doing so even though I already do so for macros and classes to attach documentation strings (https://github.com/soppera/lilypond-harmony-rules/blob/d53011cf6c23d8187c1ee4d39847ec645239eaaf/documentation.scm#L23-L43).
The downsides of this approach are:

1. It is easy to forget using them.
2. It will mandates updating the configuration of code editors to take
   into account the new names when doing the syntax coloring and the
   automatic indentation.

I can't use the compilation trick you propose since I am defining several sub-modules (loaded in Lilypond using a root `(use-modules)` after changing the modules `load-path`).

That said this gave me a simpler idea. I can simply run Lilypond with `GUILE_AUTO_COMPILE=1`. I just did that (https://github.com/soppera/lilypond-harmony-rules/blob/d53011cf6c23d8187c1ee4d39847ec645239eaaf/Makefile#L44) and this solve my issue.
On top of that subsequent executions of Lilypond are much faster.

So I think for the time being I'll stick with setting `GUILE_AUTO_COMPILE` in the Make rule that generates my Info file. This is the only use-case where I care about getting the parameter names.

On 2022-05-01 20:53, Jean Abou Samra wrote:
Le 01/05/2022 à 20:29, Stéphane SOPPERA a écrit :
Hi,

While trying to make sure my automatic documentation generation code works with Lilypond 2.23.8 (and especially Guile 2.2) I noticed a bug that may be due to how Lilypond is using Guile 2.2. The current version of my code uses /(p//rocedure-source)/ <https://github.com/soppera/lilypond-harmony-rules/blob/master/generate-doc.scm#L45> to get the names of the parameters of my functions & methods and generate the documentation. I noticed that with Guile 2.2 I always get /#f/ when I call /(//procedure-source)/. But we now have /(program-lambda-list)/ <https://www.gnu.org/software/guile/manual/html_node/Compiled-Procedures.html> that removes the need from parsing the source to get the parameter names.

Thus I tried to use /(program-lambda-list)/ to get the parameters names with Lilypond 2.23.8 (i.e. Guile 2.2) but this fails and instead I get anonymized parameters ("a", "b"... instead of the expected values).

To illustrate the issue let's first see what happens with Lilypond 2.22 (and thus Guile 1.8), compiling:

\version "2.22.0"

#(begin
  (define (f lhs rhs) (+ lhs rhs))

  (display "\nUsing Guile ")
  (display (version))
  (newline)

  (display "source: ")
  (display (procedure-source f))
  (newline))

prints:

GNU LilyPond 2.22.2
Processing `test_2.22.ly'
Parsing...
Using Guile 1.8.7
source: (lambda (lhs rhs) (+ lhs rhs))

(we can't use /(program-lambda-list)/ here since it is not supported by Guile 1.8)

With Lilypond 2.23 (and thus Guile 2.2), compiling:

\version "2.23.8"

#(begin
  (use-modules (system vm program))
  (define (f lhs rhs) (+ lhs rhs))

  (display "Using Guile ")
  (display (version))
  (newline)

  (display "λ-list: ")
  (display (program-lambda-list f))
  (newline)

  (display "source: ")
  (display (procedure-source f))
  (newline))

prints:

GNU LilyPond 2.23.8 (running Guile 2.2)
Processing `test_2.23.ly'
Parsing...Using Guile 2.2.7
λ-list: *(a b)*
source: *#f*

We can see that:

1. We don't have access to the function source anymore (as when using
   Guile 2.2 directly).
2. /(program-lambda-list)/ returns "(a b)" instead of "(lhs rhs)",
   erasing the parameters' names.

To confirm if this is the default behavior of Guile 2.2, I tested this Guile script:

(use-modules (system vm program))
(define (f lhs rhs) (+ lhs rhs))

(display "Using Guile ")
(display (version))
(newline)

(display "λ-list: ")
(display (program-lambda-list f))
(newline)

(display "source: ")
(display (procedure-source f))
(newline)

Running Guile command line tool on this script with the default parameters result in:

Using Guile 2.2.7
λ-list: (lhs rhs)
source: #f

We can see that:

1. Guile 2.2 does not return the source either.
2. Guile 2.2 does return "(lhs rhs)" as expected,  and not "(a b)" as
   Lilypond 2.23.8 is doing.

I dig a bit further into this issue and I can make Guile 2.2 behave like Lilypond by using the flags:

 * --fresh-auto-compile
 * --no-auto-compile

*With those two flags *I indeed get the same output as with Lilypond 2.23.8:

Using Guile 2.2.7
λ-list: (a b)
source: #f

Note that using --fresh-auto-compile is _mandatory_ since without it Guile seems to use previous auto-compilation's output and indeed prints the correct list of parameters.


To summarize the issues:

 * Lilypond 2.23.8 is using Guile 2.2 which does not support
   /(//proceduce-source)/ anymore.
 * But Guile 2.2 offers /(program-lambda-list)/ which can replace the
   use of /(//proceduce-source)/ to get the parameters' names.
 * The issue is that the way Lilypond 2.23.8 uses Guile 2.2 erases the
   parameter names returned by /(program-lambda-list)/, making it
   impossible to use this method either.



Yes, LilyPond uses the evaluator and not the compiler. The
problem with compilation is that it takes time. Most
code snippets within LilyPond source files are very
short and run fast, so compilation is going to dominate
execution. Since Guile 2 is slow at compiling, with the
intent being that you do it ahead of time, we have a performance
issue. It is actually possible that we will move to compiling
anyway, because this might make for better error message.
But it can't be done without careful thought.

Meanwhile, I wouldn't consider this a bug on the LilyPond side,
more like something to report at Guile.

If you need correct signatures, you can call the compiler explicitly:

\version "2.23.9"

#(use-modules (system base compile))
#(define f
   (compile
    '(lambda (a b)
       'x)))

#(use-modules (system vm program))
#(display (program-lambda-list f))
%% This is actually more powerful:
#(use-modules (ice-9 session))
#(display (procedure-arguments f))


Probably most reliably, you can also define a macro that catches
the arguments.

\version "2.23.9"

#(define args-prop (make-object-property))

#(define (find-lvalue syntaks)
   (syntax-case syntaks ()
     ((first . rest)
      (find-lvalue #'first))
     (x
      #'x)))

#(define-syntax define-documented
   (lambda (syntaks)
     (syntax-case syntaks ()
       ((_ target expr)
         #`(begin (define target expr)
                  (set! (args-prop #,(find-lvalue #'target))
                        'target))))))

#(define-documented (f a b c)
   'x)

#(display (f 1 2 3))
#(newline)
#(display (args-prop f))


Best,
Jean


reply via email to

[Prev in Thread] Current Thread [Next in Thread]