use p101_is::*;
use crate::encoding::*;
#[derive(Default)]
pub struct AsciiEncoding;
impl AsciiEncoding {
const OP_ADD: &'static str = "add";
const OP_COPY_M: &'static str = "copy_m";
const OP_COPY_TO_A: &'static str = "copy_to_a";
const OP_DIV: &'static str = "div";
const OP_MUL: &'static str = "mul";
const OP_PRINT: &'static str = "print";
const OP_RESET: &'static str = "reset";
const OP_SUB: &'static str = "sub";
const OP_SWAP: &'static str = "swap";
const OP_CAI: &'static str = "cai";
fn add(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_ADD.into(),
_ => format!("{} {}", o, Self::OP_ADD)
}
}
fn copy_m(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_COPY_M.into(),
_ => format!("{} {}", o, Self::OP_COPY_M)
}
}
fn copy_to_a(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_COPY_TO_A.into(),
_ => format!("{} {}", o, Self::OP_COPY_TO_A)
}
}
fn div(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_DIV.into(),
_ => format!("{} {}", o, Self::OP_DIV)
}
}
fn mul(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_MUL.into(),
_ => format!("{} {}", o, Self::OP_MUL)
}
}
fn print(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_PRINT.into(),
_ => format!("{} {}", o, Self::OP_PRINT)
}
}
fn reset(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_RESET.into(),
_ => format!("{} {}", o, Self::OP_RESET)
}
}
fn sub(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_SUB.into(),
_ => format!("{} {}", o, Self::OP_SUB)
}
}
fn swap(&self, o: &Register) -> String {
match o {
Register::M => Self::OP_SWAP.into(),
_ => format!("{} {}", o, Self::OP_SWAP)
}
}
fn cai(&self, sign: &CaiSign, order: &CaiOrder, digit: &CaiDigit, comma: &CaiComma) -> std::string::String {
format!("{}{}{}{} {}", order, sign, digit, comma, Self::OP_CAI)
}
}
impl Encoding for AsciiEncoding {
fn encode(&self, i: &Instruction) -> String {
match i {
Instruction::Abs => "A abs".into(),
Instruction::Add(o) => self.add(o),
Instruction::CaiStart => "cai".into(),
Instruction::Cai(sign, order, digit, comma) => format!("{}{}{}{} cai", order, sign, digit, comma),
Instruction::ConditionalJump(o) => o.to_string(),
Instruction::CopyDecimal => "decimals".into(),
Instruction::CopyM(o) => self.copy_m(o),
Instruction::CopyToA(o) => self.copy_to_a(o),
Instruction::Div(o) => self.div(o),
Instruction::DrExchange => "dr_exchange".into(),
Instruction::Jump(o) => o.to_string(),
Instruction::Label(d) => d.to_string(),
Instruction::Mul(o) => self.mul(o),
Instruction::NewLine => "newline".into(),
Instruction::Print(o) => self.print(o),
Instruction::Reset(o) => self.reset(o),
Instruction::Sqr(o) => format!("{} sqr", o),
Instruction::Stop => "stop".into(),
Instruction::Sub(o) => self.sub(o),
Instruction::SwapA(o) => self.swap(o),
}
}
fn decode_instr(&self, _text: &str) -> DecodeResult {
unimplemented!()
}
fn decode_cai(&self, _text: &str) -> DecodeResult {
unimplemented!()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::encoder::*;
fn build_encoder() -> Encoder<AsciiEncoding, NullAnnotator> {
Encoder::<AsciiEncoding, NullAnnotator>::new()
}
#[test]
pub fn ascii_encoding_of_stop_is_s() {
let program = vec!(Instruction::Stop);
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(1, lines.len());
assert_eq!("stop", lines[0]);
}
#[test]
pub fn ascii_encoding_of_reset_is_reg_and_asterisk() {
let program = vec!(Instruction::Reset(Register::A),
Instruction::Reset(Register::B),
Instruction::Reset(Register::b),
Instruction::Reset(Register::M));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(4, lines.len());
assert_eq!(String::from("A reset"), lines[0]);
assert_eq!(String::from("B reset"), lines[1]);
assert_eq!(String::from("B/ reset"), lines[2]);
assert_eq!(String::from("reset"), lines[3]);
}
#[test]
pub fn ascii_encoding_of_print_is_reg_and_diamond() {
let program = vec!(Instruction::Print(Register::A),
Instruction::Print(Register::B),
Instruction::Print(Register::b),
Instruction::Print(Register::M));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(4, lines.len());
assert_eq!(String::from("A print"), lines[0]);
assert_eq!(String::from("B print"), lines[1]);
assert_eq!(String::from("B/ print"), lines[2]);
assert_eq!(String::from("print"), lines[3]);
}
#[test]
pub fn ascii_encoding_of_newline_is_slash_diamond() {
let program = vec!(Instruction::NewLine);
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(1, lines.len());
assert_eq!(String::from("newline"), lines[0]);
}
#[test]
pub fn ascii_encoding_of_copy_to_a_is_reg_and_down_arrow() {
let program = vec!(Instruction::CopyToA(Register::M),
Instruction::CopyToA(Register::B),
Instruction::CopyToA(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!(String::from("copy_to_a"), lines[0]);
assert_eq!(String::from("B copy_to_a"), lines[1]);
assert_eq!(String::from("B/ copy_to_a"), lines[2]);
}
#[test]
pub fn ascii_encoding_of_copy_m_is_reg_and_up_arrow() {
let program = vec!(Instruction::CopyM(Register::M),
Instruction::CopyM(Register::B),
Instruction::CopyM(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!(String::from("copy_m"), lines[0]);
assert_eq!(String::from("B copy_m"), lines[1]);
assert_eq!(String::from("B/ copy_m"), lines[2]);
}
#[test]
pub fn ascii_encoding_of_exchange_is_reg_and_up_down_arrow() {
let program = vec!(Instruction::SwapA(Register::M),
Instruction::SwapA(Register::B),
Instruction::SwapA(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("swap", lines[0]);
assert_eq!("B swap", lines[1]);
assert_eq!("B/ swap", lines[2]);
}
#[test]
pub fn ascii_encoding_of_d_r_exchange_is_rs() {
let program = vec!(Instruction::DrExchange);
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(1, lines.len());
assert_eq!("dr_exchange", lines[0]);
}
#[test]
pub fn ascii_encoding_of_decimal_part_to_is_slash_up_down_arrow() {
let program = vec!(Instruction::CopyDecimal);
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(1, lines.len());
assert_eq!("decimals", lines[0]);
}
#[test]
pub fn ascii_encoding_of_add_is_reg_plus() {
let program = vec!(Instruction::Add(Register::M),
Instruction::Add(Register::B),
Instruction::Add(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("add", lines[0]);
assert_eq!("B add", lines[1]);
assert_eq!("B/ add", lines[2]);
}
#[test]
pub fn ascii_encoding_of_sub_is_reg_minus() {
let program = vec!(Instruction::Sub(Register::M),
Instruction::Sub(Register::B),
Instruction::Sub(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("sub", lines[0]);
assert_eq!("B sub", lines[1]);
assert_eq!("B/ sub", lines[2]);
}
#[test]
pub fn ascii_encoding_of_mul_is_reg_x() {
let program = vec!(Instruction::Mul(Register::M),
Instruction::Mul(Register::B),
Instruction::Mul(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("mul", lines[0]);
assert_eq!("B mul", lines[1]);
assert_eq!("B/ mul", lines[2]);
}
#[test]
pub fn ascii_encoding_of_div_is_reg_divided_by() {
let program = vec!(Instruction::Div(Register::M),
Instruction::Div(Register::B),
Instruction::Div(Register::b));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("div", lines[0]);
assert_eq!("B div", lines[1]);
assert_eq!("B/ div", lines[2]);
}
#[test]
pub fn ascii_encoding_of_sqr() {
}
#[test]
pub fn ascii_encoding_of_abs_is_accumulator_up_down_arrows() {
let program = vec!(Instruction::Abs);
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(String::from("A abs"), lines[0]);
}
#[test]
pub fn ascii_encoding_of_jump_is_the_point_of_origin() {
let program = vec!(Instruction::Jump(Origin::V),
Instruction::Jump(Origin::RZ),
Instruction::Jump(Origin::CW));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("V", lines[0]);
assert_eq!(String::from("RZ"), lines[1]);
assert_eq!(String::from("CW"), lines[2]);
}
#[test]
pub fn ascii_encoding_of_conditional_jump_the_point_of_origin() {
let program = vec!(Instruction::ConditionalJump(ConditionalOrigin::_V),
Instruction::ConditionalJump(ConditionalOrigin::rV),
Instruction::ConditionalJump(ConditionalOrigin::dY));
let encoder = build_encoder();
let text = encoder.encode(&program);
let lines: Vec<&str> = text.lines().collect();
assert_eq!(3, lines.len());
assert_eq!("/V", lines[0]);
assert_eq!(String::from("rV"), lines[1]);
assert_eq!(String::from("dY"), lines[2]);
}
#[test]
pub fn ascii_encoding_of_cai() {
return;
}
}