1use crate::{
2 config::Config,
3 result::RunResult,
4 syntax::{AutomatonType, MacroType, Move, Program, StateType},
5 tape::Tape,
6};
7use colored::*;
8use std::collections::{HashMap, HashSet};
9
10#[derive(Debug)]
11pub enum Macro {
12 Move(String, Move, u32),
13 Override(String, Move, u32, char),
14 Place(String, String),
15 Shift(String, Move, u32),
16 Complement(String, TuringMachine),
17 Reunion(String, Vec<TuringMachine>),
18 Intersect(String, Vec<TuringMachine>),
19 Chain(String, Vec<TuringMachine>),
20 Repeat(String, u32, TuringMachine),
21}
22
23fn into_macro(
24 _type_name: String,
25 name: String,
26 macro_type: MacroType,
27 automata: &HashMap<String, AutomatonType>,
28 visited: &mut HashSet<String>,
29) -> Result<Macro, String> {
30 Ok(match macro_type {
31 MacroType::Move(move_symbol, number) => Macro::Move(name, move_symbol, number),
32 MacroType::Override(move_symbol, number, tape_symbol) => {
33 Macro::Override(name, move_symbol, number, tape_symbol)
34 }
35 MacroType::Place(str) => Macro::Place(name, str),
36 MacroType::Shift(move_symbol, number) => Macro::Shift(name, move_symbol, number),
37 MacroType::Complement(component) => {
38 let mut tm = TuringMachine::default();
39 tm.add_component(
40 name.to_string() + &component + ".",
41 &component,
42 automata,
43 visited,
44 )?;
45 tm.validate()?;
46 Macro::Complement(name, tm)
47 }
48 MacroType::Reunion(components) => Macro::Reunion(
49 name.to_owned(),
50 (*components)
51 .iter()
52 .map(|component| {
53 let mut tm = TuringMachine::default();
54 tm.add_component(
55 name.to_string() + component + ".",
56 &component,
57 automata,
58 visited,
59 )?;
60 tm.validate()?;
61 Ok(tm)
62 })
63 .collect::<Result<Vec<TuringMachine>, String>>()?,
64 ),
65 MacroType::Intersect(components) => Macro::Intersect(
66 name.to_owned(),
67 (*components)
68 .iter()
69 .map(|component| {
70 let mut tm = TuringMachine::default();
71 tm.add_component(
72 name.to_string() + component + ".",
73 &component,
74 automata,
75 visited,
76 )?;
77 tm.validate()?;
78 Ok(tm)
79 })
80 .collect::<Result<Vec<TuringMachine>, String>>()?,
81 ),
82 MacroType::Chain(components) => Macro::Chain(
83 name.to_owned(),
84 (*components)
85 .iter()
86 .map(|component| {
87 let mut tm = TuringMachine::default();
88 tm.add_component(
89 name.to_string() + component + ".",
90 &component,
91 automata,
92 visited,
93 )?;
94 tm.validate()?;
95 Ok(tm)
96 })
97 .collect::<Result<Vec<TuringMachine>, String>>()?,
98 ),
99 MacroType::Repeat(component, num) => {
100 let mut tm = TuringMachine::default();
101 tm.add_component(
102 name.to_string() + &component + ".",
103 &component,
104 automata,
105 visited,
106 )?;
107 tm.validate()?;
108 Macro::Repeat(name, num, tm)
109 }
110 })
111}
112
113#[derive(Debug)]
114pub struct TuringMachine {
115 pub initial_state: String,
116 states: HashSet<String>,
117 accept_states: HashSet<String>,
118 reject_states: HashSet<String>,
119 transitions: HashMap<String, HashMap<char, (String, char, Move)>>, macros: HashMap<String, Box<Macro>>, }
122
123#[derive(Debug, Clone)]
124pub struct TuringState {
125 current_state: String,
126 tape: Tape,
127 iteration: u32,
128}
129
130impl Default for TuringMachine {
131 fn default() -> Self {
132 Self {
133 initial_state: "".to_owned(),
134 states: HashSet::new(),
135 accept_states: HashSet::new(),
136 reject_states: HashSet::new(),
137 transitions: HashMap::new(),
138 macros: HashMap::new(),
139 }
140 }
141}
142
143impl TuringState {
144 pub fn new(initial_state: String, tape_symbols: String) -> Self {
145 let mut tape = Tape::default();
146 tape.initialize(tape_symbols);
147 Self {
148 current_state: initial_state,
149 tape,
150 iteration: 0,
151 }
152 }
153}
154
155fn get_state_name(s: &StateType) -> &str {
156 match s {
157 StateType::Accept(name) => name,
158 StateType::Reject(name) => name,
159 StateType::State(name, _) => name,
160 }
161}
162
163fn get_automaton_name(a: &AutomatonType) -> &str {
164 match a {
165 AutomatonType::Machine(name, _) => name,
166 AutomatonType::Macro(name, _) => name,
167 }
168}
169impl TuringMachine {
171 pub fn make(
172 &mut self,
173 syntax: &Program,
174 start: &String,
175 visited: &mut HashSet<String>,
176 ) -> Result<(), String> {
177 let automata: HashMap<String, AutomatonType> = (*syntax.automata)
178 .iter()
179 .map(|automaton| (get_automaton_name(automaton).to_string(), automaton.clone()))
180 .collect();
181 if !automata.contains_key(start) {
182 return Err(format!(
183 "Could not find start machine {}!",
184 start.to_string()
185 ));
186 }
187 self.add_component("".to_string(), start, &automata, visited)?;
188 self.validate()
189 }
190
191 pub fn add_component(
192 &mut self,
193 prefix: String,
194 component: &String,
195 automata: &HashMap<String, AutomatonType>,
196 visited: &mut HashSet<String>,
197 ) -> Result<(), String> {
198 if visited.contains(component) {
199 return Err(format!(
200 "Cycles are not allowed in components. Error for component {}!",
201 prefix
202 .chars()
203 .take(prefix.chars().count() - 1)
204 .collect::<String>()
205 ));
206 }
207 visited.insert(component.to_string());
208 self.add_state(&StateType::Reject("reject".to_owned()), "".to_owned());
209 match automata.get(component) {
210 None => Err(format!(
211 "Could not find component {} of type {}!",
212 prefix
213 .chars()
214 .take(prefix.chars().count() - 1)
215 .collect::<String>(),
216 component
217 )),
218 Some(automaton) => {
219 match automaton {
220 AutomatonType::Machine(_, machine) => {
221 (*machine.components)
222 .iter()
223 .try_for_each(|(automaton, c_name)| {
224 self.add_component(
225 prefix.to_owned() + c_name + ".",
226 automaton,
227 &automata,
228 visited,
229 )
230 })?;
231 (*machine.states).iter().for_each(|state| {
232 self.add_state(state, prefix.to_owned());
233 });
234 }
235 AutomatonType::Macro(type_name, macro_type) => {
236 self.states.insert(prefix.to_string() + "input");
238 self.initial_state = prefix.to_string() + "input";
239 self.states.insert(prefix.to_string() + "accept");
241 self.accept_states.insert(prefix.to_string() + "accept");
242 self.states.insert(prefix.to_string() + "reject");
244 self.reject_states.insert(prefix.to_string() + "reject");
245 self.macros.insert(
247 prefix.to_string() + "input",
248 Box::new(into_macro(
249 type_name.to_owned(),
250 prefix.to_owned(),
251 macro_type.clone(),
252 automata,
253 visited,
254 )?),
255 );
256 }
257 }
258 visited.remove(component);
259 Ok(())
260 }
261 }
262 }
263
264 pub fn add_state(&mut self, state_type: &StateType, prefix: String) {
265 let name = get_state_name(state_type);
266 let state_name = prefix.to_owned() + name;
267
268 match state_type {
269 StateType::Accept(_) => {
270 self.states.insert(state_name.to_owned());
271 self.accept_states.insert(state_name);
272 }
273 StateType::Reject(_) => {
274 self.states.insert(state_name.to_owned());
275 self.reject_states.insert(state_name);
276 }
277 StateType::State(_, state) => {
278 self.states.insert(state_name.to_owned());
279 self.accept_states.remove(&state_name);
280 self.reject_states.remove(&state_name);
281
282 if state.initial {
283 self.initial_state = state_name.to_owned();
284 }
285 (*state.transitions).iter().for_each(|transition| {
286 self.add_transition(
287 state_name.to_owned(),
288 transition.read_symbol,
289 &transition.new_state,
290 transition.write_symbol,
291 transition.move_symbol,
292 prefix.to_owned(),
293 )
294 });
295 }
296 }
297 }
298
299 pub fn add_transition(
300 &mut self,
301 from: String,
302 read_symbol: char,
303 new_state: &String,
304 write_symbol: char,
305 move_symbol: Move,
306 prefix: String,
307 ) {
308 let new_state_name = prefix + new_state;
309 match self.transitions.get_mut(&from) {
310 None => {
311 let mut inner_map = HashMap::new();
312 inner_map.insert(read_symbol, (new_state_name, write_symbol, move_symbol));
313 self.transitions.insert(from, inner_map);
314 }
315 Some(inner_map) => {
316 inner_map.insert(read_symbol, (new_state_name, write_symbol, move_symbol));
317 }
318 }
319 }
320
321 pub fn validate(&mut self) -> Result<(), String> {
322 self.transitions.values().try_for_each(|inner| {
323 inner.values().try_for_each(|(state, _, _)| {
324 if !self.states.contains(state) {
325 Err("Undefined state ".to_owned() + state)
326 } else {
327 Ok(())
328 }
329 })
330 })
331 }
332
333 pub fn get_transition(&self, state: &String, read_symbol: char) -> (String, char, Move) {
334 match self.transitions.get(state).unwrap().get(&read_symbol) {
335 Some(tuple) => (*tuple).clone(),
336 None => match self.transitions.get(state).unwrap().get(&'_') {
337 None => ("reject".to_owned(), '@', Move::Neutral),
338 Some(&(ref new_state, write_symbol, move_symbol)) => {
339 if write_symbol != '_' {
340 (new_state.to_owned(), write_symbol, move_symbol)
341 } else {
342 (new_state.to_owned(), read_symbol, move_symbol)
343 }
344 }
345 },
346 }
347 }
348
349 pub fn check_final(&self, tstate: &TuringState) -> Option<RunResult> {
350 if self.accept_states.contains(&tstate.current_state) {
351 return Some(RunResult::Accept);
352 }
353 if self.reject_states.contains(&tstate.current_state) {
354 return Some(RunResult::Reject);
355 }
356 None
357 }
358
359 pub fn start(&self, config: &Config) -> RunResult {
360 let mut turing_state =
361 TuringState::new(self.initial_state.to_owned(), config.input.to_owned());
362 if config.debug {
363 print!("{}\n{}", "State:".bright_blue(), turing_state.current_state);
364 }
365 let result = self.run(&mut turing_state, config);
366 if config.debug {
367 println!("");
368 }
369 if config.show_tape {
370 turing_state.tape.show_tape();
371 }
372 if config.show_output {
373 turing_state.tape.show_output();
374 }
375 result
376 }
377
378 pub fn run(&self, tstate: &mut TuringState, config: &Config) -> RunResult {
379 while tstate.iteration < config.iterations {
380 if let Some(result) = self.check_final(tstate) {
381 return result;
382 }
383
384 if let Some(macro_component) = self.macros.get(&tstate.current_state) {
385 let applied = self.apply_macro(tstate, ¯o_component, &config);
386 match applied {
387 Err(result) => return result,
388 Ok(()) => {
389 if config.debug {
390 print!(" -> {}", &tstate.current_state)
391 }
392 }
393 }
394 }
395 if let Some(result) = self.check_final(tstate) {
396 return result;
397 }
398
399 let read_symbol = tstate.tape.read();
400 let (new_state, write_symbol, move_symbol) =
401 self.get_transition(&tstate.current_state, read_symbol);
402 if !self.states.contains(&new_state) {
403 panic!("Could not find state {}!", new_state);
404 }
405
406 tstate.current_state = new_state;
407 tstate.tape.write(write_symbol);
408 match move_symbol {
409 Move::Left => tstate.tape.move_left(),
410 Move::Right => tstate.tape.move_right(),
411 Move::Neutral => {}
412 }
413 if config.debug {
414 print!(" -> {}", tstate.current_state);
415 }
416 match config.bound {
417 Some(max_memory) => {
418 if tstate.tape.memory() > max_memory {
419 return RunResult::ExceededMemory;
420 }
421 }
422 None => {}
423 }
424 tstate.iteration += 1;
425 }
426
427 return RunResult::ExceededTime;
428 }
429
430 fn apply_macro(
431 &self,
432 tstate: &mut TuringState,
433 macro_component: &Box<Macro>,
434 config: &Config,
435 ) -> Result<(), RunResult> {
436 match macro_component.as_ref() {
437 Macro::Move(name, move_symbol, num) => {
438 tstate.iteration += num;
439 if tstate.iteration > config.iterations {
440 return Err(RunResult::ExceededTime);
441 }
442 match move_symbol {
443 Move::Left => (0..*num).for_each(|_| tstate.tape.move_left()),
444 Move::Right => (0..*num).for_each(|_| tstate.tape.move_right()),
445 Move::Neutral => {}
446 }
447 tstate.current_state = name.to_string() + "accept";
448 Ok(())
449 }
450 Macro::Override(name, move_symbol, num, symbol) => {
451 tstate.iteration += num;
452 if tstate.iteration > config.iterations {
453 return Err(RunResult::ExceededTime);
454 }
455 match move_symbol {
456 Move::Left => (0..*num).for_each(|_| {
457 tstate.tape.write(*symbol);
458 tstate.tape.move_left();
459 }),
460 Move::Right => (0..*num).for_each(|_| {
461 tstate.tape.write(*symbol);
462 tstate.tape.move_right();
463 }),
464 Move::Neutral => tstate.tape.write(*symbol),
465 }
466 tstate.current_state = name.to_string() + "accept";
467 Ok(())
468 }
469 Macro::Place(name, tape_symbols) => {
470 tstate.iteration += tape_symbols.len() as u32;
471 if tstate.iteration > config.iterations {
472 return Err(RunResult::ExceededTime);
473 }
474 tape_symbols.chars().for_each(|symbol| {
475 tstate.tape.write(symbol);
476 tstate.tape.move_right();
477 });
478 tstate.current_state = name.to_string() + "accept";
479 Ok(())
480 }
481 Macro::Shift(name, move_symbol, num) => {
482 tstate.iteration += num;
483 if tstate.iteration > config.iterations {
484 return Err(RunResult::ExceededTime);
485 }
486 match move_symbol {
487 Move::Left => (0..*num).for_each(|_| tstate.tape.shift_left()),
488 Move::Right => (0..*num).for_each(|_| tstate.tape.shift_right()),
489 Move::Neutral => {}
490 }
491 tstate.current_state = name.to_string() + "accept";
492 Ok(())
493 }
494 Macro::Complement(name, tm) => {
495 tstate.current_state = tm.initial_state.to_owned();
496 if config.debug {
497 print!(" -> {}", &tstate.current_state)
498 }
499 match tm.run(tstate, config) {
500 RunResult::Accept => tstate.current_state = name.to_string() + "reject",
501 RunResult::Reject => tstate.current_state = name.to_string() + "accept",
502 r => return Err(r),
503 }
504 Ok(())
505 }
506 Macro::Reunion(name, tms) => {
507 let old_tstate = tstate.clone();
508 for tm in tms {
509 *tstate = old_tstate.clone();
510 tstate.current_state = tm.initial_state.to_owned();
511 if config.debug {
512 print!(" -> {}", &tstate.current_state)
513 }
514 match tm.run(tstate, config) {
515 RunResult::Accept => {
516 tstate.current_state = name.to_string() + "accept";
517 return Ok(());
518 }
519 RunResult::Reject => {}
520 r => return Err(r),
521 }
522 }
523 tstate.current_state = name.to_string() + "reject";
524 Ok(())
525 }
526 Macro::Intersect(name, tms) => {
527 let old_tstate = tstate.clone();
528 for tm in tms {
529 *tstate = old_tstate.clone();
530 tstate.current_state = tm.initial_state.to_owned();
531 if config.debug {
532 print!(" -> {}", &tstate.current_state)
533 }
534 match tm.run(tstate, config) {
535 RunResult::Accept => {}
536 RunResult::Reject => {
537 tstate.current_state = name.to_string() + "reject";
538 return Ok(());
539 }
540 r => return Err(r),
541 }
542 }
543 tstate.current_state = name.to_string() + "accept";
544 Ok(())
545 }
546 Macro::Chain(name, tms) => {
547 for tm in tms {
548 tstate.current_state = tm.initial_state.to_owned();
549 if config.debug {
550 print!(" -> {}", &tstate.current_state)
551 }
552 match tm.run(tstate, config) {
553 RunResult::Accept => {}
554 RunResult::Reject => {
555 tstate.current_state = name.to_string() + "reject";
556 return Ok(());
557 }
558 r => return Err(r),
559 }
560 }
561 tstate.current_state = name.to_string() + "accept";
562 Ok(())
563 }
564 Macro::Repeat(name, num, tm) => {
565 for _ in 0..*num {
566 tstate.current_state = tm.initial_state.to_owned();
567 if config.debug {
568 print!(" -> {}", &tstate.current_state)
569 }
570 match tm.run(tstate, config) {
571 RunResult::Accept => {}
572 RunResult::Reject => {
573 tstate.current_state = name.to_string() + "reject";
574 return Ok(());
575 }
576 r => return Err(r),
577 }
578 }
579 tstate.current_state = name.to_string() + "accept";
580 Ok(())
581 }
582 }
583 }
584}