Re: Solution for including a file only once

2010-02-12 Thread Karl Hammar
Reinhold Kainhofer:
...
> In my view there are two different kinds of include uses:
> 1) To include package-like .ily files, which define additional functionality. 
> There many utility functions really might/should be in their own namespace, 
> but many definitions (and in particular all \header, \paper or \layout 
> blocks) 
> need to be at toplevel.

I would be interested in conditionally including files with \paper and 
\header blocks, so can with a command line flag get output for 
"choirbook" booklets or plain a4 sheets. The common thing with this 
thread would be the ability to \include thoose blocks.

> 2) ...
...
> I think it should be as easy and straightforward to use to a non-programmer 
> as 
> possible, while allowing more complex use without making easy things harder 
> than necessary for easy things. 

Ack.

Regards,
/Karl

---
Karl HammarAspö Data   k...@aspodata.se
Lilla Aspö 148 Networks
S-742 94 Östhammar  +46  173 140 57   Computers
Sweden +46  70 511 97 84 Consulting
---




___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Carl Sorensen



On 2/11/10 1:54 PM, "Michael J. O'Donnell"  wrote:

> Carl,
> 
> includeIfAbsent is indeed the sort of void music function that you
> mention. I gave myself a \voidMusic utility function to help me remember
> it when I need it. Now, I realize that for other purposes I would also
> like a \nullMusic, analogous to the \null markup (which holds a
> point-sized place, but doesn't put anything there, and doesn't occupy
> space). Since \voidMusic is completely ignored by the parser, I'm pretty
> sure it won't even mark a point in score time. Not needed today, but
> I'll be hunting for it.
> 
> I've found that the parser passed to the music function seems to put Scm
> definitions in the right global scope, but causes that final
> segmentation fault. The cloned parser avoids the seg fault, but makes a
> scope that hides Scm definitions.

This is way beyond my depth.  I've copied this to -devel because I'm
assuming somebody there might have an idea.

> 
> Maybe I need to do something else to the parser to resolve some
> inconsistency resulting from feeding it a string not in the normal input
> stream.
> 
> Alternatively, I wonder if the \function notation allows for things that
> are not music functions? Not sure whether that will help this problem,
> but the music function might be leading to the necessity for explicitly
> calling the parser, ... Anyway, it seems silly to have things like
> \include and \includeIfAbsent pretend to be music functions, when all
> sorts of types are allowed at the top level.

If you look at the 2.13 latest docs, Extending LilyPond Section 1.2.3,
there's a discussion about this that might help you.  It may be possible
to step entirely out of the music function environment.

See the unofficial link:


You can always do 

#(define (include-if-absent filename)  ...)

then

#(include-if-absent "HeaderOne.ly")
#(include-if-absent "TitleUtilities.ly")

etc.

HTH,

Carl



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Michael J. O'Donnell
Thanks, Carl. I was hunting for a music void before, and missed it. I
have several uses for it.

I'm very fuzzy on using parser vs. (ly:parser-clone parser). I have a
pretty good guess what it means technically at the low level (presumably
parser is an object with state, and the clone gives a separate local
state). I chose the clone empirically to avoid a segmentation fault.
But, ...

I now find that my solution seems to evaluate LilyPond variable definitions

variable = {  ... }

in an acceptable context.

But Scheme variable definitions:

#(define variable ...)

appear to define the variable only in some limited scope, so that they
aren't available globally as they would be with \include instead of
\includeIfAbsent. It's not clear to me what part of the syntax is
generating that scope, and it could even be the cloning of the parser.

I found define-public-toplevel, which can be used in the included file
(and probably should be in most cases, for greater robustness), but I'd
still like to make \includeIfAbsent work for legacy include files.

And, of course, every error of this sort that I find, springing from my
ignorance rather than just a little programming blunder, increases my
hope that someone with fuller knowledge will point out some challenging
test cases.

Cheers,

Mike O'D.

Carl Sorensen wrote:
>
> On 2/11/10 11:05 AM, "Michael J. O'Donnell" 
> wrote:
>
>   
>> Here's what I *now think* is correct code O:-) :
>>
>> includeIfAbsent =
>>
>> #(define-music-function (parser location fileName) (string?)
>>
>> (let ((guardName (string-append "Already Got " fileName)))
>>
>> (if (not (defined? (string->symbol guardName)))
>> (begin
>>
>> (primitive-eval (list 'define (string->symbol guardName) #t))
>>
>> (ly:parser-parse-string (ly:parser-clone parser) (string-concatenate
>> (list "\\include \"" fileName "\"")))
>>
>> #{ #}
>> 
>
> When I see #{ #}, I suspect that instead of using the substitution syntax,
> you should be using void  music functions (i.e. your return should be
> (make-music 'SequentialMusic 'void #t)).  This is the empty music you refer
> to below.
>
> You can read more about void music functions in Notation Reference 6.1.5 for
> version 2.12 or in Extending LilyPond 2.1.5 for version 2.13.
>
> Thanks,
>
> Carl
>
>
>   


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Hans Aberg

On 11 Feb 2010, at 18:18, Michael J. O'Donnell wrote:

At present, I am seeking an add-on solution, involving a definition  
that
I can put in a utility file to include. I think I am near finding  
that.
I am not ready to hack the lexical analyzer, and I think that should  
be
pondered carefully, particularly when a global reconsideration of  
syntax
is planned. But at some point, a better integrated solution is  
desirable.


It may not be so difficult, it has the lines:
\\include   {
 yy_push_state (incl);
 }
 \"[^"]*\"   { /* got the include file name */
 string s (YYText ()+1);
 s = s.substr (0, s.rfind ('"'));

 new_input (s, sources_);
 yy_pop_state ();
 }

So add something like:
\\import   {
 yy_push_state (impo);
 }
 \"[^"]*\"   { /* got the include file name */
 string s (YYText ()+1);
 s = s.substr (0, s.rfind ('"'));

 new_input (s, sources_);
 yy_pop_state ();
 }

with a check if the module has been loaded before, perhaps by making a  
variation of new_input() if LilyPond saves the filenames somewhere.


Haskell and ML have put a lot of thought into modules, which I think  
are

much better conceived than objects in C++.


They come from different traditions, I think. C++ just tries to add  
support for a common C programming practice, where a name space means  
adding a prefix.


Haskell actually does essentially the same, but checks if the module  
has been loaded.



I don't know Hans' programming ideology, but I think that
systems like LilyPond should follow best programming language practice
as much as possible. No matter how simple designers expect the uses of
the system to be, later practice almost inevitably goes into regions
where the more advanced structure is important. And I think that  
modules
are near if not at the state of the art for organization of  
programming

information.


I thought that perhaps getting some hooks might give ideas on how to  
move ahead.



The association
of \include with the lexical level is like the old C preprocessor
attitude. That sort of lexical manipulation is often a good choice  
in an

early design, when one is not sure of the right structure, and first
attempts at good structure tend to be too restrictive. But by now we
know how to do better without being too restrictive.


LilyPond has expanded to such a degree that it might be beneficial  
with some module system.



I noticed that Guile also has a module system, and I have a generally
good impression of the thinking behind Guile. As long as LilyPond uses
Guile, the first thing to see is whether it can use the Guile module
system directly for this sort of organization. The Guile macro  
system is

also a possible hook for include-like things. Include is essentially a
parameterless macro invoker. Guile follows work in the Scheme  
community

to apply macros at the syntax level instead of the lexical level. Once
syntax is well defined (which it has been in LISP much longer than in
other languages), that is usually a better approach than lexical-level
macros. Modules take similar facilities to the semantic level.


So it might be good if LilyPond can use the Guile module system.

  Hans




___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Carl Sorensen



On 2/11/10 11:05 AM, "Michael J. O'Donnell" 
wrote:

> Here's what I *now think* is correct code O:-) :
> 
> includeIfAbsent =
> 
> #(define-music-function (parser location fileName) (string?)
> 
> (let ((guardName (string-append "Already Got " fileName)))
> 
> (if (not (defined? (string->symbol guardName)))
> (begin
> 
> (primitive-eval (list 'define (string->symbol guardName) #t))
> 
> (ly:parser-parse-string (ly:parser-clone parser) (string-concatenate
> (list "\\include \"" fileName "\"")))
> 
> #{ #}

When I see #{ #}, I suspect that instead of using the substitution syntax,
you should be using void  music functions (i.e. your return should be
(make-music 'SequentialMusic 'void #t)).  This is the empty music you refer
to below.

You can read more about void music functions in Notation Reference 6.1.5 for
version 2.12 or in Extending LilyPond 2.1.5 for version 2.13.

Thanks,

Carl



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Reinhold Kainhofer
Am Donnerstag, 11. Februar 2010 19:05:26 schrieb Michael J. O'Donnell:
> Here's what I *now think* is correct code O:-) :
> 
> includeIfAbsent =
> 
> #(define-music-function (parser location fileName) (string?)
> 
> (let ((guardName (string-append "Already Got " fileName)))
> (if (not (defined? (string->symbol guardName)))

Huh? So you are constructing a string like "Already Got testinclude.ily" and 
turn that into a symbol?

First, I suppose the "Already Got" is there just for testing purposes? (Or are 
you trying to prevent symbols that start with ../somedir/...?)

And second, why don't you simply store the strings in a global list or so? I 
doubt that the overhead of the (a)list member lookup can have any influence on 
speed. On the other hand it means one global symbol less per included file.

> (ly:parser-parse-string (ly:parser-clone parser) (string-concatenate
> (list "\\include \"" fileName "\"")))
> 
> #{ #}

Wouldn't it be better to put that only once after the (let...) function?


Instead of #{ #} you can also use the scheme construct for an empty music 
expression:
(make-music 'Music 'void #t)

In scm/ly-syntax-constructors.scm a (void-music) function is defined, which 
creates also an empty music expression, but does not set the 'void property... 
I'm not sure if that would also work, in particulat since collect-music-aux in 
scm/lily-library explicitly checks for the 'void property and discards the 
music if 'void is set to #t...

So, is this an oversight and 'void #t should / needs to be added to the 
definition of (void-music)?


Cheers,
Reinhold

-- 
--
Reinhold Kainhofer, reinh...@kainhofer.com, http://reinhold.kainhofer.com/
 * Financial & Actuarial Math., Vienna Univ. of Technology, Austria
 * http://www.fam.tuwien.ac.at/, DVR: 0005886
 * LilyPond, Music typesetting, http://www.lilypond.org


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Michael J. O'Donnell
Here's what I *now think* is correct code O:-) :

includeIfAbsent =

#(define-music-function (parser location fileName) (string?)

(let ((guardName (string-append "Already Got " fileName)))

(if (not (defined? (string->symbol guardName)))
(begin

(primitive-eval (list 'define (string->symbol guardName) #t))

(ly:parser-parse-string (ly:parser-clone parser) (string-concatenate
(list "\\include \"" fileName "\"")))

#{ #}

)

#{ #}

) ) )

It appears to include/not include appropriately in a project that I'm
working on. When I failed to clone the parser, I got desired *.ps and
*.pdf output, but a segmentation fault at the end, presumably due to
putting the parser in a bad state. I'm a bit uncomfortable with the
empty braces #{ #}, which were necessary so that the "music" function
includeIfAbsent would return some rather empty music. I'm uncomfortable
because LilyPond design so far seems to have neglected the notion of
empty music (similar to the null markup, which it includes), and because
it's not clear to me why head material of this sort needs to be
classified as music at all.

I don't understand the interaction of Scheme variable scope with
LilyPond syntax, so I'm not sure how this will behave in contexts other
than toplevel. And I don't know the right sort of comprehensive test
cases. If anybody can beat on it, please do.

Cheers,

Mike O'D.



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Michael J. O'Donnell
Hans and Carl (and the list, which I neglected first time),

At present, I am seeking an add-on solution, involving a definition that
I can put in a utility file to include. I think I am near finding that.
I am not ready to hack the lexical analyzer, and I think that should be
pondered carefully, particularly when a global reconsideration of syntax
is planned. But at some point, a better integrated solution is desirable.

Haskell and ML have put a lot of thought into modules, which I think are
much better conceived than objects in C++. When we get to the GLISS
rethinking of syntax, it will be good to look carefully at what such
languages have already done. One of the two main implementors of
Standard ML of New Jersey is down the hall from me, and he's a module
proponent, so I can help with that when the time comes. The association
of \include with the lexical level is like the old C preprocessor
attitude. That sort of lexical manipulation is often a good choice in an
early design, when one is not sure of the right structure, and first
attempts at good structure tend to be too restrictive. But by now we
know how to do better without being too restrictive.

I noticed that Guile also has a module system, and I have a generally
good impression of the thinking behind Guile. As long as LilyPond uses
Guile, the first thing to see is whether it can use the Guile module
system directly for this sort of organization. The Guile macro system is
also a possible hook for include-like things. Include is essentially a
parameterless macro invoker. Guile follows work in the Scheme community
to apply macros at the syntax level instead of the lexical level. Once
syntax is well defined (which it has been in LISP much longer than in
other languages), that is usually a better approach than lexical-level
macros. Modules take similar facilities to the semantic level.

For the very short term, I expect that "\includeIfAbsent", or whatever
we call it, will be most useful if it duplicates the current behavior of
"\include" as much as possible, except when it does nothing due to a
previous inclusion. So, I'm going to stack thoughts about specific uses
and connections to name spaces. I will try to insert them into the GLISS
discussion---I don't know Hans' programming ideology, but I think that
systems like LilyPond should follow best programming language practice
as much as possible. No matter how simple designers expect the uses of
the system to be, later practice almost inevitably goes into regions
where the more advanced structure is important. And I think that modules
are near if not at the state of the art for organization of programming
information.

In case you want to see that much detail, I'll stick in my current
prototype:

% Include a file unless it has already been included

includeIfAbsent =

#(define-music-function (parser location fileName) (string?)

(let ((guardName (string-append "Already Got " fileName)))

(if (not (defined? (string->symbol guardName)))
(begin

(primitive-eval (list 'define (string->symbol guardName) #t))

(ly:parser-parse-string parser (string-concatenate (list "\\include \""
fileName "\"\n")))

#{ #}

)

#{ #}

) ) )

I mimicked some code for includePageLayoutFile from
music-functions-init.ly, which feeds its own constructed \include
command to a parser, which presumably has the same old lexical analyzer
as its front end. I wasn't sure which parser gets passed to a music
function, but it looks like I've got the right one. My current problem
seems to have to do with the need to return an actual bit of music,
which I would like to be an empty bit. It may be that includeIfAbsent
doesn't have to be a music function, but so far I haven't found an
alternative. The code above actually seems to create the right output,
but then it hits a segmentation fault, perhaps in some final end code.
That probably reveals some bug that only affects somewhat weird
programs. I'll try to chase it down further.

Cheers,

Mike O'D.
> On 11 Feb 2010, at 05:32, Carl Sorensen wrote:
>
>>> I have been hunting, so far in vain, for the code implementing
>>> \include,
>>> in the hope that I can tweak that code to get the right behavior.
>>
>> It appears to me that \include is implemented in two places:
>>
>> 1) lily/lexer.ll, lines 304-336
>>
>> 2) lily/lily-lexer.cc, lines 255-271
>>
>> Now, please understand that I'm not at all an expert on the
>> parser/lexer of
>> LilyPond. But I think that lexer.ll calls new_input, and lily-lexer.cc
>> defines new-input.
>
> The .ll (or .l) file is what is passed to the lexer, and you probably
> use Flex. It compiles the code to a .cc (or .c) file, which is then
> passed to the compiler which produces .o object code, a format that
> typically has embedded machine code, which is actually what is executed.
>
>> lily-lexer.ll is where the file identifier is extracted (lexed?), and
>> would
>> be an ideal place to see if the include has already been processed,
>> if the
>> necessary variable str

Re: Solution for including a file only once

2010-02-11 Thread Reinhold Kainhofer
Am Donnerstag, 11. Februar 2010 18:18:52 schrieb Michael J. O'Donnell:
> For the very short term, I expect that "\includeIfAbsent", or whatever
> we call it, will be most useful if it duplicates the current behavior of
> "\include" as much as possible, except when it does nothing due to a
> previous inclusion. So, I'm going to stack thoughts about specific uses
> and connections to name spaces. 

In my view there are two different kinds of include uses:
1) To include package-like .ily files, which define additional functionality. 
There many utility functions really might/should be in their own namespace, 
but many definitions (and in particular all \header, \paper or \layout blocks) 
need to be at toplevel.

2) Included music definitions, where you define parts (or smaller building 
blocks, which are used all over the place) of your scores. These definitely 
should simply be inserted into the stream without namespaces and the like.

> I will try to insert them into the GLISS
> discussion---I don't know Hans' programming ideology, but I think that
> systems like LilyPond should follow best programming language practice
> as much as possible. 

I think it should be as easy and straightforward to use to a non-programmer as 
possible, while allowing more complex use without making easy things harder 
than necessary for easy things. 

Cheers,
Reinhold
-- 
--
Reinhold Kainhofer, reinh...@kainhofer.com, http://reinhold.kainhofer.com/
 * Financial & Actuarial Math., Vienna Univ. of Technology, Austria
 * http://www.fam.tuwien.ac.at/, DVR: 0005886
 * LilyPond, Music typesetting, http://www.lilypond.org


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Michael J. O'Donnell
Hans and Carl,

At present, I am seeking an add-on solution, involving a definition that
I can put in a utility file to include. I think I am near finding that.
I am not ready to hack the lexical analyzer, and I think that should be
pondered carefully, particularly when a global reconsideration of syntax
is planned. But at some point, a better integrated solution is desirable.

Haskell and ML have put a lot of thought into modules, which I think are
much better conceived than objects in C++. When we get to the GLISS
rethinking of syntax, it will be good to look carefully at what such
languages have already done. One of the two main implementors of
Standard ML of New Jersey is down the hall from me, and he's a module
proponent, so I can help with that when the time comes. The association
of \include with the lexical level is like the old C preprocessor
attitude. That sort of lexical manipulation is often a good choice in an
early design, when one is not sure of the right structure, and first
attempts at good structure tend to be too restrictive. But by now we
know how to do better without being too restrictive.

I noticed that Guile also has a module system, and I have a generally
good impression of the thinking behind Guile. As long as LilyPond uses
Guile, the first thing to see is whether it can use the Guile module
system directly for this sort of organization. The Guile macro system is
also a possible hook for include-like things. Include is essentially a
parameterless macro invoker. Guile follows work in the Scheme community
to apply macros at the syntax level instead of the lexical level. Once
syntax is well defined (which it has been in LISP much longer than in
other languages), that is usually a better approach than lexical-level
macros. Modules take similar facilities to the semantic level.

For the very short term, I expect that "\includeIfAbsent", or whatever
we call it, will be most useful if it duplicates the current behavior of
"\include" as much as possible, except when it does nothing due to a
previous inclusion. So, I'm going to stack thoughts about specific uses
and connections to name spaces. I will try to insert them into the GLISS
discussion---I don't know Hans' programming ideology, but I think that
systems like LilyPond should follow best programming language practice
as much as possible. No matter how simple designers expect the uses of
the system to be, later practice almost inevitably goes into regions
where the more advanced structure is important. And I think that modules
are near if not at the state of the art for organization of programming
information.

In case you want to see that much detail, I'll stick in my current
prototype:

% Include a file unless it has already been included

includeIfAbsent =

#(define-music-function (parser location fileName) (string?)

(let ((guardName (string-append "Already Got " fileName)))

(if (not (defined? (string->symbol guardName)))
(begin

(primitive-eval (list 'define (string->symbol guardName) #t))

(ly:parser-parse-string parser (string-concatenate (list "\\include \""
fileName "\"\n")))

#{ #}

)

#{ #}

) ) )

I mimicked some code for includePageLayoutFile from
music-functions-init.ly, which feeds its own constructed \include
command to a parser, which presumably has the same old lexical analyzer
as its front end. I wasn't sure which parser gets passed to a music
function, but it looks like I've got the right one. My current problem
seems to have to do with the need to return an actual bit of music,
which I would like to be an empty bit. It may be that includeIfAbsent
doesn't have to be a music function, but so far I haven't found an
alternative. The code above actually seems to create the right output,
but then it hits a segmentation fault, perhaps in some final end code.
That probably reveals some bug that only affects somewhat weird
programs. I'll try to chase it down further.

Cheers,

Mike O'D.
> On 11 Feb 2010, at 05:32, Carl Sorensen wrote:
>
>>> I have been hunting, so far in vain, for the code implementing
>>> \include,
>>> in the hope that I can tweak that code to get the right behavior.
>>
>> It appears to me that \include is implemented in two places:
>>
>> 1) lily/lexer.ll, lines 304-336
>>
>> 2) lily/lily-lexer.cc, lines 255-271
>>
>> Now, please understand that I'm not at all an expert on the
>> parser/lexer of
>> LilyPond. But I think that lexer.ll calls new_input, and lily-lexer.cc
>> defines new-input.
>
> The .ll (or .l) file is what is passed to the lexer, and you probably
> use Flex. It compiles the code to a .cc (or .c) file, which is then
> passed to the compiler which produces .o object code, a format that
> typically has embedded machine code, which is actually what is executed.
>
>> lily-lexer.ll is where the file identifier is extracted (lexed?), and
>> would
>> be an ideal place to see if the include has already been processed,
>> if the
>> necessary variable structure is available.
>
> So this is the file 

Re: Solution for including a file only once

2010-02-11 Thread Hans Aberg

On 11 Feb 2010, at 05:32, Carl Sorensen wrote:

I have been hunting, so far in vain, for the code implementing  
\include,

in the hope that I can tweak that code to get the right behavior.


It appears to me that \include is implemented in two places:

1) lily/lexer.ll, lines 304-336

2) lily/lily-lexer.cc, lines 255-271

Now, please understand that I'm not at all an expert on the parser/ 
lexer of
LilyPond.  But I think that lexer.ll calls new_input, and lily- 
lexer.cc

defines new-input.


The .ll (or .l) file is what is passed to the lexer, and you probably  
use Flex. It compiles the code to a .cc (or .c) file, which is then  
passed to the compiler which produces .o object code, a format that  
typically has embedded machine code, which is actually what is executed.


lily-lexer.ll is where the file identifier is extracted (lexed?),  
and would
be an ideal place to see if the include has already been processed,  
if the

necessary variable structure is available.


So this is the file that one would change. Then 'make' will sense that  
this file hjas been changed, invoking flex, producing a new .cc file.


From what I can see on git.savannah, the \include definition in lily/ 
lily-lexer.ll just inserts the file in the stream using a method that  
Flex provides.


By contrast, if one would want to have an import command that checks  
that a module isn't loaded twice, one should have table for the module  
names. Then an opened module is read all through, the definitions  
entered into Guile, and then the module is closed.


This may not be so difficult to implement if there is some top level  
command where lilypond starts reading the first file. Then the new \ 
\import just calls that command.


  Hans




___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-11 Thread Hans Aberg

On 7 Feb 2010, at 04:51, Michael J. O'Donnell wrote:


I *think* that I have the essential solution to include a file exactly
once, no matter how many times it is mentioned. That is, with the
following definition,

   \includeIfAbsent "MyFile.ly"

should copy in MyFile.ly, just as though you had written

   \include "MyFile.ly"

unless an inclusion (either through \include or through
\includeIfAbsent) has already started (and usually finished). If there
is a circular path of \includes, LilyPond appears to enter an infinite
loop, but \includeAbsent will break a cycle. That's why it's important
that I said "unless an inclusion ... has already *started*," rather  
than

"already happened."

The sweat here involved avoiding any preparatory code to enable the
mechanism. You need nothing more than the definition of  
includeIfAbsent.


I'm not sure how either \include or \includeIfAbsent behave inside a
context. It's probably not a good idea to use either one except at the
outermost level---inner stuff should usually be done with variables.
But, it would be cool if someone tested the possibility.


The Haskell functional language  has a module  
system. The command that ensures that a module is loaded only once is  
called "import".


One can only use "import" at the beginning of a file. So it is not  
possible to appear inside code.


There are some other things attached to the module system:

It defines a name-space, like namespace in C++. So
  module Foo

  ...
  f = ...
causes that actual name of f to be Foo.f. If one imports a name f form  
a module Bar, then one has both Foo.f and Bar.f present. If one wants  
to use the name for one of them, one needs to have system for  
disambiguation.


In addition, a module can decide which names to export: all or just  
some of them, creating a user interface. Though the syntax in Haskell  
is just (...) after the module name, here write

  export f
Then f can be use, not not other names not in the list.

  Hans




___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-10 Thread Carl Sorensen



On 2/10/10 9:16 PM, "Michael J. O'Donnell"  wrote:

> 
> I have been hunting, so far in vain, for the code implementing \include,
> in the hope that I can tweak that code to get the right behavior.

It appears to me that \include is implemented in two places:

1) lily/lexer.ll, lines 304-336

2) lily/lily-lexer.cc, lines 255-271

Now, please understand that I'm not at all an expert on the parser/lexer of
LilyPond.  But I think that lexer.ll calls new_input, and lily-lexer.cc
defines new-input.

lily-lexer.ll is where the file identifier is extracted (lexed?), and would
be an ideal place to see if the include has already been processed, if the
necessary variable structure is available.

lily-lexer.cc is where the input file is actually opened (and the file name
exists there, as well).  This is where the input is aborted if safe mode is
running, so it might also be a place to check for definition of a
variable...

HTH,

Carl



___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Solution for including a file only once

2010-02-10 Thread Michael J. O'Donnell
My proposed solution behaves as though you had written

 { \include "MyFile.ly" }

rather than the desired

 \include "MyFile.ly"

Lots of simple debugging code works fine, but in the usual case where
MyFile.ly is full of variable definitions, those definitions are not
parsed in the outermost level, and they get syntactic errors.

I have been hunting, so far in vain, for the code implementing \include,
in the hope that I can tweak that code to get the right behavior.

A general way of switching to the outermost parsing layer would also
possibly solve the problem, but I can't find that either. Still hunting,
and of course ready to take any hint.

Michael J. O'Donnell wrote:
> I *think* that I have the essential solution to include a file exactly
> once, no matter how many times it is mentioned. That is, with the
> following definition,
>
> \includeIfAbsent "MyFile.ly"
>
> should copy in MyFile.ly, just as though you had written
>
> \include "MyFile.ly"
>
> unless an inclusion (either through \include or through
> \includeIfAbsent) has already started (and usually finished). If there
> is a circular path of \includes, LilyPond appears to enter an infinite
> loop, but \includeAbsent will break a cycle. That's why it's important
> that I said "unless an inclusion ... has already *started*," rather than
> "already happened."
>
> I think that some such function should be added to the distributed code.
> I posted to lilypond-user for people who would like to cut and paste for
> now. I'm new to the development game, so I'll pause briefly before
> trying to turn this into a patch, in case someone has objections or
> ideas to improve (besides "follow the coding standards," which I plan to
> learn before submitting). I mentioned some alternative possibilities below.
>
> The sweat here involved avoiding any preparatory code to enable the
> mechanism. You need nothing more than the definition of includeIfAbsent.
>
> I'm not sure how either \include or \includeIfAbsent behave inside a
> context. It's probably not a good idea to use either one except at the
> outermost level---inner stuff should usually be done with variables.
> But, it would be cool if someone tested the possibility.
>
> Notice that I let the file *calling* for inclusion control whether it
> wants to allow multiple inclusions or not. Some systems, including the C
> preprocessor, put a guard in the included file, disabling its inclusion
> if it has already appeared. I think that I like this form (which
> corresponds pretty well to "require" in some languages, but I've
> forgotten which ones) better. I think that the guard within a file is
> not hard to implement by a similar method.
>
> There is a chance, very small I hope, that the string I used for a
> file's guard could be introduced elsewhere, gumming things up. E.g., if
> someone wants to have guards within the include files, as well as within
> the including files, the names need to be different.
>
> -
>
> includeIfAbsent =
>
> #(define-music-function (parser location fileName) (string?)
>
>   (let ((guardName (string-append "Already Got " fileName)))
>
> (if (not (defined? (string->symbol guardName)))
>   (begin
>
> (primitive-eval (list 'define (string->symbol guardName) #t))
>
> #{ \include $fileName #}
>
>   )
>
>   #{ #}
>
> )
>   )
> )
>
> 
>
> Cheerio,
>
> Mike O'Donnell
>
>
>
>   


___
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel