SML# Document Version 3.7.1
16 The SML# Structure

16.2 Programs in the separate compilation mode

A program in the separate compilation mode is a set of source files and their interface files. The contents of a source file, denoted here as source, are given below.

source ::= (interfaceFileSpec)?  sourceProgram
interfaceFileSpec ::= _interface  "filePath"
sourceProgram ::=
 | decl  sourceProgram
 | topdecl  sourceProgram

If there is no interface file specification interfaceFileSpec in a source file and there is a file of the same name S.smi as that of the source file S.sml (except for its suffix) in the same directory, then that file is implicitly specified as the interface file of the source file. filePath is a relative path. Regardless of OS, / (slash) is used for directory separator.

The contents of an interface file, interface, consist of requireList that specifies the set of interface file paths required for the source file, and provideList that specifies the set of declarations the source file provides to the other compilation units.

interface ::= requireList  provideList
requireList ::=
 | _require  (local)?  interfaceName  requireList  (init)?
 | _require  (local)?  sigFilePath  requireList  (init)?
interfaceName ::= smiFilePath
 | librarySmiFilePath
provideList ::=
 | provide  provideList
provide ::= provideInfix
 | provideVal
 | provideType
 | provideDatatype
 | provideException
 | provideStr
 | provideFun

requireList specifies interface file names (file path or library name) of source files or signature file paths referenced by the source file. local directive in a _require declaration indicates that the specified interface file is only used inside of the source file and does not referenced in provideList. init is an annotation indicating that the program corresponding to the specified interface must be executed and precede the program that _requires it. provideList specifies the set of declarations the source file provides to the other compilation units.

smiFilePath, sigFilePath, and librarySmiFilePath are file paths relative to the file in which _require is written. Regardless of OS, / (slash) is used for directory separators. If a path does not begins with . (period) and the specified file does not exist, the compiler searches for the file from the load path given in the command line.

SML# provides the following interface libraries.

library smi file name contents
basis.smi Standard ML Basis Library
ml-yacc-lib.smi yacc and lex tools
smlformat-lib.smi SMLFormat formatter generator
smlnj-lib.smi Standard ML of New Jersey library
ffi.smi C FFI support library
thread.smi Multithread library
reify.smi Dynamic typing library
smlunit-lib.smi SMLUnit tool

The following summarizes provide specifications corresponding to declarations.

  • Correspondence between core declarations and their interfaces

    declaration (decl) corresponding provide (provide)
    infixDecl provideInfix
    valDecl provideVal
    valRecDecl provideVal
    funDecl provideVal
    datatypeDecl provideData
    typeDecl provideType
    exceptionDecl provideException
    localDecl
  • Correspondence between module delcarations and their interfaces

    declaration (topdecl) corresponding provide (provide)
    strDecl provideStr
    sigDecl
    functorDecl provideFun
    localTopdecl

    Signature files are directly referenced in the interface through _require sigFilePath.

We show simple examples below.

  • Example 1 (Using the Standard ML Basis Library)

    file code
    hello.sml val _ = print "Welcome to SML#\n"
    hello.smi _require "basis.smi"

    Compilation and execution

    $ smlsharp hello.sml
    $ ./a.out
    Welcome to SML# $

  • Example 3 (separate compilation)

    file code
    hello.sml val _ = puts "Welcome to SML#"
    hello.smi _require "puts.smi"
    puts.sml val puts = _import "puts" : string -> int
    puts.smi val puts : string -> int

    Compilation and execution

    $ smlsharp -c hello.sml
    $ smlsharp -c puts.sml
    $ smlsharp -o hello hello.smi
    $ ./hello
    Welcome to SML# $