Hide keyboard shortcuts

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 

6 

7class _Tape: 

8 tape: [u8] 

9 pos: i64 

10 

11 func __init__(self): 

12 self.tape = [0] 

13 self.pos = 0 

14 

15 func get(self) -> u8: 

16 return self.tape[self.pos] 

17 

18 func put(self, value: u8): 

19 self.tape[self.pos] = value 

20 

21 func increment(self): 

22 self.tape[self.pos] += 1 

23 

24 func decrement(self): 

25 self.tape[self.pos] -= 1 

26 

27 func move_right(self): 

28 self.pos += 1 

29 

30 if self.pos >= self.tape.length(): 

31 self.tape.append(0) 

32 

33 func move_left(self): 

34 self.pos -= 1 

35 

36trait _Op: 

37 

38 func execute(self, tape: _Tape): 

39 pass 

40 

41class _Increment(_Op): 

42 

43 func execute(self, tape: _Tape): 

44 tape.increment() 

45 

46class _Decrement(_Op): 

47 

48 func execute(self, tape: _Tape): 

49 tape.decrement() 

50 

51class _MoveRight(_Op): 

52 

53 func execute(self, tape: _Tape): 

54 tape.move_right() 

55 

56class _MoveLeft(_Op): 

57 

58 func execute(self, tape: _Tape): 

59 tape.move_left() 

60 

61class _Output(_Op): 

62 

63 func execute(self, tape: _Tape): 

64 STDOUT.put(u8(tape.get())) 

65 STDOUT.flush() 

66 

67class _Input(_Op): 

68 

69 func execute(self, tape: _Tape): 

70 tape.put(u8(STDIN.get())) 

71 

72class _Loop(_Op): 

73 ops: [_Op] 

74 

75 func execute(self, tape: _Tape): 

76 while tape.get() > 0: 

77 _run(self.ops, tape) 

78 

79func _parse(source: StringReader) -> [_Op]: 

80 ops: [_Op] = [] 

81 

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 

102 

103 ops.append(op) 

104 

105 return ops 

106 

107func _run(ops: [_Op], tape: _Tape): 

108 for op in ops: 

109 op.execute(tape) 

110 

111func execute(program: string): 

112 """Execute given program. 

113 

114 """ 

115 

116 ops = _parse(StringReader(program)) 

117 _run(ops, _Tape()) 

118 

119test increment(): 

120 inc = _Increment() 

121 tape = _Tape() 

122 

123 tape.put(3) 

124 inc.execute(tape) 

125 assert tape.get() == 4 

126 

127 tape.put(254) 

128 inc.execute(tape) 

129 assert tape.get() == 255 

130 

131 inc.execute(tape) 

132 assert tape.get() == 0 

133 

134test decrement(): 

135 dec = _Decrement() 

136 tape = _Tape() 

137 

138 tape.put(2) 

139 dec.execute(tape) 

140 assert tape.get() == 1 

141 

142 dec.execute(tape) 

143 assert tape.get() == 0 

144 

145 dec.execute(tape) 

146 assert tape.get() == 255