The standalone batch compiler is used to produce components from source files.
________ Synopsis ____________________________________________________
All <input file>s are compiled as Alice source programs and corresponding components are written as output. If <output file> is given after an <input file>, it is used as the respective output file name, else the basename of <input file> is used with .alc as extension. Compiled components can be executed by invoking the virtual machine.
An <input file> may be a URL. See below for notes on how they are interpreted. An <output file> may only be omitted if the preceding <input file> represents a local file.
To compile a component, the compiler requires access to all imported component files whose import signature omit type information in the source file. If one does not exist, but a source file for it (i.e., a file with same name but ending in .aml, .sml, or .sig) can be located, the compiler first invokes itself recursively to compile the imported component. If a component does exist, the compiler does not perform any check to verify whether it is up-to-date. External tools like make have to be used, in conjunction with the dependency analyzer, to ensure proper recompilation if necessary.
Invoking the compiler with option -r instead of -c enables smart recompilation. When the compiler is initiated in this mode, the output component is only created when it does not exist yet, or is out of date.
The target component file is considered out of date if either of the following holds:
The smart recompilation mode is particularly useful in conjunction with tools like make. It avoids redundant regeneration of existing target files and hence can cut off subsequent recompilation further down the dependency chain. To take advantage of this, simply invoke the Alice compiler in smart recompilation mode in your Makefile and the tool figures out the rest by itself. You do not need to modify dependencies declarations (like e.g. generated by the dependency analyzer for Alice).
Print compiler version.
Set assertion level (0 by default).
Trace compilation phases.
Output component's export signature.
Warn about unused imports (on by default).
Warn about imports inserted by the compiler for closing over implicit import signatures (off by default).
Warn about local types occuring in the computed export signature of the component, as they will prevent the component being imported in full (on by default).
Warn about violations of standard naming conventions (on by default).
Warn about shadowing of identifiers (off by default, gives a lot of spurious warnings).
Recursively compile imports if they do not exist in compiled form yet (does not perform any up-to-date checks!).
Use dependency file to automatically derive import announcements.
Write type information to a file for use by external tools, e.g. smart editors.
Minimize output component.
Alice employs a compilation model that is quite different from other Standard ML systems. In particular, Alice ML requires putting explicit import announcements into source files to enable separate compilation.
In order to allow for easier migration or sharing of SML source code with other SML systems, the Alice compiler supports two methods for inserting import announcements automatically:
If the input file has the file extension .sml or .sig, then the compiler looks for a file with the same name but the extension .import. If found, the contents of that file is prepended to the actual input file.
The --dependency-file option allows specifying a file listing the dependencies between ML source files. The format of a dependency file is as follows:
dep-file | ::= | {dep-line}* |
dep-line | ::= | file-name : {file-name}* |
The format resembles (a subset of) makefile syntax:
Each line is headed by a file name denoting a source file, the target. After the colon follows a list of files the target depends on, its prerequisites. When a source file is compiled with a dependency file that contains its name as a target, then the source file is modified by prepending an import announcement for each prerequisite of the target. Extensions of target file names are ignored, a target is assumed to denote the current source file if its base name is the same. Likewise, prerequisites are stripped of their extension. That allows using makefile dependencies directly as dependency files.
Consider the following dependency file:
# project.depend A.alc: B.alc C.alc D.alc B.alc: C.alc: D.alc
By invoking
alicec --dependency-file project.depend A.sml
A.sml will be compiled as if it contained the following import announcements:
import "B" import "C" import "D"
Moreover, if both, a requisite and the respective target are relative paths, then the requisite's path is rewritten relative to its target. For example, assume:
# project.depend sub/A.alc: B.alc ../C.alc sub/D.alc
By invoking
alicec --dependency-file project.depend sub/A.sml
sub/A.sml will be compiled as if it contained the following import announcements:
import "../B" import "../../C" import "D"
If a target is contained multiple times in a dependency file the corresponding prerequisites are accumulated. The compiler may be invoked with multiple dependency files, with the effect of invoking it with the concatenation of those files.
The first of these options essentially requires creating a separate import file for each individual SML file. The second option allows gathering all the necessary information into a single dependency file.
Please note that these methods are provided solely for better compatibility with other SML systems. Using them for native Alice components is strongly discouraged.
Depending on the structure of the sources, using a dependency file may yield a lot of spurious "unused import" warnings, because it invariably inserts imports for all entities defined on the top-level of a source file. You may want to use the --no-warn-unused-imports flag to avoid this.
The batch compiler is parameterized by the same environment variables as the virtual machine, plus:
specifies how source file URLs are interpreted. If set, the value of this environment variable is parsed by the parse method of the Resolver.Handler structure. If not set, uses only the default identity method.