use super::TuringEngine;
use crate::engine::{Engine, RawEngine};
use crate::tmh::TMH;
use crate::traits::Handle;
use rstm_core::{Head, Symbol, Tail};
use rstm_programs::Program;
use rstm_state::{HaltState, RawState, State};
impl<'a, Q, A> TuringEngine<'a, Q, A>
where
Q: RawState,
{
pub fn find_tail<K>(&self, state: State<&Q>, symbol: &A) -> Option<&Tail<Q, A>>
where
Q: Eq + core::hash::Hash,
A: Eq + core::hash::Hash,
{
self.program.as_ref()?.find_tail(state, symbol)
}
pub fn read(&self) -> crate::Result<Head<&Q, &A>> {
self.driver().read()
}
pub fn read_uninit(&self) -> Head<&Q, core::mem::MaybeUninit<&A>> {
if let Ok(Head { state, symbol }) = self.read() {
Head {
state,
symbol: core::mem::MaybeUninit::new(symbol),
}
} else {
Head {
state: self.current_state().view(),
symbol: core::mem::MaybeUninit::uninit(),
}
}
}
pub fn run(&mut self) -> crate::Result<()>
where
Q: 'static + HaltState + Clone + PartialEq,
A: Symbol,
{
if !self.has_program() {
#[cfg(feature = "tracing")]
tracing::error!("No program loaded; cannot execute step.");
return Err(crate::Error::NoProgram);
}
#[cfg(feature = "tracing")]
tracing::info!("Running the program...");
while let Some(_h) = self.step()? {
if self.driver.is_halted() {
#[cfg(feature = "tracing")]
tracing::info!(
"The engine has halted after {} steps; terminating the execution of the program.",
self.cycles
);
break;
}
}
Ok(())
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, fields(step = self.cycles), name = "step", target = "TuringEngine", level = "trace")
)]
pub fn step(&mut self) -> crate::Result<Option<Head<Q, A>>>
where
Q: 'static + HaltState + Clone + PartialEq,
A: Symbol,
{
self.next_cycle();
#[cfg(feature = "tracing")]
tracing::info!("{tape:?}", tape = self.driver());
if self.driver.is_halted() {
#[cfg(feature = "tracing")]
tracing::warn!(
"A halted stated was detected; terminating the execution of the program..."
);
return Ok(None);
}
let head = if let Ok(cur) = self.read() {
cur
} else {
Head {
state: self.driver().state().view(),
symbol: &<A>::default(),
}
};
let tail = self
.program()?
.find_tail(head.state, head.symbol)
.ok_or(crate::Error::NoRuleFound)?
.clone();
let next = tail.clone().into_head();
let _prev = self.handle(tail);
Ok(Some(next))
}
}
#[allow(dead_code)]
impl<'a, Q, A> TuringEngine<'a, Q, A>
where
Q: RawState,
{
pub(crate) const fn next_cycle(&mut self) {
self.cycles += 1;
}
}
impl<'a, Q, A, X, Y> Handle<X> for TuringEngine<'a, Q, A>
where
Q: RawState,
TMH<Q, A>: Handle<X, Output = Y>,
{
type Output = Y;
fn handle(&mut self, args: X) -> Self::Output {
self.driver_mut().handle(args)
}
}
impl<'a, Q, A> RawEngine<Q, A> for TuringEngine<'a, Q, A>
where
Q: RawState,
{
type Driver = TMH<Q, A>;
seal!();
}
impl<'a, Q, S> Engine<Q, S> for TuringEngine<'a, Q, S>
where
Q: 'static + HaltState + Clone + PartialEq,
S: Symbol,
{
fn load(&mut self, program: Program<Q, S>) {
self.program = Some(program);
}
fn run(&mut self) -> Result<(), crate::Error> {
TuringEngine::run(self)
}
}
impl<'a, Q, S> Iterator for TuringEngine<'a, Q, S>
where
Q: 'static + HaltState + Clone + PartialEq,
S: Symbol,
{
type Item = Head<Q, S>;
fn next(&mut self) -> Option<Self::Item> {
match self.step() {
Ok(output) => match output {
Some(h) => Some(h),
None => {
#[cfg(feature = "tracing")]
tracing::info!("The engine has halted; terminating the iteration.");
None
}
},
Err(_e) => {
#[cfg(feature = "tracing")]
tracing::error!("An error occurred during execution: {_e}");
None
}
}
}
}