2  Writing an Scmxlate configuration

2.1  A minimal configuration

Let us say you have a number of Scheme files in a directory that you intend to package as a distribution. For specificity let’s say the name of the directory is pkgdir and you have three Scheme files in it, viz, apple, orange.scm, and banana.rkt. There is no restriction on the names of these Scheme files: They may have any or no extension. An end-user of your distribution will unpack it to produce a pkgdir of their own with the three Scheme files in it.

Let us now say that you wrote the Scheme files in the Racket dialect of Scheme, but that the end-user uses the Guile dialect of Scheme. In order for them to be able to create Guile versions of your files, you need to provide in pkgdir some configuration information. This can be done as follows:

Create a subdirectory called dialects in pkgdir. In the dialects subdirectory, create a file called files‑to‑be‑ported.scm containing the names of the Scheme files to be translated, viz.,

"apple"
"orange.scm"
"banana.rkt"

and a file called dialects‑supported.scm containing the line

guile

The symbol guile of course stands for the Scheme dialect Guile.

The Guile-using user can now start Guile in pkgdir, and load scmxlate.scm (using the appropriate pathname for scmxlate.scm on their system, as described in Section 1). Scmxlate will learn from dialects/files‑to‑be‑ported.scm that the files apple, orange.scm, and banana.rkt need to be translated. It will ask the user what the dialect is, offering as choices the dialects listed in dialects/dialects‑supported.scm, plus a catch-all dialect called Other:1

What is your Scheme dialect?
     (guile other)

The user types guile in response. Scmxlate now understands that it is to create Guile translations of the three files, and proceeds to do so. By default, the translation-result files are created in the pkgdir directory and have the same names as the original but with the prefix my‑ attached. Thus, in this case, their names are my‑apple, my‑orange.scm, and my‑banana.rkt.

In the following, we will for convenience use the following terms:

(i) input file: a file to be translated;

(ii) output file: a file that is the result of a translation;

(iii) target dialect: the dialect translated to.

In our example above, apple is an input file, my‑apple is its corresponding output file, and Guile is the target dialect.

2.2  Dialect-configuration files

The output file my‑apple above uses Scmxlate’s default rules for an Racket-to-Guile translation. These rules are general and cannot be expected to cover any peculiar translational information that may be relevant to the code in apple. You can supply such additional information to Scmxlate via a dialect-configuration file called guile‑apple in the dialects subdirectory. I.e., the name of the dialect-configuration file for a given input file and a given dialect is formed from the Scmxlate symbol for the dialect, followed by a hyphen, followed by the name of the input file.

Scmxlate typically takes code from a dialect-configuration file and sticks it ahead of the translated code in the output file. This code can be any Scheme code in the target dialect, and in particular, it can include definitions. The order of the code in the dialect-configuration file is preserved in the output file.

For instance, if the Racket code in apple made use of a nonstandard (Racket-only) primitive such as file‑or‑directory‑modify‑seconds, we could supply the following Guile definition in the dialect-configuration file, dialects/guile‑apple:

(define file-or-directory-modify-seconds
  (lambda (f) (vector-ref (stat f) 9)))

If the dialect-configuration file supplies a definition for a name that is also defined in the input file, then the output file will contain the definition from the dialect-configuration file, not the input file. For example, if apple contained the definition

(define file-newer?
  (lambda (f1 f2)
    ;checks if f1 is newer than f2
    (> (file-or-directory-modify-seconds f1)
       (file-or-directory-modify-seconds f2))))

we could put a competing Guile-specific definition in dialects/guile‑apple:

(define file-newer?
  (lambda (f1 f2)
    (> (vector-ref (stat f1) 9)
       (vector-ref (stat f2) 9))))

When Scmxlate translates apple, it will directly incorporate this Guile definition into the output file my‑apple and won’t even attempt to translate the Racket definition of the same name in the input file.

2.3  Target dialects

In the above, we used the symbol guile in the dialects/dialects‑supported.scm file to signal to Scmxlate that Guile is one of the dialects into which the package can be translated. The list of dialect symbols recognized by Scmxlate is: bigloo, chez, chibi, chicken, cl, gambit, gauche, guile, ikarus, kawa, mitscheme, mzscheme, other, petite, plt, pscheme, racket, scheme48, scm, scsh, stk, stklos, sxm, umbscheme, ypsilon.

The symbol cl stands for Common Lisp.2

The symbol other can be used by the package author to provide a default configuration for an unforeseen dialect. Since the dialect is unknown, there isn’t much information to exploit, but it may be possible to provide some bare-minimum functionality (or at least display some advice).

The package author can make use of other symbols to denote other Scheme dialects. However, as Scmxlate cannot do any special translation for such dialects, it is the responsibility of the package author to provide additional configuration information for them by writing dialect-configuration files.

2.4  User-configuration files

Some packages need some configuration information that the package author cannot predict and that therefore can come only come from the user. The information typically contains user preferences for global variables in the program. It should not be dialect-specific.

Such user information can be placed in user-configuration files in the package directory. Each input file can have its own user-configuration file, and the latter’s name consists of the prefix scmxlate‑ followed by the name of the input file. Thus the user configuration file for orange.scm is scmxlate‑orange.scm.

While the package author may not be able to predict the values of the globals preferred by their various users, they can include in the package sample user-configuration files that mention the globals requiring the user’s intervention, with comments instructing how the user is to customize them.

Note that user-configuration code comes ahead of the dialect-configuration code in the output file. Definitions in the user-configuration code override definitions in the dialect-configuration code, just as the latter themselves override definitions in the input file.


1 The astute reader may wonder why Scmxlate needs to explicitly ask the user what the target dialect is, when it is already running on it! Unfortunately, since the Scxmlate code is necessarily written in a style that must load in all Schemes, it cannot portably determine the identity of the particular Scheme dialect it is currently running on.

2 Note that Scmxlate can readily determine if it’s running on Common Lisp (as opposed to Scheme), so it will not query the user for further “dialect” information.