;Pep/8 BrainF**k Compiler
;Written by Christine E. Meyer
;University of Illinois at Springfield
;3/18/19
;
;The following Pep/8 code runs a compiler that can take batch
;or terminal input terminating in an * end sentinel, and
;compiles from it a BrainF**k program.
;
;More details about the language here:
;https://esolangs.org/wiki/brainfuck
;
;It runs with a 256 byte size cell long tape starting at address
;location 0x0295 and ending at 0x0394. Compiled code begins at,
;and runs from, address location 0x0395. It catches and reports
;various errors such as moving beyond tape bounds, trying to
;move beyond cell size limits, or not properly pairing the
;looping brackets.
;
         BR      main        
c:       .BYTE   0x00        
jmpaddr: .EQUATE 2           ;formal parameter #h
code:    .EQUATE 0x0395      
main:    LDX     0x0000,i    
compile: LDA     0x0000,i    
         CHARI   c,d         
         LDBYTEA c,d         
         CPA     '*',i       
         BRNE    parser      
         BR      init        
parser:  CPA     '>',i       
         BRNE    parsel      
         CALL    r           
         BR      compile     
parsel:  CPA     '<',i       
         BRNE    parseinc    
         CALL    l           
         BR      compile     
parseinc:CPA     '+',i       
         BRNE    parsedec    
         CALL    inc         
         BR      compile     
parsedec:CPA     '-',i       
         BRNE    parseout    
         CALL    dec         
         BR      compile     
parseout:CPA     '.',i       
         BRNE    parsein     
         CALL    out         
         BR      compile     
parsein: CPA     ',',i       
         BRNE    parsellp    
         CALL    in          
         BR      compile     
parsellp:CPA     '[',i       
         BRNE    parserlp    
         SUBSP   2,i         ;push #jmpaddr
         CALL    llp         
         BR      compile     
parserlp:CPA     ']',i       
         BRNE    comment     
         CALL    rlp         
         ADDSP   2,i         ;pop #jmpaddr
comment: BR      compile     
;
;
; >
r:       LDA     0xB800,i    
         STA     0x0395,x    
         LDA     0xFF08,i    
         STA     0x0397,x    
         LDA     0x0395,i    
         STX     -2,s        ;Calculates the jump address past
         ADDA    -2,s        ;  the error string.
         ADDA    0x000A,i    
         STA     0x0399,x    
         LDA     0x4102,i    
         STA     0x039B,x    
         LDA     0x3800,i    
         STA     0x039D,x    
         LDA     0x7800,i    
         STA     0x039F,x    
         LDBYTEA 0x0001,i    
         STBYTEA 0x03A1,x    
         ADDX    0x000D,i    
         RET0                
;
;
; <
l:       LDA     0xB800,i    
         STA     0x0395,x    
         LDA     0x0010,i    
         STA     0x0397,x    
         LDA     0x0395,i    
         STX     -2,s        ;Calculates the jump address past
         ADDA    -2,s        ;  the error string.
         ADDA    0x000A,i    
         STA     0x0399,x    
         LDA     0x4102,i    
         STA     0x039B,x    
         LDA     0x4600,i    
         STA     0x039D,x    
         LDA     0x8800,i    
         STA     0x039F,x    
         LDBYTEA 0x0001,i    
         STBYTEA 0x03A1,x    
         ADDX    0x000D,i    
         RET0                
;
;
; +
inc:     LDA     0xD502,i    
         STA     0x0395,x    
         LDA     0x9590,i    
         STA     0x0397,x    
         LDA     0x00FF,i    
         STA     0x0399,x    
         LDA     0xB000,i    
         STA     0x039B,x    
         LDA     0xFF08,i    
         STA     0x039D,x    
         LDA     0x0395,i    
         STX     -2,s        ;Calculates the jump address past
         ADDA    -2,s        ;  the error string.
         ADDA    0x0010,i    
         STA     0x039F,x    
         LDA     0x4102,i    
         STA     0x03A1,x    
         LDA     0x5400,i    
         STA     0x03A3,x    
         LDA     0x7000,i    
         STA     0x03A5,x    
         LDA     0x01F5,i    
         STA     0x03A7,x    
         LDA     0x0295,i    
         STA     0x03A9,x    
         ADDX    0x0016,i    
         RET0                
;
;
; -
dec:     LDA     0xD502,i    
         STA     0x0395,x    
         LDA     0x9590,i    
         STA     0x0397,x    
         LDA     0x00FF,i    
         STA     0x0399,x    
         LDA     0xB000,i    
         STA     0x039B,x    
         LDA     0x0010,i    
         STA     0x039D,x    
         LDA     0x0395,i    
         STX     -2,s        ;Calculates the jump address past
         ADDA    -2,s        ;  the error string.
         ADDA    0x0010,i    
         STA     0x039F,x    
         LDA     0x4102,i    
         STA     0x03A1,x    
         LDA     0x5E00,i    
         STA     0x03A2,x    
         LDA     0x8000,i    
         STA     0x03A5,x    
         LDA     0x01F5,i    
         STA     0x03A7,x    
         LDA     0x0295,i    
         STA     0x03A9,x    
         ADDX    0x0016,i    
         RET0                
;
;
; .
out:     LDA     0x5502,i    
         STA     0x0395,x    
         LDBYTEA 0x0095,i    
         STBYTEA 0x0397,x    
         ADDX    0x0003,i    
         RET0                
;
;
; ,
in:      LDA     0x4D02,i    
         STA     0x0395,x    
         LDBYTEA 0x0095,i    
         STBYTEA 0x0397,x    
         ADDX    0x0003,i    
         RET0                
;
;
; [
llp:     STX     jmpaddr,s   ;allocate #jmpaddr
         LDA     jmpaddr,s   ;Calculates and stores the address of the
         ADDA    0x0395,i    ;  begining of this sequence of commands.
         STA     jmpaddr,s   
         LDA     0xD502,i    
         STA     0x0395,x    
         LDA     0x9590,i    
         STA     0x0397,x    
         LDA     0x00FF,i    
         STA     0x0399,x    
         LDA     0x0A00,i    ;The address for jumping is left as
         STA     0x039B,x    ;  0x0000 at this time.
         LDBYTEA 0x0000,i    
         STBYTEA 0x039D,x    
         ADDX    0x0009,i    
         RET0                
;
;
; ]
rlp:     MOVSPA              ;Checks to ensure there is actually an
         CPA     0xFBCD,i    ;  unpaired [ avaliable.
         BRNE    elserlp     
         STRO    error5,d    
         STOP                
elserlp: LDA     0xD502,i    
         STA     0x0395,x    
         LDA     0x9590,i    
         STA     0x0397,x    
         LDA     0x00FF,i    
         STA     0x0399,x    
         LDBYTEA 0x000C,i    
         STBYTEA 0x039B,x    
         LDA     jmpaddr,s   ;Calculates the location immediately after
         ADDA    0x0009,i    ;  the paired [ per BrainF*ck specification.
         STA     0x039C,x    
         SUBA    0x0002,i    ;Calculates the location of the unfinished
         STA     jmpaddr,s   ;  jump instruction in the previous [.
         STX     -2,s        
         LDA     -2,s        
         ADDA    0x039E,i    ;Calculates the location immediately after
         STA     jmpaddr,sf  ;  this instruction and inserts it in the
         ADDX    0x0009,i    ;  previous [ jump.
         RET0                
;
;
; Initialize compiled code
init:    LDA     0x0000,i    ;Inserts a stop at the end of the program.
         STBYTEA code,x      
         MOVSPA              ;Ensures there are no unpaired [ commands.
         CPA     0xFBCF,i    
         BREQ    elseinit    
         STRO    error6,d    
         STOP                
elseinit:LDA     0x0000,i    ;Clears registers.
         LDX     0x0000,i    
         STRO    success,d   
         BR      code        ;Jumps to compiled code.
error1:  .ASCII  "End of tape >\x00"
error2:  .ASCII  "End of tape <\x00"
error3:  .ASCII  "Cell full\x00"
erorr4:  .ASCII  "Cell empty\x00"
error5:  .ASCII  "Unmatched ]\x00"
error6:  .ASCII  "Unmatched [\x00"
success: .ASCII  "Compile successful\n\x00"
         .BLOCK  0x0100      
         .END                  