Module Structure

This section explains Austral’s module system.

What is a module?

A module is the main unit of code organization in Austral. A module is a name and a set of declarations, which can be public (importable by other modules) or private.

Module names, like in many programming languages, look like this:

Module names are identifiers separated by dots. Module names are conceptually hierarchical: you start with the name of the project or organization, and subsequent names denote how code is organized. However, modules do not actually form a hierarchy: the module namespace is flat.

Declarations

Modules contain declarations, and there are five kinds of declarations:

We’ll learn about each of these throughout the tutorial.

Visibility

Declarations are be either public or private. Private declarations are invisible to the outside world. Public declarations may be imported by other modules, and imported public declarations act as if they had been defined in the module that imports them.

Type definitions have a third visibility category: opaque. An opaque type is one that can be imported and referred to by other modules, but its contents are hidden. Outside the module that defines them, opaque types cannot be constructed, nor can their contents be accessed.

The usefulness of opaque types is that they can only be created, accessed, and transformed by the API functions of the module that defines them. This allows you to define types which are “correct by construction”, by having the constructor and transformation functions enforce certain invariants.

Interfaces and Implementations

Austral separates modules into a module interface file, with file extension .aui, and a module body file, with file extension .aum.

The point of separating interfaces and implementations is readability: the interface describes all the things module’s declarations that are public and importable by other modules. The implementation contains the things that are private, and the bodies of functions and such. When you’re trying to familiarize yourself with a module in order to use it, you just have to read the interface.

It should be stressed: unlike C and C++, the separation of modules into interfaces and implementations is not a hack to enable separate compilation (in fact, the compiler combines that interface and implementation into a single module representation as one of the earliest stages of compilation).

Examples

This section contains examples of the module system.

Example: Physical Constants

Let’s define a module that exports physical constants.

In the interface file PhysicalConstants.aui, we declare the names of the constants, along with their types and a docstring, but not their values:

module Example.PhysicalConstants is
    """
    The speed of light in meters per second.
    """
    constant speed_of_light: Float64;

    """
    The elementary charge in Coulomb.
    """
    constant elementary_charge: Float64;
end module.

In the module file PhysicalConstants.aum, we actually define the values:

module body Example.PhysicalConstants is
    constant speed_of_light: Float64 := 299792458.0;

    constant elementary_charge: Float64 := 1.602176634e-19;
end module body.

Then, in another module, we can import these constants:

import Example.PhysicalConstants (
    speed_of_light,
    elementary_charge
);

module body Example.Main is
    function main(): ExitCode is
        print("The speed of light is ");
        print(speed_of_light);
        printLn(" meters per second.");
        print("The elementary charge is ");
        print(elementary_charge);
        printLn(" coulombs.");
        return ExitSuccess();
    end;
end module body.

To use all these files together, we must pass all their names to the compiler, with each pair of interface with implementation gathered together via a comma:

$ austral compile PhysicalConstants.aui,PhysicalConstants.aum Main.aum --entrypoint=Example.Main:main --output=constants
$ ./constants
The speed of light is 299792458.000000 meters per second.
The elementary charge is 0.000000 coulombs.