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.
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.
Typically, the Scheme code and scmxlate‑insert
s
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‑insert
s, will show up in the
output file after the translated contents of the input
file.
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"))
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.
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.
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!))
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.
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.
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.
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.
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.
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.