diff --git a/src/interpreter.rs b/src/interpreter.rs index ff3d020..1f85981 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -18,38 +18,38 @@ pub fn interpret(ast: &Ast) -> Result<()> { #[cfg(test)] pub fn interpret_expr(expr: &Spanned) -> Result { - Interpreter::::interpret_expr(expr, &Env::default()) + Interpreter::interpret_expr(expr, &Env::default()) } -pub struct Interpreter { +pub struct Interpreter<'a> { env: Env, - output: Output, + output: Box, } -impl Interpreter { +impl Interpreter<'static> { pub fn new() -> Self { Self { env: Env::default(), - output: std::io::stdout(), + output: Box::new(std::io::stdout()), } } } #[cfg(test)] -impl Interpreter { - fn with_output(output: Output) -> Self { +impl<'a> Interpreter<'a> { + fn with_output(output: Box) -> Self { Self { env: Env::default(), output, } } - fn decompose(self) -> (Env, Output) { + fn decompose(self) -> (Env, Box) { (self.env, self.output) } } -impl Interpreter { +impl<'a> Interpreter<'a> { pub fn interpret(&mut self, ast: &Ast) -> Result<()> { for stmt in &ast.0 { Self::execute_stmt(stmt, &mut self.output, &self.env)?; @@ -59,7 +59,7 @@ impl Interpreter { } #[tracing::instrument(name = "stmt", skip_all)] - fn execute_stmt(stmt: &Spanned, output: &mut Output, env: &Env) -> Result<()> { + fn execute_stmt(stmt: &Spanned, output: &mut dyn Write, env: &Env) -> Result<()> { match stmt.as_ref() { Stmt::Expr(e) => { Self::interpret_expr(e, env)?; @@ -411,16 +411,27 @@ mod test { }; use claims::{assert_matches, assert_some_eq}; + // Increase this if tests are failing to write to the output buffer + const TEST_OUTPUT_BUFFER_SIZE: usize = 128; + fn execute_stmts(input: &str) -> (Env, String) { let tokens = scan(input).unwrap_or_else(|e| panic!("input `{input}` should scan. error: {e:?}")); let ast = parse(tokens).unwrap_or_else(|e| panic!("input `{input}` should parse. error: {e:?}")); - let mut i = Interpreter::with_output(Vec::new()); + let mut output = vec![0; TEST_OUTPUT_BUFFER_SIZE]; + + let mut i = Interpreter::with_output(Box::new(output.as_mut_slice())); i.interpret(&ast).unwrap(); - let (env, output) = i.decompose(); - (env, String::from_utf8(output).unwrap().trim().to_string()) + let (env, _) = i.decompose(); + + let output = String::from_utf8(output) + .unwrap() + .trim_end_matches('\0') + .trim() + .to_string(); + (env, output) } fn interpret_expr_to_value(input: &str) -> Value {