use std::convert::TryFrom;
mod comment;
mod evaluation;
mod expansion;
use corewars_core::load_file;
use super::error::Error;
#[derive(Debug)]
pub struct Phase<PhaseState> {
buffer: String,
pub state: PhaseState,
}
pub struct Raw;
impl From<&str> for Phase<Raw> {
fn from(buf: &str) -> Self {
Phase {
buffer: buf.to_string(),
state: Raw,
}
}
}
#[derive(Debug, Default, PartialEq)]
pub struct CommentsRemoved {
pub lines: Vec<String>,
pub metadata: load_file::Metadata,
pub origin: Option<String>,
}
impl From<Phase<Raw>> for Phase<CommentsRemoved> {
fn from(prev: Phase<Raw>) -> Self {
let state = comment::extract_from_string(&prev.buffer);
Self {
buffer: prev.buffer,
state,
}
}
}
#[derive(Debug, Default)]
pub struct Expanded {
lines: Vec<String>,
metadata: load_file::Metadata,
origin: Option<String>,
}
impl From<Phase<CommentsRemoved>> for Phase<Expanded> {
fn from(prev: Phase<CommentsRemoved>) -> Self {
let lines = expansion::expand(prev.state.lines, prev.state.origin);
Self {
buffer: prev.buffer,
state: Expanded {
lines: lines.text,
origin: lines.origin,
metadata: prev.state.metadata,
},
}
}
}
#[derive(Debug, Default)]
pub struct Evaluated {
metadata: load_file::Metadata,
program: load_file::Program,
}
impl TryFrom<Phase<Expanded>> for Phase<Evaluated> {
type Error = Error;
fn try_from(prev: Phase<Expanded>) -> Result<Self, Error> {
let instructions = evaluation::evaluate(prev.state.lines)?;
let origin = prev
.state
.origin
.map(evaluation::evaluate_origin)
.transpose()?;
Ok(Self {
buffer: prev.buffer,
state: Evaluated {
metadata: prev.state.metadata,
program: load_file::Program {
instructions,
origin,
},
},
})
}
}
#[derive(Debug)]
pub struct Output {
pub warrior: load_file::Warrior,
}
impl From<Phase<Evaluated>> for Phase<Output> {
fn from(prev: Phase<Evaluated>) -> Self {
Self {
buffer: prev.buffer,
state: Output {
warrior: load_file::Warrior {
metadata: prev.state.metadata,
program: prev.state.program,
},
},
}
}
}