- Up - | Next >> |
The purpose of programming languages is of course the construction of applications. In this chapter we will use Oz for our first small application.
Webget.oza
Our first application is a program that copies a file from a url to a local file. The program is called Webget.oza
.
Our goal is to have an application that can be started like any other application from the operating system shell. For example, executing the command shown in Figure 1.1 gets us a local copy of the Mozart license file.
In addition to taking arguments from the command line, Webget.oza
should report problems by returning an error status to the operating system shell. The error status is an integer, where the value 0
means okay. Any other values signals an error.
In the following we consider the three main steps in constructing our application. We give a brief outline of what to do, the following sections are going to detail the steps.
The first step, of course, is to program our application. For this purpose, we will create a file Webget.oz
that contains the Oz program implementing webget. More specifically, the file Webget.oz
contains a functor definition.
Next, we compile the functor definition contained in Webget.oz
. The compiler takes the functor definition and executes it. By this it creates a functor. Then the functor is written to a file Webget.oza
. This persistent representation of a functor value is called a pickled functor.
The pickled functor Webget.oza
is executed by the Oz virtual machine ozengine
. The engine takes a pickled functor (Webget.oza
in our case), unpickles the functor, runs the functor, and supplies it with application arguments. After execution terminates, it reports the application's execution status back to the operating system shell.
Webget.oza
The toplevel structure of the file Webget.oz
is as follows.
functor
<Module import>
<Functor body>
end
Importing modules
Our application requires the system module Application
to both process the command line arguments as well as for terminating the application. In addition, the module Open
provides the class Open.file
required for reading and writing files.
The functor needs to import these two modules. The functor definition thus contains the following import specification:
import
Application
Open
The import specification serves two purposes: the variable identifiers Application
and Open
are introduced with a lexical scope that extends over the entire body of the functor. Secondly, the identifiers also serve as module names. When the functor corresponding to this definition is executed, the variables are given as values the system modules with the same names.
More precisely, the import specification above is a convenient abbreviation for the more verbose specification below:
import
Application at 'x-oz://system/Application'
Open at 'x-oz://system/Open'
In Section 3.3 we will discuss system modules in more detail. In particular, Table 3.1 lists available system modules.
Functor body
The body of a functor is a statement that is executed when the application is run.
define
<Argument processing>
Status = try
<Opening input and output files>
in
<Copying input file to output file>
0
catch _ then 1
end
<Terminating the application>
The structure for our application is straightforward: after processing the command line arguments, file objects for source and destination are created and the content is copied from the source file to the destination file.
If a runtime error occurs either during opening the files or while copying the file content, the raised exception is caught and the Status
is bound to 1
. Otherwise, Status
gets bound to zero.
Note that the body of a functor is like the part of a local ... in ... end
statement before the in
: definitions and statements are allowed, where the left hand side of definitions can introduce variables.
Processing arguments
The application needs two input parameters: the URL to get the file from, and the file name under which the downloaded content should be stored.
The following application of Application.getCmdArgs
Args = {Application.getArgs record('in'(single type:string)
'out'(single type:string))}
computes Args
to be a record (as signalled by the label record
of the single argument to Application.getArgs
. The features of the record are 'in'
and 'out'
where both fields are of type string and both are allowed to be given only once on the command line (that is specified by single
).
For a complete reference of how application arguments are processed see Chapter 1 of ``System Modules''.
Opening input & output
The two files are opened as follows:
I={New Open.file init(url: Args.'in')}
O={New Open.file init(name: Args.'out'
flags:[write create truncate])}
Note how the strings Args.'in'
and Args.'out'
computed by argument processing are used for the source URL and the destination filename.
Copying input to output
Copying the file from source to destination is straightforward: As long as we can read a non-empty string S
from the source file, we write it to the destination file and repeat the procedure.
local
proc {Copy}
S={I read(list:$)}
in
if S\="" then
{O write(vs:S)} {Copy}
end
end
in
{Copy}
end
Terminating the application
Termination of the application is effected by invocation of Application.exit
which takes the application status as single integer argument. In our case an exit value of 1
indicates an error, otherwise 0
is returned to the operating system shell.
{Application.exit Status}
As is the case for many programming languages, the functor definition must be compiled before it can be executed. This is achieved by invoking the Oz compiler ozc
as follows:
ozc -c Webget.oz -o Webget.oza
Note the intentional similarity between the options illustrated above and those accepted by a C compiler. The compiler ozc
offers a variety of other options that control compilation, an overview of which can be found in Chapter 2 of ``Oz Shell Utilities''.
The functor pickled into Webget.oza
can be executed by applying the program ozengine
to the functor and the application arguments. For example, to copy the Mozart license file at url http://www.mozart-oz.org/LICENSE
to the local file LICENSE
, simply enter the command line shown in Figure 1.1 at your shell promt.
Execution of an application proceeds as follows:
ozengine
, the Oz virtual machine, is started by the operating system.
ozengine
starts to execute a module manager.
The module manager loads the pickled functor Webget.oza
. This initial application functor is called the root functor.
The module manager links the functor by applying the functor body to argument modules. The argument modules in our example are the system modules Application
and Open
.
Then it executes the functor body.
The different steps in application are detailed in the following sections.
- Up - | Next >> |