From d3040a63f2db17212390b855b4988c390a64f613 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Thu, 18 Jul 2024 21:21:41 +0200 Subject: [PATCH] Default vm.out to stdout. Enable capturing through a ref cell. This is still not ideal, but we're getting there. --- src/interpreter/run.rs | 4 ++-- src/interpreter/runtime.rs | 2 +- src/interpreter/tests.rs | 25 ++++++++++++++++--------- src/interpreter/vm.rs | 10 ++++++---- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/interpreter/run.rs b/src/interpreter/run.rs index e14ceeb..b7e50bb 100644 --- a/src/interpreter/run.rs +++ b/src/interpreter/run.rs @@ -18,7 +18,7 @@ pub fn main(module: &Module, runtime: &mut Runtime) -> RResult<()> { let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?; unsafe { - runtime.vm.run(compiled, &runtime.compile_server, vec![], &mut std::io::stdout())?; + runtime.vm.run(compiled, &runtime.compile_server, vec![])?; } Ok(()) @@ -48,7 +48,7 @@ pub fn transpile(module: &Module, runtime: &mut Runtime) -> RResult = vec![]; - let result = runtime.vm.run(Rc::new(chunk), &runtime.compile_server, vec![], &mut out)?; + let result = runtime.vm.run(Rc::new(chunk), &runtime.compile_server, vec![])?; unsafe { assert_eq!(result.unwrap().bool, true); } @@ -55,12 +56,13 @@ mod tests { // TODO Should gather all used functions and compile them let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?; - let mut out: Vec = vec![]; - unsafe { - runtime.vm.run(compiled, &runtime.compile_server, vec![], &mut out)?; - } + runtime.vm.out = RefCell::new(Box::new(vec![])); + runtime.vm.run(compiled, &runtime.compile_server, vec![])?; + let out = unsafe { + ((runtime.vm.out.borrow_mut().as_mut() as *mut dyn Write) as *mut Vec).as_ref().unwrap() + }; - Ok(std::str::from_utf8(&out).unwrap().to_string()) + Ok(std::str::from_utf8(out).unwrap().to_string()) } /// This tests the transpiler, interpreter and function calls. @@ -160,7 +162,12 @@ mod tests { let mut out: Vec = vec![]; unsafe { - let result = runtime.vm.run(compiled, &runtime.compile_server, vec![], &mut out); + runtime.vm.out = RefCell::new(Box::new(vec![])); + let result = runtime.vm.run(compiled, &runtime.compile_server, vec![]); + let out = unsafe { + ((runtime.vm.out.borrow_mut().as_mut() as *mut dyn Write) as *mut Vec).as_ref().unwrap() + }; + assert_eq!(std::str::from_utf8(&out).unwrap().to_string(), "Assertion failure.\n"); if let Ok(_) = result { diff --git a/src/interpreter/vm.rs b/src/interpreter/vm.rs index 82aca7a..e1e1443 100644 --- a/src/interpreter/vm.rs +++ b/src/interpreter/vm.rs @@ -1,8 +1,9 @@ use std::alloc::{alloc, Layout}; +use std::cell::RefCell; use std::mem::transmute; use std::ops::Neg; use std::ptr::{read_unaligned, write_unaligned}; -use std::rc::Rc; +use std::rc::{Rc, Weak}; use monoteny_macro::{bin_expr, pop_ip, pop_sp, un_expr}; use uuid::Uuid; @@ -12,12 +13,12 @@ use crate::interpreter::chunks::Chunk; use crate::interpreter::compile::compile_server::CompileServer; use crate::interpreter::data::{string_to_ptr, Value}; use crate::interpreter::opcode::{OpCode, Primitive}; -use crate::interpreter::runtime::Runtime; use crate::interpreter::vm::call_frame::CallFrame; pub mod call_frame; pub struct VM { + pub out: RefCell>, pub stack: Vec, pub transpile_functions: Vec, pub call_frames: Vec, @@ -32,13 +33,14 @@ impl VM { pub fn new() -> VM { VM { // TODO This should dynamically resize probably. + out: RefCell::new(Box::new(std::io::stdout())), stack: vec![Value::alloc(); 1024 * 1024], transpile_functions: vec![], call_frames: Default::default(), } } - pub fn run(&mut self, initial_chunk: Rc, compile_server: &CompileServer, parameters: Vec, pipe_out: &mut dyn std::io::Write) -> RResult> { + pub fn run(&mut self, initial_chunk: Rc, compile_server: &CompileServer, parameters: Vec) -> RResult> { unsafe { let mut sp: *mut Value = &mut self.stack[0] as *mut Value; for parameter in parameters { @@ -332,7 +334,7 @@ impl VM { OpCode::PRINT => { // TODO Shouldn't need to copy it let string: String = read_unaligned(pop_sp!().ptr as *mut String); - writeln!(pipe_out, "{}", string) + writeln!(self.out.borrow_mut(), "{}", string) .map_err(|e| RuntimeError::error(&e.to_string()).to_array())?; } OpCode::NEG => {