[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / CONTRIB / pphs / docs / How.tex
1 \chapter{How it does it}
2
3 This chapter explains in detail how the program {\tt pphs} was implemented
4 from a programmer's viewpoint.  It was implemented in the C programming
5 language, as this is a commonly used language often used for writing UNIX tools.
6 The program code is shown in Appendix~\ref{prog-code} and the makefile in
7 Appendix~\ref{make-code}.
8
9 \section{General sequence of events}
10
11 When the {\tt pphs} program is run, the program first finds out what, if any,
12 options it has been called with.  If any have been specified, the appropriate
13 variables are set.  The program then checks it has been called with exactly one
14 further argument.  If not, the program terminates with an
15 explanatory error message.  If called correctly, the program then checks that the
16 supplied argument is the name of a file that exists and is readable.
17 The program is normally used
18 on files ending with a {\tt .hs} extension.  When called with a filename
19 with no extension and that file is not found, then it appends the extension and searches
20 for that file.  If no file with that name is found or the file is unreadable, an
21 error message is produced and the program terminates.  If the file is found, the
22 program starts the typesetting process by writing out the opening
23 \LaTeX\ command to {\tt stdout}.
24 This defines the \LaTeX\ environment which the program exploits to do the typesetting.
25 It then initialises the variables used in the program.
26
27 This done, the first character is read.  The program enters a loop and keeps
28 reading characters until the end of the file is reached.  As each character is read
29 in, its typeface is established and it is stored with its typeface in something
30 called the {\em line store\/}.  If any left indentation is
31 encountered, the correct characters to be skipped are identified from the {\em left
32 indentation stack} and copied into the line store.  Internal alignment is checked
33 for and if any is found, appropriate variables are set accordingly.  Each stored line is
34 added to both the left indentation stack and the {\em writing queue}.  When the value of the
35 internal alignment changes, or it has been established that the first line in the writing
36 queue is not part of any internal alignment section, the lines in the queue are written out.
37
38 Once all the lines are written out, {\tt pphs} then writes the closing \LaTeX\ command
39 and terminates.
40
41 \section{Basic storage unit for a line of code} \label{line-store}
42
43 The basic storage unit used in {\tt pphs} is the line store unit.
44 This stores the details of one line of Haskell code.  These are
45 the characters on the line, the typeface associated with each
46 character, the length of the line, the indentation level and the position of
47 any internal alignment in the line.
48
49 In the C program, {\tt ElementType} is the structure used for this type.  This has
50 five parts:
51 \begin{itemize}
52 \item {\tt chars} which stores the characters used on the line of Haskell
53 code
54
55 \item {\tt typeface} which stores the typeface values associated with the
56 characters on that line
57
58 \item {\tt indentation} which stores the level of the line's indentation
59
60 \item {\tt length} which stores the length of the line
61
62 \item {\tt col} which stores the column where any internal alignment occurs or
63 is set to {\tt 0} if there is none
64 \end{itemize}
65 The variable {\tt store} in the main program is of type {\tt ElementType} and
66 is used as the basic storage unit for the current line.  Its C declaration is
67 \begin{quote}
68 \begin{verbatim}
69 typedef struct ElementType_Tag {
70   char chars[MAXLINELENGTH];
71   enum face typeface[MAXLINELENGTH];
72   int indentation, length, col;
73 } ElementType;
74 \end{verbatim}
75 \end{quote}
76
77 \section{Stack of lines for left indentation}
78
79 Due to \LaTeX 's variable width characters, {\tt pphs} cannot simply uses spaces
80 for the left indentation as in the input Haskell file.  It has to work out how far
81 each line is indented by finding out what it is indented under.  As each line is
82 completed, it is added to a stack of lines, each line being stored in a basic
83 storage unit.  If the line at the top of the stack is of a greater or equal
84 indentation level and of a lesser or equal length, then it is no
85 longer required for calculating typeset indentation
86 and can be disposed of.  Once all lines of greater indentation level have been removed
87 from the top of the stack, the current line can then be added.
88
89 When a line's indentation level, in terms of the number of spaces used in the
90 input, has been determined, {\tt pphs} has to find
91 out the characters that determine the actual typeset length of the indentation.  To get this,
92 {\tt pphs} looks down the stack until it comes to a line whose indentation is less than
93 that of the current line and whose length is greater than the indentation level of the
94 current line.  Once a suitable line is found, its characters and typefaces are copied
95 into the line store of the current line; then the rest of the current line is read in,
96 overwriting the characters beyond the indentation level.  If there is no line preceding
97 the current one that is as long as the indentation level of the current line, spaces
98 are placed in the line store instead.
99
100 A special case has been made for left indentation.  Most of the time, the left-hand edge
101 of the characters will be aligned, but where a {\tt |} is aligned under an {\tt =} sign, it is
102 centered under the sign.  This will be the case for any further {\tt |} symbols aligned
103 under this {\tt =} sign.
104
105 The type {\tt StackType} is used in the program for the stack.  This makes a stack of
106 the basic line storage units of {\tt ElementType}, together with a set of functions available
107 for use with stacks.  These are {\tt CreateStack}, which returns an empty stack;
108 {\tt IsEmptyStack}, which returns {\tt 1} if the stack which it is called with is empty,
109 {\tt 0} otherwise; {\tt Push}, which takes a stack and an element and returns the stack
110 with the element pushed onto the top; {\tt Top}, which takes a stack and returns the top
111 element of the stack; {\tt Pop}, which takes a stack and returns it with the top element
112 removed; and {\tt PopSym}, which is the same as {\tt Pop} except that it does not free the
113 memory used by the top element - this function was found necessary to fix a fault caused by
114 returning to a stack's previous state, having popped off elements in the interim period.
115
116 \section{Internal alignment identification}
117
118 Internal alignment is deemed to have occurred when a character matches the one
119 immediately above it, the preceding characters in both lines are spaces, and there is
120 more than one space preceding the character on at least one of the lines.
121
122 To check for this in {\tt pphs}, the current position on the line, indicated by
123 the linecounter, must be greater than one because either the current line or
124 the previous line will be required to have two spaces before the current position.  The current
125 line will be located in the line store and the previous line will be at the rear of the queue
126 of lines waiting to be written out.
127
128 One special case has been implemented for internal alignment.  This is to allow Haskell
129 type declarations, such as in the example below, to align with their corresponding function
130 definitions.
131 \begin{quote}
132 \input{Haskell_internalalign2}
133 \end{quote}
134 The {\tt =} sign can be under either the first or second {\tt :} symbol for the
135 internal alignment to be recognised.
136
137 \section{Typefaces and mathematical characters}
138
139 Each character has a typeface value associated with it.  Normally, this will
140 indicate the type of token the character is part of, either keyword, identifier,
141 string, comment, number or maths symbol, but where Haskell uses an ASCII character
142 simulation of a mathematical character or some other special symbol, the typeface
143 value will indicate this as well.
144
145 In the program, the typeface values are of the
146 enumerated type called {\tt face}, which has the values shown in Table~\ref{tf-val}.
147 They are used in the basic storage unit {\tt ElementType} in the {\tt typeface} part.
148
149 \begin{table}
150 \begin{center}
151 \begin{tabular}{|c|l|} \hline
152 {\em value\/} & {\em indicates\/} \\ \hline
153 {\tt KW} & keyword \\
154 {\tt ID} & identifier \\
155 {\tt IE} & exponent identifier \\
156 {\tt ST} & string \\
157 {\tt SE} & exponent string \\
158 {\tt CO} & comment \\
159 {\tt CE} & exponent comment \\
160 {\tt NU} & number \\
161 {\tt NE} & exponent number \\
162 {\tt MA} & maths \\
163 {\tt SP} & space \\
164 {\tt LC} & line comment \\
165 {\tt RC} & regional comment begin \\
166 {\tt CR} & regional comment end \\
167 {\tt BF} & backwards/forwards quote \\
168 {\tt FQ} & forwards quote \\
169 {\tt EQ} & escape quote \\
170 {\tt DQ} & double quote begin \\
171 {\tt QD} & double quote end \\
172 {\tt EE} & escape double quote \\
173 {\tt DC} & second part of double character \\
174 {\tt DP} & double plus \\
175 {\tt CP} & colon plus \\
176 {\tt LE} & less than or equal to \\
177 {\tt GE} & greater than or equal to \\
178 {\tt LA} & left arrow \\
179 {\tt RA} & right arrow \\
180 {\tt RR} & double right arrow \\
181 {\tt TI} & times \\
182 {\tt EX} & double exponent character \\
183 {\tt XP} & exponent \\
184 {\tt BE} & bar aligned under equals \\ \hline
185 \end{tabular}
186 \end{center}
187 \caption{Typeface values} \label{tf-val}
188 \end{table}
189
190 \subsection{Current character and retrospective update}
191
192 The {\tt pphs} program has to determine the typeface of a character without knowledge of the
193 characters to follow.  Therefore it allocates the value depending on the status
194 of various boolean variables.  This may subsequently be found to be wrong once the remaining
195 characters of that token have been read.
196
197 In the case of keywords and double characters, these are only identifiable
198 as such once all the characters of the token have been read in.  Having established
199 the existence of a keyword or double character, {\tt pphs} then goes back and changes
200 the typeface values for the appropriate characters.
201
202 The functions {\tt CheckForDoubleChar} and {\tt CheckForKeyword} perform this in the
203 program.
204
205 \section{Writing lines out}
206
207 Lines are written to {\tt stdout}, but not immediately on being read in.  Instead they
208 are held back while it is established whether or not they form part of a section of
209 internal alignment.
210
211 Before any typeset Haskell code is written, {\tt pphs} writes an opening \LaTeX\ command
212 {\tt \char'134 begin\char'173 tabbing\char'175 } to {\tt stdout}.  This defines the
213 \LaTeX\ environment that the typeset code will be written in.  At the end,
214 {\tt \char'134 end\char'173 tabbing\char'175 } is written to terminate this
215 environment.
216
217 \subsection{The line queue}
218
219 Lines are stored in a queue while they are waiting to be written out.  
220 The elements of the queue are the basic line storage units described in
221 Section~\ref{line-store}.
222
223 In the program, the queue is of type {\tt QueueType}
224 and a set of functions related to queues is available.  This set consists of
225 {\tt CreateQueue}, which returns an empty queue; {\tt IsEmptyQueue}, which takes
226 a queue and returns {\tt 1} if the queue is empty, {\tt 0} otherwise; {\tt LengthOfQueue},
227 which takes a queue and returns its length; {\tt FrontOfQueue}, which takes a queue and
228 returns a pointer to its front element; {\tt RearOfQueue}, which takes a queue and returns
229 a pointer to its rear element; {\tt AddToQueue}, which takes a queue and an element and
230 returns the queue with the element added to the rear; {\tt TakeFromQueue}, which takes
231 a queue and returns the queue with the front element removed.
232
233 The last line in the queue is inspected to search
234 for internal alignment; if any is found, the internal alignment variable of that
235 line is altered accordingly.
236
237 \subsection{When lines are written}
238
239 The queue is written out by the function {\tt WriteQueue} when a section of internal
240 alignment is commenced or terminated
241 or when it has been established that there is no internal alignment involving the first line
242 in the queue.  If the section being written out has been found to have
243 no internal alignment, then the last line is retained
244 in the queue because it may form part of the next section of internal alignment.
245
246 At the end of the input, {\tt WriteRestOfQueue} writes all the lines remaining in the queue.
247 This is because the last line of Haskell code will not form part of any further section of
248 internal alignment and can therefore be written out.  Facilities
249 are provided in the function {\tt WriteLine} to avoid writing the last newline
250 character at the end of the Haskell
251 file, as this would create an unwanted blank line in the final document.
252
253 \subsection{Writing a line}
254
255 The function {\tt WriteLine} is used in {\tt pphs} to write out one line.  This is
256 called from either {\tt WriteQueue} or {\tt WriteRestOfQueue} and is supplied with
257 a basic line storage unit containing the line needing to be written out together with a
258 flag stating whether or not a \LaTeX\ newline character is required.
259
260 If a line has any left indentation, this is written out first by calling the function
261 {\tt WriteSkipover}.  The rest of the line is then written out by {\tt WriteWords}
262 followed if necessary by the newline character.  Both these functions are given
263 the current line in the line store.
264
265 \subsection{Writing left indentation}
266
267 As \LaTeX\ uses variable width characters, fixed width spaces cannot be used for the
268 left indentation.  Instead, the width of the characters above the current line needs
269 to be skipped.  The {\tt \char'134 skipover} command, defined in the {\tt pphs.sty}
270 style file (see Section~\ref{style-file}), is used by the function {\tt WriteSkipover}
271 to get \LaTeX\ to do this.  The command is supplied with the typefaces and characters
272 in the lines above, and, with this, \LaTeX\ creates the correct amount of
273 indentation in the typeset result.  The typefaces and characters are written in
274 braces as the argument to {\tt \char'134 skipover} by calling {\tt WriteStartFace},
275 {\tt WriteChar}, {\tt WriteSpaces} and {\tt WriteFinishFace}.  The typeface functions
276 are called with the typeface value whereas the other two are given the line store,
277 current position and where the end of the skipover section is.
278
279 Using this specially defined {\tt \char'134 skipover} command avoids having to get
280 information back from \LaTeX , therefore keeping the information flow unidirectional.
281
282 \subsection{Writing the rest of a line}
283
284 The function {\tt WriteWords} writes out the indented line once any left indentation
285 has been dealt with.  Starting at the indentation level of the line, it uses the functions
286 {\tt WriteStartFace}, {\tt WriteChar}, {\tt WriteSpaces} and {\tt WriteFinishFace} to
287 write out each character and its typeface.  The typeface functions are called with
288 the typeface value whereas the other two are given the line store, current position
289 and where the end of the line is.
290
291 \subsection{Writing \LaTeX\ typeface commands}
292
293 Every character has a typeface associated with it, so at the start and finish of every
294 line and every time the current typeface changes, typeface commands have to be written
295 out.  This is done by the functions {\tt WriteStartFace} and {\tt WriteFinishFace}.
296 They write the appropriate \LaTeX\ typeface commands according to the typeface values
297 given as shown in Table~\ref{tf-comms}.  To avoid complications, double characters have
298 their typefaces written out as part of the character command, therefore they need no
299 further typeface commands.  Similarly, the user-redefinable quote mark characters
300 have their typeface defined in their definitions, so do not need any more typeface
301 commands.
302
303 \begin{table}
304 \begin{center}
305 \begin{tabular}{|c|l|l|} \hline % ``commands'' to be over two columns
306 {\em value\/} & \multicolumn{2}{c|}{\em commands\/} \\ \cline{2-3}
307               & {\em begin\/} & {\em end\/} \\ \hline
308 {\tt KW} & {\tt \char'173 \char'134 keyword} & {\tt \char'134 /\char'175 }\\
309 {\tt ID} & {\tt \char'173 \char'134 iden} & {\tt \char'134 /\char'175 }\\
310 {\tt IE} & {\tt \char'173 \char'134 iden} & {\tt \char'134 /\char'175 \$ }\\
311 {\tt ST} & {\tt \char'173 \char'134 stri} & {\tt \char'134 /\char'175 }\\
312 {\tt SE} & {\tt \char'173 \char'134 stri} & {\tt \char'134 /\char'175 \$ }\\
313 {\tt CO} & {\tt \char'173 \char'134 com} & {\tt \char'134 /\char'175 }\\
314 {\tt CE} & {\tt \char'173 \char'134 com} & {\tt \char'134 /\char'175 \$ }\\
315 {\tt NU} & {\tt \char'173 \char'134 numb} & {\tt \char'134 /\char'175 }\\
316 {\tt NE} & {\tt \char'173 \char'134 numb} & {\tt \char'134 /\char'175 \$ }\\
317 {\tt MA} & {\tt \$ } & {\tt \$ }\\
318 {\tt SP} & & \\
319 {\tt LC} & & \\
320 {\tt RC} & & \\
321 {\tt CR} & & \\
322 {\tt BF} & &  \\
323 {\tt FQ} & &  \\ \hline
324 \end{tabular} \hskip3mm \begin{tabular}{|c|l|l|} \hline
325 {\em value\/} & \multicolumn{2}{c|}{\em commands\/} \\ \cline{2-3}
326               & {\em begin\/} & {\em end\/} \\ \hline
327 {\tt EQ} & & \\
328 {\tt DQ} & & \\
329 {\tt QD} & & \\
330 {\tt EE} & & \\
331 {\tt DC} & & \\
332 {\tt DP} & & \\
333 {\tt CP} & & \\
334 {\tt LE} & & \\
335 {\tt GE} & & \\
336 {\tt LA} & & \\
337 {\tt RA} & & \\
338 {\tt RR} & & \\
339 {\tt TI} & {\tt \$ } & {\tt \$ } \\
340 {\tt EX} & {\tt \$ } & \\
341 {\tt XP} & {\tt \$ } & \\
342 {\tt BE} & & \\ \hline
343 \end{tabular}
344 \end{center}
345 \caption{Typeface values and related \LaTeX\ commands} \label{tf-comms}
346 \end{table}
347
348 \subsection{Writing characters}
349
350 {\tt WriteChar} is the function which handles writing characters.  It takes the line store,
351 the current position on the line and the end of the current section - either the skipover
352 section or the writing section - and returns the current position on the line which will
353 have been incremented if a double character has been written.  If the first character of
354 a double character is the last character of a skipover section, it will not be written
355 so the indentation for that line will fall instead, below the start of the double
356 character in a line above.  Most characters are written out as they were inputted,
357 but many require special \LaTeX\ code.
358
359 As \LaTeX\ uses embedded typesetting commands, some characters are reserved for this
360 purpose.  Should any of these characters appear in the input Haskell code, {\tt pphs}
361 has to produce the appropriate \LaTeX\ code to avoid these characters upsetting the typesetting
362 process.  The characters and the replacement \LaTeX\ code are shown in Table~\ref{rep-chars}.
363 \begin{table}
364 \begin{center}
365 \begin{tabular}{|c|l|} \hline
366 {\em input\/} & {\em \LaTeX\ code output } \\ \hline
367 {\tt \#} & {\tt \char'134 \#} \\
368 {\tt \$} & {\tt \char'134 \$} \\
369 {\tt \%} & {\tt \char'134 \%} \\
370 {\tt \&} & {\tt \char'134 \&} \\
371 {\tt \char'176 } & {\tt \char'134 char'176 } \\
372 {\tt \_} & {\tt \char'134 \_} \\
373 {\tt \char'134} & {\tt \char'134 hbox\char'173 \$setminus\$\char'175 } \\
374 {\tt \char'173} & {\tt \char'134 hbox\char'173 \$\char'134 cal \char'134 char'146 \$\char'175 } \\
375 {\tt \char'175} & {\tt \char'134 hbox\char'173 \$\char'134 cal \char'134 char'147 \$\char'175 } \\
376 {\tt *} & {\tt \char'134 times}\\ \hline
377 \end{tabular} \hskip3mm \begin{tabular}{|c|l|} \hline
378 {\em input\/} & {\em \LaTeX\ code output } \\ \hline
379 {\tt ++} & {\tt \char'134 plusplus}\\
380 {\tt :+} & {\tt \char'173 :\char'175 \char'173 +\char'175}\\
381 {\tt <=} & {\tt \$\char'134 leq\$}\\
382 {\tt >=} & {\tt \$\char'134 geq\$}\\
383 {\tt <-} & {\tt \$\char'134 leftarrow\$}\\
384 {\tt ->} & {\tt \$\char'134 rightarrow\$}\\
385 {\tt =>} & {\tt \$\char'134 Rightarrow\$}\\
386 {\tt \char'173 -} & {\tt \char'173 \char'134 com \char'134 \char'173 -\char'134 /\char'175 }\\
387 {\tt -\char'175 } & {\tt \char'173 \char'134 com -\char'134 \char'175 \char'134 /\char'175 }\\
388 {\tt --} & {\tt \char'173 \char'134 rm -\char'175 \char'173 \char'134 rm -\char'175 }\\ \hline
389 \end{tabular}
390 \end{center}
391 \caption{Haskell input and replacement \LaTeX\ code} \label{rep-chars}
392 \end{table}
393
394 When a mathematical character needs written, {\tt WriteChar} outputs the \LaTeX\ code for
395 the character rather than the Haskell ASCII character simulation.  Some of these
396 simulations use more than one character, so this could cause problems if some left
397 indentation is aligned under the second character of such a simulation.  It has been
398 decided that in this case, the output from {\tt pphs} will cause the indented line
399 to align under the start of the double character rather than the centre or end of it.
400 The Haskell ASCII simulations and the \LaTeX\ codes that replaces them are shown in
401 Table~\ref{rep-chars}.  The non-standard command {\tt \char'134 plusplus} is defined
402 in the {\tt pphs.sty} style file (see Section~\ref{style-file}).
403
404 When a {\tt |} symbol is aligned under an {\tt =} sign at the left indentation,
405 {\tt \char'134 bareq} is output.  This command is defined in the {\tt pphs.sty}
406 style file explained in Section~\ref{style-file} and causes \LaTeX\ to write the bar symbol
407 centrally in the space it would have taken to write an equals sign, thereby causing
408 the bar to be positioned centrally under the equals sign it is aligned under and the text
409 following the bar to align with that after the equals sign.
410
411 For writing spaces, {\tt WriteSpaces}, called with the line store, current position and the
412 position of the end of the current section, first counts the number of consecutive spaces
413 to be written before writing out a {\tt \char'134 xspa} command with an argument of
414 the number of spaces needed.  This makes the output code easier to read.  The
415 {\tt \char'134 xspa} command is defined in the {\tt pphs.sty} style file explained
416 in Section~\ref{style-file}.  Any tab characters are treated as spaces by {\tt pphs}
417 with the number of spaces they represent being calculated from the current position
418 on the line and the {\tt tablength} variable, which may have been changed from its
419 default of 8 by the {\tt -t} option at the program call.
420
421 Numbers are written by {\tt WriteChar}, including floating point numbers.
422
423 As \LaTeX\ provides several different quote marks, it was decided that the user
424 should be able to choose a preferred symbol.  An input quote mark {\tt '} can
425 either be a prime or a quote mark in the output.  This requires the program to
426 determine which it is.  In program code this is fine, but in comments or strings
427 the marks won't necessarily be used in a manner from which it can easily be
428 determined which symbol is required.  In program code, an input {\tt '} is deemed
429 to be a quote mark if either it is preceded by punctuation or a quote has
430 already been opened; otherwise it is a prime.  Of the quote marks, these can
431 either be for actual quotes or an escape quote where a quote mark is being quoted.
432 Special cases has been implemented when the input file contains a quote within a comment
433 started with a backquote and ended with a forwards quote, and for \LaTeX\ style
434 quotes in comments started with two backquotes and ended with two forwards quote
435 marks.  All input {\tt '} in strings, other than escape quotes, are treated
436 as primes.  In strings, an input {\tt '} may be an apostrophe, however, there is
437 little way of telling this.\label{string-apostrophe}  One of five different pieces
438 of \LaTeX\ code can be produced having received {\tt '} as input.
439 \begin{itemize}
440 \item {\tt \char'134 forquo} for a forwards quote mark
441 \item {\tt \char'134 escquo} for an escape (quoted) quote mark
442 \item {\tt \char'173 \char'134 com '\char'134 /\char'175 } for a forward quote ending a quote
443 in a comment opened by a backquote
444 \item {\tt \char'173 \char'134 com ''\char'134 /\char'175 } for two forward quotes ending a quote
445 in a comment opened by two backquotes
446 \item {\tt '} for a prime which will be in the math font
447 \end{itemize}
448 The first two are commands defined in the {\tt pphs.sty} style file and are
449 thus user-redefinable as described in Section~\ref{user-adj}.  Backquotes, input
450 as {\tt `}, are either in the comment typeface for backquotes in comments or in
451 math font elsewhere.
452
453 \subsection{Writing internal alignment}
454
455 To commence a section of internal alignment, either of the functions {\tt WriteQueue}
456 or {\tt WriteRestOfQueue} write out
457 {\tt \char'134 begin\char'173 tabular\char'175 \char'173 @\char'173 \char'175 l@\char'173 \char'134 xspa1\char'175 c@\char'173 \char'175 l\char'175 }
458 before writing the first line of the section.  This provides an environment
459 with three columns.  The first column accommodates the Haskell code to the left of the
460 internal alignment, the second has the symbols that line up vertically, while the third
461 has the Haskell code to the right.  The Haskell code is written complete with its \LaTeX\
462 typesetting commands with the addition of {\tt \&} symbols denoting the breaks between
463 columns.  Once the internal alignment section has been completed, the
464 {\tt \char'134 end\char'173 tabular\char'175 } command is written to terminate the
465 environment.