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	wikitest
   
When 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
LABEL IF-00
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
LABEL XWHILE-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
LABEL IF-20
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
FETCH VALUE OF LOCAL f
FETCH VALUE OF LOCAL g
SUBTRACT
SAVE RESULT

JUMP TO LABEL XIF-3
LABEL IF-30
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