September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -0,0 +1,331 @@
;
; 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

View file

@ -0,0 +1,89 @@
# Brain**** interpreter
# execute the Brain**** program in the code string
bf := proc( code :: string ) is
local address := 1; # current data address
local pc := 1; # current position in code
local data := []; # data - initially empty
local input := ""; # user input - initially empty
local bfOperations := # table of operations and their implemntations
[ ">" ~ proc() is inc address, 1 end
, "<" ~ proc() is dec address, 1 end
, "+" ~ proc() is inc data[ address ], 1 end
, "-" ~ proc() is dec data[ address ], 1 end
, "." ~ proc() is io.write( char( data[ address ] ) ) end
, "," ~ proc() is
# get next input character, converted to an integer
while input = ""
do
# no input left - get the next line
input := io.read()
od;
data[ address ] := abs( input[ 1 ] );
# remove the latest character from the input
if size input < 2
then
input := ""
else
input := input[ 2 to -1 ]
fi
end
, "[" ~ proc() is
if data[ address ] = 0
then
# skip to the end of the loop
local depth := 0;
do
inc pc, 1;
if code[ pc ] = "["
then
inc depth, 1
elif code[ pc ] = "]"
then
dec depth, 1
fi
until depth < 0
fi
end
, "]" ~ proc() is
if data[ address ] <> 0
then
# skip to the start of the loop
local depth := 0;
do
dec pc, 1;
if code[ pc ] = "["
then
dec depth, 1
elif code[ pc ] = "]"
then
inc depth, 1
fi
until depth < 0
fi
end
];
# execute the operations - ignore anything invalid
while pc <= size code
do
if data[ address ] = null
then
data[ address ] := 0
fi;
if bfOperations[ code[ pc ] ] <> null
then
bfOperations[ code[ pc ] ]()
fi;
inc pc, 1
od
end;
# prompt for Brain**** code and execute it, repeating until an empty code string is entered
scope
local code;
do
io.write( "BF> " );
code := io.read();
bf( code )
until code = ""
epocs;

View file

@ -0,0 +1,88 @@
REM
REM Brainfuck interpreter
REM Get the separate arguments
SPLIT ARGUMENT$ BY " " TO arg$ SIZE dim
IF dim < 2 THEN
PRINT "Usage: bf <file>"
END
ENDIF
REM Determine size
filesize = FILELEN(arg$[1])
REM Get the contents
OPEN arg$[1] FOR READING AS bf
REM claim memory
txt = MEMORY(filesize)
REM Read file into memory
GETBYTE txt FROM bf SIZE filesize
CLOSE FILE bf
REM Initialize work memory
mem = MEMORY(30000)
REM This is The Pointer pointing to memory
thepointer = 0
REM This is the cursor pointing in the current program
cursor = 0
REM Start interpreting program
WHILE cursor < filesize DO
command = PEEK(txt + cursor)
SELECT command
CASE 62
INCR thepointer
CASE 60
DECR thepointer
CASE 43
POKE mem + thepointer, PEEK(mem + thepointer) + 1
CASE 45
POKE mem + thepointer, PEEK(mem + thepointer) - 1
CASE 46
PRINT CHR$(PEEK(mem + thepointer));
CASE 44
key = GETKEY
POKE mem + thepointer, key
CASE 91
jmp = 1
IF ISFALSE(PEEK(mem + thepointer)) THEN
REPEAT
INCR cursor
IF PEEK(txt + cursor) = 91 THEN
INCR jmp
ELIF PEEK(txt + cursor) = 93 THEN
DECR jmp
END IF
UNTIL PEEK(txt + cursor) = 93 AND NOT(jmp)
END IF
CASE 93
jmp = 1
IF ISTRUE(PEEK(mem + thepointer)) THEN
REPEAT
DECR cursor
IF PEEK(txt + cursor) = 93 THEN
INCR jmp
ELIF PEEK(txt + cursor) = 91 THEN
DECR jmp
END IF
UNTIL PEEK(txt + cursor) = 91 AND NOT(jmp)
END IF
END SELECT
INCR cursor
WEND

View file

@ -0,0 +1,183 @@
pointer_alpha = 1/0
pointer_numeric = 1/0
tape_behind = ''
tape_ahead = 1/0
tape_pos = 0 # only for debugging
array_behind = 1/0
array_ahead = ''
set_tape_ahead = array_ahead
array_ahead = 1/0
#
shift
comefrom if array_ahead is array_ahead
cdr = 1/0
cdr = array_ahead
shift_tail = cdr
new_cell
comefrom shift if shift_tail is ''
itoa = 0
shift_tail = itoa
car = 1/0
car = array_ahead
array_behind = car array_behind
done = shift_tail
array_ahead = shift_tail
comefrom shift if array_ahead is done
set_pointer_alpha = 1/0
set_pointer_alpha
comefrom if set_pointer_alpha
atoi = set_pointer_alpha
cdr = tape_ahead
set_tape_ahead = set_pointer_alpha cdr
set_pointer_alpha = 1/0
set_tape_ahead = 1/0
set_pointer_vals
comefrom if set_tape_ahead
tape_ahead = set_tape_ahead
car = tape_ahead
pointer_alpha = car
atoi = pointer_alpha
pointer_numeric = atoi
set_tape_ahead = 1/0
pointer_change = 1/0
change_pointer_val
comefrom if pointer_change
car = tape_ahead
cdr = tape_ahead
itoa = pointer_numeric + pointer_change
set_tape_ahead = itoa cdr
pointer_change = 1/0
file = 0 # initialize to something other than undefined so jump from file works when read fails
read_path = argv
error_reading_program
comefrom file if file + 0 is 0
'Error: cannot read Brainfuck program at "' read_path '"'
''
program_loaded
comefrom file if file is file
program_behind = ''
program_ahead = file
run
comefrom program_loaded
opcode = 1/0
opcode_numeric = 1/0
in_buffer = '' # cf0x10 stdin is line-buffered
jumping = 0
moving = 1
comefrom run
comefrom execute if opcode_numeric is 0
''
execute
comefrom run if moving
# can be useful for debugging:
#program_ahead moving ':' jumping '@' tape_pos ':' pointer_numeric
car = program_ahead
atoi = car
opcode_numeric = atoi
opcode = car
opcode = 1/0
#
program_forward
comefrom execute if moving > 0
array_behind = program_behind
array_ahead = 1/0
array_ahead = program_ahead
program_behind = array_behind
program_ahead = array_ahead
forward_jump
comefrom execute if opcode is '['
jump
comefrom forward_jump if pointer_numeric is 0
jumping = jumping + 1
moving = 1
match_brace
comefrom forward_jump if jumping < 0
jumping = jumping + 1
stop_jump
comefrom match_brace if jumping is 0
moving = 1
program_backward
comefrom execute if moving < 0
array_behind = program_ahead
array_ahead = 1/0
array_ahead = program_behind
program_behind = array_ahead
program_ahead = array_behind
backward_jump
comefrom execute if opcode is ']'
jump
comefrom backward_jump if pointer_numeric > 0
jumping = jumping - 1
moving = -1
match_brace
comefrom backward_jump if jumping > 0
jumping = jumping - 1
stop_jump
comefrom match_brace if jumping is 0
moving = 1
op
comefrom execute if opcode
moving = 1
do_op = opcode
comefrom op if jumping
#
forward
comefrom op if do_op is '>'
tape_pos = tape_pos + 1
array_ahead = 1/0
array_behind = tape_behind
array_ahead = tape_ahead
tape_behind = array_behind
set_tape_ahead = array_ahead
backward
comefrom op if do_op is '<'
tape_pos = tape_pos - 1
array_ahead = 1/0
array_behind = tape_ahead
array_ahead = tape_behind
tape_behind = array_ahead
set_tape_ahead = array_behind
increment
comefrom op if do_op is '+'
pointer_change = 1
decrement
comefrom op if do_op is '-'
pointer_change = -1
print
comefrom op if do_op is '.'
pointer_alpha...
read
comefrom op if do_op is ','
#
cdr = 1/0
cdr = in_buffer
car = in_buffer
set_pointer_alpha = car
cdr = in_buffer
in_buffer = cdr
comefrom stdin if stdin + 0 is 0
#
block_for_input
comefrom read if cdr is ''
stdin = ''
in_buffer = stdin
cdr = in_buffer
comefrom stdin if stdin + 0 is 0

View file

@ -0,0 +1,243 @@
#Import some functions
clojure('count', 1) -> size
clojure('nth', 2) -> charAt
clojure('inc', 1) -> inc
clojure('dec', 1) -> dec
clojure('char', 1) -> char
clojure('int', 1) -> int
clojure('read-line', 0) -> readLine
#The characters we will need
charAt("\n", 0) -> newLine
charAt("@", 0) -> exitCommand
charAt("+", 0) -> incrCommand
charAt("-", 0) -> decrCommand
charAt("<", 0) -> shlCommand
charAt(">", 0) -> shrCommand
charAt(".", 0) -> printCommand
charAt(",", 0) -> inputCommand
charAt("[", 0) -> repeatCommand
charAt("]", 0) -> endCommand
#Read a character from a line of input.
fun readChar -> return
(
readLine() -> line
size(line) -> length
#Return the ith character and a continuation
fun nextFromLine -> i, return
(
'='(i, length) -> eol
if (eol) ->
(
return(newLine, readChar) #end of line
)
|
charAt(line, i) -> value
inc(i) -> i
fun next (-> return) nextFromLine(i, return) | next
return(value, next)
)
| nextFromLine
nextFromLine(0, return) #first character (position 0)
)
| readChar
#Define a buffer as a value and a left and right stack
fun empty (-> return, throw) throw("Error: out of bounds") | empty
fun fill (-> return, throw) return(0, fill) | fill
fun makeBuffer -> value, left, right, return
(
fun buffer (-> return) return(value, left, right) | buffer
return(buffer)
)
| makeBuffer
fun push -> value, stack, return
(
fun newStack (-> return, throw) return(value, stack) | newStack
return(newStack)
)
| push
#Brainf*** operations
fun noop -> buffer, input, return
(
return(buffer, input)
)
| noop
fun selectOp -> command, return
(
'='(command, incrCommand) -> eq
if (eq) ->
(
fun increment -> buffer, input, return
(
buffer() -> value, left, right
inc(value) -> value
makeBuffer(value, left, right) -> buffer
return(buffer, input)
)
| increment
return(increment)
)
|
'='(command, decrCommand) -> eq
if (eq) ->
(
fun decrement -> buffer, input, return
(
buffer() -> value, left, right
dec(value) -> value
makeBuffer(value, left, right) -> buffer
return(buffer, input)
)
| decrement
return(decrement)
)
|
'='(command, shlCommand) -> eq
if (eq) ->
(
fun shiftLeft -> buffer, input, return
(
buffer() -> value, left, right
push(value, right) -> right
left() -> value, left
(
makeBuffer(value, left, right) -> buffer
return(buffer, input)
)
| message
println(message) ->
exit()
)
| shiftLeft
return(shiftLeft)
)
|
'='(command, shrCommand) -> eq
if (eq) ->
(
fun shiftRight -> buffer, input, return
(
buffer() -> value, left, right
push(value, left) -> left
right() -> value, right
(
makeBuffer(value, left, right) -> buffer
return(buffer, input)
)
| message
println(message) ->
exit()
)
| shiftRight
return(shiftRight)
)
|
'='(command, printCommand) -> eq
if (eq) ->
(
fun putChar -> buffer, input, return
(
buffer() -> value, left, right
char(value) -> value
'print'(value) -> dummy
'flush'() -> dummy
return(buffer, input)
)
| putChar
return(putChar)
)
|
'='(command, inputCommand) -> eq
if (eq) ->
(
fun getChar -> buffer, input, return
(
input() -> letter, input
int(letter) -> letter
buffer() -> value, left, right
makeBuffer(letter, left, right) -> buffer
return(buffer, input)
)
| getChar
return(getChar)
)
|
return(noop)
)
| selectOp
#Repeat until zero operation
fun whileLoop -> buffer, input, continue, break
(
buffer() -> value, left, right
'='(value, 0) -> zero
if (zero) ->
(
break(buffer, input)
)
|
continue(buffer, input) -> buffer, input
whileLoop(buffer, input, continue, break)
)
| whileLoop
#Convert the Brainf*** program into dodo0 instructions
fun compile -> input, endmark, return
(
input() -> command, input
'='(command, endmark) -> eq
if (eq) ->
(
return(noop, input) #the end, stop compiling
)
|
#Put in sequence the current operation and the rest of the program
fun chainOp -> op, input, return
(
compile(input, endmark) -> program, input
fun exec -> buffer, input, return
(
op(buffer, input) -> buffer, input
program(buffer, input, return)
)
| exec
return(exec, input)
)
| chainOp
'='(command, repeatCommand) -> eq
if (eq) ->
(
compile(input, endCommand) -> body, input #compile until "]"
#Repeat the loop body until zero
fun repeat -> buffer, input, return
(
whileLoop(buffer, input, body, return)
)
| repeat
chainOp(repeat, input, return)
)
|
selectOp(command) -> op
chainOp(op, input, return)
)
| compile
#Main program
compile(readChar, exitCommand) -> program, input
makeBuffer(0, empty, fill) -> buffer
input() -> nl, input #consume newline from input
#Execute the program instructions
program(buffer, input) -> buffer, input
exit()

View file

@ -1,82 +0,0 @@
statement ::= next;
statement ::= prev;
statement ::= inc;
statement ::= dec;
statement ::= out;
statement ::= in;
statement ::= "[" while;
statement ::= idle;
next ::= ">";
prev ::= "<";
inc ::= "+";
dec ::= "-";
out ::= ".";
in ::= ",";
idle ::= $any;
while ::= statement while_r;
while_r ::= "]";
while_r ::= statement while_r;
tape ::= statement statements;
statements ::= statement statements;
statements ::= $eps;
start ::= tape;
tape =>
// 1: append
&subject
// 2: goto
&subject
// 3: loop
&subject
// 4: inc action
&1 1 &echo
// 5: dec action
&1 -1 &echo
// 6: next action
&2 1 &echo
// 7: prev action
&2 -1 &echo
// 8: output action
&__write &nil 'program'output &wrap
// 9: group
&nil
sys'dynamics'groupvariable
&std'basic'factory'array_size &sys'vm'routines'egetprop 1024 &prop
&std'basic'factory'pattern &sys'vm'routines'egetprop 0 std'basic'widecharvar &prop
&union2
std'basic'factory'patternarrayfactory
std'basic'factory'newarray
0 ^refer
~ sys'dynamics'group_member ^append
// :: append method
&1 &__append &9 &prop
~ sys'dynamics'group_member ^append
// :: goto method
&2 &__append &std'dictionary'index &9 &wrap &prop
~ sys'dynamics'group_member ^append
// :: loop method
&3 &__run &std'patterns'ewhilenotzero &9 &wrap &prop
~ sys'dynamics'group_member ^append
// 10: in action
&__save &__get &nil 'program'input &nil &action &wrap
// build command batch
&cast
$body
&9
^ invoke;
inc => &4 |= $body;
dec => &5 |= $body;
next => &6 |= $body;
prev => &7 |= $body;
out => &8 |= $body;
in => &10 |= $body;
while => &3 &__eval &cast $body &wrap &echo |=;

View file

@ -10,29 +10,21 @@
I = 1 !First element of the prog.
DO WHILE(I.LE.LEN(PROG)) !Off the end yet?
C = PROG(I:I) !Load the opcode fingered by I.
I = I + 1 !Advance one. The classic.
SELECT CASE(C) !Now decode the instruction.
CASE(">") !Move the data finger one place right.
D = D + 1
CASE("<") !Move the data finger one place left.
D = D - 1
CASE("+") !Add one to the fingered datum.
STORE(D) = CHAR(ICHAR(STORE(D)) + 1)
CASE("-") !Subtract one.
STORE(D) = CHAR(ICHAR(STORE(D)) - 1)
CASE(".") !Write a character.
WRITE (MSG,1) STORE(D)
CASE(",") !Read a character.
READ (KBD,1) STORE(D)
CASE("[") !Conditionally, surge forward.
IF (ICHAR(STORE(D)).EQ.0) CALL SEEK(+1)
CASE("]") !Conditionally, retreat.
IF (ICHAR(STORE(D)).NE.0) CALL SEEK(-1)
CASE DEFAULT !For all others,
!Do nothing.
END SELECT !That was simple.
END DO !See what comes next.
C = PROG(I:I) !Load the opcode fingered by I.
I = I + 1 !Advance one. The classic.
SELECT CASE(C) !Now decode the instruction.
CASE(">"); D = D + 1 !Move the data finger one place right.
CASE("<"); D = D - 1 !Move the data finger one place left.
CASE("+"); STORE(D) = CHAR(ICHAR(STORE(D)) + 1) !Add one to the fingered datum.
CASE("-"); STORE(D) = CHAR(ICHAR(STORE(D)) - 1) !Subtract one.
CASE("."); WRITE (MSG,1) STORE(D) !Write a character.
CASE(","); READ (KBD,1) STORE(D) !Read a character.
CASE("["); IF (ICHAR(STORE(D)).EQ.0) CALL SEEK(+1) !Conditionally, surge forward.
CASE("]"); IF (ICHAR(STORE(D)).NE.0) CALL SEEK(-1) !Conditionally, retreat.
CASE DEFAULT !For all others,
!Do nothing.
END SELECT !That was simple.
END DO !See what comes next.
1 FORMAT (A1,$) !One character, no advance to the next line.
CONTAINS !Now for an assistant.

View file

@ -79,7 +79,7 @@ Closedown.
END IF !Rather than just one at a time.
END IF !Curse the double evaluation of WHILE(L < LEN(PROG) & ...)
END FUNCTION RATTLE !Computers excel at counting.
END SUBROUTINE BRAINFORT!They only need be direction as to what to count...
END SUBROUTINE BRAINFORT!Their only need be direction as to what to count...
END MODULE BRAIN !Simple in itself.
PROGRAM POKE !A tester.

View file

@ -4,18 +4,17 @@ class BrainfuckProgram {
def instructionPointer = 0, dataPointer = 0
def execute() {
while (instructionPointer < program.size()) {
while (instructionPointer < program.size())
switch(program[instructionPointer++]) {
case '>': dataPointer++; break;
case '<': dataPointer--; break;
case '+': memory[dataPointer] = memoryValue + 1; break;
case '-': memory[dataPointer] = memoryValue - 1; break;
case ',': memory[dataPointer] = System.in.read(); break;
case '.': print((char)memoryValue); break;
case '[': handleLoopStart(); break;
case ']': handleLoopEnd(); break;
case '+': memory[dataPointer] = memoryValue + 1; break
case '-': memory[dataPointer] = memoryValue - 1; break
case ',': memory[dataPointer] = System.in.read(); break
case '.': print String.valueOf(Character.toChars(memoryValue)); break
case '[': handleLoopStart(); break
case ']': handleLoopEnd(); break
}
}
}
private getMemoryValue() { memory[dataPointer] ?: 0 }
@ -23,13 +22,12 @@ class BrainfuckProgram {
private handleLoopStart() {
if (memoryValue) return
int depth = 1;
while (instructionPointer < program.size()) {
int depth = 1
while (instructionPointer < program.size())
switch(program[instructionPointer++]) {
case '[': depth++; break;
case ']': if (!(--depth)) return;
case '[': depth++; break
case ']': if (!(--depth)) return
}
}
throw new IllegalStateException('Could not find matching end bracket')
}
@ -37,8 +35,8 @@ class BrainfuckProgram {
int depth = 0
while (instructionPointer >= 0) {
switch(program[--instructionPointer]) {
case ']': depth++; break;
case '[': if (!(--depth)) return; break;
case ']': depth++; break
case '[': if (!(--depth)) return; break
}
}
throw new IllegalStateException('Could not find matching start bracket')

View file

@ -0,0 +1,51 @@
// version 1.1.2
class Brainf__k(val prog: String, memSize: Int) {
private val mem = IntArray(memSize)
private var ip = 0
private var dp = 0
private val memVal get() = mem.getOrElse(dp) { 0 }
fun execute() {
while (ip < prog.length) {
when (prog[ip++]) {
'>' -> dp++
'<' -> dp--
'+' -> mem[dp] = memVal + 1
'-' -> mem[dp] = memVal - 1
',' -> mem[dp] = System.`in`.read()
'.' -> print(memVal.toChar())
'[' -> handleLoopStart()
']' -> handleLoopEnd()
}
}
}
private fun handleLoopStart() {
if (memVal != 0) return
var depth = 1
while (ip < prog.length) {
when (prog[ip++]) {
'[' -> depth++
']' -> if (--depth == 0) return
}
}
throw IllegalStateException("Could not find matching end bracket")
}
private fun handleLoopEnd() {
var depth = 0
while (ip >= 0) {
when (prog[--ip]) {
']' -> depth++
'[' -> if (--depth == 0) return
}
}
throw IllegalStateException("Could not find matching start bracket")
}
}
fun main(args: Array<String>) {
val prog = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
Brainf__k(prog, 10).execute()
}

View file

@ -1,63 +0,0 @@
import strutils
proc jumpBackward(pos: var int, program: string) =
var level = 1
while pos > 0 and level != 0:
dec pos
case program[pos]
of '[':
dec level
of ']':
inc level
else:
discard 1
dec pos
proc jumpForward(pos: var int, program: string) =
var level = 1
while pos < program.len and level != 0:
inc pos
case program[pos]
of ']':
inc level
of '[':
dec level
else:
discard 1
proc bf(program: string) =
var tape: array[0..20, int]
var pointer = 0
var pos = 0
var indent = 0
while pos < program.len:
var token = program[pos]
case token
of '+':
inc tape[pointer]
of '-':
dec tape[pointer]
of ',':
tape[pointer] = int(stdin.readChar())
of '.':
stdout.write(chr(tape[pointer]))
of '[':
if tape[pointer] == 0:
jumpForward(pos, program)
of ']':
if tape[pointer] != 0:
jumpBackward(pos, program)
of '>':
inc pointer
of '<':
dec pointer
else:
discard 1
inc pos
var addition = ",>++++++[<-------->-],[<+>-]<."
var hello_world = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
bf(addition)
# bf(hello_world)

View file

@ -0,0 +1,70 @@
class Brainfu_k {
@program : String; @mem : Int[];
@ip : Int; @dp : Int;
New(program : String, size : Int) {
@program := program;
@mem := Int → New[size];
}
function : Main(args : String[]) ~ Nil {
if(args → Size() = 2) {
Brainfu_k → New(args[0], args[1] → ToInt()) → Execute();
};
}
method : Execute() ~ Nil {
while(@ip < @program → Size()) {
instr := @program → Get(@ip);
select(instr) {
label '>': { @dp += 1; }
label '<': { @dp -= 1; }
label '+': { @mem[@dp] := @mem[@dp] + 1; }
label '-': { @mem[@dp] := @mem[@dp] - 1; }
label '.': { value := @mem[@dp] → As(Char); value → Print(); }
label ',': { @mem[@dp] := Read(); }
label '[': { JumpForward(); }
label ']': { JumpBack(); }
};
@ip += 1;
};
}
method : JumpForward() ~ Nil {
depth := 1;
if(@mem[@dp] = 0) {
while(@ip < @program → Size()) {
instr := @program → Get(@ip);
if(instr = ']') {
depth -= 1; if(depth = 0) { return; };
}
else if(instr = '[') { depth += 1; };
@ip += 1;
};
"*** Unbalanced jump ***" → ErrorLine();
Runtime → Exit(1);
};
}
method : JumpBack() ~ Nil {
depth := 1;
if(@mem[@dp] <> 0) {
while(@ip > 0) {
@ip -= 1;
instr := @program → Get(@ip);
if(instr = '[') {
depth -= 1; if(depth = 0) { return; };
}
else if(instr = ']') { depth += 1; };
};
"*** Unbalanced jump ***" → ErrorLine();
Runtime → Exit(1);
};
}
method : Read() ~ Int {
in := IO.Console → ReadString();
if(in → Size() > 0) { return in → ToInt(); };
return 0;
}
}

View file

@ -0,0 +1,40 @@
(define (bf program stack-length)
(let ((program (string-append program "]"))
(program-counter 0)
(stack (make-vector stack-length 0))
(stack-pointer 0))
(letrec ((skip (lambda (PC sp)
(let loop ((pc PC) (sp sp))
(let ((ch (string-ref program pc))
(pc (+ pc 1)))
(case ch
(#\] (list pc sp))
(#\[ (apply loop (skip pc sp)))
(else
(loop pc sp)))))))
(step (lambda (PC SP)
(let loop ((pc PC) (sp SP))
(let ((ch (string-ref program pc))
(pc (+ pc 1)))
(case ch
(#\] (list (- PC 1) sp))
(#\[ (if (eq? (vector-ref stack sp) 0)
(apply loop (skip pc sp))
(apply loop (step pc sp))))
(#\+ (set-ref! stack sp (+ (vector-ref stack sp) 1))
(loop pc sp))
(#\- (set-ref! stack sp (- (vector-ref stack sp) 1))
(loop pc sp))
(#\> (loop pc (+ sp 1)))
(#\< (loop pc (- sp 1)))
(#\. (display (make-string 1 (vector-ref stack sp)))
(loop pc sp))
(else
(loop pc sp))))))))
(step 0 0))))
; testing:
; (bf ",++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>." 30000)
; ==> Hello World!
; (bf ">>++++[<++++[<++++>-]>-]<<.[-]++++++++++." 30000)
; ==> @

View file

@ -0,0 +1,96 @@
program rcExceuteBrainF;
uses
Crt;
Const
DataSize= 1024; // Size of Data segment
MaxNest= 1000; // Maximum nesting depth of []
procedure ExecuteBF(Source: string);
var
Dp: pByte; // Used as the Data Pointer
DataSeg: Pointer; // Start of the DataSegment (Cell 0)
Ip: pChar; // Used as instruction Pointer
LastIp: Pointer; // Last adr of code.
JmpStack: array[0..MaxNest-1] of pChar; // Stack to Keep track of active "[" locations
JmpPnt: Integer; // Stack pointer ^^
JmpCnt: Word; // Used to count brackets when skipping forward.
begin
// Set up then data segment
getmem(DataSeg,dataSize);
dp:=DataSeg;
fillbyte(dp^,dataSize,0);
// Set up the JmpStack
JmpPnt:=-1;
// Set up Instruction Pointer
Ip:=@Source[1];
LastIp:=@Source[length(source)];
if Ip=nil then exit;
// Main Execution loop
repeat { until Ip > LastIp }
Case Ip^ of
'<': dec(dp);
'>': inc(dp);
'+': inc(dp^);
'-': dec(dp^);
'.': write(stdout,chr(dp^));
',': dp^:=ord(readkey);
'[': if dp^=0 then
begin
// skip forward until matching bracket;
JmpCnt:=1;
while (JmpCnt>0) and (ip<=lastip) do
begin
inc(ip);
Case ip^ of
'[': inc(JmpCnt);
']': dec(JmpCnt);
#0: begin
Writeln(StdErr,'Error brackets don''t match');
halt;
end;
end;
end;
end else begin
// Add location to Jump stack
inc(JmpPnt);
JmpStack[jmpPnt]:=ip;
end;
']': if dp^>0 then
// Jump Back to matching [
ip:=JmpStack[jmpPnt]
else
// Remove Jump from stack
dec(jmpPnt);
end;
inc(ip);
until Ip>lastIp;
freemem(DataSeg,dataSize);
end;
Const
HelloWorldWiki = '++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>'+
'---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.';
pressESCtoCont = '>[-]+++++++[<++++++++++>-]<->>[-]+++++++[<+++++++++++'+
'+>-]<->>[-]++++[<++++++++>-]+>[-]++++++++++[<++++++++'+
'++>-]>[-]++++++++[<++++++++++++++>-]<.++.+<.>..<<.<<.'+
'-->.<.>>.>>+.-----.<<.[<<+>>-]<<.>>>>.-.++++++.<++++.'+
'+++++.>+.<<<<++.>+[>+<--]>++++...';
waitForEsc = '[-]>[-]++++[<+++++++>-]<->[-]>+[[-]<<[>+>+<<-]'+'>>[<'+
'<+>>-],<[->-<]>]';
begin
// Execute "Hello World" example from Wikipedia
ExecuteBF(HelloWorldWiki);
// Print text "press ESC to continue....." and wait for ESC to be pressed
ExecuteBF(pressESCtoCont+waitForEsc);
end.

View file

@ -0,0 +1,76 @@
'Execute BrainFuck
'VBScript Implementation
'The Main Interpreter
Function BFInpt(s, sp, d, dp, i, ip, o)
While sp < Len(s)
Select Case Mid(s, sp + 1, 1)
Case "+"
newd = Asc(d(dp)) + 1
If newd > 255 Then newd = newd Mod 256 'To take account of values over 255
d(dp) = Chr(newd)
Case "-"
newd = Asc(d(dp)) - 1
If newd < 0 Then newd = (newd Mod 256) + 256 'To take account of negative values
d(dp) = Chr(newd)
Case ">"
dp = dp + 1
If dp > UBound(d) Then
ReDim Preserve d(UBound(d) + 1)
d(dp) = Chr(0)
End If
Case "<"
dp = dp - 1
Case "."
o = o & d(dp)
Case ","
If ip = Len(i) Then d(dp) = Chr(0) Else ip = ip + 1 : d(dp) = Mid(i, ip, 1)
Case "["
If Asc(d(dp)) = 0 Then
bracket = 1
While bracket And sp < Len(s)
sp = sp + 1
If Mid(s, sp + 1, 1) = "[" Then
bracket = bracket + 1
ElseIf Mid(s, sp + 1, 1) = "]" Then
bracket = bracket - 1
End If
WEnd
Else
pos = sp - 1
sp = sp + 1
If BFInpt(s, sp, d, dp, i, ip, o) Then sp = pos
End If
Case "]"
BFInpt = Asc(d(dp)) <> 0
Exit Function
End Select
sp = sp + 1
WEnd
End Function
'This Prepares the Intepreter
Function BFuck(source, input)
Dim data() : ReDim data(0)
data(0) = Chr(0)
DataPtr = 0
SrcPtr = 0
InputPtr = 0
output = ""
BFInpt source , SrcPtr , _
data , DataPtr , _
input , InputPtr , _
output
BFuck = output
End Function
'Sample Run
'The input is a string. The first character will be scanned by the first comma
'in the code, the next character will be scanned by the next comma, and so on.
code = ">++++++++[<+++++++++>-]<.>>+>+>++>[-]+<[>[->+<<++++>]<<]>.+++++++..+++.>" & _
">+++++++.<<<[[-]<[-]>]<+++++++++++++++.>>.+++.------.--------.>>+.>++++."
inpstr = ""
WScript.StdOut.Write BFuck(code, inpstr)

View file

@ -0,0 +1,29 @@
fcn bf(pgm,input=""){ pgm=pgm.text; // handle both String and Data
const CELLS=0d30_000;
if(Void==pgm.span("[","]")){ println("Mismatched brackets"); return(); }
fcn(code,z,jmpTable){ // build jump table (for [ & ])
if(span:=code.span("[","]")){
a,b:=span; b+=a-1; jmpTable[a+z]=b+z; jmpTable[b+z]=a+z;
self.fcn(code[a+1,b-a-1],z+a+1,jmpTable);
self.fcn(code[b+1,*],z+b+1,jmpTable);
}
}(pgm,0,jmpTable:=Dictionary());
tape:=CELLS.pump(Data(CELLS,Int),0);
ip:=dp:=0; input=input.walker();
try{
while(1){
switch(pgm[ip]){
case(">"){ dp+=1 }
case("<"){ dp-=1 }
case("+"){ tape[dp]=tape[dp]+1 }
case("-"){ tape[dp]=tape[dp]-1 }
case("."){ tape[dp].toChar().print() }
case(","){ c:=input._next(); tape[dp]=(c and input.value or 0); }
case("["){ if(0==tape[dp]){ ip=jmpTable[ip] }}
case("]"){ if(tape[dp]) { ip=jmpTable[ip] }}
}
ip+=1;
} // while
}catch(IndexError){} // read past end of tape == end of program
}

View file

@ -0,0 +1,27 @@
// print Hello World!
bf("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++.."
"+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.");
// print @
bf(">>++++[<++++[<++++>-]>-]<<.[-]++++++++++.");
// read 3 characters, inc by 1 and print: "abc"-->"bcd"
bf(",>,>,><<<[+.>]","abc"); println();
bf(",>++++++[<-------->-],[<+>-]<.","23"); println(); // add two digits
// "Enter your name:", prints name backwards
bf(">+++++++++++++++++++++++++++++++++++++++++"
"++++++++++++++++++++++++++++.++++++++++++++"
"+++++++++++++++++++++++++++.++++++.-------------"
"--.+++++++++++++.>++++++++++++++++++++++++++"
"++++++.<+++++++.----------.++++++.---.>.<----.----------"
"---.++++++++++++.--------.-----------------------------------"
"--------.>.<>>>+[>,----------]++++++++++.<[+++++++++"
"+.<][<]","Sam Iam\n");
// word count
bf(File("wc.b").read(),"This\n is a test");
// rot13
bf(File("rot13.b").read(),"This is a test 123");