-
Notifications
You must be signed in to change notification settings - Fork 255
/
bf.jl
124 lines (105 loc) · 2.7 KB
/
bf.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# code from https://github.com/MikeInnes/BrainForth/blob/master/src/brainfuck.jl
using Sockets
mutable struct Tape
count::Int
pos::Int
tape::Vector{Int}
end
Tape() = Tape(0, 1, [0])
mutable struct Printer
sum1::Int
sum2::Int
quiet::Bool
end
Printer(quiet) = Printer(0, 0, quiet)
getChecksum(p::Printer) = (p.sum2 << 8) | p.sum1
Base.getindex(t::Tape) = t.tape[t.pos]
Base.setindex!(t::Tape, v) = t.tape[t.pos] = v
Base.:(==)(a::Tape, b::Tape) = a.tape == b.tape
function left!(t::Tape)
t.pos == length(t.tape) && t.tape[end] == 0 && pop!(t.tape)
t.pos == 1 ? pushfirst!(t.tape, 0) : (t.pos -= 1)
return
end
function right!(t::Tape)
t.pos == 1 && t.tape[1] == 0 && (popfirst!(t.tape); t.pos -= 1)
t.pos == length(t.tape) && push!(t.tape, 0)
t.pos += 1
return
end
inc!(t::Tape) = t[] += 0x01
dec!(t::Tape) = t[] -= 0x01
function write!(n::Int, p::Printer)
if p.quiet
p.sum1 = (p.sum1 + n) % 255
p.sum2 = (p.sum2 + p.sum1) % 255
else
write(stdout, n)
end
end
function interpret(t::Tape, bf, p::Printer)
loops = Int[]
scan = 0
ip = 1
@inbounds while ip <= length(bf)
t.count += 1
op = bf[ip]
if op == '['
scan > 0 || t[] == 0 ? (scan += 1) : push!(loops, ip)
elseif op == ']'
scan > 0 ? (scan -= 1) : t[] == 0 ? pop!(loops) : (ip = loops[end])
elseif scan == 0
if op == '+'
inc!(t)
elseif op == '-'
dec!(t)
elseif op == '<'
left!(t)
elseif op == '>'
right!(t)
elseif op == '.'
write!(t[], p)
end
end
ip += 1
end
return t
end
function notify(msg)
try
socket = connect("localhost", 9001)
write(socket, msg)
close(socket)
catch
# standalone usage
end
end
function verify()
text = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>
---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."""
pLeft = Printer(true)
interpret(Tape(), collect(text), pLeft)
left = getChecksum(pLeft)
pRight = Printer(true)
for c in "Hello World!\n"
write!(convert(Int, c), pRight)
end
right = getChecksum(pRight)
if left != right
println(stderr, "$(left) != $(right)")
exit(1)
end
end
if abspath(PROGRAM_FILE) == @__FILE__
verify()
text = open(ARGS[1]) do file
read(file, String)
end
p = Printer(haskey(ENV, "QUIET"))
notify("Julia\t$(getpid())")
interpret(Tape(), collect(text), p)
notify("stop")
if p.quiet
println("Output checksum: $(getChecksum(p))")
end
end