Plov : parser and code generator.

The parser reads the text fragments and checks how well they fit in the Plov EBNF definitions. If they fit, the code generator will produce 'code' but not in the sense of a usual code generator. The Plov will spit out Palo, an intermediate language. Palo is the language for a virtual stack machine and Palo programs are pure text files.

The meaning behind this all, is to create a front-end/back-end compiler system. The Plov compiler will do the semantics and produce errorfree intermediate code for a non existing processor called 'Palo'.
After the Plov compiler works, the Palo code can be used to write dedicated object code for just about any real processor, using the back-end generator called 'Alto'. In short:

This way, one source will be able to be used on many targets using the Palo Alto scheme. If you have a new processor, you will only need to write a new backend for it, called 'Alto' that accepts Palo as input. Simple as pi.

"But then", the smart guy is quibbling to himself, "why don't you use 'C' instead of the Palo language? C is the universal assembler language, don't you forget that!". And in a way that person is right.
My reason to come up with the Palo language was rather simple. If Plov is to produce C code, it must produce errorfree C code and C is mainly targeted to the PDP-8 processor. Not many of them around, nowadays. The Palo language on the other hand is a simple language, with a slight resemblance to Forth.
Forth used to be the universal assembler, until some C guys borrowed it, never to give it back. Palo is like Forth. Palo is easy to implement in just about any processor. You could even use your assembler of choice and just translate all Palo instructions into macro's to produce a simple Alto back end generator. Try that with C....

OK, there are lots of C compilers around. And for those cases, it could have been better to have Plov produce C code. But there are still lots of processors that are not covered by a C compiler. And writing a C compiler is not as easy as writing a Plov compiler.... So in the end, it will pay off to use the Palo Alto detour.

People familiar with the life and times of Professors Wirth and Gutknecht by now will understand why I chose the names for the front/back end generators. Call it a tribute to three parties.

Palo : the virtual language.

As I told above: Palo is a simple language. It is intended to be intermediate code. It is liable to change while still a toddler (born on April 1, 2006). At this moment, Palo is defined as follows. On the left is the mnemonic. On the right is a description. Refer to the diagram in the top of this page, depicting what TOS and TOS-1 mean. Of course you alredy knew this was TopOfStack and TopOfStack-1. Just testing you...

PALO Description Action
Local and global variables
VARIABLE Create a global variable and remind the address  
LOCAL Dynamically create variable local to a PROCEDURE
RELEASE Remove local variables from storage  
Store and retrieve
STORE NUMBER Put NUMBER on top of the data stack (TOS). TOS := NUMBER
STORE ADDRESS OF Put ADDRESS of variable on top of the data stack (=TOS). TOS := ADDRESS
FETCH VALUE OF Get the specified value and put it on top of the datastack TOS := value
SAVE RESULT Store the NUMBER which is in TOS at the address which is in TOS-1. [TOS-1] := TOS
Data operations
SWAP Swap top two elements on the data stack TOS := TOS-1; TOS-1 := TOS
MULTIPLY Multiply top two elements on the data stack and store the result on the stack TOS := TOS-1 * TOS
DIVIDE Divide TOS-1 by TOS; leave result on the stack TOS := TOS-1 / TOS
MODULO Determine Modulo function for TOS-1 and TOS TOS := TOS-1 MOD TOS
ADD Add top of data stack to the element before it TOS := TOS-1 + TOS
SUBTRACT Subtract TOS from TOS-1 TOS := TOS-1 - TOS
SHIFT LEFT Shift data to the left; shiftcount is TOS, number to be shifted is TOS-1. TOS := TOS-1 << TOS
SHIFT RIGHT Shift data to the right; shiftcount is TOS, number to be shifted is TOS-1. TOS := TOS-1 >> TOS
AND Logical AND of top elements on stack TOS := TOS-1 AND TOS
OR Logical OR of top elements on stack TOS := TOS-1 OR TOS
XOR Logical XOR of top elements on stack TOS := TOS-1 XOR TOS
PACK {data} Store ASCII or other data in one machineword, depending on the endian-ness of the processor family. TOS is address of data
PORT READ Read from an I/O port. Port address is in TOS. TOS := IOREAD (TOS)
PORT WRITE Write to an I/O port. Port address is in TOS-1, datavalue is in TOS. IOWRITE (TOS-1, TOS)
Jump and call
LABEL Defines a label for the ALTO backend  
JUMP TO LABEL Jump to LABEL
CALL Temporarily jump to the address of the specified subroutine
RETURN Abandon subroutine and return to where we left off
IF Condition JUMP TO If the condition is true, jump to the specified label
Conditions
LESS Compare TOS-1 and TOS TOS-1 < TOS
LESS OR EQUAL TOS-1 <= TOS
EQUAL TOS = TOS-1
GREATER OR EQUAL TOS-1 >= TOS
GREATER TOS-1 > TOS
NOT EQUAL TOS # TOS-1

I hope the scheme will be somewhat clear.

Palo : the wirthian trick.

In his Oberon-0 compiler, Professor Wirth uses a neat trick. He applies numbers and constants to just about any keyword. This makes checking and sorting easier. I decided to follow his example and I applied numbers to the most appropriate keywords:

PALO Code PALO Code PALO Code
VARIABLE 1 MODULO 16 LABEL 31
LOCAL 2 ADD 17 CALL 32
RELEASE 3 SUBTRACT 18 RETURN 33
STORE 4 SHIFT 19 IF 34
NUMBER 5 LEFT 20 LESS 35
ADDRESS 6 RIGHT 21 EQUAL 36
OF 7 AND 22 GREATER 37
FETCH 8 OR 23 NOT 38
VALUE 9 XOR 24    
VECTOR 10 PACK 25    
SAVE 11 PORT 26    
RESULT 12 READ 27    
SWAP 13 WRITE 28    
MULTIPLY 14 JUMP 29    
DIVIDE 15 TO 30    

Palo : Version 2.

Below is a table with the old and the new PALO codes. PALO version 1 was too complex to parse. Too much filling. Too much candles on the cake. I blew some of them out. The target is to get single PALO keywords, wherever possible.

PALO old PALO new Description Action
Local and global variables
VARIABLE Create a global variable and remind the address  
LOCAL Dynamically create variable local to a PROCEDURE  
PARAMETER Pass parameter from caller to procedure
Store as local variable
 
RELEASE Remove local variables from storage  
Store and retrieve
STORE NUMBER STORE Put NUMBER on top of the data stack (TOS). TOS := NUMBER
STORE ADDRESS OF ADDRESS Put ADDRESS of variable on top of the data stack (=TOS). TOS := ADDRESS
FETCH VALUE OF FETCH Get the specified value and put it on top of the datastack TOS := value
SAVE RESULT SAVE Store the NUMBER which is in TOS at the address which is in TOS-1. [TOS-1] := TOS
Data operations
SWAP Swap top two elements on the data stack TOS := TOS-1; TOS-1 := TOS
INCREMENT Increment the data contained in the variable param param := param + 1
DECREMENT Decrement the data contained in the variable param param := param - 1
MULTIPLY Multiply top two elements on the data stack and store the result on the stack TOS := TOS-1 * TOS
DIVIDE Divide TOS-1 by TOS; leave result on the stack TOS := TOS-1 / TOS
MODULO Determine Modulo function for TOS-1 and TOS TOS := TOS-1 MOD TOS
ADD Add top of data stack to the element before it TOS := TOS-1 + TOS
SUBTRACT Subtract TOS from TOS-1 TOS := TOS-1 - TOS
SHIFT LEFT LEFTSHIFT Shift data to the left; shiftcount is TOS, number to be shifted is TOS-1. TOS := TOS-1 << TOS
SHIFT RIGHT RIGHTSHIFT Shift data to the right; shiftcount is TOS, number to be shifted is TOS-1. TOS := TOS-1 >> TOS
AND Logical AND of top elements on stack TOS := TOS-1 AND TOS
OR Logical OR of top elements on stack TOS := TOS-1 OR TOS
XOR Logical XOR of top elements on stack TOS := TOS-1 XOR TOS
PACK {data} Store ASCII or other data in one machineword, depending on the endian-ness of the processor family. TOS is address of data
PORT READ INPORT Read from an I/O port. Port address is in TOS. TOS := IOREAD (TOS)
PORT WRITE OUTPORT Write data to I/O port. Port address is in TOS-1, datavalue is in TOS. IOWRITE (TOS, TOS-1)
Jump and call
LABEL Defines a label for the ALTO backend  
JUMP TO LABEL GOTO Jump to LABEL  
CALL Temporarily jump to the address of the specified subroutine  
RETURN Abandon subroutine and return to where we left off  
IF Condition JUMP TO IFTRUE If the condition is true, jump to the specified label  
Conditions
LESS Compare TOS-1 and TOS TOS-1 < TOS
LESS OR EQUAL LEQ TOS-1 <= TOS
EQUAL TOS = TOS-1
GREATER OR EQUAL GREQ TOS-1 >= TOS
GREATER TOS-1 > TOS
NOT EQUAL DIFFERENT TOS # TOS-1

Palo 2 : the wirthian numbers re-applied.

PALO Code PALO Code PALO Code
VARIABLE 1 RIGHTSHIFT 16 GREQ 31
LOCAL 2 AND 17 GREATER 32
RELEASE 3 OR 18 DIFFERENT 33
STORE 4 XOR 19 PARAMETER 34
ADDRESS 5 PACK 20 INCREMENT 35
FETCH 6 INPORT 21 DECREMENT 36
VECTOR 7 OUTPORT 22  
SAVE 8 GOTO 23
SWAP 9 LABEL 24
MULTIPLY 10 CALL 25
DIVIDE 11 RETURN 26
MODULO 12 IFTRUE 27
ADD 13 LESS 28
SUBTRACT 14 LEQ 29
LEFTSHIFT 15 EQUAL 30

Page created 1 March 2006,

Page equipped with FroogleBuster technology