% (C) Copyright International Business Machines Corporation 23 January 
% 1990.  All Rights Reserved. 
%  
% See the file USERAGREEMENT distributed with this software for full 
% terms and conditions of use. 
\section{Using Hermes under Unix}
\label{Unix}
\subsection{Storing Hermes modules in Unix files}
Hermes programs consist of definition modules and process modules,  
each contained in a separate Unix file.  
A definition module {\bf foo} must be stored in a file named
{\bf foo.d}; a process module {\bf bar} must reside in a file 
named {\bf bar.p}.
The compiler creates
files with names ending in {\bf .o} to store
object modules.
A {\bf .po} file stores a compiled process module; a {\bf .do}
file stores a compiled definitions module. 
These
generated files will be placed in the current directory by the compiler,
overwriting any previous versions in the directory.

% In summary, there are four types of files of interest to the Hermes 
% compiler and run-time system:
% \begin{itemize}
% \item a {\bf .d} file is a definition module source file, created by a Hermes 
% programmer, 
% 
% \item a {\bf .p} file is a process module source file, created by a Hermes 
% programmer, 
% 
% \item a {\bf .do} file is a compiled definitions module created by the Hermes 
% compiler from a definitions module, and \\
% 
% \item a {\bf .lo} file is a compiled process module created by the Hermes 
% compiler from a process module.
% \end{itemize}

\subsection{Where Hermes looks for files}
To compile a module that imports another module, the compiler must read
the imported module's object file.
For instance, to compile a module {\bf bar} with {\bf foo} in its
{\tt using} list, the compiler must load
{\bf foo.do}.  Similarly, if {\bf boz}
statically links module {\bf zip}, then the compiler must load {\bf zip.po}
to compile {\bf boz}.  {\em Of course, imported modules must 
be compiled before the module that uses them.}

The run-time system must also
read compiled {\bf .po} files.  When a running Hermes program {\bf bar}
dynamically loads a process module {\bf zip}, the run-time system must
load the module {\bf zip.po}.  

Hermes
programs identify modules by their internal Hermes names, which keeps
Hermes independent of any specific operating system.
To use Hermes on Unix these names are mapped into file names by
searching for files in the list of directories in the 
the Unix environment variable HPATH.  
The Unix Hermes compiler and run-time system load an object module
by appending the appropriate suffix ({\bf do} or {\bf po}) and
searching sequentially through the list of directories in HPATH
for a file with that name.
%(HPATH can be set with the csh command `setenv HPATH dir1:dir2: ... :dirn',
% and printed with the csh command printenv.)
(HPATH also navigates the search for other Hermes objects.  See section
\ref{mainIntf} on the standard interface). 

% Because Hermes programs specify modules only by their internal Hermes
% name (e.g., {\bf foo, bar, zip}), but not by a path prefix (e.g., 
% % {\bf /distributed/computing/lib/foo.do, /hermes/progs/bar.po, 
% % /local/u/pip/zip.po}), the Hermes compiler and run-time system
% need to know where to locate {\bf .do} and {\bf .po} files.  This
% is done by the Unix environment variable HPATH.  

% HPATH is a Unix path variable that specifies what directories should
% be searched (and the order of the search) to find {\bf .do} and {\bf .po}
% files.  (This path variable is used to search for other Hermes objects as 
% well.  See section \ref{mainIntf} on the standard interface). 

For example, suppose HPATH is defined as follows:\\
HPATH = .:/hermes/lib:/hermes/defs:/u/pip:/progs/v1:/progs/v2

In this case, the compiler searches for a file named {\bf foo.do}
or {\bf bar.po} by first looking in the current directory, and then in
/hermes/lib, then in /hermes/defs, etc.  
If the file is not in any of these directories, the appropriate exception
would be raised.  

\subsection{Other Unix environment variables}
BLOCKINGIO determines whether the interpreter blocks for terminal IO.
If BLOCKINGIO is set
(its value is irrelevant), then the interpreter will block whenever
waiting for IO from the terminal.  If variable is not set, then it
will not block when waiting for IO.  The disadvantage of using
BLOCKINGIO is that the whole system may hang while waiting for IO.
The disadvantage of using non-blocking IO is that it is currently
implemented using polling and therefore degrades system performance.

The HDEBUG environment is an integer that controls the level of debugging
information displayed by the Hermes interpreter.  The higher the value
of HDEBUG the more debugging information displayed.
A HDEBUG value of $n$ enables debugging output for all levels $i \leq n$.
Current debugging levels follow.\footnote{Debugging support will certainly change.}

\begin{enumerate}

\item[0]A message is generated when an interface mismatch occurs.
The message includes the names of the processes involved in the
attempted create operation, as in: $$\hbox{'foo' can't create 'bar'}$$

\item[1]

\begin{itemize}

\item If an unhandled exception occurs (this should never happen for
programs parsed by the Hermes compiler), the offending process's
status info is displayed.

\item An error message is displayed when a Hermes object file cannot be opened
for reading.

\item An error message is displayed when a second attempt is made to set the
network linking port.

\end{itemize}

\item[2]A message is displayed every time a Hermes object file is
read.  This can be very useful for tracking down problems related to
incorrect HPATH settings, since the full pathname of the object file
is displayed.
The message says {\tt XDR Reading '<full pathname>'}.

\item[7]All messages sent to or received from remote interpreters are
logged.

\item[15]When an {\tt OTHERS} handler is invoked for a process,
the process' status is displayed.

\item[20]{\tt malloc\_debug(1)} is issued, to cause extra checking to
be performed by {\tt malloc} and related routines.  ({\em Sun only})

\item[99]{\tt malloc\_debug(2)} is issued, to cause the entire heap to
be checked for consistency on every call to {\tt malloc} and friends.
({\em Sun only})

\end{enumerate}


\section{Compiling and executing Hermes programs}
\label{compile}
To run a Hermes program {\bf bar} (stored in file {\bf bar.po}) from 
a Unix shell, issue the command: \\
{\bf hermi bar \{ args \}}.  

{\bf hermi} invokes the Hermes interpreter.  {\bf hermi bar \{ args \}} starts a root 
process that parses the command line and attempts to load
the  
process module {\bf bar}.  Section \ref{mainIntf} below discusses
how command line arguments are passed to the {\bf bar}.  

The Hermes program that compiles a Hermes definitions module is {\bf dcom}.  
Hence
to compile the definitions module {\bf foo}, issue the command
{\bf hermi dcom foo}.  {\bf dcom} assumes that the file {\bf foo.d} exists
in the current directory.  If you want to compile a definitions module which 
resides in a different directory, you must supply a pathname, such as 
{\bf hermi dcom /hermes/defs/foo}.  In either case, the compiled 
definitions {\bf foo.do} will be put in the current directory.  

The compiler {\bf dcom} has 3 phases: parsing, checking, and
typestate rewriting.\footnote{The final phase converts certain
typestate constructions into the canonical form required by the
typestate checker.}  A successful compilation of definitions module
{\bf foo} will generate the message:

{\bf parse[foo.d] checkdefs fixdefs store[foo.do]}

The Hermes program {\bf pcom} compiles Hermes process modules, so
to compile the process modules {\bf bar [ bar2 ] }, issue the 
command {\bf hermi pcom [ options ] bar [ bar2 ] }.   
The Unix file {\bf bar.p} must be stored in the current directory, or
{\bf bar} must be a full pathname, as discussed above for definitions modules.  
A successfully compiled process module, {\bf bar.po}, will be put 
in the current directory.  

The compiler {\bf pcom} has 4 phases: parsing, type checking,
typestate checking, and code generation.  A successful compilation
of module {\bf bar} will generate the message:

{\bf parse[bar.p] typecheck typestate codegen store[bar.po]}

If the compilation detects an error it prints an error message and
halts without writing {\bf bar.po}.

% The following options can be supplied to pcom.
% \begin{itemize}
% \item[-noTCheck]  The program is not checked for type errors, 
% and no type inferencing is done.  Subsequent code generation may fail
% if the source program was not completely typemarked.  
% Run-time errors can result from incorrect programs, since
% things like passing an object of the wrong type on an outport will 
% be allowed.
% 
% \item[-noTSCheck]  The program is not checked for typestate errors, and no
% coercions are generated.  Due to the lack of coercions, the resulting
% program can have unintended semantic effects and will probably contain
% memory leaks.  If the program is not typestate correct, skipping this
% checking phase can result in run-time errors since
% things like accessing fields of uninitialized records will be allowed.
% 
% \item[-noObject]  No compiled program object will be generated.  This is 
% useful for submitting a program to type or typestate checking only,
% without overwriting an existing .po file.
% 
% \end{itemize}
% 
% We stress that no code can be relied upon unless it is run through the 
% compiler in its entirety.  

\section{Using the Hermes shell and cache}
\label{shell}

Executing every Hermes command from the Unix command line performs
poorly because {\bf hermi} 
reads a lot of object modules from disk.
To improve performance we provide the Hermes shell and cache, which
provides an environment in which to efficiently load and run many 
Hermes programs.  We recommend that you use the cache shell.

To start the shell type {\bf hermi shell}.
This produces a new prompt ({\bf shell:}).  Any Hermes program can now
be invoked by typing its name.
(You cannot prefix the command with {\bf hermi})  For instance, to
compile the definitions module {\bf foo} from the shell, type the command 
{\bf dcom foo}.  

The shell supports a limited number of commands, such as changing 
directories.  To change directories from the shell, issue the
command {\bf cd pathname}, where {\bf pathname} is a complete Unix
path.  For example, to connect to /distributed/computing/lib from
/distributed/computing issue the command 
{\bf cd /distributed/computing/lib}.

Another utility provided with the Hermes system is a software cache.  It
is invoked by the command {\bf hermi cache zip}, 
where {\bf zip} is a Hermes program.  This will run the program {\bf zip}, 
and will also cache all processes dynamically loaded during the execution 
of {\bf zip}.  Hence, 
if {\bf zip} causes process {\bf bar} to be loaded many times, only the first 
time will {\bf bar} be fetched from disk.  Subsequently {\bf bar} will be 
loaded directly from the cache (assuming that {\bf bar.po} has not 
been changed since it was first loaded).  For many applications, the cache 
can significantly improve run-time performance.

The best way to use the Hermes shell is in conjunction with the cache
by invoking the command {\bf hermi cache shell}.  
This will create a shell with a software cache.  Any modules loaded while
in the shell will be cached.  For instance, when compiling many 
modules from the cached shell, the compiler will be loaded on only the 
first compile.  This dramatically improves compilation time on subsequent compiles.  

\section{The standard interface}
\label{mainIntf}
When a Hermes program starts up, the Hermes run-time system provides
initial capabilities (e.g., to load in additional modules, to print to
the terminal, etc.) to the program.  This is done by passing a message
to the program on its {\it initport}.   Currently, Hermes supports
two  types of interfaces.  In section \ref{main}, we describe
the {\tt main} interface.  In the following section we describe the {\tt rmain}
interface.  Although most existing Hermes code uses the
{\tt main} interface, we expect future releases of Hermes to use the latter
type of interface, as it is based on a more generic {\it resource manager}
paradigm.  

\subsection{The {\tt main} interface}
\label{main}
When invoking a Hermes process {\bf bar} by the command {\bf hermi bar},
the Hermes system will send a callmessage to {\bf bar} over its 
{\em initport}  (see the manual for a detailed explanation of callmessages
and ports).   The type of this initport should be declared to be
{\em main\_Q}, which is an inport of the callmessage type 
{\em main\_Intf} \footnote{In general, we encourage adopting the following
naming conventions: if an interface type is {\bf foo}, then an inport of
type {\bf foo} is named {\bf fooQ} and an outport of {\bf fooQ} is named
{\bf fooFn}.  Some old Hermes code may use different conventions.}.  

The callmessage main\_Intf is defined in {\bf main.d}.  It imports definitions
from {\bf CLoad.d,  common.d, root.d, unix.d}, and {\bf stdenv.d}.  These 
modules can all be found in the directory hermes/interface.  We will
present an overview of the interface callmessage main\_Intf.  We encourage
users to become familiar with this interface as it provides many services
they may want to use.  

\begin{tt}
\begin{verbatim}
-- interface to Hermes main programs (as called by root.p)  
  main_Intf: callmessage (
    argv: common!charstringList,
    environ: root!environ,
    std: stdenv!stdenv,
    unix: unix!unix,
    CLoader: CLoad!CLoadFn
  ) constant (argv, environ, std, unix, CLoader)
    exit { full };
\end{verbatim}
\end{tt}

The first field, argv, gives the command line arguments when the function 
is invoked.  E.g., the command {\bf hermi bar cat dog gorilla} would pass
the strings {\bf hermi}, {\bf bar},  {\bf cat}, {\bf dog}, and {\bf gorilla} in 
the argv field to the function bar.  

The second field, environ, contains the name and value of all Unix 
environment variables.  

The third field, std, contains I/O related capabilities;  In particular, it
provides a function to dynamically load compiled Hermes programs, functions
to read/write arbitrary Hermes objects to disk\footnote{For instance, a program 
can write a table to disk and then read the table back from disk into a 
variable of the appropriate type.}, a function to store programs into a
library, functions to manipulate the current working directory, and 
functions for doing terminal IO.  (See section \ref{tools} on tools for
doing window IO).  

For example, the shortest Hermes {\tt Hello, world!} program is
\begin{verbatim}
main:  using(main) process(Init: main_Q)
  declare  
    Parms: main_intF; 
  begin 
    receive Parms from init;
    call Parms.std.terminal.putLine("Hello, World!");
    return Parms;
  end process 
\end{verbatim}

The fourth field, unix, provides capabilities to invoke Unix services.  
This is divided into general Unix functions, functions to check the access
modes of files, functions access to special Unix variables
(errno, stdin, stdout, stderr), and functions for file-related services.  

The last field, CLoad, contains the capability to invoke special built-in
processes written in C.

\subsection{The resource manager interface}
Another paradigm for providing initial capabilities to a program is 
based upon the {\it resource manager} paradigm, described in section
\ref{resource}.  In this case, the type of the initport of the program is
not {\it main\_Intf} but {\it rMain}, defined in 
hermes/tools/rmanager/rmain.d. 

If the program {\bf bar} uses the rmain interface, then to invoke the
program issue the command: {\bf hermi rmain bar}  (not 
hermi bar!).  This invokes the program {\bf rmain}
(which can be found in hermes/tools/rmanager/rmain.p) which initializes
the resource manager passed to {\bf bar} on its initport and then
invokes {\bf bar}.  The resources
it provides to {\bf bar} are exactly those it would get using the 
{\it main\_Intf}.  Note, however, that {\bf bar} accesses these resources
differently then it would using the main\_Intf interface.  

Section \ref{distributed} will describe a tool to communicate with Hermes processes
running on remote machines.  As described in that section, this tool also makes
use of resource manager, but it provides additional capabilities to 
the invoked process.  


