diff --git a/core/src/rules/parts/head.rs b/core/src/rules/parts/head.rs index b2db9ea..3fb272e 100644 --- a/core/src/rules/parts/head.rs +++ b/core/src/rules/parts/head.rs @@ -83,6 +83,20 @@ impl Head { self.symbol = symbol; } } + + pub fn to_ref<'a>(&'a self) -> Head<&'a Q, &'a S> { + Head { + state: self.state.to_ref(), + symbol: &self.symbol, + } + } + + pub fn to_mut<'a>(&'a mut self) -> Head<&'a mut Q, &'a mut S> { + Head { + state: self.state.to_mut(), + symbol: &mut self.symbol, + } + } } impl<'a, Q, S> Head<&'a Q, &'a S> { diff --git a/core/src/rules/parts/tail.rs b/core/src/rules/parts/tail.rs index 5d5c609..1c89fc9 100644 --- a/core/src/rules/parts/tail.rs +++ b/core/src/rules/parts/tail.rs @@ -38,15 +38,6 @@ impl Tail { pub fn as_tuple(&self) -> (Direction, &State, &S) { (self.direction, &self.state, &self.symbol) } - /// Returns an instance of the [head](Head) where each element within - /// the created instance is an immutable reference - pub fn as_head(&self) -> Head<&'_ Q, &'_ S> { - super::Head::new(self.state.to_ref(), &self.symbol) - } - /// Consumes the tail and returns a new instance of the [Head] - pub fn into_head(self) -> Head { - super::Head::new(self.state, self.symbol) - } /// Consumes the tail and returns the direction, state, and symbol as a 3-tuple pub fn into_tuple(self) -> (Direction, State, S) { (self.direction, self.state, self.symbol) @@ -63,6 +54,83 @@ impl Tail { pub const fn write_symbol(&self) -> &S { &self.symbol } + /// Consumes the tail and returns a new instance of the [Head] + pub fn into_head(self) -> Head { + super::Head::new(self.state, self.symbol) + } + /// Returns an instance of the [head](Head) where each element within + /// the created instance is an immutable reference + pub fn to_head_ref<'a>(&'a self) -> Head<&'a Q, &'a S> { + super::Head::new(self.state.to_ref(), &self.symbol) + } + + pub fn to_ref(&self) -> Tail<&'_ Q, &'_ S> { + Tail { + direction: self.direction, + state: self.state.to_ref(), + symbol: &self.symbol, + } + } + + pub fn to_mut(&mut self) -> Tail<&'_ mut Q, &'_ mut S> { + Tail { + direction: self.direction, + state: self.state.to_mut(), + symbol: &mut self.symbol, + } + } + + pub fn into_owned(self) -> Tail + where + Q: Clone, + S: Clone, + { + Tail { + direction: self.direction, + state: self.state, + symbol: self.symbol, + } + } + + pub fn to_owned(&self) -> Tail + where + Q: Clone, + S: Clone, + { + Tail { + direction: self.direction, + state: self.state.to_owned(), + symbol: self.symbol.clone(), + } + } +} + +impl<'a, Q, S> Tail<&'a Q, &'a S> { + pub fn cloned(&self) -> Tail + where + Q: Clone, + S: Clone, + { + Tail { + direction: self.direction, + state: self.state.cloned(), + symbol: self.symbol.clone(), + } + } +} + +impl<'a, Q, S> Tail<&'a mut Q, &'a mut S> { + pub fn cloned(&self) -> Tail + where + Q: Clone, + S: Clone, + { + Tail { + direction: self.direction, + state: self.state.cloned(), + symbol: self.symbol.clone(), + } + } } mod builder { diff --git a/core/src/rules/program.rs b/core/src/rules/program.rs index bc32588..e3127e4 100644 --- a/core/src/rules/program.rs +++ b/core/src/rules/program.rs @@ -73,7 +73,7 @@ impl Program { self.ruleset.get(idx) } /// Returns a collection of tails for a given head. - pub fn get_head(&self, head: &Head) -> Vec<&Tail> + pub fn get_head(&self, head: &Head) -> Vec> where Q: PartialEq, S: PartialEq, @@ -81,13 +81,21 @@ impl Program { self.iter() .filter_map(|i| { if i.head() == head { - Some(i.tail()) + Some(i.tail().to_ref()) } else { None } }) .collect() } + + pub fn find_head(&self, head: Head<&'_ Q, &'_ S>) -> Option<&Tail> + where + Q: PartialEq, + S: PartialEq, + { + self.iter().find(|i| i.head().to_ref() == head).map(|i| i.tail()) + } } impl From> for Program { diff --git a/core/src/tape/tape.rs b/core/src/tape/tape.rs index c0883e5..d9af628 100644 --- a/core/src/tape/tape.rs +++ b/core/src/tape/tape.rs @@ -19,7 +19,8 @@ use core::cell::Cell; /// This is done to quantify the impact of operations whose directions are defined to /// be [Direction::Stay]. Moving left and right within a linear space speaks directly /// to a translation or shift in space, however, staying in place does not result in -/// any movement, shift, or translation within space. +/// any movement, shift, or translation within space. That being said, staying still +/// is an operation that does result in some change in-time. #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct StdTape { diff --git a/rstm/src/turing/model.rs b/rstm/src/turing/model.rs index 0a39f11..da916ae 100644 --- a/rstm/src/turing/model.rs +++ b/rstm/src/turing/model.rs @@ -73,37 +73,14 @@ impl TM { pub fn tape_mut(&mut self) -> &mut StdTape { &mut self.tape } -} - -// #[cfg(feature = "std")] -impl TM -where - Q: Clone + PartialEq, - S: Symbolic, -{ - #[cfg_attr( - feature = "tracing", - tracing::instrument(skip_all, name = "step", target = "fsm") - )] - pub fn step_inplace(&mut self) -> Result, Error> { - #[cfg(feature = "tracing")] - tracing::info!("Stepping..."); - let prog = self.program().clone(); - // Create a new head from the current state and symbol - let head = self.head().cloned(); - // Get the first instruction for the current head - if let Some(&tail) = prog.get_head(&head).first() { - let nxt = self.tape.update_inplace(tail.clone()); - self.set_state(nxt); - return Ok(tail.as_head().cloned()); - } - Err(Error::state_not_found()) - } + /// Runs the program until the + /// + /// The program will continue to run until the current state is a halt state. #[cfg_attr( feature = "tracing", tracing::instrument(skip_all, name = "run", target = "fsm") )] - pub fn run(mut self) -> Result<(), Error> { + pub fn run(mut self) -> Result<(), Error> where Q: Clone + PartialEq, S: Symbolic { #[cfg(feature = "tracing")] tracing::info!("Running the program..."); loop { @@ -131,18 +108,20 @@ where { type Item = Head; + #[cfg_attr( + feature = "tracing", + tracing::instrument(skip_all, name = "step", target = "fsm") + )] fn next(&mut self) -> Option { #[cfg(feature = "tracing")] tracing::info!("Stepping..."); - let prog = self.program().clone(); // Create a new head from the current state and symbol let head = self.head().cloned(); // Get the first instruction for the current head - if let Some(&tail) = prog.get_head(&head).first() { - let nxt = self.tape_mut().update_inplace(tail.clone()); - self.set_state(nxt); - return Some(tail.as_head().cloned()); + if let Some(&tail) = self.program.get_head(&head).first() { + self.state = self.tape.update_inplace(tail.cloned()); + return Some(tail.cloned().into_head()); } - self.step_inplace().ok() + None } }