Notes on Programming in Modula-2

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], or Compilerbau[Wir86].

My interest in Modula-2 began after studying Pascal as part of working through Software Tools in Pascal[KP81], part of a study of Unix and GNU/Linux that occurred as part of my computing hobby (and a career). See my article hello, world about some of my early computing interests, and my Notes on The Unix Programming Environment.

Observations in Programming in Modula-2

The first thing to note is this is written solely by Wirth, something he hadn't done since Systematic Programming: An Introduction[W76]. 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.

PIM (both 1 and 2) programs were primarily tested using the Medos-2 4.2 disc of Emulith. I noticed that programs using the REAL type sometimes gave off-by-one output, e.g. 2.999999 instead of 3. When testing the code using other compilers this didn't occur. The Queens program gave an error that made me wonder if the problem was with the Emulith display. 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 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 both editions (otherwise noted):

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.

Observations in the Report

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.

References

[KP81]
B. W. Kernighan, P. J. Plauger, Software Tools in Pascal, Addison-Wesley, 1981
[W76]
N. E. Wirth, Systematic Programming: An Introduction, Prentice Hall, Englewood, 1976.
[Wi76]
N. E. Wirth, Modula: a language for modular multiprogramming, ETH-18, March 1976.
[Wir76]
N. E. Wirth, The Use of Modula and Design and implementation of Modula, ETH-19, 1976.
[W82]
N. E. Wirth, Programming in Modula-2, Springer-Verlag, 1982
[W83]
N. E. Wirth, Programming in Modula-2, Second Edition, Springer-Verlag, 1983
[W85]
N. E. Wirth, Programming in Modula-2, Third Edition, Springer-Verlag, 1985
[W86]
N. E. Wirth, Algorithms & Data Structures, Prentice Hall, Englewood, 1986
[Wir86]
N. E. Wirth, Compilerbau, Teubner-Verlag, Stuttgart, 1986
[W88]
N. E. Wirth, Programming in Modula-2, Fourth Edition, Springer-Verlag, 1988

©2023 David Egan Evans.