You can find the sources here: https://github.com/dtoffe/adsp-pl0
Some interesting notes:
- The original compiler does not define nor implements "read" or "write" statements, as was the norm in later PL/0 implementations. - The source code in the book corresponds to the implementation in the CDC 6000 that Wirth had at hand back then. That machine used the CDC Display Code:
https://en.wikipedia.org/wiki/CDC_display_code
a 6 bit character code from before the ASCII times. Among its 64 characters, it includes single symbols for "<>", "<=" and ">=". In an attempt to change the code the least to make it run as original as possible, I changed those three character to #, { and }, as the symbols in the lexer are implemented using an array of char (only the assignment is treated as a special case).
- The interpreter printing out the values of every variable assignment, noted by another reader of this post, was a way of getting some information of the running program, since the compiler does not implement read or write statements.
- Following the compiler code, full of single letter variable names, was not the most exciting part.
<- is somewhat better, but, again, for such a common operation, a single character is just more convenient. Sure, we could have editors that turn "=" into := or <- but now we're getting too fancy especially for something pedagogical.
I also don't mind the -> for C pointers; and certainly don't mind the <= >= or even == conventions (although at least today's compilers warn when they see "if (a=b) ...".
Ultimately, humans won't be writing code anymore anyway ( ;-) ?) so maybe the issue is entirely moot.
j = 5;
The user starts writing (<|> is the cursor position): i = <|>
j = 5;
This is a valid expression (i is a boolean). But the user probably intends to finish writing something like: i = 0;
j = 5;
So in the intermediate state we would like to emit a single warning about an incomplete statement. But since it is valid as written, we instead end up warning about e.g. j being unbound.> I also don't mind the -> for C pointers
Mmm. These two opinions should be contradictory if held on principle as opposed being held out of impression.
it = next(it);
if ((*it)->node->op == EQ) ...
vs. it := next(it);
if it.node.op = EQ ...
Eh. I don't really mind either of those except for the stupid parens after the "if" in the first case.Technically, if you don't make assignment an expression, you can even get away with using "=" for both. And "->" exists only because structs originally weren't really typechecked; you could take any pointer and just do "->struct_field" at it, and the compiler would auto-cast.
That is sad, but the revised editions seem to be published online.
I learned first on Pascal & Modula-2 and only picked up C later and while I appreciated its terse minimalism at the time and through the 90s, I actually don't at all now. I find it less readable.
PL/0, PS/2, CP/M, etc.
And then Gary Kildall also seemed to like it with CP/M and PL/M, but those were after IBM had used it and I'd guess Gary was just copying IBM.
Between just those two influences you cover a huge portion of the mainframe and micro computer worlds during the 60s-80s