-
Notifications
You must be signed in to change notification settings - Fork 23
/
brainfuck.tao
106 lines (99 loc) · 2.87 KB
/
brainfuck.tao
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
import "../lib/main.tao"
data Instr =
| Left
| Right
| Incr
| Decr
| Read
| Write
\ Loop [Instr]
fn parse_bf =
| ['<' .. s] => let (xs, s) = s->parse_bf in ([Left .. xs], s)
| ['>' .. s] => let (xs, s) = s->parse_bf in ([Right .. xs], s)
| ['+' .. s] => let (xs, s) = s->parse_bf in ([Incr .. xs], s)
| ['-' .. s] => let (xs, s) = s->parse_bf in ([Decr .. xs], s)
| [',' .. s] => let (xs, s) = s->parse_bf in ([Read .. xs], s)
| ['.' .. s] => let (xs, s) = s->parse_bf in ([Write .. xs], s)
| [']' .. s] => ([], s)
| ['[' .. s] =>
let (xs, s) = s->parse_bf in
let (tail, s) = s->parse_bf in
([Loop xs] ++ tail, s)
| [_ .. s] => s->parse_bf
\ [] => ([], "")
data State = {
ptr: Nat,
tape: [Nat],
stdin: Str,
stdout: Str,
}
member State of Default =
=> default = State {
ptr: 0,
tape: [0]->repeat(1000),
stdin: "",
stdout: "",
}
fn exec : State -> Instr -> io ~ State =
| state, Left => state with {
ptr: when state.ptr is
| 0 => 9999
\ l + 1 => l
}
| state, Right => state with {
ptr: when state.ptr is
| 9999 => 0
\ l => l + 1
}
| state, Incr => state with {
tape: state.tape->swap(state.ptr, fn
| 255 => 0
\ n => n + 1)
}
| state, Decr => state with {
tape: state.tape->swap(state.ptr, fn
| 0 => 255
\ n + 1 => n)
}
| state, Read => do {
print("Read not supported yet")!;
state
}
| state, Write => when state.tape->nth(state.ptr) is
# Newline
| Just 10 => do {
print(state.stdout)!;
state with { stdout: "" }
}
| Just n + 32 => when " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"->nth(n) is
| Just c => state with { stdout: state.stdout ++ [c] }
\ None => state
\ _ => state
\ state, Loop xs => when state.tape->nth(state.ptr) is
| Just 0 => state
| Just _ => do {
let state = exec_all(state, xs)!;
exec(state, Loop xs)!
}
\ None => state
fn exec_all : State -> [Instr] -> io ~ State =
| state, [] => state
\ state, [x .. xs] => do {
let state = exec(state, x)!;
exec_all(state, xs)!
}
def main : io ~ () = do {
let (xs, _) = "
[sierpinski.b -- display Sierpinski triangle
(c) 2016 Daniel B. Cristofani
http://brainfuck.org/]
++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[
-<<<[
->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<
]>.>+[>>]>+
]
[Shows an ASCII representation of the Sierpinski triangle
(iteration 5).]
"->parse_bf;
exec_all(default, xs)!;
}