Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 23:35, David Kastrup a écrit :

Properties will be coded a lot in Scheme.  So the interface needs to map
naturally to Scheme programming.



Well, the C++ and Scheme interfaces can feel different and idiomatic
in their respective languages as long as they share the same
underlying implementation.

In the same vein, although Guile has scm_dynamic_wind (), the
recommended C interface is scm_dynwind_begin () / scm_dynwind_end ()
because that is more scalable in C code.




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread David Kastrup
Jean Abou Samra  writes:

> Le 21/04/2022 à 13:10, Dan Eble a écrit :
>> That is probably mostly due to your early remark that your
>> control-flow options are limited in the case of a with_fluid wrapper
>> taking a lambda. (It definitely steered my answer.)
>
>
> Well, I find it better if it doesn't require reworking the control
> flow logic to introduce assumptions in existing code. Also, that
> should facilitate the refactoring of unpure/pure containers into
> assumptions.

Properties will be coded a lot in Scheme.  So the interface needs to map
naturally to Scheme programming.

-- 
David Kastrup



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 13:10, Dan Eble a écrit :
That is probably mostly due to your early remark that your 
control-flow options are limited in the case of a with_fluid wrapper 
taking a lambda. (It definitely steered my answer.)



Well, I find it better if it doesn't require reworking the control
flow logic to introduce assumptions in existing code. Also, that
should facilitate the refactoring of unpure/pure containers into 
assumptions.





Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 12:58, David Kastrup a écrit :

My personal take on this would move the magic out of the normal reach of
users.  You get (*start-column*) and (*end-column*) which you can use
for accessing the respective fluids but the function *start-column* does
not merely access %start-column but it also registers the associated
impurity for the sake of caching.



Absolutely, I don't want to make the fluids accessible to
anything outside of the property infrastructure. *start-column*
(or whatever name) is an Assumption object. Assumption is
a smob type defining a call () smob procedure. That way, you
can have

(*start-column*)

and

(under-assumptions ((*start-column* 0))
  ...)

and both of these use the fluid as well as other internal members
of the assumption without ever making them accessible. For the
latter, the under-assumptions macro invocation translates to

(ly:run-under-assumption *start-column* 0 (lambda () ...))

which makes the interface completely opaque/encapsulated.




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 11:18, Han-Wen Nienhuys a écrit :

OK. I'm curious to see how that turns out.



I am too :-)

I've been intermittently working on this project for more than
6 months now. When I do an experimental refactoring, I make
a new branch from the current one to avoid losing the previous work.
Currently I am working in a branch called 'purity5' ...



Does every call to
get_property() will have to check the fluid as well to see if it
should cache the computed value?




Yes. I'm trying to make it such that this check is fast, because
get_property without purity at all is the frequent case.



How does the caching framework know if the computation depends on the
assumption?




In my current design, Output_def gains a new member, which is a
stack (SCM list). Each element of the stack corresponds to a
property callback that is currently being made. The element is
a list of assumptions that have been used for this call. Suppose,
for example, that you have the call chain

VerticalAxisGroup.adjacent-pure-heights
[introduces *prebreak-estimate*, *prebreak-estimate-start*, 
*prebreak-estimate-end*]

-> PaperColumn.Y-extent
-> NoteColumn.Y-extent
-> Stem.Y-extent

Each get_property call pushes a frame on the Output_def's stack.
During the Stem.Y-extent callback, the stack looks like

(() ;; Stem.Y-extent
 () ;; NoteColumn.Y-extent
 () ;; PaperColumn.Y-extent
 () ;; VerticalAxisGroup.adjacent-pure-heights
 ...)


Moreover, when the *prebreak-estimate* assumption is introduced,
it records the state of the stack. So *prebreak-estimate* remembers
the SCM sublist that corresponds to the part

(() ;; VerticalAxisGroup.adjacent-pure-heights
 ...)

(Equivalently, it could also remember the stack's depth.)

Now, Stem.Y-extent accesses *prebreak-estimate*. This records
in the stack that callbacks inside the scope where the assumption
has been introduced need to get special caching. More precisely,
the stack is walked until the sublist recorded by
*prebreak-estimate* is found. This makes it look like


((#) ;; Stem.Y-extent
 (#) ;; NoteColumn.Y-extent
 (#) ;; PaperColumn.Y-extent
 () ;; VerticalAxisGroup.adjacent-pure-heights
 ...)


At the end of the Stem.Y-extent get_property () call,
the top frame is popped off and checked. If it's '(), the
property can be cached normally. If it's a 1-element list
containing *prebreak-estimate*, it receives caching with
a prebreak value and a postbreak value. Anything else
leads to no caching at all. (Except if benchmarks tell that
it brings a performance advantage to cache according to
(start, end) in a hash table.)





Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Dan Eble
On Apr 21, 2022, at 06:54, Jean Abou Samra  wrote:
> 
> Le 21/04/2022 à 12:47, David Kastrup a écrit :
>> So what one would want is a C++ wrapper working with functionals? 
...
> So this needs an interface that is easier to use, whether it uses
> RAII or functionals or something else. Current talks in this thread
> favor the RAII approach.

That is probably mostly due to your early remark that your control-flow options 
are limited in the case of a with_fluid wrapper taking a lambda.  (It 
definitely steered my answer.)
— 
Dan




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread David Kastrup
Jean Abou Samra  writes:

> Le 21/04/2022 à 10:38, Han-Wen Nienhuys a écrit :
>> On Thu, Apr 21, 2022 at 12:04 AM Jean Abou Samra  wrote:
>>> I am working on code that pervasively utilizes Guile fluids. They should
>>> be set in dynamic scopes.
>> That sounds scary. Care to tell more?
>
> What is scary about it exactly?
>
> I am trying to reimplement purity in terms of fluids, so the set of
> parameters is not hardcoded to 'start, end' and all the code doesn't
> have to be littered with functions working both as pure and impure and
> forwarding start/end to the property callbacks they
> cause.

Good.

> Essentially, this should look like {   Dynwind_context dwc;  
> dwc->make_assumption (Lily::prebreak_estimate, SCM_BOOL_T);  
> ... get_property (grob, "property") ... } or in Scheme:
> (under-assumptions ((*prebreak-estimate* #t))   ...) and by virtue of
> the dynamic context, the callback that computes the grob property
> understands that it should do pure estimates.

My personal take on this would move the magic out of the normal reach of
users.  You get (*start-column*) and (*end-column*) which you can use
for accessing the respective fluids but the function *start-column* does
not merely access %start-column but it also registers the associated
impurity for the sake of caching.

This also helps by not registering impurities that don't arise for a
particular grob (things like breakpoint-depending accidentals
comparatively rarely rise to the level of actual relevance but get
everything dealt with as impure, with the associated costs, all the
time).

> I haven't gotten as far as a working proof of concept, but I expect a
> speedup. This is essentially a remix of an idea from David:
> https://lists.gnu.org/archive/html/lilypond-devel/2015-05/msg00397.html

I probably repeat myself...

-- 
David Kastrup



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 12:47, David Kastrup a écrit :
So what one would want is a C++ wrapper working with functionals? 



My criterion is rather convenience. scm_c_with_fluid could
be convenient if I could use it with a lambda. However, I cannot,
I'd need to define a separate function every time, taking void *
and casting that to some struct where needed local variables
are stored. For repeated use, that is a nuisance.

So this needs an interface that is easier to use, whether it uses
RAII or functionals or something else. Current talks in this thread
favor the RAII approach.




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Luca Fascione
I wonder if you can 'chain' them:

Dynwind_context dwc2(dwc);

(you can at a minimum 'pause' dwc so to emit a runtime message that the
"wrong" thing is happening, but I guess you could hand yourself to your
parent and do more sophisticated shenanigans too... I must say I loathe
this stateful stuff though)

L

On Thu, Apr 21, 2022 at 12:23 PM Dan Eble  wrote:

> On Apr 21, 2022, at 02:55, Luca Fascione  wrote:
> >
> > I'd think you can up this by one, and get a cleaner looking piece of code
> > if you implement scm_dynwind_fluid() as a forwarded method on your
> context:
> ...
> >  dwc.fluid (fluid2, value2);
>
> Here's something that does bother me.  That reads as if dwc holds state
> affecting the outcome, which is untrue.
>
> {
>   Dynwind_context dwc;
>   // . . .
>
>   {
> Dynwind_context dwc2;
> // . . .
> dwc.free (p);  // not what it seems
> // . . .
>   }
> }
>
> The scm_ functions operate implicitly on the current context.  Dressing
> them differently would be confusing.
> —
> Dan
>
>

-- 
Luca Fascione
Distinguished Engineer - Ray Tracing - NVIDIA


Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread David Kastrup
Jean Abou Samra  writes:

>> Le 21/04/2022 11:05, David Kastrup  a écrit :
>> Just for the record, your usage would not fit with the existing
>> lily/include/fluid.hh ,
>
>
> The existing code in fluid.hh is concerned with retrieving
> fluids. I'm asking about setting them. Whether the new code
> can go in fluid.hh is a question, but it is new code.
>
>
>> and scm_c_with_fluid does not suffice?
>
>
> It would suffice, but it does not work with C++ lambdas,
> which makes it inconvenient.

So what one would want is a C++ wrapper working with functionals?

-- 
David Kastrup



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Dan Eble
On Apr 21, 2022, at 02:55, Luca Fascione  wrote:
> 
> I'd think you can up this by one, and get a cleaner looking piece of code
> if you implement scm_dynwind_fluid() as a forwarded method on your context:
...
>  dwc.fluid (fluid2, value2);

Here's something that does bother me.  That reads as if dwc holds state 
affecting the outcome, which is untrue.

{
  Dynwind_context dwc;
  // . . .

  {
Dynwind_context dwc2;
// . . .
dwc.free (p);  // not what it seems
// . . .
  }
}

The scm_ functions operate implicitly on the current context.  Dressing them 
differently would be confusing.
— 
Dan




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Not sure why my message got mangled? Resending, properly formatted.


Le 21/04/2022 à 10:51, Jean Abou Samra a écrit :

Le 21/04/2022 à 10:38, Han-Wen Nienhuys a écrit :
On Thu, Apr 21, 2022 at 12:04 AM Jean Abou Samra  
wrote:
I am working on code that pervasively utilizes Guile fluids. They 
should

be set in dynamic scopes.

That sounds scary. Care to tell more?


What is scary about it exactly?




I am trying to reimplement purity in terms of fluids, so the set of
parameters is not hardcoded to 'start, end' and all the code doesn't
have to be littered with functions working both as pure and impure and
forwarding start/end to the property callbacks they
cause. Essentially, this should look like


{
  Dynwind_context dwc;
  dwc->make_assumption (Lily::prebreak_estimate, SCM_BOOL_T);
  ... get_property (grob, "property") ...
}

or in Scheme:

(under-assumptions ((*prebreak-estimate* #t))
  ...)

and by virtue of the dynamic context, the callback that computes the
grob property understands that it should do pure estimates. The
property then gets cached if it doesn't depend on assumptions, or if
it only depends on *prebreak-estimate* (in that case with two cached
value, prebreak and postbreak), but not if the callback uses
*prebreak-estimate-start* or *prebreak-estimate-end*. I'll have to
experiment with caching strategies, but this is the current idea.

The advantage is that 95% of code that needs to interact with purity
(via ly:make-unpure-pure-container, get_maybe_pure_property, etc.) no
longer needs to do so. Purity becomes a very localized thing and no
longer pervades the code base. It can also be worked on more easily;
my work on https://gitlab.com/lilypond/lilypond/-/merge_requests/744
involves introducing pure widths, and I don't want to add
maybe_pure_x_extent and change hundreds of callbacks so they do
maybe_pure_x_extent instead of extent ( X_AXIS). There is the same
need in order to properly implement functionality demonstrated in a
recent -user thread
https://lists.gnu.org/archive/html/lilypond-user/2022-04/msg00062.html
where LyricText.X-offset needs a pure/unpure distinction in order to
avoid after-line-breaking.

Also, since whether callbacks access start and end is now known, pure
properties that depend on whether the call is pure or not but not on
start and end (namely the vast majority of them) can start getting
cached. Right now, we use a trick to cache item pure heights, assuming
that Y-extent/Y-offset does not depend on start/end for items
(Item::pure_y_extent). This can then be done for spanners as well. I
haven't gotten as far as a working proof of concept, but I expect a
speedup.


This is essentially a remix of an idea from David:
https://lists.gnu.org/archive/html/lilypond-devel/2015-05/msg00397.html

Jean



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Han-Wen Nienhuys
On Thu, Apr 21, 2022 at 10:53 AM Jean Abou Samra  wrote:
> >> On Thu, Apr 21, 2022 at 12:04 AM Jean Abou Samra 
> >> wrote:
> >>> I am working on code that pervasively utilizes Guile fluids. They
> >>> should
> >>> be set in dynamic scopes.
> >> That sounds scary. Care to tell more?
> >
> > What is scary about it exactly?

I am worried about introducing problems associated with dynamic
scoping into the code base; the (un)pure stuff is already there
though, so it probably is not going to create new problems, though.

> I am trying to reimplement purity in terms of fluids, so the set of
> parameters is not hardcoded to 'start, end' and all the code doesn't
> have to be littered with functions working both as pure and impure and
> forwarding start/end to the property callbacks they
> cause. Essentially, this should look like
>
>
> {
>Dynwind_context dwc;
>dwc->make_assumption (Lily::prebreak_estimate, SCM_BOOL_T);
>... get_property (grob, "property") ...
> }
>
> or in Scheme:
>
> (under-assumptions ((*prebreak-estimate* #t))
>...)
>
> and by virtue of the dynamic context, the callback that computes the
> grob property understands that it should do pure estimates. The
> property then gets cached if it doesn't depend on assumptions, or if
> it only depends on *prebreak-estimate* (in that case with two cached
> value, prebreak and postbreak), but not if the callback uses
> *prebreak-estimate-start* or *prebreak-estimate-end*. I'll have to
> experiment with caching strategies, but this is the current idea.

OK. I'm curious to see how that turns out.  Does every call to
get_property() will have to check the fluid as well to see if it
should cache the computed value?
How does the caching framework know if the computation depends on the
assumption?

-- 
Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra
> Le 21/04/2022 11:05, David Kastrup  a écrit :
> Just for the record, your usage would not fit with the existing
> lily/include/fluid.hh ,


The existing code in fluid.hh is concerned with retrieving
fluids. I'm asking about setting them. Whether the new code
can go in fluid.hh is a question, but it is new code.


> and scm_c_with_fluid does not suffice?


It would suffice, but it does not work with C++ lambdas,
which makes it inconvenient.



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread David Kastrup
Jean Abou Samra  writes:

> Hi,
>
> It's me again ...
>
> I am working on code that pervasively utilizes Guile fluids. They should
> be set in dynamic scopes. In C++, usage of the Guile API looks like this:
>
>   scm_dynwind_begin ();
>   scm_dynwind_fluid (fluid, value);
>   ...
>   scm_dynwind_end ();

Just for the record, your usage would not fit with the existing
lily/include/fluid.hh , and scm_c_with_fluid does not suffice?

-- 
David Kastrup



Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Hi Luca,

Thanks for your insights! Much appreciated.


Le 21/04/2022 à 08:55, Luca Fascione a écrit :
I'd think you can up this by one, and get a cleaner looking piece of 
code if you implement scm_dynwind_fluid() as a forwarded method on 
your context:


{

  Dynwind_context dwc; // overloaded so you can call 
dwc(SCM_F_DYNWIND_REWINDABLE);

  dwc.fluid (fluid1, value1);
  dwc.fluid (fluid2, value2);

  dwc.unwind_handler(handler, data, flags); // overloaded for the SCM 
vs void* cases,
  dwc.rewind_handler(handler, data, flags); // overloaded for the SCM 
vs void* cases,
                                            // maybe it ought to check 
if the constructor was DYNWIND_REWINDABLE and complain
                                            // (only in debug builds?) 
if things are not set up right

  dwc.free(something);

}




Making a method of the context is an attractive proposal, as
it prevents from forgetting to introduce a context.

Actually, the specific use case is much narrower than this particular
set of methods: I don't need C++ wrappers for all dynwind-related Guile
APIs, I just have one need for fluids. The example in the first email was
a straw man for the sake of explanation.



However in all this, I must say I don't understand this passage in manual:

The context is ended either implicitly when a non-local exit
happens, or explicitly with scm_dynwind_end. You must make sure
that a dynwind context is indeed ended properly. If you fail to
call scm_dynwind_end for each scm_dynwind_begin, the behavior is
undefined.


It seems to me the first phrase and the rest slightly contradict each 
other: as I hear it, the first phrase says "either the C side calls 
scm_dynwind_end(), OR a non-local exit happens", whereas the rest 
seems to be saying "the C side _shall_ call scm_dynwind_end". This 
bothers me, because in the second case our C++ is nice and lovely, but 
in the first meaning the destructor of dwc has to somehow figure out 
whether a non-local exit has happened, and avoid calling 
scm_dynwind_end(). And I don't think scm library can cope on its own, 
because these things look to me like they would nest, so making 
scm_dynwind_end() idempotent without some sort of explicit marker on 
the scope seems... hard.


So yes, I'd think RAII is the idiomatic way to go, I would add the 
wrappers because they make the pattern cleaner, but do figure out 
what's up with this last question first, because it could bring it all 
crumbling down.



Let's do a little test:

diff --git a/lily/main.cc b/lily/main.cc
index c98db72e8c..b8e928e29c 100644
--- a/lily/main.cc
+++ b/lily/main.cc
@@ -496,6 +496,21 @@ do_chroot_jail ()
 }
 #endif

+class Dynwind_context
+{
+public:
+  Dynwind_context ()
+  {
+    message ("starting dynwind context");
+    scm_dynwind_begin (static_cast (0));
+  }
+  ~Dynwind_context ()
+  {
+    message ("ending dynwind context");
+    scm_dynwind_end ();
+  }
+};
+
 static void
 main_with_guile (void *, int, char **)
 /*
@@ -505,6 +520,17 @@ main_with_guile (void *, int, char **)
  * to main_with_guile.
  */
 {
+  message ("normal termination:");
+  {
+    Dynwind_context dwc;
+    message ("before normal termination");
+  }
+  message ("termination by exception:");
+  {
+    Dynwind_context dwc;
+    message ("before termination by exception");
+    scm_throw (ly_symbol2scm ("x"), SCM_EOL);
+  }
   /* Engravers use lily.scm contents, so we need to make Guile find it.
  Prepend onto GUILE %load-path.
   %load-path is the symbol Guile searches for .scm files


Running this, I get:

normal termination:
starting dynwind context
before normal termination
ending dynwind context
termination by exception:
starting dynwind context
before termination by exceptionBacktrace:
In ice-9/boot-9.scm:
  1752:10  1 (with-exception-handler _ _ #:unwind? _ # _)
In unknown file:
   0 (apply-smob/0 #)

ERROR: In procedure apply-smob/0:
Throw to key `x' with args `()'.

As you can see, scm_dynwind_end () is not called on the non-local exit.

There are actually two kinds of non-local exits that we are talking about
here: the C++ ones, and the Guile ones. C++ does them via return,
break, continue, C++ exceptions. Guile does them via Guile exceptions
and continuations. When Guile captures a continuation, for example,
it just copies the whole C(++) stack in an object, and reinstating
the continuation simply copies the saved stack data back into the
stack. See the end of
https://www.gnu.org/software/guile/manual/html_node/Continuations.html

Exceptions are kind of a special case of this (except that in Guile 2
and later it looks like they are actually implemented with
delimited/composable continuations, aka prompts, rather than traditional
continuations, but I haven't looked at that too closely).

Thus, C++ RAII stuff ensures destructors get called upon C++ non-local
exits, but not Guile ones.

So the meaning of the docs here is that you must insert a call to

Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 10:38, Han-Wen Nienhuys a écrit :

On Thu, Apr 21, 2022 at 12:04 AM Jean Abou Samra  wrote:

I am working on code that pervasively utilizes Guile fluids. They should
be set in dynamic scopes.

That sounds scary. Care to tell more?


What is scary about it exactly?

I am trying to reimplement purity in terms of fluids, so the set of 
parameters is not hardcoded to 'start, end' and all the code doesn't 
have to be littered with functions working both as pure and impure and 
forwarding start/end to the property callbacks they cause. Essentially, 
this should look like {   Dynwind_context dwc;   dwc->make_assumption 
(Lily::prebreak_estimate, SCM_BOOL_T);   ... get_property (grob, 
"property") ... } or in Scheme: (under-assumptions ((*prebreak-estimate* 
#t))   ...) and by virtue of the dynamic context, the callback that 
computes the grob property understands that it should do pure estimates. 
The property then gets cached if it doesn't depend on assumptions, or if 
it only depends on *prebreak-estimate* (in that case with two cached 
value, prebreak and postbreak), but not if the callback uses 
*prebreak-estimate-start* or *prebreak-estimate-end*. I'll have to 
experiment with caching strategies, but this is the current idea. The 
advantage is that 95% of code that needs to interact with purity (via 
ly:make-unpure-pure-container, get_maybe_pure_property, etc.) no longer 
needs to do so. Purity becomes a very localized thing and no longer 
pervades the code base. It can also be worked on more easily; my work on 
https://gitlab.com/lilypond/lilypond/-/merge_requests/744 involves 
introducing pure widths, and I don't want to add maybe_pure_x_extent and 
change hundreds of callbacks so they do maybe_pure_x_extent instead of 
extent ( X_AXIS). There is the same need in order to properly implement 
functionality demonstrated in a recent -user thread 
https://lists.gnu.org/archive/html/lilypond-user/2022-04/msg00062.html 
where LyricText.X-offset needs a pure/unpure distinction in order to 
avoid after-line-breaking. Also, since whether callbacks access start 
and end is now known, pure properties that depend on whether the call is 
pure or not but not on start and end (namely the vast majority of them) 
can start getting cached. Right now, we use a trick to cache item pure 
heights, assuming that Y-extent/Y-offset does not depend on start/end 
for items (Item::pure_y_extent). This can then be done for spanners as 
well. I haven't gotten as far as a working proof of concept, but I 
expect a speedup. This is essentially a remix of an idea from David: 
https://lists.gnu.org/archive/html/lilypond-devel/2015-05/msg00397.html




Jean




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Han-Wen Nienhuys
On Thu, Apr 21, 2022 at 12:04 AM Jean Abou Samra  wrote:
> I am working on code that pervasively utilizes Guile fluids. They should
> be set in dynamic scopes.

That sounds scary. Care to tell more?

-- 
Han-Wen Nienhuys - hanw...@gmail.com - http://www.xs4all.nl/~hanwen



Re: Missing dependencies in doc build after addition of PDF syntax highlighting?

2022-04-21 Thread Jonas Hahnfeld via Discussions on LilyPond development
On Thu, 2022-04-21 at 09:13 +0200, Jean Abou Samra wrote:
> Le 21/04/2022 à 08:31, Jonas Hahnfeld a écrit :
> > On Tue, 2022-04-19 at 20:13 +0200, Jean Abou Samra wrote:
> > > Hi,
> > > 
> > > This used to work for me in order to build just one document, as
> > > opposed to building the full documentation:
> > > 
> > > make -j9 CPU_COUNT=9 -C Documentation out=www out-www/en/internals.pdf
> > > 
> > > This is also recommended in the CG.
> > Where? I couldn't find it.
> 
> 
> Here:
> 
> https://lilypond.org/doc/v2.23/Documentation/contributor/generating-documentation#documentation-editor_0027s-edit_002fcompile-cycle
> 
> The third section on that page, "Building a single document", also uses
> 'make out=www out-www/en/contributor.pdf' after 'cd Documentation/'.

This says "to rebuild only 'contributor.pdf'", which should still work
fine in an incremental build, no?

Jonas


signature.asc
Description: This is a digitally signed message part


Re: Missing dependencies in doc build after addition of PDF syntax highlighting?

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 08:31, Jonas Hahnfeld a écrit :

On Tue, 2022-04-19 at 20:13 +0200, Jean Abou Samra wrote:

Hi,

This used to work for me in order to build just one document, as
opposed to building the full documentation:

make -j9 CPU_COUNT=9 -C Documentation out=www out-www/en/internals.pdf

This is also recommended in the CG.

Where? I couldn't find it.



Here:

https://lilypond.org/doc/v2.23/Documentation/contributor/generating-documentation#documentation-editor_0027s-edit_002fcompile-cycle

The third section on that page, "Building a single document", also uses
'make out=www out-www/en/contributor.pdf' after 'cd Documentation/'.




[...]
If I do 'make -j9 CPU_COUNT=9 doc' instead, the start of
the build shows the generation of the missing files:

Making .pl files for lm fonts < afm
Making tex/out-www/lmttb.tfm < pl
Making tex/out-www/lmttbo.tfm < pl
Making tex/out-www/lmttr.tfm < pl
Making tex/out-www/lmttro.tfm < pl
Making .map and .enc files for lm fonts (tex)


Am I doing something wrong (in which case the CG needs updating) or
is the doc build missing some dependencies?

This is totally expected to me, 'make doc' first needs to generate the
fonts, which is done in tex/. Directly descending into a directory can
only work for incremental builds.




The specific way to build a single document doesn't matter all
that much to me. I would just like there to be a way.

Thanks,
Jean




Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Luca Fascione
On Thu, Apr 21, 2022 at 8:12 AM Jean Abou Samra  wrote:

> Le 21/04/2022 à 04:57, Dan Eble a écrit :
> >  {
> >// dwc constructor calls scm_dynwind_begin ()
> >Dynwind_context dwc;
> >scm_dynwind_fluid (fluid1, value1);
> >scm_dynwind_fluid (fluid2, value2);
> >. . .
> >// dwc destructor calls scm_dynwind_end ()
> >  }
>
>
>
> Why not. There is likely just one caller that will need to introduce
> several
> fluids at once, but it is probably clearer this way.
>

I'd think you can up this by one, and get a cleaner looking piece of code
if you implement scm_dynwind_fluid() as a forwarded method on your context:

{

  Dynwind_context dwc; // overloaded so you can call
dwc(SCM_F_DYNWIND_REWINDABLE);
  dwc.fluid (fluid1, value1);
  dwc.fluid (fluid2, value2);

  dwc.unwind_handler(handler, data, flags); // overloaded for the SCM vs
void* cases,
  dwc.rewind_handler(handler, data, flags); // overloaded for the SCM vs
void* cases,
// maybe it ought to check if
the constructor was DYNWIND_REWINDABLE and complain
// (only in debug builds?) if
things are not set up right
  dwc.free(something);

}

However in all this, I must say I don't understand this passage in manual:

The context is ended either implicitly when a non-local exit happens, or
explicitly with scm_dynwind_end. You must make sure that a dynwind context
is indeed ended properly. If you fail to call scm_dynwind_end for each
scm_dynwind_begin, the behavior is undefined.

It seems to me the first phrase and the rest slightly contradict each
other: as I hear it, the first phrase says "either the C side calls
scm_dynwind_end(), OR a non-local exit happens", whereas the rest seems to
be saying "the C side _shall_ call scm_dynwind_end". This bothers me,
because in the second case our C++ is nice and lovely, but in the first
meaning the destructor of dwc has to somehow figure out whether a non-local
exit has happened, and avoid calling scm_dynwind_end(). And I don't think
scm library can cope on its own, because these things look to me like they
would nest, so making scm_dynwind_end() idempotent without some sort of
explicit marker on the scope seems... hard.

So yes, I'd think RAII is the idiomatic way to go, I would add the wrappers
because they make the pattern cleaner, but do figure out what's up with
this last question first, because it could bring it all crumbling down.

HTH
Luca


Re: Missing dependencies in doc build after addition of PDF syntax highlighting?

2022-04-21 Thread Jonas Hahnfeld via Discussions on LilyPond development
On Tue, 2022-04-19 at 20:13 +0200, Jean Abou Samra wrote:
> Hi,
> 
> This used to work for me in order to build just one document, as
> opposed to building the full documentation:
> 
> make -j9 CPU_COUNT=9 -C Documentation out=www out-www/en/internals.pdf
> 
> This is also recommended in the CG.

Where? I couldn't find it.

> [...]
> If I do 'make -j9 CPU_COUNT=9 doc' instead, the start of
> the build shows the generation of the missing files:
> 
> Making .pl files for lm fonts < afm
> Making tex/out-www/lmttb.tfm < pl
> Making tex/out-www/lmttbo.tfm < pl
> Making tex/out-www/lmttr.tfm < pl
> Making tex/out-www/lmttro.tfm < pl
> Making .map and .enc files for lm fonts (tex)
> 
> 
> Am I doing something wrong (in which case the CG needs updating) or
> is the doc build missing some dependencies?

This is totally expected to me, 'make doc' first needs to generate the
fonts, which is done in tex/. Directly descending into a directory can
only work for incremental builds.

Jonas


signature.asc
Description: This is a digitally signed message part


Re: C++ question on wrapper API for setting Guile fluids

2022-04-21 Thread Jean Abou Samra

Le 21/04/2022 à 04:57, Dan Eble a écrit :

On Apr 20, 2022, at 18:04, Jean Abou Samra  wrote:

Calls to scm_dynwind_begin () and scm_dynwind_end () must be
paired correctly. Obviously, if '...' contains statements
causing non-local control flow like return, break, continue,
and such, it is easy to miss a scm_dynwind_end (). I read
that you can avoid that using RAII:

Yes.


   {
 // Constructor does scm_dynwind_begin () and scm_dynwind_fluid ()
 Fluid_setter setter (fluid, value);

Might you want to call scm_dynwind_fluid () more than once?  How about this?

 {
   // dwc constructor calls scm_dynwind_begin ()
   Dynwind_context dwc;
   scm_dynwind_fluid (fluid1, value1);
   scm_dynwind_fluid (fluid2, value2);
   . . .
   // dwc destructor calls scm_dynwind_end ()
 }




Why not. There is likely just one caller that will need to introduce several
fluids at once, but it is probably clearer this way.




What disturbs me slightly with this approach is the variable 'setter',
which will never be used, but must nevertheless be defined in order
for the object not to be thrown away as temporary.

If I understand you, turning the main effect (scm_dynwind_begin) into a side 
effect of the constructor bothers you.  It wouldn't bother me as long as the 
class had a good name.  I can think of two alternatives, but they have their 
own problems.


Does that sound about right? Would this be considered an idiomatic
approach?

Yes.



Thanks!

Jean