Решение на Basic BASIC от Теодор Борисов

Обратно към всички решения

Към профила на Теодор Борисов

Резултати

  • 13 точки от тестове
  • 0 бонус точки
  • 13 точки общо
  • 10 успешни тест(а)
  • 5 неуспешни тест(а)

Код

use std::io::{self, Write, Read, BufReader, Error, ErrorKind};
use std::io::BufRead;
use std::collections::HashMap;
#[derive(Debug)]
pub enum InterpreterError {
IoError(io::Error),
UnknownVariable { name: String },
NotANumber { value: String },
SyntaxError { code: String },
RuntimeError { line_number: u16, message: String },
NotValidNumber {},
}
pub struct Interpreter<'a, R: Read, W: Write> {
input: BufReader<R>,
output: &'a mut W,
commands: Vec::<&'a str>,
hm: HashMap::<&'a str, u16>,
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn new(input: R, output: &'a mut W) -> Self {
Interpreter {
input: BufReader::new(input),
output: output,
commands: Vec::<&'a str>::new(),
hm: HashMap::<&'a str, u16>::new(),
}
}
}
impl<'a, R: Read, W: Write,> Interpreter<'a, R, W> {
pub fn add(&mut self, code: &'a str) -> Result<(), InterpreterError> {
let split_vec: Vec<&str> = code.split_whitespace().collect();
if !split_vec[0].chars().all(char::is_numeric) {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
let line = split_vec[0].parse::<u16>();
if line.is_err() {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
if split_vec[1] == "PRINT" {
if !(split_vec.len() == 3 && (split_vec[2].chars().all(char::is_numeric) || split_vec[2].chars().nth(0).unwrap().is_uppercase() || split_vec[2].chars().all(char::is_lowercase))) {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
} else if split_vec[1] == "READ" {
if !(split_vec.len() == 3 && split_vec[2].chars().nth(0).unwrap().is_uppercase()) {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
} else if split_vec[1] == "GOTO" {
if split_vec.len() != 3 {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
let num = split_vec[2].parse::<u16>();
if num.is_err() {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
} else if split_vec[1] == "IF" {
if split_vec.len() != 7 {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
if !(split_vec[2].chars().nth(0).unwrap().is_uppercase() || split_vec[2].chars().all(char::is_numeric)) {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
if !(split_vec[4].chars().nth(0).unwrap().is_uppercase() || split_vec[4].chars().all(char::is_numeric)) {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
let num = split_vec[6].parse::<u16>();
if num.is_err() || split_vec[5] != "GOTO" || (split_vec[3] != "<" && split_vec[3] != ">" && split_vec[3] != "=") {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
} else {
return Err(InterpreterError::SyntaxError { code: code.to_string() });
}
let mut flag = 0;
for i in 0..self.commands.len() {
let vec: Vec<&str> = self.commands[i].split_whitespace().collect();
if vec[0] == split_vec[0] {
self.commands[i] = code;
flag = 1;
}
}
if flag == 0 {
self.commands.push(code);
}
return Ok(());
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn sort(&mut self) -> () {
for i in 0..(self.commands.len() - 1) {
for j in (i + 1)..self.commands.len() {
let a: Vec<&str> = self.commands[i].split_whitespace().collect();
let b: Vec<&str> = self.commands[j].split_whitespace().collect();
let num1 = a[0].parse::<u16>().unwrap();
let num2 = b[0].parse::<u16>().unwrap();
if num1 > num2 {
(self.commands[i], self.commands[j]) = (self.commands[j], self.commands[i]);
}
}
}
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn eval_value(&self, value: &str) -> Result<u16, InterpreterError> {
if value.chars().nth(0).unwrap().is_uppercase() {
if self.hm.contains_key(&value) {
let val = self.hm.get(&value);
return Ok(*val.unwrap());
} else {
return Err(InterpreterError::UnknownVariable { name: value.to_string() });
}
} else if value.chars().all(char::is_numeric) {
let num = value.parse::<u16>();
if num.is_err() {
return Err(InterpreterError::NotANumber { value: value.to_string() });
} else {
return Ok(num.unwrap());
}
}
return Err(InterpreterError::UnknownVariable { name: value.to_string() });
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn run(&mut self) -> Result<(), InterpreterError> {
self.sort();
let mut i = 0;
while i != self.commands.len() {
let command: Vec<&str> = self.commands[i].split_whitespace().collect();
if command[1] == "READ" {
let mut line = String::new();
assert!(self.input.read_line(&mut line).is_ok());
if line.is_empty() {
return Err(InterpreterError::IoError(Error::from(ErrorKind::UnexpectedEof)));
}
let value = &line[0..(line.len() - 1)];
self.hm.insert(command[2], value.parse::<u16>().unwrap());
i += 1;
} else if command[1] == "PRINT" {
let value = self.eval_value(command[2]);
if value.is_err() {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot find variable!".to_string() });
}
let str_u8 = value.unwrap().to_string();
if self.output.write(str_u8.as_bytes()).is_err() {
return Err(InterpreterError::IoError(Error::from(ErrorKind::Other)));
}
if self.output.write(b"\n").is_err() {
return Err(InterpreterError::IoError(Error::from(ErrorKind::Other)));
}
i += 1;
} else if command[1] == "GOTO" {
let a = i;
for j in 0..self.commands.len() {
let current: Vec<&str> = self.commands[j].split_whitespace().collect();
if current[0] == command[2] {
println!("Break j: {:?}", j);
i = j;
break;
}
}
if a == i {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot find new line in goto!".to_string() });
}
} else if command[1] == "IF" {
let mut num1: u16 = 0;
if command[2].chars().nth(0).unwrap().is_uppercase() {
if self.hm.contains_key(command[2]) == true {
num1 = *self.hm.get(&command[2]).unwrap();
} else {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot find variable!".to_string() });
}
} else if command[2].chars().all(char::is_numeric) {
let a = command[2].parse::<u16>();
if a.is_err() {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot parse to u16!".to_string() });
} else {
num1 = a.unwrap();
}
}
let mut num2: u16 = 0;
if command[4].chars().nth(0).unwrap().is_uppercase() {
if self.hm.contains_key(command[4]) == true {
num2 = *self.hm.get(&command[4]).unwrap();
} else {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot find variable!".to_string() });
}
} else if command[4].chars().all(char::is_numeric) {
let b = command[4].parse::<u16>();
if b.is_err() {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot parse to u16!".to_string() });
} else {
num2 = b.unwrap();
}
}
let mut flag = 0;
if (command[3] == "<" && num1 < num2) || (command[3] == ">" && num1 > num2) || (command[3] == "=" && num1 == num2) {
flag = 1;
}
if flag == 1 {
let a = i;
for j in 0..self.commands.len() {
let current: Vec<&str> = self.commands[j].split_whitespace().collect();
if current[0] == command[6] {
i = j;
break;
}
}
if a == i {
return Err(InterpreterError::RuntimeError { line_number: command[0].parse::<u16>().unwrap(), message: "Cannot find new line in goto!".to_string() });
}
} else {
i += 1;
}
}
}
return Ok(());
}
}
// За тестване че някакъв резултат пасва на някакъв pattern:
macro_rules! assert_match {
($expr:expr, $pat:pat) => {
let result = $expr;
if let $pat = result {
// all good
} else {
assert!(false, "Expression {:?} does not match the pattern {:?}", result, stringify!($pat));
}
}
}
#[test]
fn test_basic_1() {
let input: &[u8] = b"1\n2\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
interpreter.add("10 READ A").unwrap();
interpreter.add("20 READ B").unwrap();
interpreter.add("30 PRINT A").unwrap();
interpreter.add("40 PRINT B").unwrap();
interpreter.run().unwrap();
assert_eq!(interpreter.eval_value("A").unwrap(), 1_u16);
assert_eq!(String::from_utf8(output).unwrap(), "1\n2\n");
}
#[test]
fn test_basic_2() {
let input: &[u8] = b"";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("10 PRINT"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn start_with_string() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("das PRINT A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("D GOTO 10"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("A READ A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("Я READ A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("a10 PRINT A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10a READ B"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn start_with_bigger_number() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("65536 PRINT A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("1522336 GOTO 10"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn err_when_read() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("10 READ"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 READ 10 A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 READ 10"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn err_when_goto() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("10 GOTO"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 GOTO 10 A"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 GOTO 65536"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 GOTO 152423"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn err_when_if() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("10 IF 2 > 1"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 IF 2 > 1 GOTO"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 IF 2 > 1 GOTO 10 10"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 IF 2 > 1 GOTO f"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 IF 2 >= 1 GOTO 10"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 IF 2 <= 1 GOTO 10"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 IF 2 == 1 GOTO 10"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn err_command() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("10 ЯАЯѝ 2 > 1"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 10 2 > 1 GOTO"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("10 das 2 > 1 GOTO 10 10"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn replace_lines() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("30 PRINT A").is_ok());
assert!(interpreter.add("30 PRINT B").is_ok());
interpreter.run().unwrap();
assert_eq!(interpreter.eval_value("A").unwrap(), 1_u16);
assert_eq!(interpreter.eval_value("B").unwrap(), 3_u16);
assert_eq!(String::from_utf8(output).unwrap(), "3\n");
}
#[test]
fn check_sort_function() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("20 PRINT A").is_ok());
assert!(interpreter.add("10 READ B").is_ok());
assert!(interpreter.add("5 READ A").is_ok());
assert_match!(interpreter.commands[0], "20 PRINT A");
assert_match!(interpreter.commands[1], "10 READ B");
assert_match!(interpreter.commands[2], "5 READ A");
interpreter.sort();
assert_match!(interpreter.commands[0], "5 READ A");
assert_match!(interpreter.commands[1], "10 READ B");
assert_match!(interpreter.commands[2], "20 PRINT A");
}
#[test]
fn print_unknown_variable() {
let input: &[u8] = b"1\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("30 PRINT B").is_ok());
assert!(interpreter.add("40 PRINT D").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError {..}));
assert!(interpreter.eval_value("D").is_err());
}
#[test]
fn print_num() {
let input: &[u8] = b"";
let mut output = Vec::<u8>::new();
let interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.eval_value(&"5").unwrap(), 5_u16);
assert_match!(interpreter.eval_value(&"54544333"), Err(InterpreterError::NotANumber{..}));
}
#[test]
fn print_unknown() {
let input: &[u8] = b"";
let mut output = Vec::<u8>::new();
let interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.eval_value(&"aasdas6f"), Err(InterpreterError::UnknownVariable {..}));
assert_match!(interpreter.eval_value(&"5454433a"), Err(InterpreterError::UnknownVariable {..}));
assert_match!(interpreter.eval_value(&"a"), Err(InterpreterError::UnknownVariable {..}));
assert_match!(interpreter.eval_value(&"т"), Err(InterpreterError::UnknownVariable {..}));
}
#[test]
fn test_goto() {
let input: &[u8] = b"1\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 GOTO 50").is_ok());
assert!(interpreter.add("30 READ B").is_ok());
assert!(interpreter.add("50 PRINT A").is_ok());
assert!(interpreter.run().is_ok());
}
#[test]
fn test_goto2() {
let input: &[u8] = b"1\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 GOTO 60").is_ok());
assert!(interpreter.add("30 READ B").is_ok());
assert!(interpreter.add("50 PRINT A").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError {..}));
}
#[test]
fn test_if() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("30 READ C").is_ok());
assert!(interpreter.add("50 IF A > B GOTO 100").is_ok());
assert!(interpreter.add("60 IF A < B GOTO 200").is_ok());
assert!(interpreter.add("70 IF A = B GOTO 300").is_ok());
assert!(interpreter.add("100 PRINT A").is_ok());
assert!(interpreter.add("200 PRINT B").is_ok());
assert!(interpreter.add("300 PRINT C").is_ok());
assert!(interpreter.run().is_ok());
assert_eq!(String::from_utf8(output).unwrap(), "2\n3\n");
}
#[test]
fn test_if_add() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert_match!(interpreter.add("50 IF ad > 2sd GOTO 100"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("60 IF a < 2 GOTO 200"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("70 IF я = a GOTO 300"), Err(InterpreterError::SyntaxError { .. }));
assert_match!(interpreter.add("70 IF A = a GOTO 300"), Err(InterpreterError::SyntaxError { .. }));
}
#[test]
fn test_if_wrong_values1() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("50 IF A > 2251525625 GOTO 100").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError { .. }));
}
#[test]
fn test_if_wrong_values2() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("60 IF D < 2 GOTO 200").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError { .. }));
}
#[test]
fn test_if_wrong_values3() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("70 IF 234535322 > A GOTO 100").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError { .. }));
}
#[test]
fn test_if_wrong_values4() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("80 IF 2 < T GOTO 200").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError { .. }));
}
#[test]
fn test_if_wrong_values5() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("50 IF A < B GOTO 100").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError { .. }));
}
#[test]
fn test_if_wrong_values6() {
let input: &[u8] = b"1\n2\n3\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("50 IF A < 25 GOTO 100").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::RuntimeError { .. }));
}
#[test]
fn test_program_read() {
let input: &[u8] = b"1\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("50 IF A < 25 GOTO 100").is_ok());
assert_match!(interpreter.run(), Err(InterpreterError::IoError { .. }));
}
#[test]
fn program_example() {
let input: &[u8] = b"1\n2\n3\n4\n5\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ A").is_ok());
assert!(interpreter.add("20 READ B").is_ok());
assert!(interpreter.add("30 PRINT A").is_ok());
assert!(interpreter.add("40 GOTO 80").is_ok());
assert!(interpreter.add("70 PRINT B").is_ok());
assert!(interpreter.add("80 IF A < B GOTO 100").is_ok());
assert!(interpreter.add("90 PRINT A").is_ok());
assert!(interpreter.add("100 PRINT B").is_ok());
assert!(interpreter.add("110 READ C").is_ok());
assert!(interpreter.add("120 READ D").is_ok());
assert!(interpreter.add("130 READ E").is_ok());
assert!(interpreter.add("200 IF D > E GOTO 210").is_ok());
assert!(interpreter.add("201 PRINT E").is_ok());
assert!(interpreter.add("210 PRINT D").is_ok());
assert!(interpreter.run().is_ok());
assert_eq!(String::from_utf8(output).unwrap(), "1\n2\n5\n4\n");
}
#[test]
fn program_example2() {
let input: &[u8] = b"1\n2\n3\n4\n5\n";
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
assert!(interpreter.add("10 READ А").is_ok());
assert!(interpreter.add("20 READ Б").is_ok());
assert!(interpreter.add("30 PRINT А").is_ok());
assert!(interpreter.add("40 GOTO 80").is_ok());
assert!(interpreter.add("70 PRINT Б").is_ok());
assert!(interpreter.add("80 IF А < Б GOTO 100").is_ok());
assert!(interpreter.add("90 PRINT А").is_ok());
assert!(interpreter.add("100 PRINT Б").is_ok());
assert!(interpreter.add("110 READ В").is_ok());
assert!(interpreter.add("120 READ Г").is_ok());
assert!(interpreter.add("130 READ Де").is_ok());
assert!(interpreter.add("200 IF Де > Г GOTO 210").is_ok());
assert!(interpreter.add("201 PRINT Г").is_ok());
assert!(interpreter.add("210 PRINT Де").is_ok());
assert!(interpreter.run().is_ok());
assert_eq!(String::from_utf8(output).unwrap(), "1\n2\n5\n");
}
struct NotBuffered {}
impl std::io::Read for NotBuffered {
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
Ok(0)
}
}
#[test]
fn test_not_buffered() {
let input = NotBuffered {};
let mut output = Vec::<u8>::new();
let mut interpreter = Interpreter::new(input, &mut output);
interpreter.add("10 PRINT 10").unwrap();
interpreter.run().unwrap();
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20230111-3772066-27rwcz/solution)
warning: unused macro definition: `assert_match`
   --> src/lib.rs:227:14
    |
227 | macro_rules! assert_match {
    |              ^^^^^^^^^^^^
    |
    = note: `#[warn(unused_macros)]` on by default

warning: `solution` (lib) generated 1 warning
    Finished test [unoptimized + debuginfo] target(s) in 1.45s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 15 tests
test solution_test::test_basic_if ... ok
test solution_test::test_basic_goto ... ok
test solution_test::test_basic_print ... ok
test solution_test::test_basic_input ... ok
test solution_test::test_basic_read ... ok
test solution_test::test_erroring_goto ... ok
test solution_test::test_io_error_read ... FAILED
test solution_test::test_full_program ... FAILED
test solution_test::test_io_error_write ... ok
test solution_test::test_line_order_and_overwriting ... ok
test solution_test::test_print_cyrillic ... FAILED
test solution_test::test_print_vars_and_strings ... FAILED
test solution_test::test_runtime_errors ... FAILED
test solution_test::test_syntax_errors_1 ... ok
test solution_test::test_syntax_errors_2 ... ok

failures:

---- solution_test::test_io_error_read stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: SyntaxError { code: "10 PRINT this_is_fine" }', tests/solution_test.rs:349:50
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'solution_test::test_io_error_read' panicked at 'called `Result::unwrap()` on an `Err` value: SyntaxError { code: "10 PRINT this_is_fine" }', tests/solution_test.rs:344:5

---- solution_test::test_full_program stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: SyntaxError { code: "100 PRINT too_high" }', tests/solution_test.rs:240:51
thread 'solution_test::test_full_program' panicked at 'called `Result::unwrap()` on an `Err` value: SyntaxError { code: "100 PRINT too_high" }', tests/solution_test.rs:230:5

---- solution_test::test_print_cyrillic stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: RuntimeError { line_number: 50, message: "Cannot find variable!" }', tests/solution_test.rs:171:31
thread 'solution_test::test_print_cyrillic' panicked at 'called `Result::unwrap()` on an `Err` value: RuntimeError { line_number: 50, message: "Cannot find variable!" }', tests/solution_test.rs:160:5

---- solution_test::test_print_vars_and_strings stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: RuntimeError { line_number: 50, message: "Cannot find variable!" }', tests/solution_test.rs:151:31
thread 'solution_test::test_print_vars_and_strings' panicked at 'called `Result::unwrap()` on an `Err` value: RuntimeError { line_number: 50, message: "Cannot find variable!" }', tests/solution_test.rs:140:5

---- solution_test::test_runtime_errors stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /tmp/d20230111-3772066-27rwcz/solution/src/lib.rs:142:65
thread 'solution_test::test_runtime_errors' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', tests/solution_test.rs:301:5


failures:
    solution_test::test_full_program
    solution_test::test_io_error_read
    solution_test::test_print_cyrillic
    solution_test::test_print_vars_and_strings
    solution_test::test_runtime_errors

test result: FAILED. 10 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--test solution_test`

История (1 версия и 0 коментара)

Теодор качи първо решение на 09.01.2023 22:30 (преди над 2 години)