rstm_actors/engine/turing_engine/
impl_turing_engine.rs1use 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 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 pub fn read(&self) -> crate::Result<Head<&Q, &A>> {
28 self.driver().read()
29 }
30 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 pub fn run(&mut self) -> crate::Result<()>
46 where
47 Q: 'static + HaltState + Clone + PartialEq,
48 A: Symbol,
49 {
50 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 #[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 self.next_cycle();
82 #[cfg(feature = "tracing")]
83 tracing::info!("{tape:?}", tape = self.driver());
84 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 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 let tail = self
103 .program()?
104 .find_tail(head.state, head.symbol)
105 .ok_or(crate::Error::NoRuleFound)?
106 .clone();
107 let next = tail.clone().into_head();
109 let _prev = self.handle(tail);
111 Ok(Some(next))
113 }
114}
115
116#[allow(dead_code)]
117impl<'a, Q, A> TuringEngine<'a, Q, A>
119where
120 Q: RawState,
121{
122 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}