[plt-scheme] MzScheme as embedded engine for LilyPond ?

From: Han-Wen Nienhuys (hanwen at xs4all.nl)
Date: Thu Feb 3 15:43:44 EST 2005

Hi there,

I am one of the main authors of the music typesetting package LilyPond
(http://lilypond.org). LilyPond derives much from its flexibility and
power from the fact that embeds a Scheme interpreter.

Unfortunately, the interpreter of our choice --GUILE-- leaves a lot to
be desired. In particular, it's slow, and development is
withering. The last stable release (GUILE 1.6) is more than two years

I'm looking into alternative Scheme interpreters, and the most obvious
alternative is the PLT Scheme suite, in particular the MzScheme
interpreter, due to its active development, excellent documentation,
and high execution speed.

I've read through the documentation and source-code, and that raised
some questions with me. I would be grateful if you could answer some
of them for me.

* How well is embedding MzScheme supported? I've read "Inside PLT
  MzScheme". Am I correct that there is no way to add "coded" types to

  In GUILE, you can add native types, called smobs, to the
  interpreter. All that is needed, is specifying C functions for

  - GC marking the object
  - freeing the object
  - printing the object
  - comparing the object
  LilyPond uses this extensively, it contains 22 different smob types.
  All major classes in the program have been smobbified.

* Can I force symbols to be conservatively GC'd?  Inside lilypond
  source code, we have a macro ly_symbol2scm(), eg.

  SCM foo = bar();
  if (foo == ly_symbol2scm ("bla-bla"))

  ly_symbol2scm interns "bla-bla", and stores the outcome, so that
  only the first invocation of ly_symbol2scm() is costly. Of course,
  this only works if the actual SCM isn't moved around.

  (I believe the MzScheme term for SCM is Scheme_Object*)

* Is there a possibility to read a single expression precisely off an
  input stream?

  In LilyPond input files, you can escape to Scheme, using # , for

    \score { #(make-music 'NoteEvent) }

  here, the lexer gives control to the Scheme interpreter when it
  reaches # . The Scheme interpreter reads up to the ) and evals the
  result. The lexer then continues at the )

  Is this somehow possible with MzScheme? 

* Is there support for read extensions?  We have a special feature,
  that allows us to parse LilyPond code inside one of these embedded
  Scheme fragments, for example

  (make-sequential-music #{ \notes { c4 d8 } #} )

  will pass "\notes { c4 d8 }" to a function that we hooked up with

* Is there support for stack-traces/source annotation?  If I make an
  error in GUILE in debug mode, I get 

	byrd:~/usr/src/lilypond$ guile --debug b.scm
	In unknown file:
	   ?: 0* [primitive-load "b.scm"]
	In b.scm:
	   9: 1* [Y]
	   7: 2  [x 0]
	   3: 3  [0]

	b.scm:3:3: In expression (a):
	b.scm:3:3: Wrong type to apply: 0

  a nice stack trace, with line/column numbers of the calling points.

  How do I get that in MzScheme?  I've understood that this is only
  supported in DrScheme, but I need to switch between both modes on
  the fly. In other words,

    lilypond --debug foo.ly

  would use the MzScheme with locations, and 

    lilypond foo.ly
  would use the non-debugging version.  Is this possible at all?

* Is there support for doc strings and self-documentation?  In
  LilyPond, almost all coded subroutines come with docstrings, and
  would show up if you did

    (apropos "ly:music?")

* MzScheme doesn't support OS level threads.  Will this ever be

  I have the impression that the current trend in chip design is not
  to go faster, but to go parallel (cf: HyperThreading and multi-core
  chips). Of course, this only helps if your app uses OS level

Of course if any of these is not supported, then would these features
stand a chance of being added/incorporated? I'm willing to work on
this or transplant the appropriate code from GUILE.

 Han-Wen Nienhuys | hanwen at xs4all.nl | http://www.xs4all.nl/~hanwen

Posted on the users mailing list.