Skip to main content

rstm_actors/engine/turing_engine/
impl_turing_engine.rs

1/*
2    Appellation: impl_turing_engine <module>
3    Created At: 2025.08.31:14:48:57
4    Contrib: @FL03
5*/
6use super::TuringEngine;
7use crate::engine::{Engine, RawEngine};
8use crate::tmh::TMH;
9use crate::traits::Handle;
10use rstm_core::{Head, Symbol, Tail};
11use rstm_programs::Program;
12use rstm_state::{HaltState, RawState, State};
13
14impl<'a, Q, A> TuringEngine<'a, Q, A>
15where
16    Q: RawState,
17{
18    /// returns the tail associated with the head that is equal to the given state and symbol
19    pub fn find_tail<K>(&self, state: State<&Q>, symbol: &A) -> Option<&Tail<Q, A>>
20    where
21        Q: Eq + core::hash::Hash,
22        A: Eq + core::hash::Hash,
23    {
24        self.program.as_ref()?.find_tail(state, symbol)
25    }
26    /// Reads the current symbol at the head of the tape
27    pub fn read(&self) -> crate::Result<Head<&Q, &A>> {
28        self.driver().read()
29    }
30    /// Reads the current symbol at the head of the tape
31    pub fn read_uninit(&self) -> Head<&Q, core::mem::MaybeUninit<&A>> {
32        if let Ok(Head { state, symbol }) = self.read() {
33            Head {
34                state,
35                symbol: core::mem::MaybeUninit::new(symbol),
36            }
37        } else {
38            Head {
39                state: self.current_state().view(),
40                symbol: core::mem::MaybeUninit::uninit(),
41            }
42        }
43    }
44    /// runs the program until termination (i.e., a halt state is reached, an error occurs, etc.)
45    pub fn run(&mut self) -> crate::Result<()>
46    where
47        Q: 'static + HaltState + Clone + PartialEq,
48        A: Symbol,
49    {
50        // check for a program
51        if !self.has_program() {
52            #[cfg(feature = "tracing")]
53            tracing::error!("No program loaded; cannot execute step.");
54            return Err(crate::Error::NoProgram);
55        }
56        #[cfg(feature = "tracing")]
57        tracing::info!("Running the program...");
58        while let Some(_h) = self.step()? {
59            if self.driver.is_halted() {
60                #[cfg(feature = "tracing")]
61                tracing::info!(
62                    "The engine has halted after {} steps; terminating the execution of the program.",
63                    self.cycles
64                );
65                break;
66            }
67        }
68        Ok(())
69    }
70    /// execute a single step of the program
71    #[cfg_attr(
72        feature = "tracing", 
73        tracing::instrument(skip_all, fields(step = self.cycles), name = "step", target = "TuringEngine", level = "trace")
74    )]
75    pub fn step(&mut self) -> crate::Result<Option<Head<Q, A>>>
76    where
77        Q: 'static + HaltState + Clone + PartialEq,
78        A: Symbol,
79    {
80        // increment the steps
81        self.next_cycle();
82        #[cfg(feature = "tracing")]
83        tracing::info!("{tape:?}", tape = self.driver());
84        // check if the actor is halted
85        if self.driver.is_halted() {
86            #[cfg(feature = "tracing")]
87            tracing::warn!(
88                "A halted stated was detected; terminating the execution of the program..."
89            );
90            return Ok(None);
91        }
92        // read the tape
93        let head = if let Ok(cur) = self.read() {
94            cur
95        } else {
96            Head {
97                state: self.driver().state().view(),
98                symbol: &<A>::default(),
99            }
100        };
101        // execute the program
102        let tail = self
103            .program()?
104            .find_tail(head.state, head.symbol)
105            .ok_or(crate::Error::NoRuleFound)?
106            .clone();
107        // process the instruction
108        let next = tail.clone().into_head();
109        // process the instruction
110        let _prev = self.handle(tail);
111        // return the head
112        Ok(Some(next))
113    }
114}
115
116#[allow(dead_code)]
117/// This implementation is for any private methods used internally by the engine
118impl<'a, Q, A> TuringEngine<'a, Q, A>
119where
120    Q: RawState,
121{
122    /// increments the current epoch by a single unit
123    pub(crate) const fn next_cycle(&mut self) {
124        self.cycles += 1;
125    }
126}
127
128impl<'a, Q, A, X, Y> Handle<X> for TuringEngine<'a, Q, A>
129where
130    Q: RawState,
131    TMH<Q, A>: Handle<X, Output = Y>,
132{
133    type Output = Y;
134
135    fn handle(&mut self, args: X) -> Self::Output {
136        self.driver_mut().handle(args)
137    }
138}
139
140impl<'a, Q, A> RawEngine<Q, A> for TuringEngine<'a, Q, A>
141where
142    Q: RawState,
143{
144    type Driver = TMH<Q, A>;
145
146    seal!();
147}
148
149impl<'a, Q, S> Engine<Q, S> for TuringEngine<'a, Q, S>
150where
151    Q: 'static + HaltState + Clone + PartialEq,
152    S: Symbol,
153{
154    fn load(&mut self, program: Program<Q, S>) {
155        self.program = Some(program);
156    }
157
158    fn run(&mut self) -> Result<(), crate::Error> {
159        TuringEngine::run(self)
160    }
161}
162
163impl<'a, Q, S> Iterator for TuringEngine<'a, Q, S>
164where
165    Q: 'static + HaltState + Clone + PartialEq,
166    S: Symbol,
167{
168    type Item = Head<Q, S>;
169
170    fn next(&mut self) -> Option<Self::Item> {
171        match self.step() {
172            Ok(output) => match output {
173                Some(h) => Some(h),
174                None => {
175                    #[cfg(feature = "tracing")]
176                    tracing::info!("The engine has halted; terminating the iteration.");
177                    None
178                }
179            },
180            Err(_e) => {
181                #[cfg(feature = "tracing")]
182                tracing::error!("An error occurred during execution: {_e}");
183                None
184            }
185        }
186    }
187}