Monday, October 16, 2006

My first PL/I program

My first PL/I program [1] was a few dozen lines transliterated from Algol. I compiled it using IBM's PL/I F compiler for the IBM System/360.
The PL/I F compiler was a wondrous beast. To borrow Brian Randell's phrase, it was "a triumph of engineering over design." PL/I was one of the largest and most complex programming languages of its time--perhaps of all time--intended to replace FORTRAN, COBOL, Algol, and most other programming languages in use at the time. But IBM's F level compilers had to run on relatively small machines. [2] To resolve this dilemma, the compiler was divided into a large number of "phases." [3]
My program compiled on the first try, went into execution, and then crashed with a divide by zero, producing perhaps 100 pages of error messages and core dump. The odd thing was that I wasn't aware of any divisions in my program.

It took some detective work to figure out what had happened. To explain my difficulties, I should mention some more characteristics of the compiler:
  • It always converted its input into legal PL/I; whenever it encountered an error, it modified the program to a form it could deal with; and it always executed the compiled result, no matter how many errors had been encountered. [4][5]
  • Each phase's error messages were in terms of the program as modified to that point. [6]
  • Error messages were printed out sorted by severity; within a severity level, by phase; within a phase, by position in the program. So messages relating to a single statement could be widely scattered.
I eventually discovered that the offending statement was something like
PUT LIST("PL/I VERSION OF MSP ANALYZER");
This was my first time using the 029 keypunch; unlike the 026, it had both single and double quotation mark characters. Being an American, I naturally used double quotes, but PL/I used single quotes as string delimiters. I should have punched
PUT LIST('PL/I VERSION OF MSP ANALYZER');
An early phase of the compiler determined the type of a statement. Since my statement was not a valid PUT statement, it was classified by default as an assignment statement.

A later phase of the compiler noticed that the assignment statement was missing an equal sign, so it inserted one:
PUT = LIST("PL/I VERSION OF MSP ANALYZER");
Because PL/I had no reserved words, this implicitly declared the variable PUT and the array variable LIST. Another phase had trouble processing the double quotes, so it deleted them:
PUT = LIST(PL/I VERSION OF MSP ANALYZER);
PL and I also became implicitly declared variables, but there were no further operators in the "expression," so the rest of it was deleted:
PUT = LIST(PL/I);
This was the statement that was finally compiled.

Of course, the variable I had not been initialized, and it happened to be zero when the program encountered this statement, so the program crashed with a divide by zero error. What could be more informative?

Notes:
[1] Circa spring 1967.
[2] More specifically, on machines with 44 KB of core storage (exclusive of storage requirements for the Operating System), without benefit of virtual memory. The FORTRAN level H compiler got more space: "A source program of about 600 cards can be compiled in 200 KB of main storage." [FORTRAN INFORMATION BULLETIN NO. 1, February 1968]
[3] I counted in the Program Logic Manual. The compiler had 112 distinct named phases. All but a dozen or so would be invoked in compiling any non-trivial program. The FORTRAN H level compiler had 5 phases, named 10, 15, 20, 25, and 30, divided into 13 overlay segments.
[4] At the Stanford help desk I once saw the output that resulted when a user who was confused about JCL compiled and executed his FORTRAN program using the PL/I F compiler. That, too, went into execution and then crashed.
[5] A misguided policy that has been adopted by too many of its successors.
[6] To compound the difficulty, I don't believe it said what changes it made, you had to infer them.

1 Comments:

Comment by Anonymous Ross Patterson:

So that's where the autocorrection approach started. I first encountered it with Cornell's PL/C compiler at Rutgers in 1976, and from other reading I thought it actually originated with PL/C. The practice certainly died not long afterwards - I know the PL/I X compiler didn't autocorrect. Of course, I used the F level compiler too, and I don't recall the behavior, so perhaps I'm all wet.

Anyway, thanks for the memories, from one greybeard to another.

6:08 AM  

Post a Comment

<< The Way It Was home