The top level

This section describes the outer-most contexts of Mars source code. There are two such contexts: module-level, and the interactive prompt.


Mars modules are files containing top-level nodes. Mars source files typically end in the .mar extension. While this is not strictly necessary for a Mars program, it is not possible to import a module unless it ends in .mar.

A module provides procedure and type declarations, which may form all or part of a program. Modules may be used in several ways, including being imported by other modules, having their functions called from the command line, or executed directly as a program.

There are three forms of top-level node: type declarations, procedure definitions and import statements:

module        ::=  NEWLINE* toplevel_node*
toplevel_node ::=  import | typedef | proceduredef

The order in which top-level nodes appear has no consequence.

The import statement

The import statement (not actually considered a statement) is a line which may only appear in the top-level context of a module:

import ::=  "import" identifier NEWLINE

The identifier is the name of a module, to be found in another file on the system. The import statement adds all types and procedure declared in the imported module to the current one, as if they had been declared directly. There are no namespaces - all types and procedures are lumped in together.

If a module is imported more than once, subsequent imports are ignored. Therefore, it is legitimate for a module to import another module twice, or for two imported modules to each import the same module, or even for modules to have cyclic imports.

The module is found by searching for files of the same name, but with the .mar extension. For instance, the following line:

import foo

causes Mars to search for a file called foo.mar.

Mars searches the following places, in order:

  1. The directory the current module is located in.
  2. The environment variable MARSPATH, if it exists, should contain a list of paths separated by colons (”:”). Each of these paths are searched, in order from left to right.
  3. The implementation may define a fixed sequence of paths to search as a fallback. For instance, the current implementation (on Unix) searches in /usr/lib/mars, then /usr/local/lib/mars.

If a file of the given name is found, it is imported into the current module. If it is not, it is a critical error and the compiler MUST reject the program.


Modules designed to be executed directly are called programs.

For a module to be considered a program, it must have a function called main, of type () -> io Num. Mars interpreters or compilers may directly execute such a program, by calling this function.

The I/O side-effects of evaluating main form the behaviour of the program, while the result should be considered the exit status of the program. The result is rounded towards zero and converted into a signed integer with the same word size as the C int type; if the value is larger than this type allows, the result is undefined. On a successful execution, the main function should return 0.

A Mars program SHOULD be marked as executable on filesystems which support it, and begin with the following line:

#!/usr/bin/env mars

This allows the program to be executed directly in a Unix environment in which Mars has been correctly installed.

Modules SHOULD NOT begin with this line, or be marked executable, unless they contain a main function intended for direct execution, in order to avoid confusion.

Interactive environment

The interactive environment allows Mars modules to be explored at the command prompt, without having to write wrapper code just to try out a function.

The prompt asks the user for a sequence of statements. Each statement is executed immediately after it is typed. Statements executed at the interactive prompt are considered to be in an I/O context. Executing statements at the command line differs from statements inside a procedure in a number of ways:

  1. Firstly, the interactive prompt allows special commands which are not valid Mars syntax. These commands all begin with a colon (”:”), and are outside the scope of this document. Type “:?” at the prompt for information.
  2. These statements may not be compound statements. They must be of the form basic_statement.
  3. Statements are checked semantically immediately after being typed. Any semantic errors merely cause the statement to be ignored, rather than the entire program being rejected.
  4. Statements of the form expression_stmt have special behaviour – the resulting value is converted into a string using the built-in show function, and then that string is printed to standard output. This allows the result of an expression to be seen, rather than just thrown away.
  5. Variable assignment works differently to the way it works in a procedure body. If a variable is assigned when it already exists, its previous value and type are discarded, and the variable is re-declared with the type of the expression. This means that variables may be re-assigned with a new type, which is not possible in the body of a procedure.

Table Of Contents

Previous topic


Next topic

Mars Library Reference

This Page