This section explains some of the basic elements of using the Standard ML of New Jersey compiler as an interactive system into which you enter declarations and expressions or load code from source files. This is the most accessible mode of using the compiler, but for any programs of nontrivial size we recommend that the Compilation Manager be used to organize the compilation and loading process.
Warning
|
We assume below that you are using the compiler under Unix (including the macOS Terminal app). The behavior will be somewhat different under MS Windows or macOS. |
Running Standard ML
Type sml
from the shell (command line). This puts you into the interactive system or
“REPL”. The top level prompt is “-”, and the secondary prompt (printed after a newline
when the input is incomplete) is “=”. If you get the secondary prompt when you don’t expect it, typing ;
return
will often complete your input, or typing the interrupt character (normally,
control-C) will cancel your current input and return to the SML
top level.
If the command sml
doesn’t work, ask where sml
has been installed on your machine and
use the appropriate full path name or redefine your Unix PATH environment variable to include
the directory containing the sml
command.
Interactive input
Input to the top level interpreter (i.e., declarations and expressions) must be terminated
by a semicolon followed by a carriage return before the system will evaluate it. The system then
prints out a response indicating the effect of the evaluation. Expressions are treated as
implicit declarations of a standard variable named it
. For example,
- 3; (* prompt character followed by user input *)
val it = 3 : int (* system response *)
This means that the value of the last top level expression evaluated
can be referred to using the variable it
. But remember that it
will be redefined
after evaluating the next top-level expression. Top-level declarations do not redefine
it
.
Interrupting compilation or execution
Typing the interrupt character (normally control-C) should interrupt the compiler and return you to top level. Sometimes you may have to type it twice.
Exiting the interactive system
Typing control-D (EOF) at top level will cause an exit to the shell
(or to the parent process from which the sml
command was run). One can also terminate
the interactive session by calling OS.Process.exit(OS.Process.success)
.
Loading ML source text from a file
The function
val use: string -> unit
is defined at top-level (that is, in the top-level interactive environment) and, when
called, interprets its argument as a file name relative to the sml
process’s current directory
and loads the text from that file as though it had been typed into the interactive system.
This should normally be executed at top level, but the file being read can also contain calls
of use
to recursively load other files. It is a not indended that use
be called
within an expression or declaration, because the effects of such calls are not well-defined.
For loading serious multi-file programs, you should use the Compilation Manager.
Error messages
The compiler attempts to recover from syntactic errors so that it can also produce
semantic (type-checking) errors during the same compilation. Syntactic error recovery is
more accurate for source files loaded by use
or CM than it is from declarations typed
directly into the interactive system — this is because lookahead is not possible when
text is entered one line at a time.
When compiling files, the error messages include line numbers and character positions within the line. For example:
- if true
= then 5 true
= else 6;
std_in:7.6-7.11 Error: operator is not a function
operator: int
in expression:
5 true
-
Here the location information std_in:7.6-7.11
indicates that the erroneous expression 5
true
occupies characters 6 through 11 of the 7th line of input from std_in
. For simple
syntactic errors this position information is usually accurate or perhaps off by just one
line. For some classes of errors the line numbers may not be very useful, because they
delineate a potentially large declaration containing the error. If the error occurs in a
file being loaded by <code>use</code>, the line numbers will refer to lines in the file
being loaded.
There are a number of different forms of type error message, and it may require some
practice before you become adept at interpreting them. The most common form indicates a
mismatch between the type of a function (or operator) and its argument (or operand). A
representation of the offending expression is usually included, but this is an image of
the internal abstract syntax for the expression and may differ significantly from the
original source code. For instance, an expression if e1 then e2 else e3
is represented
internally as a case expression over a boolean value: case e1 of true ⇒ e2 | false ⇒
e3
.
All the error messages produced by SML/NJ are documented in the SML/NJ Error and Warning Messages page.
Compiler interface
Most users will interact with the compiler by loading code via the use
command or under
control of CM. However, some control of individual compiler phases is possible through the
Compiler.Control
structure.
Printing
The structure Compiler.Control.Print
contains
several useful flags and functions with which you can control or redirect compiler error,
diagnostic, and result messages. Among other things, there is a variable printDepth
that controls the cut-off depth of printing of large structured values.
Interacting with the operating system
The Standard ML Basis Library contains a number of structures, such as TextIO
, BinIO
,
OS
that provide support for such tasks as executing other programs from within sml
and
changing the current directory. These are documented in smlfamily.org/Basis:[The Standard
ML Basis Library].