use std::fmt::{Display, Error, Formatter};
use std::mem::replace;
use crate::instruction::{Head, Instruction, Move, State};
use crate::program::Extend;
use crate::{Symbol, With};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Program<S: Symbol> {
container: Vec<Instruction<S>>,
alphabet: Vec<S>,
l_state: State,
}
impl<S: Symbol> Program<S> {
#[rustfmt::skip]
pub fn new(alphabet: Vec<S>, l_state: State) -> Self {
let capacity = alphabet.len() * l_state.0;
let container = Vec::with_capacity(capacity);
Program { alphabet, container, l_state }
}
pub fn alphabet(&self) -> &Vec<S> {
&self.alphabet
}
pub fn get(&self, head: &Head<S>) -> Result<Option<&Instruction<S>>, String> {
if self.l_state < head.state {
return Err(format!(
"get error: required state {} is large then largest {}",
head.state, self.l_state
));
}
Ok(self
.container
.iter()
.find(|inst: &&Instruction<S>| &inst.head == head))
}
pub fn l_state(&self) -> State {
self.l_state
}
#[rustfmt::skip]
pub fn insert(&mut self, inst: Instruction<S>) -> Result<Option<Instruction<S>>, String> {
if inst.head.state == State(0) {
return Err(format!(
"set error: instruction {} cannot have 0 state in head",
inst
));
}
if !self.alphabet.contains(&inst.head.symbol)
|| !self.alphabet.contains(&inst.tail.symbol) {
return Err(format!(
"set error: instruction {} not for program with alphabet {:?}",
inst, &self.alphabet
));
}
if self.l_state < inst.head.state || self.l_state < inst.tail.state {
return Err(format!(
"set error: instruction {} have states which is large then program largest state {}",
inst, self.l_state
));
}
let position = self
.container
.iter()
.position(|cand: &Instruction<S>| cand.head == inst.head);
match position {
Some(index) => Ok(Some(replace(&mut self.container[index], inst))),
None => {
self.container.push(inst);
Ok(None)
}
}
}
}
impl<S: Symbol> With<Program<S>> for Program<S> {
type Output = Result<Program<S>, String>;
fn with(&self, other: &Program<S>) -> Result<Program<S>, String> {
if self.alphabet != other.alphabet {
return Err(format!(
"extend error: alphabet {:?} and {:?} must be equal",
&self.alphabet, &other.alphabet
));
}
let mut program = Program::new(self.alphabet.clone(), self.l_state + other.l_state);
let extension = self.container.iter().map(|inst| match inst.tail.state {
State(0) => {
let mut inst = inst.clone();
inst.tail.state = self.l_state + State(1);
inst
}
_ => inst.clone(),
});
program.container.extend(extension);
let extension = other.container.iter().map(|inst| {
let mut inst = inst.clone();
inst.head.state += self.l_state;
inst.tail.state += match inst.tail.state {
State(0) => State(0),
_ => self.l_state,
};
inst
});
program.container.extend(extension);
Ok(program)
}
}
impl<S: Symbol, I> Extend<I> for Program<S>
where
I: IntoIterator<Item = (usize, S, usize, S, Move)>,
{
fn extend(&mut self, iterable: I) -> Result<(), String> {
for (h_state, h_symbol, t_state, t_symbol, t_movement) in iterable {
self.insert(Instruction::build(
State(h_state),
h_symbol,
State(t_state),
t_symbol,
t_movement,
))?;
}
Ok(())
}
}
impl<S: Symbol> Display for Program<S> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
use std::any::type_name;
write!(
f,
"Program<{}> {{ alphabet {:?} instuctions: {}, l_state: {} }}",
type_name::<S>(),
self.alphabet,
self.container.len(),
self.l_state
)
}
}