use contained_core::states::Stateful;
use contained_core::{ArrayLike, Include, Insert};
use std::collections::{BTreeSet, HashSet};
use crate::instructions::Move;
use crate::{State, Tape};
pub trait Alphabet<S: Symbolic> {
fn default_symbol(&self) -> S {
Default::default()
}
fn is_viable(&self, symbol: &S) -> bool;
}
impl<S: Symbolic> Alphabet<S> for Vec<S> {
fn is_viable(&self, symbol: &S) -> bool {
self.contains(symbol)
}
fn default_symbol(&self) -> S {
if let Some(entry) = self.first() {
entry.clone()
} else {
Default::default()
}
}
}
impl<S: Symbolic> Alphabet<S> for BTreeSet<S> {
fn is_viable(&self, symbol: &S) -> bool {
self.contains(symbol)
}
fn default_symbol(&self) -> S {
if let Some(entry) = self.first() {
entry.clone()
} else {
Default::default()
}
}
}
impl<S: Symbolic> Alphabet<S> for HashSet<S> {
fn is_viable(&self, symbol: &S) -> bool {
self.contains(symbol)
}
fn default_symbol(&self) -> S {
if let Some(entry) = self.iter().next() {
entry.clone()
} else {
Default::default()
}
}
}
pub trait Scope<S: Symbolic>: Include<S> + Insert<usize, S> + Stateful<State> {
fn current(&self) -> S {
self.tape()
.get(self.cursor())
.expect("Index is out of bounds...")
.clone()
}
fn cursor(&self) -> usize;
fn set_index(&mut self, index: usize);
fn set_symbol(&mut self, elem: S);
fn shift(&mut self, shift: Move, elem: S) {
let index = self.cursor();
match shift {
Move::Left if self.cursor() == 0 => {
self.include(elem);
}
Move::Left => {
self.set_index(index - 1);
}
Move::Right => {
self.set_index(index + 1);
if self.cursor() == self.tape().len() {
self.include(elem);
}
}
Move::Stay => {}
}
}
fn tape(&self) -> Tape<S>;
}
pub trait Symbolic:
Clone + Default + Eq + Ord + std::fmt::Debug + std::fmt::Display + std::hash::Hash
{
}
impl<T> Symbolic for T where
T: Clone + Default + Eq + Ord + std::fmt::Debug + std::fmt::Display + std::hash::Hash
{
}
pub trait Translate<S: Symbolic> {
type Error;
fn translate(&mut self, tape: Tape<S>) -> Result<Tape<S>, Self::Error>;
}
pub trait Turing<S: Symbolic>: Translate<S> {
type Scope: Scope<S>;
fn execute(&mut self) -> Result<&Self, Self::Error>;
fn execute_once(&mut self) -> Result<&Self, Self::Error>;
fn execute_until(&mut self, until: impl Fn(&Self::Scope) -> bool)
-> Result<&Self, Self::Error>;
}
pub trait With<T> {
type Output;
fn with(&self, other: &T) -> Self::Output;
}
pub trait TryWith<T> {
type Output;
type Error;
fn try_with(&self, other: &T) -> Result<Self::Output, Self::Error>;
}