Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/root/sys/lib/texmf/doc/latex/program/program-demo.tex

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


\documentclass{article}
\usepackage{newlfont}
\usepackage{program}
\setlength{\parskip}{1ex}

% Number algorithms separately:
%\newtheorem{algorithm}{Algorithm} 

% Number algorithms within sections:
\newtheorem{algorithm}{Algorithm}[section] 

% For "floating" algorithms, use:
% \begin{figure}
% \begin{program}
% ...
% \end{program}
% \end{figure}


\begin{document}
\title{A demonstration of the {\tt program} environment}
\author{Martin Ward\\
Centre for Software Maintenance\\
University of Durham}
\maketitle

\tableofcontents

\section{Example with |first_set| and $|first_set|$.}

The {\tt program} style defines two environments, {\tt program} and {\tt
programbox} for typesetting programs and algorithms. Within the program
environment:
\begin{enumerate}
	\item Newlines are significant;
	\item Each line is in math mode, so for example spaces in the input
file are not significant;
	\item The command \verb:\\: within a line causes an extra
linebreak in the output;
	\item The indentation of each line is calculated automatically;
	\item To cause extra indentation, use the commands \verb:\tab: to
set a new tab, and \verb:\untab: to remove it (see the examples below);
	\item Vertical bars are used to delimit long variable names with
underscores (and other unusual characters).
\end{enumerate}

\verb:testing | in verbatim:

\begin{verbatim}
testing | in verbatim
\end{verbatim}



Here is a small program: 
\( |first_set|:= \set{x | x^2 + y_1 > 0 } \)
It shows how to typeset mathematics as part of a program. Since each line is
typeset in maths mode, all spacing is done automatically. The set brackets
expand automatically, for example in this program (which also demonstrates the
\verb:\tab: and \verb:\untab: commands):
\begin{program}
t := \set{x | \displaystyle\frac{x}{y} = z};
t := t \setminus u;
z := a \tab {} + b + c + d
	    {} + e + f + g
	    {} + h + i + j; \untab
\IF x = 0 \THEN y :=0 \FI
\end{program}

You can use |variable_names| in text or math mode: $|variable_name|^2 = 2$.
Names can have |odd_characters:!@#$%^&*:;_like_this!|.

Note that \verb:\(: and \verb:\): are redefined to typeset a program in
a minipage. (This is useful in running text, or to keep a short program all on
one page). There is some notation for sequences: \( \seq{x_1,x_2,\dots,x_n} \)
and for universal and existential quantifiers: $ \Forall x. \Exists y. y>x $
(yes, I use these in my programs!)

I often use bold letters to represent program fragments, formulas etc. so
I have set up commands \S{}, \R{} etc. for the most common ones. The
commands have one argument (a subscript, eg \S1, \S2, \S{23}) or a
sequence of ``prime'' characters: \S', \S''''' etc. If you want both a 
subscript and one or more primes, then you must use maths mode, eg $\S2'$
Consider the difference between typing \verb:``\S2'': which gives ``\S2'' and
\verb:``$\S2''$'': which gives ``$\S2''$''. Outside maths mode, \verb:\S: 
assumes any primes after a subscript are either closing quotes or apostrophes.

Here are two program examples with different indentation styles. Note that
all indentation is calculated automatically in either style:

\noindent
% programbox keeps the program on one page - like parbox
\begin{programbox}
\IF \T1
    \THEN \IF \T2
	      \THEN \IF \T3
			\THEN \S4 
			\ELSE \S3
		    \FI
	      \ELSE \S2
	  \FI
    \ELSE \S1
\FI;
% Blank lines are ignored, so you need a ~ on the line
% to get a blank line in the output:
~
\IF \T1 \THEN \IF \T2 \THEN \IF \T3 \THEN \S4
				    \ELSE \S3 \FI
		      \ELSE \S2 \FI
	\ELSE \S1 \FI;
\end{programbox}

Note that \keyword{then} and \keyword{else} should be at the {\em start} of
a line (as in the examples above), not at the end. This is so that you can
line them up in short \keyword{if} statements, for example:
\begin{program}
\IF x=1 \THEN |a_long_procedure_name|(|arg1|, |arg2|, \dots)
	\ELSE |another_long_procedure_name|(|arg1|, |arg2|, \dots) \FI
\end{program}
If the test is long, then you probably want an extra linebreak:
\begin{program}
\IF |a_long_boolean_function_name?|(|arg1|, |arg2|, \dots)
   \THEN |a_long_procedure_name|(|arg1|, |arg2|, \dots)
   \ELSE |another_long_procedure_name|(|arg1|, |arg2|, \dots) \FI
\end{program}
Compare this with the following (which has linebreaks in the ``wrong'' places):
\begin{program}
\IF |a_long_boolean_function_name?|(|arg1|, |arg2|, \dots) \THEN
  |a_long_procedure_name|(|arg1|, |arg2|, \dots)
	\ELSE
  |another_long_procedure_name|(|arg1|, |arg2|, \dots) \FI
\end{program}



Just to show that {\tt\origbar} still works normally to indicate the
placing of vertical lines) in the preamble of a tabular
(or array) environment:

\begin{tabular}{|r|l|} \hline
\bf Statement & \bf Conditions  \\
\hline
\S1     & \B1 \\
\S2     & \B2 \\
\hline
\end{tabular}

\section{Procedures and Functions}

Turning on line numbering here. Also using the algoritm enviroment to number
the algorithms within the sections.
\NumberProgramstrue
\begin{algorithm}
\begin{program}
\label{one}%
\mbox{A fast exponentiation function:} \\ % You can use \mbox for comments
\BEGIN % 
  \FOR i:=1 \TO 10 \STEP 1 \DO
     |print|(|expt|(2,i)); \\ |newline|() \OD
\WHERE
\FUNCT |expt|(x,n) \BODY
	  \EXP z:=1;
	       \WHILE n \ne 0 \DO 
		  \WHILE |even|(n) \DO
		     n:=n/2; x:=x*x \OD; \label{foo}
		  n:=n-1; z:=z*x \OD;
	       z \ENDEXP \ENDFUNCT
\END\label{last}
\end{program}
\end{algorithm}
First line is line~\ref{one}, last is line~\ref{last}.
Line~\ref{foo} is what makes this function fast!

\begin{algorithm}
\begin{program}
\mbox{A fast exponentiation procedure:}
\BEGIN %
  \FOR i:=1 \TO 10 \STEP 1 \DO
     |expt|(2,i); \\ |newline|() \OD %
\rcomment{This text will be set flush to the right margin}
\WHERE
\PROC |expt|(x,n) \BODY
	  z:=1;
	  \DO \IF n=0 \THEN \EXIT \FI;
	     \DO \IF |odd|(n) \THEN \EXIT \FI;
\COMMENT{This is a comment statement};
		n:=n/2; x:=x*x \OD;
	     \{ n>0 \};
	     n:=n-1; z:=z*x \OD;
	  |print|(z) \ENDPROC
\END
\end{program}
\end{algorithm}

\noindent An action system equivalent to a \keyword{while} loop:
\[
\( \ACTIONS A:
	A \EQ \IF \B{} \THEN \S{}; \CALL A
		       \ELSE \CALL Z \FI \QE
   \ENDACTIONS \)
\EQT
\( \WHILE \B{} \DO \S{} \OD \)
\]
Note the use of \verb:\(: and \verb:\): to enclose the two program boxes.
Turning off line numbers here.
\NumberProgramsfalse

\noindent Dijkstra conditionals and loops:
\begin{program}
\IF x = 1 \AR y:=y+1
\BAR x = 2 \AR y:=y^2
\utdots
\BAR x = n \AR y:=\displaystyle\sum_{i=1}^n y_i \FI

\DO 2 \origbar x \AND x>0 \AR x:= x/2
\BAR \NOT 2 \origbar x    \AR x:= \modbar{x+3} \OD
\end{program}

\noindent Loops with multiple \keyword{exit}s:
\begin{program} 
\DO \DO \IF \B1 \THEN \EXIT \FI;
	\S1;
	\IF \B2 \THEN \EXIT(2) \FI \OD;
    \IF \B1 \THEN \EXIT \FI \OD
\end{program} 

\noindent I hope you get the idea!

\section{A Reverse Engineering Example}

Here's the original program:
\begin{algorithm}
\begin{program} 
 \VAR \seq{m := 0, p := 0, |last| := `` ''}; 
 \ACTIONS |prog|: 
|prog| \ACTIONEQ %
    \seq{|line| := `` '', m := 0, i := 1};
    \CALL |inhere| \ENDACTION
l \ACTIONEQ %
    i := i+1; 
    \IF (i=(n+1)) \THEN \CALL |alldone| \FI ; 
    m := 1; 
    \IF |item|[i] \neq |last|
	\THEN |write|(|line|); |line| := `` ''; m := 0;
	      \CALL |inhere| \FI ; 
    \CALL |more| \ENDACTION
|inhere| \ACTIONEQ %
    p := |number|[i]; |line| := |item|[i];
    |line| := |line| \concat `` '' \concat p;
    \CALL |more| \ENDACTION
|more| \ACTIONEQ %
    \IF (m=1) \THEN p := |number|[i];
    |line| := |line| \concat ``, '' \concat p \FI ; 
    |last| := |item|[i]; 
    \CALL l  \ENDACTION  
|alldone| \ACTIONEQ |write|(|line|); \CALL Z \ENDACTION \ENDACTIONS \END 
\end{program} 
\end{algorithm}

And here's the transformed and corrected version:
\begin{algorithm}
\begin{program} 
\seq{|line| := `` '', i := 1};
\WHILE i \neq n+1 \DO 
  |line| := |item|[i] \concat `` '' \concat |number|[i]; 
  i := i+1; 
  \WHILE i \neq n+1 \AND |item|[i] = |item|[i-1] \DO 
    |line| := |line| \concat ``, '' \concat |number|[i]);
    i := i+1 \OD ; 
  |write|(|line|) \OD 
\end{program}
\end{algorithm}

These are the same programs in a sans-serif style, using the command
\verb:\sfvariables::
\sfvariables
\begin{program}
 \VAR \seq{m := 0, p := 0, |last| := `` ''}; 
 \ACTIONS |prog|: 
|prog| \ACTIONEQ %
    \seq{|line| := `` '', m := 0, i := 1};
    \CALL |inhere| \ENDACTION
l \ACTIONEQ %
    i := i+1; 
    \IF (i=(n+1)) \THEN \CALL |alldone| \FI ; 
    m := 1; 
    \IF |item|[i] \neq |last|
	\THEN |write|(|line|); |line| := `` ''; m := 0;
	      \CALL |inhere| \FI ; 
    \CALL |more| \ENDACTION
|inhere| \ACTIONEQ %
    p := |number|[i]; |line| := |item|[i];
    |line| := |line| \concat `` '' \concat p;
    \CALL |more| \ENDACTION
|more| \ACTIONEQ %
    \IF (m=1) \THEN p := |number|[i];
    |line| := |line| \concat ``, '' \concat p \FI ; 
    |last| := |item|[i]; 
    \CALL l  \ENDACTION  
|alldone| \ACTIONEQ |write|(|line|); \CALL Z \ENDACTION \ENDACTIONS \END 
\end{program} 

\begin{program}
\seq{|line|:=`` '', i:=1}; 
\WHILE i \neq n+1 \DO 
  |line| := |item|[i] \concat `` '' \concat |number|[i]; 
  i := i+1; 
  \WHILE i \neq n+1 \AND |item|[i] = |item|[i-1] \DO 
    |line| := |line| \concat ``, '' \concat |number|[i]);
    i := i+1 \OD ; 
  |write|(|line|) \OD 
\end{program}

\end{document}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.