implementation of SRFI 96 for Larceny
William D Clinger
(27 Nov 2007 17:08 UTC)
|
Re: implementation of SRFI 96 for Larceny Aubrey Jaffer (30 Nov 2007 01:56 UTC)
|
Re: implementation of SRFI 96 for Larceny
Aubrey Jaffer
(25 Dec 2007 02:48 UTC)
|
Re: implementation of SRFI 96 for Larceny
Donovan Kolbly
(01 Jan 2008 00:29 UTC)
|
I have uploaded the updated srfi-96.html to: http://swiss.csail.mit.edu/~jaffer/srfi/srfi-96.html | From: William D Clinger <xxxxxx@ccs.neu.edu> | Date: Tue, 27 Nov 2007 11:39:34 -0500 | | I implemented SRFI 96 for Larceny on a Solaris machine, | thinking this fresh implementation would be a good test | of the SRFI 96 specification. It was. Thanks for your responses. | I downloaded slib3a5.zip and unzipped it into a | directory named lib/SLIB relative to Larceny's root | directory. My attempt to install SLIB using gnu make | resulted in these errors: | | -------- | % make infoz | makeinfo slib.texi --no-warn --no-split -o slib.info | slib.texi:14: Unknown command `copying'. | slib.texi:32: Unmatched `@end'. | slib.texi:62: Unknown command `insertcopying'. | makeinfo: Removing output file `slib.info' due to errors; use --force to preserve. | make: *** [slib3a5.info] Error 2 The @copying command has been in Texinfo as least as early as Texinfo-4.7 (released in April 2004). I suspect your system has an older version of Texinfo. | % make install | test -d /usr/local/man/ || mkdir /usr/local/man/ | mkdir: cannot make directory `/usr/local/man/': No such file or directory | make: *** [pinstall] Error 1 Use a "prefix=" argument to "make" in order to override SLIB's default of /usr/local: make prefix=/home/will/ install | -------- | | Giving up on the Makefile, I proceeded as instructed | by the README: | | % larceny -path lib/SRFI/SLIB | > (require 'srfi-96) | > (require 'new-catalog) | | That worked well enough to begin testing, which soon | proved that the SRFI 96 specification of some things | is insufficiently detailed. | | The specification of with-load-pathname refers to "an | internal variable" as though the name of that variable | were insignificant. In reality, SLIB (as distributed) | won't work unless that internal variable is a global | variable named *load-pathname*. The only occurence of *load-pathname* in SLIB which is found by: grep -n -e '[*]load-pathname[*]' *.scm is in "Template.scm" -- which is a template for *.init files. "Template.scm" is never run. I changed *load-pathname* to *foo-load-pathname* in "gambit.init". With "gambit.init" so modified, gsi was able to load JACAL (which uses SLIB) successfully. What is your basis for asserting that the internal variable must be named *load-pathname*? | SRFI 96 refers to macro:load but does not specify it | and does not indicate that an implementation of SRFI 96 | must define it. Apparently SLIB doesn't define it either: The reference to macro:load was a typo -- it should have been defmacro:load. Corrected in the new srfi-96 upload. | -------- | % larceny -path lib/SRFI/SLIB | Larceny v0.951 "First Safety" (Nov 11 2007 09:34:53, precise:SunOS5:split) | | > (require 'srfi-96) | #t | | > (require 'new-catalog) | | > (require 'define-record-type) | | | Error: Undefined global variable "macro:load". | Entering debugger; type "?" for help. | debug> a | -------- | | Adding definitions of macro:eval and macro:load to the | implementation of SRFI 96 fixed that problem. I have added `R5RS Macros' sections detailing the operations macro:expand, macro:eval, and macro:load. [Rationale] R5RS Macros If the macro feature is provided, then the procedures macro:expand, macro:eval, and macro:load must be defined. Of these, only macro:load is used (for loading packages) by SLIB code. macro:eval would typically be used with the repl:top-level procedure in the repl package to create a macro-enabled read-eval-print loop. macro:expand is indispensable for debugging R5RS Macros; but implementations are not required to make it functional, in which case macro:expand will always return #f. [Specification] R5RS Macros If the macro feature is provided, then the procedures macro:expand, macro:eval, and macro:load will be defined. Function: macro:expand sexpression Takes an expression, macro-expands it, and returns the result of the macro expansion. If an implementation does not support macro:expand, then #f is returned. Function: macro:eval sexpression Takes an expression, macro-expands it, evals the result of the macro expansion, and returns the result of the evaluation. Procedure: macro:load filename filename should be a string. If filename names an existing file, the macro:load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially. These source code expressions and definitions may contain macro definitions. The macro:load procedure does not affect the values returned by current-input-port and current-output-port. | The SRFI 96 specification of slib:features does not | adequately describe the semantics of most features. | In particular, it does not specify what each feature | obliges an implementor to provide. For example, the | specification of program-arguments doesn't say whether | the first element of the list should be the name of | the command, e.g. "larceny". Program-arguments was insufficiently specified; I have added text to both SLIB (http://swiss.csail.mit.edu/~jaffer/slib_7.html#SEC267) and SRFI-96: If (provided? 'program-arguments): Function: program-arguments Returns a list of strings, the first of which is the program name followed by the command-line arguments. | It would probably be enough for SRFI 96 to provide a pointer to the | relevant SLIB documentation for these features. I have added the text: If a feature is provided whose name is the same as an SLIB module, then it will provide the procedures and syntax as documented for that SLIB module. | SRFI 96 does not explain the obligations incurred by an | implementation that provides its own defmacro. All implementations must implement defmacro. The obligations are gentemp, defmacro:eval, defmacro:load, defmacro?, macroexpand-1, macroexpand, and defmacro, specified in the section "Defmacro". | If the defmacro feature is listed in slib:features, then code that | uses defmacro will trigger an infinite loop in defmacro:expand*. defmacro:expand* is a part of the defmacroexpand package, not part of the defmacro feature. Several implementations have an "autoload" which brings in the defmacroexpand package the first time that defmacro:eval (calling defmacro:expand*) is called: (define base:eval slib:eval) (define (defmacro:eval x) (base:eval (defmacro:expand* x))) (define (defmacro:expand* x) (slib:require 'defmacroexpand) (apply defmacro:expand* x '())) | I got rid of this loop by defining defmacro:expand* as follows, | where macro-expand is Larceny's native macro-expander: | | (define (defmacro:expand* x) | (macro-expand x)) | | I doubt whether that definition is fully compatible with SLIB, | however. If your macro-expand expands all the defmacros in its argument, then your definition is fine; just add the symbol defmacroexpand to slib:features. | My implementation of SRFI 96 now appears to be working, | but it's hard to tell how well it's working because I | don't have a test suite for SLIB. Running JACAL (http://swiss.csail.mit.edu/~jaffer/JACAL) on "test.math" is a good test case, using some DEFMACRO:LOADs and many procedure packages. | Question: Should SLIB be distributed with Larceny, or | would it be better to provide SRFI 96 alone and to tell | users of Larceny how to obtain and to install the latest | version of SLIB themselves? UMB-Scheme included an ancient copy of SLIB, which Guile originally used only for its copy of SLIB. This arrangement violated SLIB's license and generated reports over and over for SLIB bugs which had been fixed years ago. I would rather not repeat that experience. Please don't incorporate a copy of SLIB in your distribution. If you send me "larceny.init", then I will include it in the SLIB distribution and a SRFI-96 link along with the other implementations.