Plov006 : get some code generated

After some idle time I had gained enough mental rest again to do some more work on PLOV. I decided to spend one higher version number on it: Plov006 was born. It's main addition: code generation. in PALO format. Here is the source:

MODULE Plov006;

(*  Plov is the PL/0 compiler as modified by Verhoeven				*)
(*  Ver	  Comment						:     Date  	*)
(*  ----- -----------------------------------------------------   ------------ 	*)
(*  0.01  First version: read symbols and store them in a list	  01 Oct 2007	*)
(*  0.02  Introduce a limited symbol processor; aborted		  02 Oct 2007	*)
(*  0.03  Introduce a recursive descent parser			  06 Oct 2007	*)
(*  0.04  Fine tune the parser					  18 Oct 2007	*)
(*  0.05  Adapt it for file IO and command line			  26 Nov 2007	*)
(*  0.06  Try some code generation						*)

IMPORT	ASCII, InOut, MemPools, NumConv, Strings, SYSTEM, TextIO, Arguments;


TYPE	Identifier	= ARRAY [0..31] OF CHAR;
	Opcode		= ARRAY [0..7]  OF CHAR;
	SymbolType	= (Progtype, Proctype, Constype, Vartype, Keytype);
	SymbolPtr	= POINTER TO SymbolNode;
	SymbolNode	= RECORD
			    Name	: Identifier;
			    previous,
			    next	: SymbolPtr;
			    type	: SymbolType;
			    value,
			    address	: CARDINAL
			  END;

VAR	token, op		: Identifier;
	InProcedure,
	LineEnd,
	Exhausted		: BOOLEAN;
	Symbols			: MemPools.MemPool;
	firstSymbol,
	lastSymbol,
	thisSymbol		: SymbolPtr;
	currentType		: SymbolType;
	LOOPcount, IFcount,
	LabelCount,
	LOOPdepth, PROCdepth,
	currentValue		: CARDINAL;
	inFile, outFile		: TextIO.File;
	buffer			: Arguments.ArgTable;
	EXITcount		: ARRAY [0..25] OF CARDINAL;


PROCEDURE ErrorMessage (n  : CARDINAL);

BEGIN
   CASE  n  OF
      0 : InOut.WriteString ("Error filling Symbol table")		|
      1 : InOut.WriteString ("Invalid digit in : ");
      	  InOut.WriteString (token)					|
      2 : InOut.WriteString ("Invalid letter in : ");
      	  InOut.WriteString (token)					|
      3 : InOut.WriteString ("Program names do not match.")		|
      4 : InOut.WriteString ("BEGIN expected") 				|
      5 : InOut.WriteString ("Illegal identifier name : ");
      	  InOut.WriteString (token)					|
      6 : InOut.WriteString ("Duplicate identifier : ");
      	  InOut.WriteString (token)					|
      7 : InOut.WriteString ("'=' expected")				|
      8 : InOut.WriteString ("END expected")				|
      9 : InOut.WriteString ("Undefined symbol : ");
      	  InOut.WriteString (token)					|
     10 : InOut.WriteString ("Error in StatementSequence")		|
     11 : InOut.WriteString ("EXIT without LOOP")			|
     12 : InOut.WriteString ("THEN expected")				|
     13 : InOut.WriteString ("Illegal comparator : ");
     	  InOut.WriteString (token)					|
     14 : InOut.WriteString ("Illegal operator in factor : ");
     	  InOut.WriteString (token)					|
     15 : InOut.WriteString ("Error in factor : ");
     	  InOut.WriteString (token)					|
     16 : InOut.WriteString ("Missing right parenthesis")		|
     17 : InOut.WriteString ("Missing assigment operator")		|
     18 : InOut.WriteString ("PROGRAM expected")			|
     19 : InOut.WriteString ("Procedure names do not match.")		|
     20 : InOut.WriteString ("Error converting numer.")			|
     33 : InOut.WriteString ("Syntax : Plov infile")			|
     34 : InOut.WriteString ("Cannot open file '");
     	  InOut.WriteString (buffer^[1]^);	InOut.Write ("'")
   ELSE
      InOut.WriteString ("Unknown error detected.")
   END;
   InOut.WriteLn;
   InOut.WriteBf
END ErrorMessage;


PROCEDURE StoreSymbol (str   : Identifier) : BOOLEAN;

VAR	thisOne, nextOne	: SymbolPtr;

BEGIN
   thisOne := firstSymbol;
   LOOP
      IF  Strings.StrEq (thisOne^.Name, str)  THEN  RETURN FALSE  END;
      IF  thisOne^.next = NIL  THEN  EXIT  END;
      thisOne := thisOne^.next
   END;
   MemPools.PoolAllocate (Symbols, nextOne, SYSTEM.TSIZE (SymbolNode));
   thisOne^.next := nextOne;
   WITH  nextOne^  DO
      Name := str;
      type := currentType;
      next := NIL;
      previous := thisOne
   END;
   lastSymbol := nextOne;
   thisSymbol := nextOne;
   RETURN TRUE
END StoreSymbol;


PROCEDURE FindSymbol (str  : Identifier) : BOOLEAN;

VAR	thisOne, nextOne	: SymbolPtr;

BEGIN
   thisOne := firstSymbol;
   LOOP
      IF  Strings.StrEq (thisOne^.Name, str)  THEN
	    thisSymbol := thisOne;
	    RETURN TRUE
      END;
      IF  thisOne^.next = NIL  THEN  EXIT  END;
      thisOne := thisOne^.next
   END;
   RETURN  FALSE
END FindSymbol;


PROCEDURE InsertLabel;

VAR	ok	: BOOLEAN;
	string	: Identifier;

BEGIN
   NumConv.Num2Str (LabelCount, 10, string, ok);
   IF  NOT ok  THEN  ErrorMessage (20)  END;
   CG ("LABEL-");
   CG (string);		CG ("");
   INC (LabelCount)
END InsertLabel;


PROCEDURE CG (string	: ARRAY OF CHAR);

BEGIN
   IF  Strings.Length (string) = 0  THEN
      TextIO.PutLn (outFile)
   ELSE
      TextIO.PutString (outFile, string)
   END
END CG;


PROCEDURE PrintNames;

VAR	  thisOne    		: SymbolPtr;

BEGIN
   thisOne := firstSymbol;
   InOut.WriteLn;
   LOOP
      InOut.WriteString (thisOne^.Name);		InOut.Write (11C);
      CASE  thisOne^.type  OF
        Progtype : InOut.WriteString ("Program type")	|
	Proctype : InOut.WriteString ("Procedure type")	|
	Constype : InOut.WriteString ("Constant type = ");
		   InOut.WriteCard (thisOne^.value, 5)	|
	Vartype	 : InOut.WriteString ("Variable type")	|
	Keytype	 : InOut.WriteString ("Keyword type")
      END;
      InOut.WriteLn;
      IF  thisOne^.next = NIL  THEN
         EXIT
      ELSE
         thisOne := thisOne^.next
      END
   END
END PrintNames;


PROCEDURE ReadString (str : Identifier);

VAR	n, m		: CARDINAL;

BEGIN
   TextIO.GetString (inFile, str)
END ReadString;


PROCEDURE GetSymbol;

BEGIN
   IF  TextIO.EOF (inFile) = FALSE  THEN
      TextIO.GetString (inFile, token)
   ELSE
      InOut.WriteString ("EOF!!!   ");
   END;
InOut.WriteString (token);	InOut.Write (11C);	   InOut.WriteBf
END GetSymbol;


PROCEDURE isDigit (chr : CHAR) : BOOLEAN;

BEGIN
   IF  (chr >= '0') AND (chr <= '9')  THEN
      RETURN TRUE
   END;
   RETURN FALSE
END isDigit;


PROCEDURE isAlpha (chr  : CHAR) : BOOLEAN;

BEGIN
   chr := CAP (chr);
   IF  (chr >= 'A') AND (chr <= 'Z')  THEN
      RETURN TRUE
   END;
   RETURN FALSE
END isAlpha;


PROCEDURE isAlphaNum (chr  : CHAR) : BOOLEAN;

BEGIN
   RETURN  isAlpha (chr) OR isDigit (chr)
END isAlphaNum;


PROCEDURE isNumber (str  : Identifier) : BOOLEAN;

VAR	i	: CARDINAL;

BEGIN
   i := 0;
   REPEAT
      IF  isDigit (str [i]) = FALSE  THEN  RETURN FALSE  END;
      INC (i)
   UNTIL  (str [i] = 0C) OR (i > HIGH (str));
   RETURN TRUE
END isNumber;


PROCEDURE isIdentifier (str  : Identifier) : BOOLEAN;

VAR	i	: CARDINAL;

BEGIN
   IF  NOT isAlpha (str [0])  THEN  RETURN FALSE  END;
   IF  Strings.Length (str) = 1  THEN  RETURN TRUE  END;
   i := 1;
   REPEAT
      IF  NOT isAlphaNum (str [i])  THEN  RETURN FALSE  END;
      INC (i)
   UNTIL  (str [i] = 0C) OR (i > HIGH (str));
   RETURN TRUE
END isIdentifier;


PROCEDURE Program;

BEGIN
   GetSymbol;
   IF  Strings.StrEq (token, "PROGRAM")  THEN
      GetSymbol;
      IF  isIdentifier (token)  THEN
         WITH  firstSymbol^  DO
	    Name := token;
	    type := Progtype
	 END;
	 CG ("# PROGRAM ");	CG (token);	CG ("");	CG ("");
	 Block;
	 IF  Strings.StrEq (token, firstSymbol^.Name) = FALSE  THEN
	    ErrorMessage (3)
	 END;
	 CG ("# Done #");	CG ("");
      ELSE
         ErrorMessage (5)	(* Illegal identifier		*)
      END
   ELSE
      ErrorMessage (18)		(* 'PROGRAM' expected		*)
   END
END Program;


PROCEDURE Block;

BEGIN
   GetSymbol;
   IF	  Strings.StrEq (token, "CONSTANTS")  THEN  ConstantDeclaration;  END;
   IF	  Strings.StrEq (token, "VARIABLES")  THEN
      VariableDeclaration;
      CG ("")
   END;
   WHILE  Strings.StrEq (token, "PROCEDURE")  DO
      ProcedureDeclaration;
      CG ("")
   END;
   BlockBody;
END Block;


PROCEDURE BlockBody;

BEGIN
   IF  Strings.StrEq (token, "BEGIN")  THEN
      IF  PROCdepth = 0  THEN
	 CG ("LABEL MAINLOOP");		CG ("")
      END;
      GetSymbol;
      StatementSequence
   ELSE
      ErrorMessage (4)		(* BEGIN expected	*)
   END;
   IF  Strings.StrEq (token, "END")  THEN
      IF  PROCdepth = 0  THEN
	 CG ("LABEL EXITMAINLOOP");	CG ("")
      END;
      GetSymbol;
      RETURN
   ELSE
      ErrorMessage (8);		(* END expected		*)
      GetSymbol
   END
END BlockBody;


PROCEDURE StatementSequence;

BEGIN
   LOOP
      CG ("");
      IF  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, "EXIT")	THEN  isEXIT
	 ELSIF  Strings.StrEq (token, "END")	THEN
	    RETURN
	 ELSE
	    ErrorMessage (10);		(* Error in StatementSequence	*)
	 END
      ELSE
	 ErrorMessage (9);		(* Undefined symbol	*)
      END;
   END;
END StatementSequence;


PROCEDURE ConstantDeclaration;

VAR	Val	: CARDINAL;
	ok	: BOOLEAN;

BEGIN
   GetSymbol;
   REPEAT
      currentType := Constype;
      IF  isIdentifier (token)  THEN
         IF  StoreSymbol (token) = TRUE  THEN
	    GetSymbol;
	    IF  token [0] = '='  THEN
	       GetSymbol;
	       NumConv.Str2Num (Val, 10, token, ok);
	       IF  ok  THEN
		  WITH  thisSymbol^  DO
		     value := Val;
		     type := Constype
		  END;
	       ELSE
	          ErrorMessage (1)	(* Invalid digit	*)
	       END
	    ELSE
	       ErrorMessage (7);	(* '=' expected		*)
	    END
	 ELSE
	    ErrorMessage (6);		(* Duplicate identifier	*)
	 END
      ELSE
         ErrorMessage (5);		(* Illegal Identifier	*)
      END;
      GetSymbol
   UNTIL  Strings.StrEq (token, "END");
   GetSymbol
END ConstantDeclaration;


PROCEDURE VariableDeclaration;

BEGIN
   GetSymbol;
   REPEAT
      currentType := Vartype;
      IF  isIdentifier (token)  THEN
         IF  StoreSymbol (token) = FALSE  THEN
	    ErrorMessage (6)		(* Duplicate identifier *)
	 END
      ELSE
         ErrorMessage (5);		(* Illegal Identifier	*)
      END;
      CG ("VARIABLE	");		CG (token);		CG ("");
      GetSymbol
   UNTIL Strings.StrEq (token, "END");
   GetSymbol
END VariableDeclaration;


PROCEDURE ProcedureDeclaration;

VAR	thisP	: SymbolPtr;
	name	: Identifier;

BEGIN
   GetSymbol;
   currentType := Proctype;
   IF  isIdentifier (token)  THEN
      name := token;
      CG ("LABEL ");
      CG (name);		CG ("");
      IF  StoreSymbol (token) = TRUE  THEN
	 thisP := thisSymbol;
	 INC (PROCdepth);
	 GetSymbol;
	 BlockBody;
	 DEC (PROCdepth);
	 IF  Strings.StrEq (thisP^.Name, token) = FALSE  THEN
	    ErrorMessage (19)		(* Names do not match	*)
	 END;
	 GetSymbol
      ELSE
	 ErrorMessage (6)		(* Duplicate identifier	*)
      END
   ELSE
      ErrorMessage (5)			(* Illegal identifier 	*)
   END;
   CG ("LABEL EXIT");
   CG (name);			CG ("");	CG ("");
END ProcedureDeclaration;


PROCEDURE Procedurecall;

BEGIN
   CG ("CALL ");		CG (token);		CG ("");
   GetSymbol
END Procedurecall;


PROCEDURE isLOOP;

VAR	LC	: CARDINAL;

BEGIN
   INC (LOOPcount);
   LC := LOOPcount;
   CG ("LABEL LOOP-");		TextIO.PutCard (outFile, LC, 1);
   CG ("");
   INC (LOOPdepth);
   EXITcount [LOOPdepth] := LOOPcount;
   GetSymbol;
   StatementSequence;
   IF  Strings.StrEq (token, "END")  THEN
      DEC (LOOPdepth);
      CG ("JUMP TO LOOP-");	TextIO.PutCard (outFile, LC, 1);
      CG ("")
   ELSE
      ErrorMessage (8)		(* END expected		*)
   END;
   CG ("LABEL XLOOP-");		TextIO.PutCard (outFile, LC, 1);
   CG ("");
   GetSymbol
END isLOOP;


PROCEDURE isEXIT;

BEGIN
   IF  LOOPdepth = 0  THEN
      ErrorMessage (11)			(* EXIT without LOOP	*)
   ELSE
      CG ("JUMP TO XLOOP-");		TextIO.PutCard (outFile, EXITcount [LOOPdepth], 1);
      CG ("");
      DEC (LOOPdepth)
   END;
   GetSymbol
END isEXIT;


PROCEDURE isRETURN;

BEGIN
   IF  PROCdepth = 0  THEN
      ErrorMessage (19)			(* RETURN without PROCEDURE	*)
   END;
   CG ("RETURN");	CG ("");
   LOOPdepth := 0;
   GetSymbol
END isRETURN;


PROCEDURE isIF;

BEGIN
   Condition;
   IF  Strings.StrEq (token, "THEN")  THEN
      GetSymbol;
      StatementSequence;
      WHILE  Strings.StrEq (token, "ELSIF")  DO
	 InsertLabel;
         Condition;
	 IF  Strings.StrEq (token, "THEN")  THEN
	    InsertLabel;
	    GetSymbol;
	    StatementSequence
	 ELSE
	    ErrorMessage (12)		(* THEN expected	*)
	 END
      END;
      IF  Strings.StrEq (token, "ELSE")  THEN
(*	 InsertLabel;	*)
         GetSymbol;	
	 StatementSequence
      END;
      IF  Strings.StrEq (token, "END") = FALSE  THEN
         ErrorMessage (8)		(* END expected		*)
      END;
      InsertLabel;
      GetSymbol
   ELSE
      ErrorMessage (12)			(* THEN expected	*)
   END
END isIF;


PROCEDURE Condition;

VAR	ok	: BOOLEAN;
	str	: Identifier;
	op	: Identifier;

   PROCEDURE Comparison;

   BEGIN
      CASE  token [0]  OF
       '=' :  op := 'EQUAL'			|
       '<' :  CASE  token [1]  OF
		0C  : op := 'LESS THAN'		|
		'>' : op := 'NOT EQUAL'		|
		'=' : op := 'LESS OR EQUAL'
	      ELSE
		ErrorMessage (13)			(* Illegal comparator   *)
	      END				|
       '>' :  CASE  token [1]  OF
	        0C  : op := 'GREATER'		|
	        '=' : op := 'GREATER OR EQUAL'
	      ELSE
	        ErrorMessage (13)			(* Illegal comparator   *)
	      END					|
       '#' :  op := 'NOT EQUAL'
      ELSE
         ErrorMessage (13)				(* Illegal comparator	*)
      END;
   END Comparison;


BEGIN
   IF  Strings.StrEq (token, "ODD")  THEN
      Expression
   ELSE
      GetSymbol;	Expression;
      Comparison;
      GetSymbol;	Expression;
      CG ("IF NOT ");	CG (op);	CG (" JUMP TO LABEL-");
      NumConv.Num2Str (LabelCount, 10, str, ok);
      CG (str);
      CG ("")
   END
END Condition;


PROCEDURE Assignment;

BEGIN
   CG ("STORE ADDRESS OF ");		CG (token);		CG ("");
   GetSymbol;
   IF  Strings.StrEq (token, ':=')  THEN
      GetSymbol;
      Expression
   ELSE
      ErrorMessage (17);		(* Missing ':=' 	*)
   END;
   CG ("SAVE RESULT");		CG ("")
END Assignment;


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;
   END
END Expression;


PROCEDURE TermOperator () : BOOLEAN;

VAR	oper	: CHAR;

BEGIN
   oper := token [0];
   IF	  (oper = 'x') OR (oper = '*') OR (oper = '.')  THEN  RETURN TRUE
   ELSIF  (oper = ':') OR (oper = '/')  		THEN  RETURN TRUE
   ELSIF  (oper = '%') OR Strings.StrEq (token, 'MOD')  THEN  RETURN TRUE
   ELSE
      RETURN FALSE
   END
END TermOperator;


PROCEDURE Term;

VAR	Operator	: CHAR;
	op		: Identifier;

BEGIN
   Factor;
   GetSymbol;
   WHILE  TermOperator () = TRUE  DO
      CASE  token [0]  OF
	'.', 'x', '*'	: op := 'MULTIPLY'		|
	':', '/'	: op := 'DIVIDE'
      ELSE
	op := 'MODULO'
      END;
      GetSymbol;
      Factor;
      CG (op);		CG ("");
      GetSymbol
   END
END Term;


PROCEDURE Factor;

BEGIN
   IF  FindSymbol (token) = TRUE  THEN			(* token is CONST or VAR	*)
      IF  (thisSymbol^.type = Constype)  THEN
         CG ("STORE	");				(* push value of CONST 		*)
	 TextIO.PutCard (outFile, thisSymbol^.value, 1);
	 CG ("")
      END;
      IF  (thisSymbol^.type = Vartype)  THEN
         CG ("FETCH VALUE OF	");
	 CG (thisSymbol^.Name);		CG ("");	(* fetch value at addr of VAR 	*)
      END
   ELSIF  isNumber (token)  THEN
      CG ("STORE	");		CG (token);	(* Literal value		*)
      CG ("")
   ELSIF  token [0] = '(' THEN
      GetSymbol;
      Expression;
      IF  token [0] # ')'  THEN  ErrorMessage (16)  END
   ELSE
      ErrorMessage (15)					(* Error in Factor	*)
   END
END Factor;


PROCEDURE OpenOutputs (name	: Identifier);

VAR	i		: CARDINAL;
	Fname 		: Identifier;

BEGIN
   i := Strings.pos ('.', name);
   IF  i <= HIGH (name)  THEN  name [i] := 0C  END;
   Fname := name;
   Strings.Append (Fname, '.palo');
   TextIO.OpenOutput (outFile, Fname);
END OpenOutputs;


PROCEDURE Init;

VAR	count		: SHORTCARD;
	FileName	: Identifier;

BEGIN
   Arguments.GetArgs (count, buffer);
   IF  count = 1  THEN
      ErrorMessage (33);
      HALT
   END;
   Strings.Assign (FileName, buffer^[1]^);
   TextIO.OpenInput (inFile, FileName);
   IF  NOT TextIO.Done ()  THEN
      ErrorMessage (34);
      HALT
   END;
   OpenOutputs (FileName);

   MemPools.NewPool (Symbols);
   MemPools.PoolAllocate (Symbols, firstSymbol, SYSTEM.TSIZE (SymbolNode));
   WITH  firstSymbol^  DO
      Name := "|";
      next := NIL;
      previous := NIL
   END;
   currentType := Keytype;
   IF  StoreSymbol ("PROGRAM")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("LOOP")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("EXIT") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("BEGIN")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("END")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("IF")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("THEN")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("ELSIF")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("ELSE")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("ODD") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("OR") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("AND") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("NOT") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("MOD") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("IRQ") 	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("STATIC")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("RETURN")	 = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("PROCEDURE") = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("CONSTANTS") = FALSE  THEN  ErrorMessage (0)  END;
   IF  StoreSymbol ("VARIABLES") = FALSE  THEN  ErrorMessage (0)  END;
   currentType := Constype;
   IF  StoreSymbol ("TRUE")	 = FALSE  THEN  ErrorMessage (0)  ELSE  thisSymbol^.value := 1  END;
   IF  StoreSymbol ("FALSE")	 = FALSE  THEN  ErrorMessage (0)  ELSE  thisSymbol^.value := 0  END;
   currentType := Progtype;
   LOOPdepth := 0;
   PROCdepth := 0;
   Exhausted := FALSE;
   LabelCount := 0
END Init;


PROCEDURE ShutDown;

BEGIN
   TextIO.Close (inFile);
   TextIO.Close (outFile);
   InOut.WriteLn;		InOut.WriteLn;			PrintNames;
   MemPools.KillPool (Symbols)
END ShutDown;


BEGIN
   Init;
   Program;
   ShutDown
END Plov006.
   

Plov006 : results

Above you see the pudding. But there is no proof of it, so I did some eating too. Let's start with the source to be compiled: test17.

      
PROGRAM test17

CONSTANTS  pi = 314159625
	   ee = 271828182
	   END

VARIABLES  temp
	   x
	   Fahr
	   Kelvin
	   result
	   END

PROCEDURE Blow

BEGIN
   temp := temp + 273
   LOOP
      Fahr := 32 + temp x 5 : 4
      IF  Fahr < 0  THEN  EXIT  END
      x := x + 1
   END
   IF result > 0 THEN RETURN END
   RETURN
END Blow

BEGIN
   Kelvin := temp + 273
   LOOP
      Kelvin := Kelvin + ee
      LOOP
         Fahr := ee + x
	 IF  Fahr > 12  THEN  EXIT  END
	 Fahr := Fahr - 1
      END
      IF  Kelvin = 10000  THEN  EXIT  END
      Kelvin := ee
   END
   IF  Kelvin = 300  THEN  Kelvin := 10  END
   Fahr := 32 + temp x 5 : 4
   result := ( Fahr - 32 ) . x / 5
END test17
   
If we compile this, the file 'test17.palo' is generated with the following contents. Left is the generated PALO code and on the right is the PLOV source.

PLOV PALO
PROGRAM test17 # PROGRAM test17
CONSTANTS pi = 314159625  
ee = 271828182  
END  
VARIABLES temp VARIABLE temp
x VARIABLE x
Fahr VARIABLE Fahr
Kelvin VARIABLE Kelvin
result VARIABLE result
END  
PROCEDURE Blow LABEL Blow
BEGIN  
temp := temp + 273 STORE ADDRESS OF temp
FETCH VALUE OF temp
STORE 273
ADD
SAVE RESULT
LOOP LABEL LOOP-1
Fahr := 32 + temp x 5 : 4 STORE ADDRESS OF Fahr
STORE 32
FETCH VALUE OF temp
STORE 5
MULTIPLY
STORE 4
DIVIDE
ADD
SAVE RESULT
IF Fahr < 0 THEN EXIT END FETCH VALUE OF Fahr
STORE 0
IF NOT LESS THAN JUMP TO LABEL-0

JUMP TO XLOOP-1

LABEL-0

x := x + 1 STORE ADDRESS OF x
FETCH VALUE OF x
STORE 1
ADD
SAVE RESULT
END JUMP TO LOOP-1
LABEL XLOOP-1
IF result > 0 THEN RETURN END FETCH VALUE OF result
STORE 0
IF NOT GREATER JUMP TO LABEL-1

RETURN

LABEL-1

RETURN RETURN
END Blow LABEL EXITBlow
BEGIN LABEL MAINLOOP
Kelvin := temp + 273 STORE ADDRESS OF Kelvin
FETCH VALUE OF temp
STORE 273
ADD
SAVE RESULT
LOOP LABEL LOOP-2
Kelvin := Kelvin + ee STORE ADDRESS OF Kelvin
FETCH VALUE OF Kelvin
STORE 271828182
ADD
SAVE RESULT
LOOP LABEL LOOP-3
Fahr := ee + x STORE ADDRESS OF Fahr
STORE 271828182
FETCH VALUE OF x
ADD
SAVE RESULT
IF Fahr > 12 THEN EXIT END FETCH VALUE OF Fahr
STORE 12
IF NOT GREATER JUMP TO LABEL-2

JUMP TO XLOOP-3

LABEL-2

Fahr := Fahr - 1 STORE ADDRESS OF Fahr
FETCH VALUE OF Fahr
STORE 1
SUBTRACT
SAVE RESULT
END JUMP TO LOOP-3
LABEL XLOOP-3
IF Kelvin = 10000 THEN EXIT END FETCH VALUE OF Kelvin
STORE 10000
IF NOT EQUAL JUMP TO LABEL-3

LABEL-3

Kelvin := ee STORE ADDRESS OF Kelvin
STORE 271828182
SAVE RESULT
END JUMP TO LOOP-2
LABEL XLOOP-2
IF Kelvin = 300 THEN Kelvin := 10 END FETCH VALUE OF Kelvin
STORE 300
IF NOT EQUAL JUMP TO LABEL-4

STORE ADDRESS OF Kelvin
STORE 10
SAVE RESULT

LABEL-4

Fahr := 32 + temp x 5 : 4 STORE ADDRESS OF Fahr
STORE 32
FETCH VALUE OF temp
STORE 5
MULTIPLY
STORE 4
DIVIDE
ADD
SAVE RESULT
result := ( Fahr - 32 ) . x / 5 STORE ADDRESS OF result
FETCH VALUE OF Fahr
STORE 32
SUBTRACT
FETCH VALUE OF x
MULTIPLY
STORE 5
DIVIDE
SAVE RESULT
END test17 LABEL EXITMAINLOOP
# Done #

Plov006 has converted a modula-like language (PLOV) into a stack oriented meta language (PALO). The general idea behind the Plov compiler is to make a PALO file that can be converted to ANY target processor with the ALTO backend compiler. The ALTO compiler will be fed 100% errorfree code so it can be easily made and it's backend for various processors only needs to be made once.
If my next project is about a C compiler (heaven forbid) it just needs to provide a PALO file again and it will be processed by the same ALTO compiler that was made before.

Page created on 21 august 2008 and

Page equipped with FroogleBuster technology