Skip to content
Will Clinger edited this page Feb 19, 2015 · 5 revisions

R6RS-compatible Execution

Larceny's R6RS-compatible mode, described below, is deprecated.

Several core elements of the R6RS standard of 2007 have been superseded by the R7RS (small) standard approved in 2013. To preserve backward compatibility, Larceny's implementation of the R7RS continues to support those superseded elements of the R6RS standard. The Scheme programming language as described by the R6RS is now a proper subset of the R7RS (small) language as extended by Larceny. In most cases, it will make more sense to execute R6RS programs using Larceny's R7RS modes than to use the more restricted R6RS mode described below.

Executing an R6RS Program in R6RS-compatible Mode

Larceny's R6RS-compatible mode is entered when Larceny is called in either of the following ways:


    larceny -r6rs -program filename
    larceny -r6rs < filename

Importing Non-standard Libraries

The R6RS does not specify any portable way for programs to use libraries other than the R6RS standard libraries. As extensions to the R6RS, however, Larceny provides five Larceny-specific ways for non-portable R6RS programs to use non-standard libraries:

  • Top-level programs may import any of the R7RS, R6RS, SRFI, and other libraries that Larceny provides for use by R7RS programs.
  • Top-level programs may import any of the libraries that Larceny's autoload-on-import feature can locate in the directories listed by the startup.sch file in Larceny's root directory.
  • Top-level programs may import any of the libraries that Larceny's autoload-on-import feature can locate in the directories specified by a -path option on Larceny's command line.
  • Top-level programs may import any of the libraries that Larceny's autoload-on-import feature can locate in the directories specified by Larceny's LARCENY_LIBPATH environment variable.
  • Top-level programs may import any libraries that are defined within the same file as the top-level program.

We emphasize that all of those mechanisms are non-portable. Although portability was an alleged goal of the R6RS, and libraries were the most prominent new feature of the R6RS, the R6RS does not describe any portable way for R6RS programs to import libraries other than those specified by the R6RS documents themselves.

Defining Non-standard Libraries

The R6RS does not specify any portable way for programmers to define their own libraries. As an extension to the R6RS, Larceny allows R6RS programmers to define non-standard libraries subject to the following restrictions:

  • All nonstandard libraries must be written in R6RS or R7RS Scheme as extended by Larceny.
  • All nonstandard libraries must be defined in files that follow Larceny's standard naming conventions for R7RS/R6RS libraries.
  • All files that define nonstandard libraries must reside in one of the directories that belong to Larceny's library search path.

Note that Larceny uses Andre van Tonder's library system, which allows libraries to import arbitrary procedures from Larceny's underlying implementation of R5RS Scheme. Since Larceny's implementation of R5RS Scheme includes a powerful FFI, the above restrictions permit access to code written in many other programming languages and to a vast number of libraries.

Defining Non-standard Libraries Within a Program

As an extension to the R6RS, Larceny allows R6RS top-level programs and Scheme scripts to define non-standard libraries subject to the following restrictions:

  • All nonstandard libraries must be written in Scheme, using R6RS syntax.
  • All nonstandard libraries must be contained within the same file as the top-level program.
  • If a nonstandard library imports other nonstandard libraries, then the imported libraries must be placed before the importing library.

(The restriction to R6RS syntax can be removed by using Larceny's R7RS mode instead of the R6RS-compatible mode being described here.)

Known Deviations from R6RS Conformance

Larceny's R6RS-compatible mode is almost, but not quite, R6RS-conforming. As of v0.97, Larceny passes 99.99% of the tests in PLT Scheme's R6RS test suite. The only failed test concerns the letrec* restriction discussed below, and is unlikely to affect real programs.

Larceny's major known deviations from R6RS-conformance are:

  • Larceny does not conform to known errors in the R6RS.

  • Larceny does not enforce deliberate weaknesses and restrictions whose primary purpose is to justify additional features.

  • Larceny may not support all of the additional features whose primary purpose is to work around the deliberate weaknesses and restrictions of the R6RS. Such features, whether supported or not, are classified as deprecated.

  • As a consequence of the above, Larceny doesn't always raise a violation exception when the R6RS says it must, and doesn't always create the precise condition object the R6RS says it must create when it raises those exceptions. Larceny raises almost all of the required exceptions, however, and is always memory-safe on programs that are said to be safe as defined by the R6RS.

  • The R6RS specifies letrec* semantics for internal definitions, and also requires a violation exception to be raised if the letrec* restriction is violated. Enforcement of the letrec* restriction is costly in time and/or space, however, and will remain so unless we add a new flow analysis to Larceny's compiler (Twobit). We do not expect users of R6RS-compatible mode to write code that deliberately violates the letrec* restriction, and we expect most users of R6RS-compatible mode would prefer we spend our time on more useful flow analyses. (The R7RS standard relaxed the R6RS semantics for letrec* by allowing but not requiring implementations to raise an exception when the letrec* restriction is violated.)

  • By default, Larceny's compiler rejects programs that contain apparent errors of certain kinds. In most programming situations, we believe it is better to reject such programs at compile time than to let them execute, but we also recognize that there are situations in which the compiler should merely warn the programmer without rejecting the program altogether. Larceny offers this choice via the compile-despite-errors compiler switch.

  • On Windows systems, the no-truncate file option doesn't work (because it apparently isn't feasible to implement that option in standard C). The no-truncate file option does work in Unix systems.

  • All ports support the port-position procedure, even though the R6RS mandates non-support of that procedure by custom ports unless they specify a custom implementation of the procedure. Furthermore custom implementations of the port-position procedure are ignored; Larceny provides accurate position information (in bytes for binary ports, in characters for textual ports) even if a custom implementation of port-position is supplied. (Larceny's efficient transcoding architecture relies upon a complex invariant that requires Larceny to maintain accurate information about port positions, and binary input/output ports must have accurate implementations of both port-position and set-port-position! so they can correct for lookahead buffering when switching from input to output. Hence all of Larceny's non-custom ports support port-position internally, and do so accurately, as do all custom textual ports and custom binary input/output ports. It is easier and less confusing to extend Larceny's port-position invariant to custom binary input-only and output-only ports than it would be to treat them as exceptional cases.)

  • The open-file-input/output-port procedure is implemented by opening the file twice: once for input, when the port is created, and once for output, when the port is closed.

Extensions to R6RS

Larceny offers several extensions to R6RS syntax and semantics:

  • As noted above, Larceny allows R6RS programs to define libraries.

  • Larceny allows libraries written in IEEE/ANSI/R5RS/R7RS Scheme to be imported by R6RS libraries and programs.

  • Larceny allows the standard R7RS libraries to be imported by R6RS libraries and programs.

  • Larceny supports numerous SRFIs using the library naming convention specified in SRFI 97.

  • Larceny recognizes the #!fold-case, #!no-fold-case, #!r7rs, #!r5rs, and #!larceny flags, which enable several extensions to the R6RS lexical syntax. See LexicalConversion.

  • Larceny extends the domains of several standard procedures as specified by the newer R7RS standard. R6RS programs that deliberately violate the R6RS specification and rely upon the R6RS exception semantics to handle those violations may not work in Larceny.

Alternatives to R6RS

Larceny supports the newer R7RS standard. The R7RS allows extensions that make R6RS Scheme into a proper subset of the extended R7RS language. Larceny has taken advantage of that, achieving near-perfect interoperability between R7RS and R6RS libraries and programs.

(The R7RS language will never be a subset of any extension of the R6RS, because the R6RS standard absolutely forbids the necessary extensions.)

Larceny continues to provide its R6RS-compatible mode only because some R6RS-conforming programs may deliberately violate the R6RS standard and rely upon the R6RS exception handling and condition systems to recover from those deliberate violations.

Larceny continues to support an IEEE/ANSI/R5RS mode of execution, which interoperates with other standards such as the R7RS, SRFIs, and SLIB. Through its FFI, Larceny also provides access to libraries written in many other languages.

Clone this wiki locally