Plov10 : WHILE DO
The Plov compiler is nearing completion. Just the WHILE is needed for the time being. Not so diffcult. It's only a few lines of code. At least, within Plov. If you have more datatypes and a looser syntax, things can get more difficult. But that's why we chose this limited language in the first place!
Anyway, here are the changes, made in Plov010:
PROCEDURE StatementSequence;
BEGIN
GetSymbol;
LOOP
CG ("");
IF weHaveLocals AND (FindLocal (token) = TRUE) THEN
IF thisLocal^.type = Vartype THEN Assignment END
ELSIF FindSymbol (token) = TRUE THEN
IF (thisSymbol^.type = Vartype) THEN Assignment
ELSIF thisSymbol^.type = Proctype THEN Procedurecall
ELSIF Strings.StrEq (token, "IF") THEN isIF
ELSIF Strings.StrEq (token, "LOOP") THEN isLOOP
ELSIF Strings.StrEq (token, "RETURN") THEN isRETURN
ELSIF Strings.StrEq (token, "WHILE") THEN isWHILE
ELSIF Strings.StrEq (token, "REPEAT") THEN isREPEAT
ELSIF Strings.StrEq (token, "EXIT") THEN isEXIT
ELSIF Strings.StrEq (token, "END") THEN RETURN
ELSIF Strings.StrEq (token, "UNTIL") THEN RETURN
ELSIF Strings.StrEq (token, "ELSIF") THEN RETURN
ELSIF Strings.StrEq (token, "ELSE") THEN RETURN
ELSE
ErrorMessage (10) (* Error in StatementSequence *)
END
ELSE
ErrorMessage (9) (* Undefined symbol *)
END
END
END StatementSequence;
StatementSequence "needs to know" which keywords exist. WHILE is a new keyword so one line as added. Also the
line filling the symbol table needed to be added:
IF StoreSymbol ("WHILE") = FALSE THEN ErrorMessage (0) END;
and of course the WHILEcounter was loaded with 'zero' in the Init section. Here is the WHILE section:
PROCEDURE isWHILE;
VAR count : CARDINAL;
BEGIN
count := WHILEcount;
CG ("LABEL WHILE-"); CGn (count); CG ("");
INC (WHILEcount);
Condition;
CG ("IF "); CG (op);
CG (" JUMP TO XWHILE-"); CGn (count); CG ("");
StatementSequence;
CG ("JUMP TO LABEL WHILE-");
CGn (count); CG ("");
IF Strings.StrEq (token, "END") THEN
CG ("LABEL XWHILE-"); CGn (count); CG ("")
ELSE
ErrorMessage (8) (* END expected *)
END;
GetSymbol
END isWHILE;
Also 'Condition' was changed in the IF handler. Here is the new definition. Now it can be used in all cases
where a condition need be specified. Here it comes:
PROCEDURE Condition; BEGIN GetSymbol; Expression; Comparison; GetSymbol; Expression; END Condition;Difficult, isn't it? :o)
Plov010 : trials
While we're still in pre-alpha stage, visual feedback is highly appreciated. So this is what it looks like when Plov010 is run from a terminal:
jan@beryllium:~/modula/Plov$ Plov010 wikitest PROGRAM wikitest CONSTANTS m = 7 n = 85 END VARIABLES x y z q r END PROCEDURE MULTIPLY LOCAL a b END BEGIN a := x b := y z := 0 WHILE b MOD 2 = 1 DO IF b = 1 THEN z := z + a END a := a + a b := b / 2 END END MULTIPLY PROCEDURE DIVIDE LOCAL w END BEGIN r := x q := 0 w := y WHILE w <= r DO w := w + w END WHILE w > y DO q := q + q w := w / 2 IF w <= r THEN r := r - w q := q + 1 END END END DIVIDE PROCEDURE Gcd LOCAL f g END BEGIN f := x g := y WHILE f # g DO IF f < g THEN g := g - f END IF g < f THEN f := f - g END END z := f END Gcd BEGIN x := m y := n MULTIPLY x := 25 y := 3 DIVIDE x := 84 y := 36 Gcd END wikitestWhen I see this, I know all was OK with GetSymbol and the parser statemachine. If I don't see this, I pipe the data to file and less it. Your bugs is there, where the data stopped being printed to screen.
The source listed above is 'wikitest' and formatted it looks like this:
PROGRAM wikitest
CONSTANTS m = 7
n = 85
END
VARIABLES x
y
z
q
r
END
PROCEDURE MULTIPLY
LOCAL a b END
BEGIN
a := x
b := y
z := 0
WHILE b MOD 2 = 1 DO
IF b = 1 THEN z := z + a END
a := a + a
b := b / 2
END
END MULTIPLY
PROCEDURE DIVIDE
LOCAL w END
BEGIN
r := x
q := 0
w := y
WHILE w <= r DO w := w + w END
WHILE w > y DO
q := q + q
w := w / 2
IF w <= r THEN
r := r - w
q := q + 1
END
END
END DIVIDE
PROCEDURE Gcd
LOCAL f g END
BEGIN
f := x
g := y
WHILE f # g DO
IF f < g THEN g := g - f END
IF g < f THEN f := f - g END
END
z := f
END Gcd
BEGIN
x := m
y := n
MULTIPLY
x := 25
y := 3
DIVIDE
x := 84
y := 36
Gcd
END wikitest
Of course this source compiled. You saw the screen output already above. Still, how does it compare with the
output? Below is a side by side comparison.
| Plov | PALO |
|---|---|
| PROGRAM wikitest | # PROGRAM wikitest |
|
CONSTANTS m = 7 n = 85 END |
|
|
VARIABLES x y z q r END |
VARIABLE x VARIABLE y VARIABLE z VARIABLE q VARIABLE r |
| PROCEDURE MULTIPLY |
# PROCEDURE DECLARATION OF MULTIPLY LABEL MULTIPLY |
| LOCAL a b END |
LOCAL a LOCAL b |
| BEGIN | |
| a := x |
STORE ADDRESS OF LOCAL a FETCH VALUE OF x SAVE RESULT |
| b := y |
STORE ADDRESS OF LOCAL b FETCH VALUE OF y SAVE RESULT |
| z := 0 |
STORE ADDRESS OF z STORE 0 SAVE RESULT |
| WHILE b MOD 2 = 1 DO |
LABEL WHILE-0 FETCH VALUE OF LOCAL b STORE 2 MODULO STORE 1 IF NOT EQUAL JUMP TO XWHILE-0 |
| IF b = 1 THEN z := z + a END |
FETCH VALUE OF LOCAL b STORE 1 IF NOT EQUAL JUMP TO LABEL IF-00 STORE ADDRESS OF z FETCH VALUE OF z FETCH VALUE OF LOCAL a ADD SAVE RESULT
JUMP TO LABEL XIF-0 |
| a := a + a |
STORE ADDRESS OF LOCAL a FETCH VALUE OF LOCAL a FETCH VALUE OF LOCAL a ADD SAVE RESULT |
| b := b / 2 |
STORE ADDRESS OF LOCAL b FETCH VALUE OF LOCAL b STORE 2 DIVIDE SAVE RESULT |
| END |
JUMP TO LABEL WHILE-0 LABEL XWHILE-0 |
| END MULTIPLY |
RELEASE 2 # END OF PROCEDURE MULTIPLY |
| PROCEDURE DIVIDE |
# PROCEDURE DECLARATION OF DIVIDE LABEL DIVIDE |
| LOCAL w END | LOCAL w |
| BEGIN | |
| r := x |
STORE ADDRESS OF r FETCH VALUE OF x SAVE RESULT |
| q := 0 |
STORE ADDRESS OF q STORE 0 SAVE RESULT |
| w := y |
STORE ADDRESS OF LOCAL w FETCH VALUE OF y SAVE RESULT |
| WHILE w <= r DO w := w + w END |
LABEL WHILE-1 FETCH VALUE OF LOCAL w FETCH VALUE OF r IF GREATER JUMP TO XWHILE-1 STORE ADDRESS OF LOCAL w FETCH VALUE OF LOCAL w FETCH VALUE OF LOCAL w ADD SAVE RESULT
JUMP TO LABEL WHILE-1 |
| WHILE w > y DO |
LABEL WHILE-2 FETCH VALUE OF LOCAL w FETCH VALUE OF y IF LESS OR EQUAL JUMP TO XWHILE-2 |
| q := q + q |
STORE ADDRESS OF q FETCH VALUE OF q FETCH VALUE OF q ADD SAVE RESULT |
| w := w / 2 |
STORE ADDRESS OF LOCAL w FETCH VALUE OF LOCAL w STORE 2 DIVIDE SAVE RESULT |
| IF w <= r THEN |
FETCH VALUE OF LOCAL w FETCH VALUE OF r IF GREATER JUMP TO LABEL IF-10 |
| r := r - w |
STORE ADDRESS OF r FETCH VALUE OF r FETCH VALUE OF LOCAL w SUBTRACT SAVE RESULT |
| q := q + 1 |
STORE ADDRESS OF q FETCH VALUE OF q STORE 1 ADD SAVE RESULT JUMP TO LABEL XIF-1 |
| END |
LABEL IF-10 LABEL XIF-1 |
| END |
JUMP TO LABEL WHILE-2 LABEL XWHILE-2 |
| END DIVIDE |
RELEASE 1 # END OF PROCEDURE DIVIDE |
| PROCEDURE Gcd |
# PROCEDURE DECLARATION OF Gcd LABEL Gcd |
| LOCAL f g END |
LOCAL f LOCAL g |
| BEGIN | |
| f := x |
STORE ADDRESS OF LOCAL f FETCH VALUE OF x SAVE RESULT |
| g := y |
STORE ADDRESS OF LOCAL g FETCH VALUE OF y SAVE RESULT |
| WHILE f # g DO |
LABEL WHILE-3 FETCH VALUE OF LOCAL f FETCH VALUE OF LOCAL g IF EQUAL JUMP TO XWHILE-3 |
| IF f < g THEN g := g - f END |
FETCH VALUE OF LOCAL f FETCH VALUE OF LOCAL g IF GREATER OR EQUAL JUMP TO LABEL IF-20 STORE ADDRESS OF LOCAL g FETCH VALUE OF LOCAL g FETCH VALUE OF LOCAL f SUBTRACT SAVE RESULT
JUMP TO LABEL XIF-2 |
| IF g < f THEN f := f - g END |
FETCH VALUE OF LOCAL g FETCH VALUE OF LOCAL f IF GREATER OR EQUAL JUMP TO LABEL IF-30
STORE ADDRESS OF LOCAL f
JUMP TO LABEL XIF-3 |
| END |
JUMP TO LABEL WHILE-3 LABEL XWHILE-3 |
| z := f |
STORE ADDRESS OF z FETCH VALUE OF LOCAL f SAVE RESULT |
| END Gcd |
RELEASE 2 # END OF PROCEDURE Gcd |
| BEGIN | LABEL MAINLOOP |
| x := m |
STORE ADDRESS OF x STORE 7 SAVE RESULT |
| y := n |
STORE ADDRESS OF y STORE 85 SAVE RESULT |
| MULTIPLY | CALL MULTIPLY |
| x := 25 |
STORE ADDRESS OF x STORE 25 SAVE RESULT |
| y := 3 |
STORE ADDRESS OF y STORE 3 SAVE RESULT |
| DIVIDE | CALL DIVIDE |
| x := 84 |
STORE ADDRESS OF x STORE 84 SAVE RESULT |
| y := 36 |
STORE ADDRESS OF y STORE 36 SAVE RESULT |
| Gcd | CALL Gcd |
| END wikitest |
LABEL EXITMAINLOOP # Done # |
This ain't bad! Manual checks indicate that everything is OK. There are many labels. Some of them never used. But labels neither take up codespace nor clockcycles. Unnecessary jumps however do. They need to be optimized out.
Page created on 6 September 2008 and
Page equipped with GoogleBuster technology