Plov020 : another course
After four months of seeming rest (not quite, rest assured) I picked up the Plov thread again. And it (again) was time for a change. The Palo/Alto scheme was too demanding. So it has been abandoned yet again. In favor of direct code generation. Here are the changes in Plov020 so far:
Plov020 : the major changes
First, the changes to the declarations: BitType, Regtype. The symbol table gained a field calles 'value'. And some new global variables: BigFlash, RamStart, EEPROM, FLASH, SRAM, VarPtr, loxFile, proFile, symFile.
TYPE Identifier = ARRAY [0..31] OF CHAR; SymbolType = (ProgName, Proctype, Constype, Vartype, Keytype, BitType, Regtype, None); SymbolPtr = POINTER TO SymbolNode; SymbolNode = RECORD Name : Identifier; (* name of symbol *) next : SymbolPtr; (* next in linked list *) type : SymbolType; (* TYPE *) addr, (* address of symbol *) value : CARDINAL (* value (CONSTANT) or *) END; (* position (BIT) *) VAR token, op, CPU : Identifier; BigFlash, getNextToken, DebugMode, InProcedure, weHaveLocals, pastEOL, Exhausted : BOOLEAN; Locals, Symbols : MemPools.MemPool; firstLocal, thisLocal, firstSymbol, thisSymbol : SymbolPtr; currentType : SymbolType; RamStart, EEPROM, FLASH, SRAM, VarPtr, line, Xpos, ErrCount, LOOPcount, IFcount, REPEATcount, WHILEcount, LOOPdepth, PROCdepth : CARDINAL; lastCH : CHAR; loxFile, proFile, inFile, outFile, symFile : TextIO.File; buffer : Arguments.ArgTable; EXITcount : ARRAY [0..25] OF CARDINAL;Some new error messages:
36 : InOut.WriteString ("PROCESSOR expected; assuming ATmega128") |
37 : InOut.WriteString ("Invalid processor specified. Aborting.") |
38 : InOut.WriteString ("Hit premature end of PROCESSOR file.") |
39 : InOut.WriteString ("Error in PROCESSOR file.") |
40 : InOut.WriteString ("Duplicate identifier in PROCESSOR file.")
Two new procedures, for writing symbol tables to disk in a formatted way:
PROCEDURE DumpSymbols;
VAR thisOne : SymbolPtr;
n : CARDINAL;
BEGIN
thisOne := firstSymbol;
TextIO.PutString (symFile, "Symbol table.");
TextIO.PutLn (symFile);
TextIO.PutLn (symFile);
LOOP
TextIO.PutString (symFile, thisOne^.Name);
n := 4 - (Strings.Length (thisOne^.Name) DIV 8);
REPEAT
TextIO.PutChar (symFile, 11C);
DEC (n)
UNTIL n = 0;
CASE thisOne^.type OF
ProgName : TextIO.PutString (symFile, "Program name") |
Proctype : TextIO.PutString (symFile, "Procedure at address");
TextIO.PutChar (symFile, 11C);
TextIO.PutCard (symFile, thisOne^.addr, 8) |
Constype : TextIO.PutString (symFile, "Constant =");
TextIO.PutChar (symFile, 11C);
TextIO.PutChar (symFile, 11C);
TextIO.PutCard (symFile, thisOne^.value, 8) |
Vartype : TextIO.PutString (symFile, "INTEGER at address");
TextIO.PutChar (symFile, 11C);
TextIO.PutCard (symFile, thisOne^.addr, 8) |
Keytype : TextIO.PutString (symFile, "Keyword") |
BitType : TextIO.PutString (symFile, "BIT at register address");
TextIO.PutChar (symFile, 11C);
TextIO.PutCard (symFile, thisOne^.addr, 8);
TextIO.PutString (symFile, " at position");
TextIO.PutChar (symFile, 11C);
TextIO.PutCard (symFile, thisOne^.value, 8) |
Regtype : TextIO.PutString (symFile, "BYTE at address");
TextIO.PutChar (symFile, 11C);
TextIO.PutCard (symFile, thisOne^.addr, 8)
ELSE
TextIO.PutString (symFile, "Error in symbol table; ");
TextIO.PutString (symFile, thisOne^.Name);
TextIO.PutString (symFile, "is an unknown type. *****************************")
END;
TextIO.PutLn (symFile);
IF thisOne^.next = NIL THEN
EXIT
ELSE
thisOne := thisOne^.next
END
END;
TextIO.PutLn (symFile)
END DumpSymbols;
PROCEDURE DumpLocals (proc : SymbolPtr);
VAR thisOne : SymbolPtr;
BEGIN
thisOne := firstLocal;
TextIO.PutString (loxFile, "Procedure ");
TextIO.PutString (loxFile, proc^.Name);
TextIO.PutLn (loxFile);
LOOP
TextIO.PutString (loxFile, thisOne^.Name);
TextIO.PutChar (loxFile, 11C);
IF thisOne^.next = NIL THEN
EXIT
ELSE
thisOne := thisOne^.next
END
END;
TextIO.PutLn (loxFile)
END DumpLocals;
In VariableDeclaration, the address of the variable is added to the symbol table.
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;
thisSymbol^.addr := VarPtr;
INC (VarPtr, 2);
CG ("VARIABLE "); CG (token); CG ("");
GetSymbol
UNTIL Strings.StrEq (token, "END");
GetSymbol
END VariableDeclaration;
Read in the processor specific registers and bitfields, plus some numbers concerning size and location of
memory areas.
PROCEDURE ReadProcessor (name : Identifier) : BOOLEAN;
VAR fname, word, BitName : Identifier;
current : SymbolPtr;
nr : CARDINAL;
ok : BOOLEAN;
BEGIN
fname := name;
TextIO.OpenInput (proFile, fname); (* Try to open local file *)
IF TextIO.Done () = FALSE THEN
fname := '../';
Strings.Append (fname, name);
TextIO.OpenInput (proFile, fname); (* One directory up then? *)
IF TextIO.Done () = FALSE THEN
fname := '/usr/local/AVR/';
Strings.Append (fname, name);
TextIO.OpenInput (proFile, fname); (* In /usr/local/AVR then? *)
IF TextIO.Done () = FALSE THEN
ErrorMessage (37);
RETURN FALSE
END
END
END; (* Processor data file is open *)
REPEAT
TextIO.GetString (proFile, word)
UNTIL Strings.StrEq (word, 'BEGIN');
LOOP
IF TextIO.EOF (proFile) = TRUE THEN ErrorMessage (38); RETURN FALSE END;
TextIO.GetString (proFile, word);
IF Strings.StrEq (word, 'END') = TRUE THEN EXIT
ELSIF Strings.StrEq (word, 'FLASH') = TRUE THEN TextIO.GetCard (proFile, FLASH)
ELSIF Strings.StrEq (word, 'EEPROM') = TRUE THEN TextIO.GetCard (proFile, EEPROM)
ELSIF Strings.StrEq (word, 'SRAM') = TRUE THEN TextIO.GetCard (proFile, SRAM)
ELSIF Strings.StrEq (word, 'RAMSTART') = TRUE THEN TextIO.GetCard (proFile, RamStart)
ELSIF Strings.StrEq (word, 'COMPILER') = TRUE THEN
REPEAT TextIO.GetString (proFile, word) UNTIL Strings.StrEq (word, 'END')
ELSIF Strings.StrEq (word, 'PORTS') = TRUE THEN
currentType := Regtype;
LOOP
TextIO.GetString (proFile, word);
IF Strings.StrEq (word, 'END') = TRUE THEN EXIT END;
NumConv.Str2Num (nr, 16, word, ok);
TextIO.GetString (proFile, word);
IF NOT ok THEN
ErrorMessage (39)
ELSE
ok := StoreSymbol (word);
IF NOT ok THEN
ErrorMessage (40)
ELSE
thisSymbol^.addr := nr
END
END
END
ELSIF Strings.StrEq (word, 'BITS') = TRUE THEN
currentType := BitType;
LOOP
TextIO.GetString (proFile, word);
IF Strings.StrEq (word, 'END') = TRUE THEN EXIT END;
ok := FindSymbol (word);
current := thisSymbol;
nr := 7;
LOOP
TextIO.GetString (proFile, BitName);
IF BitName [0] # '-' THEN
ok := StoreSymbol (BitName);
thisSymbol^.value := nr;
thisSymbol^.addr := current^.addr;
END;
IF nr = 0 THEN EXIT ELSE DEC (nr) END
END
END
END
END;
VarPtr := RamStart;
TextIO.Close (proFile);
IF FLASH > 4096 THEN BigFlash := TRUE ELSE BigFlash := FALSE END;
RETURN TRUE
END ReadProcessor;
The files to be opened are composed here:
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);
Fname := name;
Strings.Append (Fname, '.symbols');
TextIO.OpenOutput (symFile, Fname);
Fname := name;
Strings.Append (Fname, '.locals');
TextIO.OpenOutput (loxFile, Fname)
END OpenOutputs;
And the shutdown procedure:
PROCEDURE ShutDown;
BEGIN
DumpSymbols;
TextIO.Close (inFile);
TextIO.Close (outFile);
TextIO.Close (symFile);
TextIO.Close (loxFile);
InOut.WriteLn; (* PrintNames; *)
MemPools.KillPool (Symbols);
IF ErrCount = 0 THEN
InOut.WriteString ("No")
ELSE
InOut.WriteCard (ErrCount, 1)
END;
InOut.WriteString (" errors found.");
InOut.WriteLn;
InOut.WriteLn;
END ShutDown;
And that's just about it!
Plov020 : see it run
Of course, Plov020 runs. I ran some tests:
PROGRAM test26
PROCESSOR ATmega8515
CONSTANTS m = 7
n = 85
END
VARIABLES x
y
z
q
r
END
PROCEDURE MULTIPLY p q
BEGIN
z := 0
WHILE q MOD 2 = 1 DO
IF q = 1 THEN z := z + p END
p := p SHL 1
q := q SHR 1
END
END MULTIPLY
PROCEDURE DIVIDE t n
LOCAL w END
BEGIN
t := x
q := 0
n := y
WHILE n <= t DO n := n SHL 1 END
WHILE n > y DO
q := q SHL 1
n := n SHR 1
IF n <= t THEN
t := t - n
INC q
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
q := f + g
END
IF g < f THEN
f := f - g
r := m . x
END
END
z := f
END Gcd
IRQ 1 = Gcd
BEGIN
MULTIPLY m n
DIVIDE x y
x := 84
y := 36
Gcd
END test26
This compiles without errors, to produce the files
jan@beryllium:~/modula/Plov$ ls -l test26* -rw-r--r-- 1 jan users 791 2009-02-09 21:59 test26 -rw-r--r-- 1 jan users 70 2009-02-09 21:59 test26.locals -rw-r--r-- 1 jan users 2079 2009-02-09 21:59 test26.palo -rw-r--r-- 1 jan users 11257 2009-02-09 21:59 test26.symbols jan@beryllium:~/modula/Plov$Here is the locals file:
Procedure MULTIPLY p q Procedure DIVIDE t n w Procedure Gcd f gAnd the symbol table:
Symbol table. test26 Program name CONSTANTS Keyword BEGIN Keyword BIT Keyword BYTE Keyword DEC Keyword DO Keyword ELSE Keyword ELSIF Keyword END Keyword EXIT Keyword IF Keyword INC Keyword IOPORT Keyword IRQ Keyword LOCAL Keyword LOOP Keyword MOD Keyword OR Keyword PORTS Keyword PROCEDURE Keyword PROGRAM Keyword REPEAT Keyword RETURN Keyword THEN Keyword UNTIL Keyword VARIABLES Keyword WHILE Keyword TRUE Constant = 1 FALSE Constant = 0 OscCal BYTE at address 4 PINE BYTE at address 5 DDRE BYTE at address 6 PORTE BYTE at address 7 ACSR BYTE at address 8 UBRRL BYTE at address 9 UCSRB BYTE at address 10 UCSRA BYTE at address 11 UDR BYTE at address 12 SPCR BYTE at address 13 SPSR BYTE at address 14 SPDR BYTE at address 15 PIND BYTE at address 16 DDRD BYTE at address 17 PORTD BYTE at address 18 PINC BYTE at address 19 DDRC BYTE at address 20 PORTC BYTE at address 21 PINB BYTE at address 22 DDRB BYTE at address 23 PORTB BYTE at address 24 PINA BYTE at address 25 DDRA BYTE at address 26 PORTA BYTE at address 27 EECR BYTE at address 28 EEDR BYTE at address 29 EEARL BYTE at address 30 EEARH BYTE at address 31 UBRRH/UCSRC BYTE at address 32 WDTCR BYTE at address 33 ICR1L BYTE at address 36 ICR1H BYTE at address 37 OCR1BL BYTE at address 40 OCR1BH BYTE at address 41 OCR1AL BYTE at address 42 OCR1AH BYTE at address 43 TCNT1L BYTE at address 44 TCNT1H BYTE at address 45 TCCR1B BYTE at address 46 TCCR1A BYTE at address 47 SFIOR BYTE at address 48 OCR0 BYTE at address 49 TCNT0 BYTE at address 50 TCCR0 BYTE at address 51 MCUCSR BYTE at address 52 MCUCR BYTE at address 53 EMCUCR BYTE at address 54 SPMCR BYTE at address 55 TIFR BYTE at address 56 TIMSK BYTE at address 57 GIFR BYTE at address 58 GICR BYTE at address 59 SPL BYTE at address 61 SPH BYTE at address 62 SREG BYTE at address 63 ACD BIT at register address 8 at position 7 ACBG BIT at register address 8 at position 6 ACO BIT at register address 8 at position 5 ACI BIT at register address 8 at position 4 ACIE BIT at register address 8 at position 3 ACIC BIT at register address 8 at position 2 ACIS1 BIT at register address 8 at position 1 ACIS0 BIT at register address 8 at position 0 RXCIE BIT at register address 10 at position 7 TXCIE BIT at register address 10 at position 6 UDRIE BIT at register address 10 at position 5 RXEN BIT at register address 10 at position 4 TXEN BIT at register address 10 at position 3 UCSZ2 BIT at register address 10 at position 2 RXB8 BIT at register address 10 at position 1 TXB8 BIT at register address 10 at position 0 RXC BIT at register address 11 at position 7 TXC BIT at register address 11 at position 6 UDRE BIT at register address 11 at position 5 FE BIT at register address 11 at position 4 DOR BIT at register address 11 at position 3 PE BIT at register address 11 at position 2 U2X BIT at register address 11 at position 1 MPCM BIT at register address 11 at position 0 SPIE BIT at register address 13 at position 7 SPE BIT at register address 13 at position 6 DORD BIT at register address 13 at position 5 MSTR BIT at register address 13 at position 4 CPOL BIT at register address 13 at position 3 CPHA BIT at register address 13 at position 2 SPR1 BIT at register address 13 at position 1 SPR0 BIT at register address 13 at position 0 SPIF BIT at register address 14 at position 7 WCOL BIT at register address 14 at position 6 SPI2X BIT at register address 14 at position 0 EERIE BIT at register address 28 at position 3 EEMWE BIT at register address 28 at position 2 EEWE BIT at register address 28 at position 1 EERE BIT at register address 28 at position 0 URSEL BIT at register address 28 at position 7 UMSEL BIT at register address 28 at position 6 UPM1 BIT at register address 28 at position 5 UPM0 BIT at register address 28 at position 4 USBS BIT at register address 28 at position 3 UCSZ1 BIT at register address 28 at position 2 UCSZ0 BIT at register address 28 at position 1 UCPOL BIT at register address 28 at position 0 WDCE BIT at register address 33 at position 4 WDE BIT at register address 33 at position 3 WDP2 BIT at register address 33 at position 2 WDP1 BIT at register address 33 at position 1 WDP0 BIT at register address 33 at position 0 ICNC1 BIT at register address 46 at position 7 ICES1 BIT at register address 46 at position 6 WGM13 BIT at register address 46 at position 4 WGM12 BIT at register address 46 at position 3 CS12 BIT at register address 46 at position 2 CS11 BIT at register address 46 at position 1 CS10 BIT at register address 46 at position 0 COM1A1 BIT at register address 47 at position 7 COM1A0 BIT at register address 47 at position 6 COM1B1 BIT at register address 47 at position 5 COM1B0 BIT at register address 47 at position 4 FOC1A BIT at register address 47 at position 3 FOC1B BIT at register address 47 at position 2 WGM11 BIT at register address 47 at position 1 WGM10 BIT at register address 47 at position 0 XMBK BIT at register address 48 at position 6 XMM2 BIT at register address 48 at position 5 XMM1 BIT at register address 48 at position 4 XMM0 BIT at register address 48 at position 3 PUD BIT at register address 48 at position 2 PSR10 BIT at register address 48 at position 0 FOC0 BIT at register address 51 at position 7 WGM00 BIT at register address 51 at position 6 COM01 BIT at register address 51 at position 5 COM00 BIT at register address 51 at position 4 WGM01 BIT at register address 51 at position 3 CS02 BIT at register address 51 at position 2 CS01 BIT at register address 51 at position 1 CS00 BIT at register address 51 at position 0 SM2 BIT at register address 52 at position 5 WRDF BIT at register address 52 at position 3 BORF BIT at register address 52 at position 2 EXTRF BIT at register address 52 at position 1 PORF BIT at register address 52 at position 0 SRE BIT at register address 53 at position 7 SRW10 BIT at register address 53 at position 6 SE BIT at register address 53 at position 5 SM1 BIT at register address 53 at position 4 ISC11 BIT at register address 53 at position 3 ISC10 BIT at register address 53 at position 2 ISC01 BIT at register address 53 at position 1 ISC00 BIT at register address 53 at position 0 SM0 BIT at register address 54 at position 7 SRL2 BIT at register address 54 at position 6 SRL1 BIT at register address 54 at position 5 SRL0 BIT at register address 54 at position 4 SRW01 BIT at register address 54 at position 3 SRW00 BIT at register address 54 at position 2 SRW11 BIT at register address 54 at position 1 ISC2 BIT at register address 54 at position 0 SPMIE BIT at register address 55 at position 7 RWWSB BIT at register address 55 at position 6 RWWSRE BIT at register address 55 at position 4 BLBSET BIT at register address 55 at position 3 PGWRT BIT at register address 55 at position 2 PGERS BIT at register address 55 at position 1 SPMEN BIT at register address 55 at position 0 TOV1 BIT at register address 56 at position 7 OCF1A BIT at register address 56 at position 6 OCF1B BIT at register address 56 at position 5 ICF1 BIT at register address 56 at position 3 TOV0 BIT at register address 56 at position 1 OCF0 BIT at register address 56 at position 0 TOIE1 BIT at register address 57 at position 7 OCIE1A BIT at register address 57 at position 6 OCIE1B BIT at register address 57 at position 5 TICIE1 BIT at register address 57 at position 3 TOIE0 BIT at register address 57 at position 1 OCIE0 BIT at register address 57 at position 0 INTF1 BIT at register address 58 at position 7 INTF0 BIT at register address 58 at position 6 INTF2 BIT at register address 58 at position 5 INT1 BIT at register address 59 at position 7 INT0 BIT at register address 59 at position 6 INT2 BIT at register address 59 at position 5 IVSEL BIT at register address 59 at position 1 IVCE BIT at register address 59 at position 0 I BIT at register address 63 at position 7 T BIT at register address 63 at position 6 H BIT at register address 63 at position 5 S BIT at register address 63 at position 4 V BIT at register address 63 at position 3 N BIT at register address 63 at position 2 Z BIT at register address 63 at position 1 C BIT at register address 63 at position 0 m Constant = 7 n Constant = 85 x INTEGER at address 96 y INTEGER at address 98 z INTEGER at address 100 q INTEGER at address 102 r INTEGER at address 104 MULTIPLY Procedure at address 0 DIVIDE Procedure at address 0 Gcd Procedure at address 0Not bad, isn't it?
Page created on 9 February 2009 and
Page equipped with FroogleBuster technology