Copyright © 1996, 1997 Lucent Technologies Inc. All rights reserved.

1 Overview and introduction

A Limbo application consists of one or more modules, each of which supplies an interface declaration and an implementation part. A module that uses another module includes its declaration part. During execution, a module dynamically attaches another module by stating the other module's type identifier and a place from which to load the object code for its implementation.

A module declaration specifies the functions and data it will make visible, its data types, and constants. Its implementation part defines the functions and data visible at its interface and any functions associated with its data types; it may also contain definitions for functions used only internally and for data local to the module.

Here is a simple module to illustrate the flavor of the language.

1	implement Command;

2	include "sys.m";
3	include "draw.m";

4	sys:	Sys;

5	Command: module
	{
6	    init: fn (ctxt: ref Draw->Context, argv: list of string);
7	};
8	# The canonical "Hello world" program, enhanced
9	init(ctxt: ref Draw->Context, argv: list of string)
10	{
11		sys = load Sys Sys->PATH;
12		sys->print("hello world\n");
13		for (; argv!=nil; argv = tl argv)
14			sys->print("%s ", hd argv);
15		sys->print("\n");
16	}
A quick glance at the program reveals that the syntax of Limbo is influenced by C in its expressions, statements, and some conventions (for example, look at lines 13-14), and also by Pascal and its successors (the declarations on lines 4, 6, 9). When executed in the Inferno environment, the program writes hello world somewhere, then echoes its arguments.

Let's look at the program line-by-line. It begins (line 1) by saying that this is the implementation of module Command. Line 2 includes a file (found in a way analogous to C's #include mechanism) named sys.m. This file defines the interface to module Sys; it says, in part,

Sys: module {
	PATH: con "$Sys";
	. . .
	print: fn (s: string, *): int;
	. . .
};
This declares Sys to be the type name for a module containing among other things a function named print; the first argument of print is a string. The * in the argument list specifies that further arguments, of unspecified type, may be given.

Line 3 includes draw.m; only one piece of information, mentioned below, is used from it. Line 4 declares the variable sys to be of type Sys; its name will be visible throughout the remainder of the file describing this module. It will be used later to refer to an instance of the Sys module. This declaration initializes it to nil; it still needs to be set to a useful value.

Lines 4-7 constitute the declaration of Command, the module being implemented. It contains only a function named init, with two arguments, a ref Draw->Context and a list of strings, and it doesn't return any value. The ref Draw->Context argument would be used if the program did any graphics; it is a data type defined in draw.m and refers to the display. Since the program just writes text, it won't be used. The init function isn't special to the Limbo language, but it is conventional in the environment, like main in C.

In a module designed to be useful to other modules in an application, it would be wise to take the module declaration for Command out, put it in a separate file called command.m and use include command.m to allow this module and others to refer to it. It is called, for example, by the program loader in the Inferno system to start the execution of applications.

Line 8 is a comment; everything from the # to the end of line is ignored.

Line 9 begins the definition for the init function that was promised in the module's declaration (line 6). The argument that is a list of strings is named argv.

Line 11 connects the program being written to the Sys module. The first token after load is the target module's name as defined by its interface (here found in the include on line 2) The next token is the place where the code for the module can be found; it is a string that usually names a file. Conventionally, in the Inferno system, each module contains a constant declaration for the name PATH as a string that names the file where the object module can be found. Loading the file is performed dynamically during execution except for a few modules built into the execution environment. (These include Sys; this accounts for the peculiar file name $Sys as the value of PATH.)

The value of load is a reference to the named module; line 11 assigns it to the variable sys for later use. The load operator dynamically loads the code for the named module if it is not already present and instantiates a new instance of it.

Line 12 starts the work by printing a familiar message, using the facilities provided by module Sys through its handle sys; the notation sys->print(...) means to call the print function of the module referred to by sys. The interface of Sys resembles a binding to some of the mechanisms of Unix and the ISO/ANSI C library.

The loop at lines 13-14 takes the list of string argument to init and iterates over it using the hd (head) and tl (tail) operators. When executed, this module combines the traditional `Hello world' and echo.

05/Jun/97