Literate Programming

Contents

  1. Reference List

  2. Overview of Literate Programming

    1. Reading Source Code

    2. What's "Literate Programming"?

    3. Deficiency of Structured and Object Oriented Programming

    4. First Literate Programming Example

    5. Observations on Example

    6. Second Example

    7. Knuth's Comments on Literate Programming

    8. Our Experience with Literate Programming

  3. The WEB System

    1. FunnelWeb Tutorial

    2. Using FunnelWeb

  4. Creative Uses of Literate Programming

  5. How to Write Bad Literate Programs

Reference List

For further information on Literate Programming:

Click here to view the Web page on literate programming.

[B86a] J. Bentley, "Programming Pearls: Literate Programming," CACM 29, No. 5, May 1986, pp. 364-369.

[B86b] J. Bentley, "Programming Pearls: A Literate Program", CACM 29, No. 6, June 1986, pp. 471-483.

[K] D. E. Knuth, "Literate Programming", The Computer Journal 27, No. 2, 1984, pp. 97-111.

[W] R. N. Williams, Funnelweb User's Manual, V1.0 for FunnelWeb 3.0, May 1992.


Reading Source Code

Do you like to read code?

What's "Literate Programming"?

Core problem:

We write code for a computer, not a human reader!
Donald Knuth observes:

A Solution: Literate Programming

Knuth invented literate programming.

"The literate programmer: [K, p. 97]

Summary of Literate Programming

From [W]: "Instead of writing code containing documentation, the literate programmer writes documentation containing code."

A Literate Programming System Can Provide

Literate Programming Benefits

(from [W])

A Caveat

You should write a program from the start as a literate program. Do not in normal cases try to "retrofit" a program with English to form a literate program.


Deficiency of Structured and Object Oriented Programming

Structured programming taught us to keep several purposes in mind when writing a program:

I personally believe that object oriented programming gives us a way to:

What's missing:

Way to understand program as whole (I see the individual trees, but what does the forest look like?)

Literate Programming Example

Problem

Input

Output

sorted list of M random numbers in range 1..N in which no integer occurs more once

Example

If M=5 and N=10, one possible output is: 1 5 6 8 9

In class we'll go over a literate program solution solution (pp. 366-367 in [B86a])


Observations on Example


Second Example

In class we'll go over a second literate program example [B86b] that illustrates procedures, gotos, and other things.

Problem

Given a text file and an integer k, "the most common words are to be printed in order of decreasing frequency, with words of equal frequency listed in alphabetic order. Printing should stop after k words have been output, if more than k words are present."

Example

Given the text "A dog is a mammal and is a four legged creature", and the value k=2, the output is:

 
a
is

Comments on the paper


Knuth's Comments on Literate Programming

"A complex piece of software consists of simple parts and simple relationships between those parts; the programmer's task is to state those parts and those relationships, in whatever order is best for human comprehension -- not in some rigidly determined order like top-down or bottom-up."

"My experiences have led me to believe that a person reading a program is ... ready to comprehend it by learning its various parts in approximately the order in which it was written."

"[Literate programming] ... allows a program to express programs in a `stream of consciousness' order." This contrasts programming languages that may enforce a particular order, such as top-down.

Literate programming is also good at separating an algorithm from its error-handling code:

    if <input data is invalid> then
      <Issue an error message and try to recover>;
  <Update data structure using input>;

Our Experiences with Literate Programming

We use literate programming with our Chitra system for visualization and statistical analysis of trace data. We use C++, shell scripts, and a little FORTRAN.

I find today that I can locate the code that performs a certain function within 5 or 10 minutes. In class I'll show the table of contents of the main document.

In contrast, versions of two similar system written by students in past years was difficult to read and maintain.


WEB System

"A program is best thought of as a web instead of a tree." [K, p. 107]

File containing literate program text (English plus code) is called a WEB file.

A WEB system strips out code, rearranges it to create compilable source code.

WEB will also write a file that can be processed by a text formatter, such as TeX.

There are several WEB implementations. We'll use funnelweb, which allows use of any programming langauge and (so far) two typesetters (TeX and html).


FunnelWeb Tutorial (see pages 20-41 in [W])

How FunnelWeb and WEB differ

FunnelWeb is:

FunnelWeb allows user to control all aspects of formatting of source code that is generated.

A Hello World Document

1. Store in file "hello.fw":

This document will write the words "Hello World."

   @O@<hello.txt@>@{Hello World@+@}

Try it and see.

In example above,

2. Run

  fw hello

The output will be:

  hello.lis  - The LISTING file
  hello.txt  - The PRODUCT file

3. To produce the typeset document, instead of step 2, do:

  fw hello +t

The output will also include:

  hello.tex - A DOCUMENTATION file (in TeX format)

Then do:

  tex hello.tex

TeX then creates file "hello.dvi". 4. To view the typeset documentation file, do either:

  dvips hello.dvi
  lpr hello.ps

or:

  xdvi hello

Macro Facilities

Here's a longer example with macros. Symbols @$ denote a macro definition. Macros are delimited by @< and @>.


@O@<hello.c@>==@{@-
  @<Include Files@>
  @<Main Program@>
@}

@$@<Main Program@>==@{@-
  main()
  {
    @<Print@>
    @<Print@>
  }
@}

@$@<Print@>==@{@-
  printf("Hellow world!");
  printf("\n");@}

@$@<Include Files@>==@{@-
  #include <stdio.h>
  #include <stdlib.h>
@}

Macros "Include Files", "Main Program", and "Print" have no parameters in this example.

Funnelweb parses and analyzes macros from input before expanding any macros.

Macros With Parameters

Macros can take parameter lists. Parameters are denoted @1, @2, ....

Suppose we wanted each invocation of the Print macro to pass a different text to printf:

    @$@<Print@>@(@1@)==@{@-
    printf("@1");
    printf("\n");@}

Then the Print macro would be invoked by:

     @<Print@>@(
          @"Hello world@"@)
or
     @<Print@<@(Hello world@)

There can be up to 9 formal parameters (i.e., @1 to @9).

Additive Macros

In class I'll go over the example on p. 27-28 of [W].

Questions on example:

Note in example:

Include files...

Suppose that camera.txt contains:
    'Cos I shoot with a camera instead of a gun.
    The animals flock to be petted and fed,
and suppose that poem.fw contains:
     I like to go shooting, it's a whole lot of fun,
     @i     camera.txt
     Cos they know my camera isn't loaded with lead.
FunnelWeb will replace the @i line by the text in camera.txt:
     I like to go shooting, it's a whole lot of fun,
     'Cos I shoot with a camera instead of a gun,
     The animals flock to be petted and fed,
     Cos they know my camera isn't loaded with lead.

Note: FunnelWeb expands include files before it starts scanning and parsing included text.

Typesetting Facilities

Overview

A FunnelWeb document contains:

These can be interspersed in any manner.

The @O directive controls the order in which the product file's text is generated. In contrast, the documentation file's order corresponds to the order of free text and macros in the .fw file.

Section headings

A .fw file is hierarchically structured using section headings. These are specified by @A to @E.

@A is a new chapter.

Example 1:

     @A@<How Tangle and Weave Work@>

     @B@<How Tangle Works>
     I need to write this section.

     @B@<How Weave Works@>
     And I need to write this section, too.

Example 2:

     @B Notice that the heading was not given.  It will be "How
     Tangle Works" due to the macro definition below.

     @$@<How Tangle Works@>==@{...@}

Typesetter instructions

Three useful instructions: See the FunnelWeb manual for more typesetter instructions.

List of Special Sequences

==       define a macro in one part 
+=       define macro in multiple part

@A...@E  section headings
@i       include a file
@M       signifies that a macro can be called multiple times
@O       output text to product file named in following argument
@p       give a pragma, such as:
             indentation = none
@t       entire line is a typesetter directive, such as:
            new_page
            table_of_contents
            title titlefont|smalltitlefont|normalfont centre|left|right ...
            vskip 40 mm
@Z       signifies that a macro can be called zero times
@$       define a macro
@{@}     delimit macro body OR sets free text in same font as
            macros
@<@>     either define a macro or call a macro
@/       delimits free text to be set in italics
@1...@9  actual parameter list
@"       used to allow insertion of white space in actual parameters
@,       used to separate actual parameters in a list
@(@)     used to enclose parameter lists
@-@+     delete or insert newline character after this symbol
@=       redefine special character (its default is "@")
@!       comment line follows on remainder of line

A Complete Example

(In class we'll look at the example in section 1.8 of [W] along with the TeX output. I'll pass a hardcopy of this out to you.)


Using FunnelWeb

Where to Find FunnelWeb

The FunnelWeb User's Manual on many CS department machines is in:

/cruncher/u3/abrams/doc/fw_userman.dvi

View the manual by doing

         xdvi   /cruncher/u3/abrams/doc/fw_userman.dvi

The binary of FunnelWeb is named fw. There are binary versions of fw for several platforms in

/cruncher/u3/abrams/bin/<platform>/fw

where <platform> is alpha, mips, next, or sparc.

The /cruncher/u3/ is an nfs mounted file from cruncher to many DECstations in the CS department. It can be mounted on other machines that you use by request.

Setting your path variable

To use fw, you must have /cruncher/u3/abrams/bin/<platform> on your path.

Running fw

Create a file containing the funnelweb input. Let it be called hello.fw.

Then execute:

    fw hello +t

This will create three files:

   hello.lis  --  A listing file
   hello.tex -- A document file (in TeX format)
   hello.txt  -- A product file

You can do "cat hello.txt" to look at the product file. To view the document file, run

   tex hello

The file hello.dvi will be created (along with hello.log). You can view the file from X-windows with

   xdvi hello &

You can print the file by first creating a postscript file (named hello.ps), and then spooling the postscript file to the printer:

    
   dvips hello
   lpr   hello.ps

Creative Uses of Literate Programming

  1. Creating more than one compile module

    You can put more than one @O into a literate program. Thus you can have one .fw file that creates multiple compile modules (e.g., .h and .c files).

  2. Including a Unix "man" page as part of the literate program

    You can put a @O into a .fw file that writes a manual entry for the command to a file.

  3. Use literate programming macros to create generic abstract data types
    @$@<Generic Node@>@(@2@)==@{
    module  @2;
    type @2 = ^@2Record;
    @2Record = record
        Member: @1;
        Next:   @2;
    end;
    @}
    
    @O<Node.pas@>==@{@-
         <Generic Node@>@(integer,integerNode@)@}
    
    @O<RealNode.pas@>==@{@-
         <Generic Node@>@(real,realNode@)@}
    

  4. Use literate programming to avoid putting private part of an abstract data type into the interface definition
    class Node { 
         @<Private Part@>
         public: void Insert(Node*);
    }
    
    
    

How to Write Bad Literate Programs

(From [W], p. 53)

  1. Use spaghetti organization

    Scramble the program so that it is layed out in an unordered, undisciplined "stream of consciousness" style. Don't think about how to order your presentation.

  2. Use a boring organization

    Use the opposite of spaghetti organization. Lay out the program in order "desired" by programming language. Even if this order is appropriate, forget to make it descriptive.

  3. Do not design the documentation for random access

    Do not strike a balance between the needs of the first time (sequential) reader and the maintenance (random-access) programmer.

  4. Use too much inter-dependency in the documentation

    Make the document a network of facts, so that changing a small piece of code invalidates many pieces of text scattered throughout the document. Overuse the conversational style (mention things many times).

  5. Use the Pavlov response in writing documentation

    Whenever you begin a new section, and the section starts with a macro, and no commentary is needed, succum to the urge to fill the space between them with useless text.

  6. Overdocument

    If a piece of code is fairly self explanatory, give in to the urge to overdocument by writing a long commentary.

  7. Duplicate a comment in text and in program code comment

    If you are generating product files that must exist on their own (i.e., the code will be used in a larger programming project that does not use literate programming), be sure to make the text and the code comments redundant. Even better, be inconsistent as to whether an important fact goes in the text or in the code.