/* Appellation: exec Contrib: FL03 Description: ... summary ... */ use crate::instructions::Instruction; use crate::{Alphabet, Program, Scope, State, Symbolic}; use async_trait::async_trait; use contained_core::{states::Stateful, Error}; use futures::{Future, StreamExt}; use predicates::Predicate; use std::sync::{Arc, Mutex}; /// [AsyncExecute] describes a self-contained executor that can be executed asynchronously. #[async_trait] pub trait AsyncExecute: Alphabet + StreamExt> + Stateful + Unpin { type Driver: Future + Scope + Send + Sync; type Error: Send + Sync; async fn execute(&mut self) -> Result<&Arc>, Self::Error> { // Get the default symbol let default_symbol = self.clone().default_symbol(); // Get the next instruction while let Some(instruction) = self.next().await { // Get the tail of the instruction let tail = instruction.clone().tail(); // Update the current state self.update_state(tail.state()); // Update the tape self.scope_mut().lock().unwrap().set_symbol(tail.symbol()); // Update the index; adjusts the index according to the direction self.scope_mut() .lock() .unwrap() .shift(tail.action(), default_symbol.clone()); } // Return the actor Ok(self.scope()) } /// Returns a reference to the scope fn scope(&self) -> &Arc>; /// Returns a mutable reference to the scope fn scope_mut(&mut self) -> &mut Arc>; } /// [Execute] describes a self-contained executor that can be executed synchronously. pub trait Execute: Alphabet + Iterator> + Stateful { type Driver: Scope; /// [Execute::execute] fn execute(&mut self) -> Result<&Self::Driver, Error> { // Get the default symbol let default_symbol = self.program().default_symbol(); // Get the next instruction while let Some(instruction) = self.next() { let tail = instruction.clone().tail(); // Update the current state self.update_state(tail.state()); // Update the tape self.scope_mut().set_symbol(tail.symbol()); // Update the index; adjusts the index according to the direction self.scope_mut() .shift(tail.action(), default_symbol.clone()); } // Return the actor Ok(self.scope()) } /// [Execute::execute_once] fn execute_once(&mut self) -> Result<&Self::Driver, Error> { // Get the default symbol let default_symbol = self.clone().default_symbol(); // Get the next instruction if let Some(instruction) = self.next() { let tail = instruction.tail(); // Update the current state self.update_state(tail.state()); // Update the tape self.scope_mut().set_symbol(tail.symbol()); // Update the index; adjusts the index according to the direction self.scope_mut().shift(tail.action(), default_symbol); // Return the actor return Ok(self.scope()); } Err(Error::ExecutionError( "No more instructions to execute".into(), )) } /// [Execute::execute_until] fn execute_until( &mut self, until: impl Predicate, ) -> Result<&Self::Driver, Error> { while !until.eval(self.scope()) { self.execute_once()?; } Ok(self.scope()) } fn program(&self) -> &Program; fn scope(&self) -> &Self::Driver; fn scope_mut(&mut self) -> &mut Self::Driver; } /// [Executable] describes a program that can be executed with an external driver. pub trait Executable: Clone + Alphabet + Iterator> { type Driver: Scope; type Error; fn execute(&mut self, driver: &mut Self::Driver) -> Result { // Get the default symbol let default_symbol = self.clone().default_symbol(); // Get the next instruction for instruction in self.by_ref() { let tail = instruction.clone().tail(); // Update the current state driver.update_state(tail.state()); // Update the tape driver.set_symbol(tail.symbol()); // Update the index; adjusts the index according to the direction driver.shift(tail.action(), default_symbol.clone()); } // Return the actor Ok(driver.clone()) } fn execute_once(&mut self, driver: &mut Self::Driver) -> Result { // Get the default symbol let default_symbol = self.clone().default_symbol(); // Get the next instruction if let Some(instruction) = self.next() { let tail = instruction.tail(); // Update the current state driver.update_state(tail.state()); // Update the tape driver.set_symbol(tail.symbol()); // Update the index; adjusts the index according to the direction driver.shift(tail.action(), default_symbol); } // Return the actor Ok(driver.clone()) } fn execute_until( &mut self, driver: &mut Self::Driver, until: impl Predicate, ) -> Result { // Get the default symbol let default_symbol = self.clone().default_symbol(); // Get the next instruction for instruction in self.by_ref() { let tail = instruction.clone().tail(); // Update the current state driver.update_state(tail.state()); // Update the tape driver.set_symbol(tail.symbol()); // Update the index; adjusts the index according to the direction driver.shift(tail.action(), default_symbol.clone()); if until.eval(driver) { break; } } // Return the actor Ok(driver.clone()) } }