File r38/doc/manual2/gentran.tex artifact 2a292563d4 part of check-in 750610997a


\chapter{GENTRAN: A code generation package}
\label{GENTRAN}
\typeout{{GENTRAN: A code generation package}}

{\footnotesize
\begin{center}
Barbara L. Gates \\
RAND \\
Santa Monica CA 90407-2138 \\
U.S.A. \\[0.1in]
Michael C. Dewar \\
School of Mathematical Sciences, The University of Bath \\
Bath BA2 7AY, England \\[0.05in]
e--mail: mcd@maths.bath.ac.uk
\end{center}
}

\ttindex{GENTRAN}

GENTRAN is an automatic code GENerator and TRANslator which runs under
\REDUCE.  It constructs complete numerical programs based on sets of
algorithmic specifications and symbolic expressions.  Formatted
FORTRAN, RATFOR, PASCAL or C code can be generated through a series of
interactive commands or under the control of a template processing
routine.  Large expressions can be automatically segmented into
subexpressions of manageable size, and a special file-handling
mechanism maintains stacks of open I/O channels to allow output to be
sent to any number of files simultaneously and to facilitate recursive
invocation of the whole code generation process.  GENTRAN provides the
flexibility necessary to handle most code generation applications.  It
is designed to work with the SCOPE code optimiser.

GENTRAN is a large system with a great many options.  This section
will only describe the FORTRAN generation facilities, and in broad
outline only.  The full manual is available as part of the \REDUCE\
documentation.

\section{Simple Use}

A substantial subset of all expressions and statements in the \REDUCE{}
programming language can be translated directly into numerical code.
The {\bf GENTRAN} command takes a \REDUCE\ expression, statement, or
procedure definition, and translates it into code in the target
language.

\begin{describe}{Syntax:}
{\bf GENTRAN} {\it stmt} [ {\bf OUT} {\it f1,f2,\dots\  ,fn} ]{\it ;}
\end{describe}

{\it stmt} is any \REDUCE\ expression, statement (simple, compound, or
group), or procedure definition that can be translated by GENTRAN into the
target language.
{\it stmt} may contain any number of calls
to the special functions {\bf EVAL}, {\bf DECLARE}, and {\bf LITERAL}.
{\it f1,f2,\dots\  ,fn } is an optional argument list containing one or more
{\it f}'s, where each {\it f} is one of:
\par
\begin{tabular}{lll}
{\it an atom} &= &an output file\\
{\bf T} &= &the terminal\\
{\bf NIL} &= &the current output file(s)\\
\ttindex{ALL"!*} {\bf ALL!*} &= &all files currently open for output \\
& & by GENTRAN (see section~\ref{GENTRAN:output})\\
\end{tabular}

If the optional part of the command is not given, generated code is simply
written to the current output file.  However, if it is
given, then the current output file is temporarily overridden.  Generated
code is written to each file represented by
{\it f1,f2,\dots\  ,fn} for this command only.  Files which were open prior
to the call to {\bf GENTRAN} will remain open after the call, and files
which did not exist prior to the call will be created, opened, written to,
and closed.  The output stack will be exactly the same both before and
after the call.

{\bf GENTRAN}  returns the name(s) of the file(s) to which code was
written.

\index{GENTRAN package ! example}
\begin{verbatim}
1: GENTRANLANG!* := 'FORTRAN$

2: GENTRAN
2:     FOR I:=1:N DO
2:         V(I) := 0$

      DO 25001 I=1,N
          V(I)=0.0
25001 CONTINUE

\end{verbatim}

\section{Precision}
\label{precision}
\index{precision}\index{DOUBLE switch}
By default {\bf GENTRAN} generates constants and type declarations in
single precision form.  If the user requires double precision output
then the switch {\bf DOUBLE} must be set {\bf ON}.

\index{PRECISION command}\index{PRINT"!-PRECISION command}
To ensure the correct number of floating point digits are
generated it may be necessary to use either the {\bf PRECISION} or
{\bf PRINT!-PRECISION} commands.  The former alters the number of
digits \REDUCE\ calculates, the latter only the number of digits
\REDUCE\ prints.  Each takes an integer argument.  It is not possible to set
the printed precision higher than the actual precision.  Calling {\bf
PRINT!-PRECISION} with a negative argument causes the printed
precision to revert to the actual precision.

\subsection{The EVAL Function}
\label{eval}
\begin{describe}{Syntax:}
{\bf EVAL} {\it exp}
\end{describe}\ttindex{EVAL}
\begin{describe}{Argument:}
{\it exp} is any \REDUCE\ expression or statement which, after evaluation
by \REDUCE, results in an expression that can be translated by
GENTRAN into the target language.
\end{describe}
When {\bf EVAL} is called on an expression which is to be translated, it
tells {\bf GENTRAN} to give the expression to \REDUCE\ for evaluation
first, and then to translate the result of that evaluation. 

\begin{verbatim}
f;

   2
2*X  - 5*X + 6
\end{verbatim}
We wish to generate an assignment statement for the quotient
of F and its derivative.
\begin{verbatim}
1: GENTRAN
1:      Q := EVAL(F)/EVAL(DF(F,X))$

      Q=(2.0*X**2-(5.0*X)+6.0)/(4.0*X-5.0)
\end{verbatim}

\subsection{The :=: Operator}
\index{:=:}
\label{rsetq}\index{GENTRAN ! preevaluation}\index{rsetq operator}
In many applications, assignments must be generated in which the
left-hand side is some known variable name, but the
right-hand side is an expression that must be evaluated.  For
this reason, a special operator is provided to indicate that the expression
on the right-hand side is to be evaluated prior to translation.  This
special operator is {\bf :=:} ({\em i.e.} the usual \REDUCE\ assignment operator
with an extra ``:'' on the right).
\begin{describe}{\example}
\begin{verbatim}
1: GENTRAN
1:  DERIV :=: DF(X^4-X^3+2*x^2+1,X)$

      DERIV=4.0*X**3-(3.0*X**2)+4.0*X
\end{verbatim}
\end{describe}

\subsection{The ::= Operator}
\label{lsetq}
\index{matrices ! in GENTRAN}
When assignments to matrix or array elements must be generated, many
times the indices of the element must be evaluated first.  The special
operator\index{::=}\index{lsetq operator}
{\bf ::=} can be used within a call to {\bf GENTRAN}
to indicate that the indices of the matrix or
array element on the left-hand side of the assignment are to
be evaluated prior to translation.  (This is the usual \REDUCE{}
assignment operator with an extra ``:'' on the left.) 
\begin{describe}{\example}
We wish to generate assignments which assign zeros to all elements
on the main diagonal of M, an n x n matrix.
\begin{verbatim}
10: FOR j := 1 : 8 DO
10:      GENTRAN
10:          M(j,j) ::= 0$

      M(1,1)=0.0
      M(2,2)=0.0
      :
      :
      M(8,8)=0.0
\end{verbatim}
\end{describe}

{\bf LSETQ} may be used interchangeably with {\bf ::=} on input.\ttindex{LSETQ}

\subsection{The ::=: Operator}
\label{lrsetq}
\index{::=:} \index{lrsetq operator}
In applications in which evaluated expressions are to be assigned to
array elements with evaluated subscripts, the {\bf ::=:} operator can be
used.  It is a combination of the {\bf ::=} and {\bf :=:} operators described
in sections~\ref{rsetq} and ~\ref{lsetq}.
\index{matrices ! in GENTRAN}

\begin{describe}{\example}
The following matrix, M, has been derived symbolically:
\newpage
\begin{verbatim}
(  A   0  -1   1)
(               )
(  0   B   0   0)
(               )
( -1   0   C  -1)
(               )
(  1   0  -1   D)
\end{verbatim}
We wish to generate assignment statements for those elements
on the main diagonal of the matrix.
\begin{verbatim}
10: FOR j := 1 : 4 DO
10:      GENTRAN
10:          M(j,j) ::=: M(j,j)$

      M(1,1)=A
      M(2,2)=B
      M(3,3)=C
      M(4,4)=D
\end{verbatim}
\end{describe}
The alternative alphanumeric identifier associated with {\bf ::=:} is
{\bf LRSETQ}.\ttindex{LRSETQ}

\section{Explicit Type Declarations}
\label{explicit:type}
Type declarations are automatically generated each time a subprogram
heading is generated.  Type declarations are constructed
from information stored in the GENTRAN symbol table.  The user
can place entries into the symbol table explicitly through calls
to the special GENTRAN function {\bf DECLARE}.\index{DECLARE function}
\begin{describe}{Syntax:}
{\bf \ \ DECLARE} {\it v1,v2,\dots\  ,vn} {\bf :} {\it type;}

    or

\begin{tabular}{ll}
{\bf DECLARE}\\
{\bf $<$$<$}\\
&{\it v11,v12,\dots\  ,v1n} {\bf :} {\it type1;}\\
&{\it v21,v22,\dots\  ,v2n} {\bf :} {\it type2;}\\
& :\\
& :\\
&{\it vn1,vnn,\dots\  ,vnn} {\bf :} {\it typen;}\\
{\bf $>$$>$}{\it ;}
\end{tabular}
\end{describe}
\begin{describe}{Arguments:}
Each {\it v1,v2,\dots\  ,vn} is a list of one or more variables
(optionally subscripted to indicate array dimensions), or
variable ranges (two letters separated by a ``-'').  {\it v}'s are
not evaluated unless given as arguments to {\bf EVAL}.

Each {\it type} is a variable type in the target language.  Each
must be an atom, optionally preceded by the atom {\bf IMPLICIT}.
\index{IMPLICIT option}
{\it type}'s are not evaluated unless given as arguments to {\bf EVAL}.
\end{describe}

The {\bf DECLARE} statement can also be used to declare subprogram
types ({\em i.e.\ } {\bf SUBROUTINE} or {\bf FUNCTION}) for
\index{SUBROUTINE}\index{FUNCTION} FORTRAN and RATFOR code, and
function types for all four languages.

\section{Expression Segmentation}
\label{segmentation}\index{segmenting expressions}
Symbolic derivations can easily produce formulas that can be anywhere
from a few lines to several pages in length.  Such formulas
can be translated into numerical assignment statements, but unless they
are broken into smaller pieces they may be too long for a compiler
to handle.  (The maximum number of continuation lines for one statement
allowed by most FORTRAN compilers is only 19.)  Therefore GENTRAN
\index{continuation lines}
contains a segmentation facility which automatically {\it segments},
or breaks down unreasonably large expressions.

The segmentation facility generates a sequence of assignment
statements, each of which assigns a subexpression to an automatically
generated temporary variable.  This sequence is generated in such a
way that temporary variables are re-used as soon as possible, thereby
keeping the number of automatically generated variables to a minimum.
The facility can be turned on or off by setting the mode
\index{GENTRANSEG switch} switch {\bf GENTRANSEG} accordingly ({\em
i.e.\ }by calling the \REDUCE\ function {\bf ON} or {\bf OFF} on it).  The user
can control the maximum allowable expression size by setting the
\ttindex{MAXEXPPRINTLEN"!*}
variable {\bf MAXEXPPRINTLEN!*} to the maximum number of characters
allowed in an expression printed in the target language (excluding
spaces automatically printed by the formatter).  The {\bf GENTRANSEG}
switch is on initially, and {\bf MAXEXPPRINTLEN!*} is initialised to
800.

\section{Template Processing}\label{GENTRAN:template}

\index{GENTRAN ! templates}\index{templates}\index{code templates}
In some code generation applications pieces of the target numerical
program are known in advance.  A {\it template} file containing a
program outline is supplied by the user, and formulas are derived in
\REDUCE, converted to numerical code, and inserted in the corresponding
places in the program outline to form a complete numerical program.  A
template processor is provided by GENTRAN for use in these
applications.

\label{templates}\index{GENTRANIN command}
\begin{describe}{Syntax:}
{\bf GENTRANIN} {\it f1,f2,\dots\ ,fm} [{\bf OUT} {\it f1,f2,\dots\
 ,fn\/}]{\it ;}
\end{describe}
\begin{describe}{Arguments:}
{\it f1,f2,\dots\ ,fm\/} is an argument list containing one or more
{\it f\/}'s,
where each {\it f\/} is one of:
\begin{center}
\begin{tabular}{lll}
{\it an atom}& = &a template (input) file\\
{\bf T}& = &the terminal\\
\end{tabular}
\end{center}
{\it f1,f2,\dots\ ,fn\/} is an optional argument list containing one or more
{\it f\/}'s, where each {\it f\/} is one of:
\begin{center}
\begin{tabular}{lll}
{\it an atom}& = &an output file\\
{\bf T}& = &the terminal\\
{\bf NIL}& = &the current output file(s)\\
{\bf ALL!*}& = &all files currently open for output \\
& &  by GENTRAN (see section~\ref{GENTRAN:output}) \\
\end{tabular}
\end{center}
\end{describe}
{\bf GENTRANIN} processes each template file {\it f1,f2,\dots\ ,fm}
sequentially.

A template file may contain any number of parts, each of which
is either an active or an inactive part.  All active parts start with
the character sequence {\bf ;BEGIN;} and end with {\bf ;END;}.  The end
of the template file is indicated by an extra {\bf ;END;} character
sequence.\index{;BEGIN; marker} \index{;END; marker}

Inactive parts of template files are assumed to contain code in the
target language.  All inactive parts are
copied to the output.

Active parts may contain any number of \REDUCE\ expressions, statements,
and commands.  They are not copied directly to the output.  Instead,
they are given to \REDUCE\ for evaluation in algebraic mode.  All output
generated by each evaluation is sent to the output file(s).  Returned
values are only printed on the terminal.\index{GENTRAN ! preevaluation}

Active parts will most likely contain calls to {\bf GENTRAN} to
generate code.  This means that the result of processing a
template file will be the original template file with all active
parts replaced by generated code.

If {\bf OUT} {\it f1,f2,\dots\ ,fn} is not given, generated code is simply
written to the current-output file.

However, if {\bf OUT} {\it  f1,f2,\dots\ ,fn}
is given, then the current-output file
is temporarily overridden.  Generated code is written to each file
represented by {\it f1,f2,\dots\ ,fn} for this command only.  Files
which were open prior to the call to {\bf GENTRANIN} will remain open
after the call, and files which did not exist prior to the call will
be created, opened, written to, and closed.  The output-stack will be
exactly the same both before and after the call.


{\bf GENTRANIN} returns the names of all files written to by this
command.
\newpage
\begin{describe}{\example}
Suppose we wish to generate a FORTRAN subprogram to compute the
determinant of a 3 x 3 matrix.  We can construct a template
file with an outline of the FORTRAN subprogram and \REDUCE\ and
GENTRAN commands to fill it in:
\index{matrices ! in GENTRAN}

Contents of file {\tt det.tem}:
\end{describe}
\begin{verbatim}
      REAL FUNCTION DET(M)
      REAL M(3,3)
;BEGIN;
      OPERATOR M$
      MATRIX MM(3,3)$
      MM := MAT( (M(1,1),M(1,2),M(1,3)),
                 (M(2,1),M(2,2),M(2,3)),
                 (M(3,1),M(3,2),M(3,3)) )$
      GENTRAN DET :=: DET(MM)$
;END;
      RETURN
      END
;END;
\end{verbatim}

\begin{describe}{}
Now we can generate a FORTRAN subprogram with the following
\REDUCE\ session:
\begin{verbatim}
1: GENTRANLANG!* := 'FORTRAN$

2: GENTRANIN
2:      "det.tem"
2: OUT "det.f"$
\end{verbatim}
Contents of file det.f:
\end{describe}
\begin{verbatim}
      REAL FUNCTION DET(M)
      REAL M(3,3)
      DET=M(3,3)*M(2,2)*M(1,1)-(M(3,3)*M(2,1)*M(1,2))-(M(3,2)
     . *M(2,3)*M(1,1))+M(3,2)*M(2,1)*M(1,3)+M(3,1)*M(2,3)*M(1
     . ,2)-(M(3,1)*M(2,2)*M(1,3))
      RETURN
      END
\end{verbatim}

\section{Output Redirection}\label{GENTRAN:output}
\index{GENTRAN ! file output}

\index{GENTRANOUT command}\index{GENTRANSHUT command}
The {\bf GENTRANOUT} and {\bf GENTRANSHUT} commands are identical to
the \REDUCE\ {\bf OUT} and {\bf SHUT} commands with the following
exceptions:

\begin{itemize}
\item {\bf GENTRANOUT} and {\bf GENTRANSHUT} redirect {\it only\/}
code which is printed as a side effect of GENTRAN commands.
\item {\bf GENTRANOUT} allows more than one file name to be given
to indicate that generated code is to be sent to two or more
files.  (It is particularly convenient to be able to
have generated code sent to
the terminal screen and one or more file simultaneously.)
\item {\bf GENTRANOUT} does not automatically erase existing files; it
prints a warning message on the terminal and asks the user whether the
existing file should be erased or the whole command be aborted.
\end{itemize}



REDUCE Historical
REDUCE Sourceforge Project | Historical SVN Repository | GitHub Mirror | SourceHut Mirror | NotABug Mirror | Chisel Mirror | Chisel RSS ]