Plov008 : multiple assignments
While running a test to check the behavior of the EXIT statement I ran into a problem. It looked like multiple assignments were not taken care of. So I made a more difficult test program, test20:
PROGRAM test20
VARIABLES a b c d e f g h i j k END
BEGIN
LOOP
REPEAT
a := a + 1
UNTIL a = 20
b := a
IF b = 12 THEN EXIT END
c := a + b x c - d
k := a - j x 2
END
END test20
And it fell astray. The problem was not new to me but I forgot about it... In normal Wirthian languages lines
of code are auto terminated. That is: if a line of code is closed by any kind of keyword, the line is properly
dealt with. If no keyword is coming up, you need to please the compiler by appending a ';' to the end of the
previous line of code to signal that 'something else is coming'.
My compiler relies on a token that is already there, although invisible: the ASCII linefeed. Or at least: it should.
Plov008 : the source
So we need to detect linefeeds. There is only one place where we can do that: in 'GetSymbol'. The current GetSymbol is rather simple: it issues a TextIO.GetString function call and that's it. We have no way to find out what happens inside this function so we need to write our own version:
PROCEDURE ReadString (VAR str : Identifier);
VAR n, max : CARDINAL;
ch : CHAR;
BEGIN
n := 0; max := HIGH (str);
IF lastCH = ASCII.LF THEN pastEOL := TRUE ELSE pastEOL := FALSE END;
REPEAT
TextIO.GetChar (inFile, ch);
IF ch = ASCII.LF THEN
pastEOL := TRUE
(* ;InOut.Write ("#") *)
END
UNTIL ch > ' ';
REPEAT
str [n] := ch;
INC (n);
TextIO.GetChar (inFile, ch)
UNTIL (ch < '!') OR (n > max);
lastCH := ch;
IF n < max THEN str [n] := 0C END
END ReadString;
The new ReadString. The line that is commented out is a remnant of the debug code. Just ignore it. What the
function does is:
PROCEDURE isComment; BEGIN REPEAT GetSymbol UNTIL Strings.StrEq (token, '*)'); GetSymbol END isComment;The 'isComment' procedure takes care of nested comments. Just like Professor Wirth showed me.
PROCEDURE GetSymbol;
BEGIN
IF TextIO.EOF (inFile) = FALSE THEN
(* TextIO.GetString (inFile, token); *)
ReadString (token);
IF Strings.StrEq (token, '(*') THEN isComment END
ELSE
InOut.WriteString ("EOF!!! ")
END;
InOut.WriteString (token); InOut.Write (11C); InOut.WriteBf
END GetSymbol;
The new GetSymbol procedure. This is how you deal with experimental additions:
Of course, making the new ReadString is not the only change. We also need to use the new variable and act upon it. This is done in the expression evaluator:
PROCEDURE Expression;
VAR op : CHAR;
BEGIN
Term;
op := token [0];
WHILE (token [0] = '+') OR (token [0] = '-') DO
GetSymbol;
Term;
IF op = '+' THEN
CG ("ADD");
CG ("")
ELSE
CG ("SUBTRACT");
CG ("")
END;
IF pastEOL THEN RETURN END
END
END Expression;
Think about it why I had to put the line here.
Plov008 : see it work
Below is a table with PLOV on the left and PALO on the right. There are two PALO fields. You'll find out why,
by reading down the page.
| Plov | PALO I | PALO II |
|---|---|---|
| PROGRAM test20 | # PROGRAM test20 | |
| VARIABLES a b c d e f g h i j k END |
VARIABLE a VARIABLE b VARIABLE c VARIABLE d VARIABLE e VARIABLE f VARIABLE g VARIABLE h VARIABLE i VARIABLE j VARIABLE k |
|
| BEGIN | LABEL MAINLOOP | |
| LOOP | LABEL LOOP-1 | |
| REPEAT | LABEL-0 | |
| a := a + 1 |
STORE ADDRESS OF a FETCH VALUE OF a STORE 1 ADD SAVE RESULT |
|
| UNTIL a = 20 |
FETCH VALUE OF a STORE 20 IF NOT EQUAL JUMP TO LABEL-0 |
|
| b := a |
STORE ADDRESS OF b FETCH VALUE OF a SAVE RESULT |
|
| IF b = 12 THEN EXIT END |
FETCH VALUE OF b STORE 12 IF NOT EQUAL JUMP TO LABEL IF-00 JUMP TO XLOOP-1
JUMP TO LABEL XIF-0 |
FETCH VALUE OF b STORE 12 IF NOT EQUAL JUMP TO LABEL IF-00 JUMP TO XLOOP-1
JUMP TO LABEL XIF-0 |
| c := a + b x c - d |
STORE ADDRESS OF c FETCH VALUE OF a FETCH VALUE OF b FETCH VALUE OF c MULTIPLY ADD FETCH VALUE OF d ADD SAVE RESULT |
STORE ADDRESS OF c FETCH VALUE OF a FETCH VALUE OF b FETCH VALUE OF c MULTIPLY ADD FETCH VALUE OF d SUBTRACT SAVE RESULT |
| k := a - j x 2 |
STORE ADDRESS OF k FETCH VALUE OF a FETCH VALUE OF j STORE 2 MULTIPLY SUBTRACT SAVE RESULT |
|
| END |
JUMP TO LOOP-1 LABEL XLOOP-1 |
|
| END test20 |
LABEL EXITMAINLOOP # Done # |
|
Impressive, isn't it?
It isn't:
Plov008 : the fix
The drawing board was happy: the source language was Modula-2 so it didn't need to use a dozen magicians to go through the source. The first problem (the ADD that should have been a SUBTRACT) was easily solved:
| Old | New |
|---|---|
PROCEDURE Expression;
VAR op : CHAR;
BEGIN
Term;
op := token [0];
WHILE (token [0] = '+') OR (token [0] = '-') DO
GetSymbol;
Term;
IF op = '+' THEN
CG ("ADD");
CG ("")
ELSE
CG ("SUBTRACT");
CG ("")
END;
IF pastEOL THEN RETURN END
END
END Expression;
|
PROCEDURE Expression;
VAR op : CHAR;
BEGIN
Term;
op := token [0];
WHILE (op = '+') OR (op = '-') DO
GetSymbol;
Term;
IF op = '+' THEN
CG ("ADD");
CG ("")
ELSE
CG ("SUBTRACT");
CG ("")
END;
|
As you can see in the old code, the while loop was entered with a value of 'op' but 'op' never changed inside the loop! So the value was static. The fix was easy.
What remains is the missing IF label. I must confess that I was not overly happy with the way in which I fixed the IF loop and I did not test it extensively. And so things take a turn of their own...
The fix was easy. The label generators were in the wrong place.... The problem is: if I make a side by side comparison, even a 1280 screen is not wide enough. So I made a screenshot with arrows... The red blocks are in the NEW position and came from their OLD positions.

The new source code is in the PALO table above. And a syou see, I fooled you: the tests were done with Plov009...
Page created on 2 September 2008 and
Page equipped with FroogleBuster technology