Execute Brain**** is an implementation of Brainf***.
Other implementations of Brainf***.
RCBF is a set of Brainf*** compilers and interpreters written for Rosetta Code in a variety of languages.

Below are links to each of the versions of RCBF.

An implementation need only properly implement the following instructions:



Command

Description


 > 
 Move the pointer to the right


 < 
 Move the pointer to the left


 + 
 Increment the memory cell under the pointer


 - 
 Decrement the memory cell under the pointer


 . 
 Output the character signified by the cell at the pointer


 , 
 Input a character and store it in the cell at the pointer


 [ 
 Jump past the matching ] if the cell under the pointer is 0


 ] 
 Jump back to the matching [ if the cell under the pointer is nonzero

Any cell size is allowed,   EOF   (End-O-File)   support is optional, as is whether you have bounded or unbounded memory.




;
; Brainfuck interpreter by Thorham
;
; 68000+ AmigaOs2+
;
; Cell size is a byte
;
    incdir  "asminc:"
 
    include "dos/dosextens.i"
    include "lvo/lvos.i"
 
execBase equ 4
 
start

; parse command line parameter
 
    move.l  a0,fileName
 
    move.b  (a0)+,d0
    beq     exit ; no parameter
 
    cmp.b   #'"',d0 ; filter out double quotes
    bne     .loop
 
    addq.l  #1,fileName
 
.loop
    move.b  (a0)+,d0
 
    cmp.b   #'"',d0 ; filter out double quotes
    beq     .done
 
    cmp.b   #32,d0
    bge     .loop
 
.done
    clr.b   -(a0) ; end of string
 
; open dos library
 
    move.l  execBase,a6
 
    lea     dosName,a1
    moveq   #36,d0
    jsr     _LVOOpenLibrary(a6)
    move.l  d0,dosBase
    beq     exit
 
; get stdin and stdout handles
 
    move.l  dosBase,a6
 
    jsr     _LVOInput(a6)
    move.l  d0,stdIn
    beq     exit
 
    jsr     _LVOOutput(a6)
    move.l  d0,stdOut
    beq     exit
 
    move.l  stdIn,d1
    jsr     _LVOFlush(a6)
 
; open file
 
    move.l  fileName,d1
    move.l  #MODE_OLDFILE,d2
    jsr     _LVOOpen(a6)
    move.l  d0,fileHandle
    beq     exit
 
; examine file
 
    lea     fileInfoBlock,a4
 
    move.l  fileHandle,d1
    move.l  a4,d2
    jsr     _LVOExamineFH(a6)
    tst.w   d0
    beq     exit
 
; exit if the file is a folder
 
    tst.l   fib_DirEntryType(a4)
    bge     exit
 
; allocate file memory
 
    move.l  execBase,a6
 
    move.l  fib_Size(a4),d0
    beq     exit ; exit if file is empty
    clr.l   d1
    jsr     _LVOAllocVec(a6)
    move.l  d0,program
    beq     exit
 
; read file
 
    move.l  dosBase,a6
 
    move.l  fileHandle,d1
    move.l  program,d2
    move.l  fib_Size(a4),d3
    jsr     _LVORead(a6)
    tst     d0
    ble     exit ; exit if read didn't succeed
 
; close file
 
    move.l  fileHandle,d1
    jsr     _LVOClose(a6)
    clr.l   fileHandle
 
; clear tape (bss section is allocated by os but not cleared)
 
    lea     tape,a0
    lea     tapeEnd,a1
 
.loopClear
    clr.b   (a0)+
    cmp.l   a0,a1
    bne     .loopClear
 
; interpreter
 
    move.l  program,a2
    lea     tape,a3
 
    clr.l   d2
 
    move.l  a2,d6 ; start of program
    move.l  a2,d7 ; end of program
    add.l   fib_Size(a4),d7
 
loop
    move.b  (a2)+,d2
 
    cmp.b   #">",d2
    beq     .incPtr
 
    cmp.b   #"<",d2
    beq     .decPtr
 
    cmp.b   #"+",d2
    beq     .incMem
 
    cmp.b   #"-",d2
    beq     .decMem
 
    cmp.b   #".",d2
    beq     .outMem
 
    cmp.b   #",",d2
    beq     .inMem
 
    cmp.b   #"[",d2
    beq     .jmpForward
 
    cmp.b   #"]",d2
    beq     .jmpBack
 
; next command
 
.next
    cmp.l   d7,a2 ; test end of program
    blt     loop
 
; end of program reached
 
    bra     exit
 
; command implementations
 
.incPtr
    addq.l  #1,a3
    cmp.l   #tapeEnd,a3 ; test end of tape
    bge     exit
    bra     .next
 
.decPtr
    subq.l  #1,a3
    cmp.l   #tape,a3 ; test start of tape
    blt     exit
    bra     .next
 
.incMem
    addq.b  #1,(a3)
    bra     .next
 
.decMem
    subq.b  #1,(a3)
    bra     .next
 
.outMem
    move.l  stdOut,d1
    move.b  (a3),d2
    jsr     _LVOFPutC(a6)
    bra     .next
 
.inMem
    move.l  stdIn,d1
    jsr     _LVOFGetC(a6)
 
    cmp.b   #27,d0 ; convert escape to 0
    bne     .notEscape
    moveq   #0,d0
.notEscape
    move.b  d0,(a3)
 
    bra     .next
 
.jmpForward
    tst.b   (a3)
    bne     .next
 
    move.l  a2,a4
    clr.l   d3
 
.loopf
    cmp.l   d7,a4 ; test end of program
    bge     exit
 
    move.b  (a4)+,d2
 
    cmp.b   #"[",d2
    bne     .lf
 
    addq.l  #1,d3
    bra     .loopf
.lf
    cmp.b   #"]",d2
    bne     .loopf
 
    subq.l  #1,d3
    bge     .loopf
 
    move.l  a4,a2
    bra     .next
 
.jmpBack
    tst.b   (a3)
    beq     .next
 
    move.l  a2,a4
    clr.l   d3
 
.loopb
    move.b  -(a4),d2
 
    cmp.l   d6,a4 ; test start of program
    blt     exit
 
    cmp.b   #"]",d2
    bne     .lb
 
    addq.l  #1,d3
    bra     .loopb
.lb
    cmp.b   #"[",d2
    bne     .loopb
 
    subq.l  #1,d3
    bgt     .loopb
 
    move.l  a4,a2
    bra     .next
 
; cleanup and exit
 
exit
    move.l  dosBase,a6
 
    move.l  fileHandle,d1
    beq     .noFile
    jsr     _LVOClose(a6)
.noFile

    move.l  execBase,a6
 
    move.l  program,a1
    tst.l   a1
    beq     .noMem
    jsr     _LVOFreeVec(a6)
.noMem

    move.l  dosBase,a1
    tst.l   a1
    beq     .noLib
    jsr     _LVOCloseLibrary(a6)
.noLib

    rts
 
; data
 
    section data,data_p
 
dosBase
    dc.l    0
 
fileName
    dc.l    0
 
fileHandle
    dc.l    0
 
fileInfoBlock
    dcb.b   fib_SIZEOF
 
stdIn
    dc.l    0
 
stdOut
    dc.l    0
 
program
    dc.l    0
 
dosName
    dc.b    "dos.library",0
 
; tape memory
 
    section mem,bss_p
 
tape
    ds.b    1024*64
tapeEnd
