3  The Scmxlate directives

In addition to Scheme code intended to either augment or override code in the input file, the dialect- and user-configuration files can use a small set of Scmxlate directives to finely control the text that goes into the output file, and even specify actions that go beyond the mere creation of the output file. These directives are now described.

3.1  scmxlate-insert

As we saw, Scheme code in the dialect- and user-configuration files is transferred verbatim to the output file. Sometimes, we need to put into the output file arbitrary text that is not Scheme code. For instance, we may want the output file to start with a “shell magic” line, so that it can be used as a shell script. Such text can be written using the scmxlate‑insert directive, which evaluates its subforms in Scheme and displays them on the output file.

E.g., if you put the following at the very head of the guile‑apple file:

(scmxlate-insert
  "#!/bin/sh
exec guile -s $0 \"$@\"
!#
")

the output Guile file my‑apple will start with the line

#!/bin/sh
exec guile -s $0 "$@"
!#

Note that the order of the code and scmxlate‑insert text in the configuration file is preserved in the output file.

3.2  scmxlate-postamble

Typically, the Scheme code and scmxlate‑inserts specified in the dialect-configuration file occur in the output file before the translated counterpart of input file’s contents, and thus may be considered as preamble text. Sometimes we need to add postamble text, i.e., things that go after the code from the input file. In order to do this, place the directive

(scmxlate-postamble)

after any preamble text in the dialect-configuration file. Everything following that, whether Scheme code or scmxlate‑inserts, will show up in the output file after the translated contents of the input file.

3.3  scmxlate-postprocess

One can also specify actions that need to performed after the output file has been written. E.g., let’s say we want the Guile output file for apple to be named pear rather than my‑apple. We can enclose Scheme code for achieving this inside the Scmxlate directive scmxlate‑postprocess:

(scmxlate-postprocess
  (rename-file "my-apple" "pear"))

3.4  scmxlate-ignoredef

Sometimes the input file has a definition that the target dialect does not need, either because the target dialect already has it as a primitive, or because we wish to completely re-write input code that uses that definition. E.g., if the target dialect is Gambit, which already contains reverse!, any definition of reverse! in the input file can be ignored.

(scmxlate-ignoredef reverse!)

scmxlate‑ignoredef can have any number of arguments. The definitions of all of them will be ignored.

3.5  scmxlate-rename

Sometimes we want to rename certain identifiers from the input file. One possible motivation is that these identifiers name nonstandard primitives that are provided under a different name in the target dialect. For instance, the Bigloo versions of the Racket primitives current‑directory and file‑or‑directory‑modify‑seconds are chdir and file‑modification‑time respectively. So if your Racket input file uses current‑directory and file‑or‑directory‑modify‑seconds, your Bigloo dialect-configuration file should contain

(scmxlate-rename
 (current-directory chdir)
 (file-or-directory-modify-seconds file-modification-time))

Note the syntax: scmxlate‑rename has any number of twosomes as arguments. The left item is the name in the input file, and the right item is its proposed replacement.

3.6  scmxlate-ignoredef-rename

Sometimes the input file includes a definition for an operator that the target dialect already has as a primitive, but with a different name. E.g., consider an input file that contains a definition for nreverse. Gambit has the same operator but with name reverse!. You could add the following to the Gambit dialect-configuration file:

(scmxlate-ignoredef-rename
  (nreverse reverse!))

Note that this is shorthand for

(scmxlate-ignoredef nreverse)
(scmxlate-rename
  (nreverse reverse!))

3.7  scmxlate-prefix

Another motivation for renaming is to avoid polluting namespace. We may wish to have short names in the input file, but when we configure it, we want longer, “qualified” names. It is possible to use scmxlate‑rename for this, but the scmxlate‑prefix is convenient when the newer names are all uniformly formed by adding a prefix.

(scmxlate-prefix
  "regexp::"
  match
  substitute
  substitute-all)

renames the identifiers match, substitute, and substitute‑all to regexp::match, regexp::substitute, and regexp::substitute‑all respectively.

The first argument of scmxlate‑prefix is the string form of the prefix; the remaining arguments are the identifiers that should be renamed.

3.8  scmxlate-cond

Sometimes we want parts of the dialect-configuration file to processed only when a condition holds. For instance, we can use the following cond-like conditional in a dialect-configuration file to write out a shell-magic line appropriate to the operating system:

(scmxlate-cond
  ((eqv? (system-type) 'unix)
   (scmxlate-insert *unix-shell-magic-line*))
  ((eqv? (system-type) 'windows)
   (scmxlate-insert *windows-shell-magic-line*)))

where *unix‑shell‑magic‑line* and *windows‑shell‑magic‑line* are replaced by appropriate strings.

Note that while scmxlate‑cond allows the else keyword for its final clause, it does not support the Scheme cond’s => keyword.

3.9  scmxlate-eval

The test argument of scmxlate‑cond and all the arguments of scmxlate‑insert are evaluated in the Scheme global environment when Scmxlate is running. You can enhance this environment with scmxlate‑eval. Thus, if we had

(scmxlate-eval
  (define *unix-shell-magic-line* <...>)
  (define *windows-shell-magic-line* <...>))

where the <...> stand for code that constructs the appropriate string, then we could use these variables as the arguments to scmxlate‑insert in the example under scmxlate‑cond.

scmxlate‑eval can have any number of subforms. It evaluates each of them in the given order.

3.10  scmxlate-compile

scmxlate‑compile can be used to tell if the output file is to be compiled. Typical usage is

(scmxlate-compile #t)      ;or
(scmxlate-compile #f)

The first forces compilation but only if the dialect supports it, and the second disables compilation even if the dialect supports it. The argument of scmxlate‑compile can be any expression, which is evaluated only for its boolean significance.

Without a scmxlate‑compile setting, Scmxlate will ask the user explicitly for advice, but only if the dialect supports compilation.

3.11  scmxlate-include

It is often convenient to keep in a separate file some of the portions of the text that should go into a dialect-configuration file. Some definitions may naturally be already written down somewhere else, or we may want the text to be shared across several dialect-configuration files (for different dialects). The call

(scmxlate-include "filename")

inserts the contents of "filename" into that location in the dialect-configuration file.

3.12  scmxlate-uncall

It is sometimes necessary to skip a top-level call when translating an input file. For instance, the input file may be used as a script file whose scriptural action consists in calling a procedure called main. The target dialect may not allow the output file to be a script, so the user may prefer to load the output file into Scheme as a library and make other arrangements to invoke its functionality. To disable the call to main in the output file, add

(scmxlate-uncall main)

to the configuration file.

scmxlate‑uncall can take any number of symbol arguments. All the corresponding top-level calls will be disabled in the output.