Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from os import STDIN
2from os import STDOUT
3from os import Stdin
4from os import Stdout
5from string import StringReader
7class _Tape:
8 tape: [u8]
9 pos: i64
11 func __init__(self):
12 self.tape = [0]
13 self.pos = 0
15 func get(self) -> u8:
16 return self.tape[self.pos]
18 func put(self, value: u8):
19 self.tape[self.pos] = value
21 func increment(self):
22 self.tape[self.pos] += 1
24 func decrement(self):
25 self.tape[self.pos] -= 1
27 func move_right(self):
28 self.pos += 1
30 if self.pos >= self.tape.length():
31 self.tape.append(0)
33 func move_left(self):
34 self.pos -= 1
36trait _Op:
38 func execute(self, tape: _Tape):
39 pass
41class _Increment(_Op):
43 func execute(self, tape: _Tape):
44 tape.increment()
46class _Decrement(_Op):
48 func execute(self, tape: _Tape):
49 tape.decrement()
51class _MoveRight(_Op):
53 func execute(self, tape: _Tape):
54 tape.move_right()
56class _MoveLeft(_Op):
58 func execute(self, tape: _Tape):
59 tape.move_left()
61class _Output(_Op):
63 func execute(self, tape: _Tape):
64 STDOUT.put(u8(tape.get()))
65 STDOUT.flush()
67class _Input(_Op):
69 func execute(self, tape: _Tape):
70 tape.put(u8(STDIN.get()))
72class _Loop(_Op):
73 ops: [_Op]
75 func execute(self, tape: _Tape):
76 while tape.get() > 0:
77 _run(self.ops, tape)
79func _parse(source: StringReader) -> [_Op]:
80 ops: [_Op] = []
82 while True:
83 match source.get():
84 case '+':
85 op = _Increment()
86 case '-':
87 op = _Decrement()
88 case '>':
89 op = _MoveRight()
90 case '<':
91 op = _MoveLeft()
92 case '.':
93 op = _Output()
94 case ',':
95 op = _Input()
96 case '[':
97 op = _Loop(_parse(source))
98 case ']':
99 break
100 case '':
101 break
103 ops.append(op)
105 return ops
107func _run(ops: [_Op], tape: _Tape):
108 for op in ops:
109 op.execute(tape)
111func execute(program: string):
112 """Execute given program.
114 """
116 ops = _parse(StringReader(program))
117 _run(ops, _Tape())
119test increment():
120 inc = _Increment()
121 tape = _Tape()
123 tape.put(3)
124 inc.execute(tape)
125 assert tape.get() == 4
127 tape.put(254)
128 inc.execute(tape)
129 assert tape.get() == 255
131 inc.execute(tape)
132 assert tape.get() == 0
134test decrement():
135 dec = _Decrement()
136 tape = _Tape()
138 tape.put(2)
139 dec.execute(tape)
140 assert tape.get() == 1
142 dec.execute(tape)
143 assert tape.get() == 0
145 dec.execute(tape)
146 assert tape.get() == 255