1mod errors;
2mod interpreter;
3mod parse_args;
4
5use std::fmt;
6use std::io::{self, Write};
7
8pub use errors::MyError;
9pub use parse_args::Config;
10
11pub fn run(mut config: Config) -> Result<(), MyError> {
12 config.token_vec = raw_code_to_token_vec(&config.raw_code)?;
13 match config.show_ir {
14 true => show_ir(config.token_vec),
15 false => interpreter::run(config)?,
16 }
17 Ok(())
18}
19
20#[derive(Debug, Clone, Copy, PartialEq)]
21pub enum Token {
22 PtrIncrease(u32),
23 PtrDecreate(u32),
24 DataIncrease(u32),
25 DataDecrease(u32),
26 JumpForward(u32),
27 JumpBack(u32),
28 Output,
29 Input,
30}
31
32#[derive(Debug, PartialEq)]
33pub enum OutputMode {
34 Individually,
35 Bulk,
36}
37
38struct IO {
39 output_mode: OutputMode,
40 output_buffer: Vec<u32>,
41}
42
43impl IO {
44 fn new(output_mode: OutputMode) -> Self {
45 IO {
46 output_mode,
47 output_buffer: Vec::new(),
48 }
49 }
50
51 fn buffer_to_string(&self) -> String {
52 let mut result = String::new();
53 for &n in self.output_buffer.iter() {
54 result.push(char::from_u32(n).unwrap());
55 }
56 result
57 }
58
59 fn output(&mut self, runtime_memory: &Memory) -> Result<char, MyError> {
60 let n = runtime_memory.output();
61 let char = match char::from_u32(n) {
62 Some(c) => c,
63 None => {
64 return Err(MyError::Custom(format!(
65 "Invalid Unicode scalar value: {}",
66 n
67 )))
68 }
69 };
70 self.output_buffer.push(n);
71 Ok(char)
72 }
73
74 fn input(&self, runtime_memory: &mut Memory) -> Result<(), MyError> {
75 print!("Input:");
76
77 match io::stdout().flush() {
78 Ok(_) => {}
79 Err(e) => return Err(MyError::Io(e)),
80 }
81 let mut buffer = String::new();
82 if let Err(e) = io::stdin().read_line(&mut buffer) {
83 return Err(MyError::Io(e));
84 }
85 let (n, eof) = input_to_u32(buffer)?;
86 if eof {
87 println!();
88 }
89 if n > runtime_memory.cell_max {
90 return Err(MyError::Custom(format!(
91 "Input value {} exceeds the maximum cell value {}",
92 n, runtime_memory.cell_max
93 )));
94 }
95 runtime_memory.input(n);
96 Ok(())
97 }
98}
99
100struct Memory {
101 view: Vec<u32>,
102 ptr: u32,
103 cell_max: u32,
104}
105
106impl fmt::Display for Memory {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 let mut s = String::new();
109 for (i, &cell) in self.view.iter().enumerate() {
110 if i == self.ptr as usize {
111 s.push('>');
112 }
113 s.push_str(&cell.to_string());
114 if i != self.view.len() - 1 {
115 s.push_str(", ");
116 }
117 }
118 write!(f, "[{}]", s)
119 }
120}
121
122impl Memory {
123 fn new(cell_max: u32) -> Self {
124 Memory {
125 view: vec![0],
126 ptr: 0,
127 cell_max,
128 }
129 }
130
131 fn ptr_increase(&mut self, n: u32) {
132 self.ptr += n;
133 if self.view.len() <= self.ptr as usize {
134 self.view.resize(self.ptr as usize + 1, 0);
135 }
136 }
137
138 fn ptr_decrease(&mut self, n: u32) -> Result<(), MyError> {
139 if n > self.ptr {
140 return Err(MyError::Custom(format!(
141 "The current pointer is at position {} and cannot move left by {} positions",
142 self.ptr, n
143 )));
144 }
145 self.ptr -= n;
146 Ok(())
147 }
148
149 fn data_increase(&mut self, n: u32) {
150 let v = &mut self.view[self.ptr as usize];
151 *v = if self.cell_max - *v >= n {
152 *v + n
153 } else {
154 n - (self.cell_max - *v + 1)
155 };
156 }
157
158 fn data_decrease(&mut self, n: u32) {
159 let v = &mut self.view[self.ptr as usize];
160 *v = if *v >= n {
161 *v - n
162 } else {
163 self.cell_max - (n - *v - 1)
164 };
165 }
166
167 fn output(&self) -> u32 {
168 self.view[self.ptr as usize]
169 }
170
171 fn input(&mut self, n: u32) {
172 self.view[self.ptr as usize] = n;
173 }
174}
175
176fn raw_code_to_token_vec(raw_code: &str) -> Result<Vec<Token>, MyError> {
177 let mut vec = Vec::new();
178 let mut stack = Vec::new();
179 let chars = raw_code.chars().enumerate();
180 for (i, char) in chars {
181 match char {
182 '>' => {
183 if let Some(Token::PtrIncrease(n)) = vec.last_mut() {
184 *n += 1;
185 } else {
186 vec.push(Token::PtrIncrease(1));
187 }
188 }
189 '<' => {
190 if let Some(Token::PtrDecreate(n)) = vec.last_mut() {
191 *n += 1;
192 } else {
193 vec.push(Token::PtrDecreate(1));
194 }
195 }
196 '+' => {
197 if let Some(Token::DataIncrease(n)) = vec.last_mut() {
198 *n += 1;
199 } else {
200 vec.push(Token::DataIncrease(1));
201 }
202 }
203 '-' => {
204 if let Some(Token::DataDecrease(n)) = vec.last_mut() {
205 *n += 1;
206 } else {
207 vec.push(Token::DataDecrease(1));
208 }
209 }
210 '.' => vec.push(Token::Output),
211 ',' => vec.push(Token::Input),
212 '[' => {
213 vec.push(Token::JumpForward(0));
214 stack.push(vec.len() as u32);
215 }
216 ']' => {
217 if let Some(start) = stack.pop() {
218 vec.push(Token::JumpBack(start));
219 *vec.get_mut(start as usize - 1).unwrap() =
220 Token::JumpForward(vec.len() as u32);
221 } else {
222 return Err(MyError::Custom(format!(
223 "Unmatched JumpBack found at [{}]",
224 i
225 )));
226 }
227 }
228 _ => (),
229 }
230 }
231
232 if !stack.is_empty() {
233 return Err(MyError::Custom(format!(
234 "Unmatched JumpForward found at {:?}",
235 stack
236 )));
237 }
238
239 Ok(vec)
240}
241
242fn input_to_u32(mut s: String) -> Result<(u32, bool), MyError> {
243 let trimed = s.trim();
244 if trimed.ends_with("u32") {
245 s.truncate(trimed.len() - 3);
246 return match s.parse::<u32>() {
247 Ok(value) => Ok((value, false)),
248 Err(e) => Err(MyError::Parse(e)),
249 };
250 }
251
252 match s.as_bytes() {
253 x if x.ends_with(&[13, 10]) => {
254 match s.chars().count() {
256 3 => {
257 let c = s.chars().next().unwrap();
258 Ok((c as u32, false))
259 }
260 2 => Ok(('\n' as u32, false)),
261 _ => Err(MyError::Custom(
262 "The length of the input string is greater than 1, unable to parse into char"
263 .to_string(),
264 )),
265 }
266 }
267
268 x if x.ends_with(&[10]) => {
269 match s.chars().count() {
271 2 => {
272 let c = s.chars().next().unwrap();
273 Ok((c as u32, false))
274 }
275 1 => Ok(('\n' as u32, false)),
276 _ => Err(MyError::Custom(
277 "The length of the input string is greater than 1, unable to parse into char"
278 .to_string(),
279 )),
280 }
281 }
282
283 _ => {
284 Ok((0, true))
286 }
287 }
288}
289
290fn show_ir(token_vec: Vec<Token>) {
291 for token in token_vec {
292 match token {
293 Token::PtrIncrease(n) => println!("PtrIncrease {}", n),
294 Token::PtrDecreate(n) => println!("PtrDecreate {}", n),
295 Token::DataIncrease(n) => println!("DataIncrease {}", n),
296 Token::DataDecrease(n) => println!("DataDecrease {}", n),
297 Token::JumpForward(n) => println!("JumpForward {}", n),
298 Token::JumpBack(n) => println!("JumpBack {}", n),
299 Token::Output => println!("Output"),
300 Token::Input => println!("Input"),
301 }
302 }
303}