This document is a work in-progress, started to reflect what I have learned about Modula-2 through ETH papers and editions of Programming in Modula-2[W82] (PIM). This will not cover the Modula-2 edition of Algorithms and Data Structures[W86], nor Compilerbau[Wir86].
My interest in Modula-2 began after studying Pascal while working through Software Tools in Pascal[KP81]. See my article hello, world about some of my early computing interests, and my Notes on The Unix Programming Environment.
The first thing to note is this is written solely by Wirth, something he hadn't done since Systematic Programming: An Introduction[W76]. (Algorithms + Data Structures = Programs[Wirt76] was also written solely by Wirth, published together.) The Preface indicates that the book is an introduction to programming, suggesting that it is, in a way, a replacement to the earlier text. That text used Pascal, introduced the computer and its history, and focused some on early algorithmic verification methods. It also looked at basics of diagraming a program.
[Note:] I am still evaluating PIM3, and comparing it to PIM2. Comparisons and comments related to PIM3 are thus incomplete. I haven't yet evaluated PIM4 nor the German translation of it (called the second edition). Though my German is rusty and incomplete, a comparison of the report in PIM4 with the translation's reproduction of it suggest that no changes to the language were made, though printed four years later.
PIM3 is a result of feedback and standardization with third parties
dealing with their compilers, (not only with ETH and Medos-2). The first
change noticed is that the typographical layout is a bit more compressed
top to bottom in some places, so that clean breaks for fitting text on a
page is sometimes abandoned, but allowed to flow without further
consideration, but improved elsewhere or sometimes entirely unchanged.
The second is the language changes are marked in the report, but not
really in the text. The first observed change is the addition of the
~ as an operator short hand for the NOT
reserved word. The section on BITSET is typographically
simplified, but the EBNF has changed to using expression
instead of ConstExpression. This is effectively the same,
and the report doesn't appear different in terms of
BITSET. The Postfix program is adjusted to use
the module TextWindows, but the program is essentially the
same otherwise. Inc() and Dec() are now
described in the text for enumerations, not only the report. The syntax
description for the SET type is simplified within the
paragraph. Example modules no longer use QUALIFIED.
The move to PIM4 seems to be about the move to the 32-bit Ceres, as well as the MacOS MacMeth, and the adaption from 16-bit RT-11 and Medos-2, perhaps with influences coming from the beginnings in 1986 from the Oberon system and language research. There is also the single pass compiler that Wirth wrote.
PIM/PIM2 programs were primarily tested using the Medos-2 4.2 disc of
Emulith, whereas
PIM3 programs were tested with dsk_1.img of Medos-2 5.2 with the
multi-pass compiler. I noticed that programs using the REAL
type sometimes gave off-by-one output, e.g. 2.999999 instead of 3,
limiting the program's size capacity. When testing the code using other
compilers this didn't occur. The Queens program gave a range
error that made me wonder if the problem was with the Emulith display.
I tried reducing the line size without success.
At least the output is given as an example in the book, (though not in
the Fourth Edition[W82]!).
Algorithms & Data Structures[W86] gives an example using InOut
instead of LineDrawing for Queens. The EBNF
tool compiled fine, but the program output failed to execute on
Emulith.
Due to bugginess with Emulith, which after a Windows 10 Pro upgrade
the edit program became unresponsive, I used an editor in
Windows to type out the programs, then copied them to Emulith using the
applecopy program. I wrote the following tool to remove the
linefeed character, since Medos-2 uses only the carriage return (the
same as with classic Mac OS):
MODULE rmlf; (* DEE 2023-06-11 *)
FROM InOut IMPORT CloseInput, CloseOutput, Done, OpenInput, OpenOutput, Read,
Write, WriteLn, WriteString;
VAR ch: CHAR;
PROCEDURE copy;
BEGIN Read(ch);
WHILE Done DO
IF ch = CHR(10)
THEN WriteLn
ELSE Write(ch)
END;
Read(ch)
END
END copy;
BEGIN WriteString("File to remove LFs: "); WriteLn;
OpenInput("TXT"); OpenOutput("TXT");
copy();
CloseInput; CloseOutput
END rmlf.
Thankfully, I was able to write this program with edit
before it failed to respond.
A word for word comparison of PIM with the Second Edition[W83] shows they are almost identical, including some corrections, but with nothing to suggest the language had changed in any way. However, the typography is less careful than the first edition, the latter of which is probably the best example of the four editions. Several other mistakes are found in the text. Here are some errata that mostly apply to the first and second editions (unless otherwise noted):
Harmonic
imports the Write procedure, and uses it throughout, but it
should import WriteString instead, (Write needing to
be removed in PIM3)Fractions module is missing lines 22-25 (see below for the
missing output), fixed in the third edition250 value given leaves the
last two values from being given, which is the same with 500 in
previous editions. However, the output shown in the text is complete, which
requires the value to be 252.IMPORT line from
program Queens does not match the definition for
LineDrawing on page 114 (116 in PIM3). The area
procedure should be used instead of paint throughout the program
(fixed in PIM3), and the clear procedure can be used without
parameters (their use is a mystery)TableHandler DEFINITION is missing the
semicolon at the end of Tabulate. In the PIM3 implementation
module, within the Search function t is allocated
but I believe this is in error, and it should be q. For
whatever reason, the one pass compiler on disk 1 gave me an error 133 when
Search(t) was called by Record.Processes IMPLEMENTATION module in
the first edition of PIM, Allocate is imported, when it should be
ALLOCATE, fixed in PIM2, (see the simple Storage)
local module in the Report for Allocate). This sneaks back in
with the discussion on pointers in PIM3, replacing NEW(p) with
Allocate (and DISPOSE with
Deallocate), and with the TableHandler.22 0.0'45 23 0.'0434782608695652173913 24 0.041'6 25 0.04'0
The change of name for MathLib, introduced in the December
1980 Modula-2 Report, to MathLib0 in PIM is a mystery. The
DEFINITION module is identical and never seems to change. The
only difference is the ETH reports for Modula and Modula-2 are all for
the implementation on the DEC PDP-11/40. The implementation for the
Lilith uses CODE statements for its M-code. Could this be
why? One other possibility is forcing the recompilation of modules that
import it, perhaps from an early version of Medos?
Module Sierpinski was iterative. It was cool how hitting
the space bar made it do another more detailed round. I seem to remember
that the output example on pg. 116 is after three iterations. A fourth
became very detailed, and beyond that started to white/black out the
display. The DrawCircle procedure example was fun to turn
into a module and see it work on Medos-2:
MODULE Circle; (* DEE 2023-07-17 *)
FROM LineDrawing IMPORT dot;
PROCEDURE DrawCircle(x0,y0,r: INTEGER);
CONST c1 = 400B; c2 = 200B;
VAR x,y: INTEGER;
BEGIN
r := r*c2; x := r; y := 0; r := r-1;
REPEAT dot(1, x DIV c2 + x0, y DIV c2 + y0);
x := x - y DIV c1; y := y + x DIV c1
UNTIL (x >= r) & (y <= 0)
END DrawCircle;
BEGIN DrawCircle(200,200,100)
END Circle.
The drawing of Wirth on pg. 119 was funny. The Draw
module on the next page allows the mouse to be used to draw this, so
someone had a surprisingly effective control of their mouse to reproduce
that. Years ago, a friend did the same of me.
The version of the Buffer module on pg. 130 appears to be a local module. The
import list seems to need a FROM Processes from the previous page, but that does not
define ElementType which is used in the program. I found this in the buffer interface
module example in the description of the
The Use of Modula[Wir76], section 2.0.
This local module version seems to be a Modula-2 update, with the deposit and
fetch procedures elaborated on. The same goes for the Keyboard
module on page 137, which appears to be a rewrite of the keyboard device module
in section 2.2 of The Use of Modula[Wir76].
There's also the curious notation of [1] in the module Buffer header,
and a similar [4] in the Keyboard module header. The
Modula(-1)[Wi76] report explains this as device
module specific interupt prority or the interupt vector store location. Reading the description on
the next page (138), detail 3 explicitly states this: [4] is the
Keyboard modules interupt priority. When this is seen, it is specific to the DEC
PDP-11 implementation of the Modula-2 compiler. In both cases, the module ending semi-colon is
missing.
It is observed that the Report, placed in an Appendix, relies on the overall text and references it. This is somewhat significant, as interpretation of the Report can thus have implications derived from the text.
The gcd example of Modula(-1)[Wi76] is
moved to the text and replaced with a log2 example against CARDINAL. The
programs are essentially untouched, other than conversion to Modula-2. Same for
LineInput, TrackReservation, Storage, and
Typewriter (removed in PIM3 with the process related priority change), though as
usual, these local modules do not have their ending semi-colon.