From b8dd59cd7cf384bda7c217b33a8d41c88b3cc776 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sun, 1 Oct 2023 21:26:47 -0500 Subject: [PATCH] :recycle: refactor: match the Lua CLI API more closely --- lunar_wave_cli/src/main.rs | 74 +++++++++++++++++------------ lunar_wave_vm/src/lib.rs | 3 +- lunar_wave_vm/src/loader.rs | 15 +++++- lunar_wave_vm/src/tests.rs | 10 ++-- lunar_wave_vm/test_vectors/args.lua | 2 + lunar_wave_vm/tests/embedding.rs | 2 +- 6 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 lunar_wave_vm/test_vectors/args.lua diff --git a/lunar_wave_cli/src/main.rs b/lunar_wave_cli/src/main.rs index d4c61e3..f0946ce 100644 --- a/lunar_wave_cli/src/main.rs +++ b/lunar_wave_cli/src/main.rs @@ -1,20 +1,28 @@ // cargo run -- --script lunar_wave_vm/test_vectors/fizz_buzz.lua +use std::io::Read; + use lunar_wave_vm as lwvm; fn main () -> Result <(), lwvm::StepError> { + let args: Vec <_> = std::env::args ().collect (); + lunar_wave (args)?; + Ok (()) +} + +fn lunar_wave (args: Vec ) -> Result , lwvm::StepError> { let mut list_bytecode = false; - let mut pipe_bytecode = false; - let mut script = None; let mut breakpoints = vec![]; + let mut chunk = None; + let mut lua_args = vec! []; - let mut args = std::env::args (); - let exe_name = args.next ().unwrap (); + let mut arg_iter = args.iter (); + let _exe_name = arg_iter.next ().unwrap (); - while let Some (arg) = args.next () { + while let Some (arg) = arg_iter.next () { match arg.as_str () { "--break" => { - let s = args.next ().unwrap (); + let s = arg_iter.next ().unwrap (); let (block_idx, program_counter) = s.split_once (":").unwrap (); let block_idx = str::parse (block_idx).unwrap (); let program_counter = str::parse (program_counter).unwrap (); @@ -25,31 +33,41 @@ fn main () -> Result <(), lwvm::StepError> { }); }, "--list-bytecode" => list_bytecode = true, - "--pipe-bytecode" => pipe_bytecode = true, - "--script" => script = Some (args.next ().unwrap ()), + "-" => { + let mut buf = vec! []; + std::io::stdin ().read_to_end (&mut buf).unwrap (); + let bc = lwvm::ensure_bytecode (buf); + let mut rdr = std::io::Cursor::new (bc); + chunk = Some (lwvm::parse_chunk (&mut rdr).unwrap ()); + + lua_args = vec! ["-".to_string ()]; + }, "--" => break, - _ => panic! ("can't parse args"), + x => { + if x.starts_with ('-') { + panic! ("Unknown flag `{x}`"); + } + else if chunk.is_none () { + let bc = lwvm::compile_bytecode_from_file (x); + let mut rdr = std::io::Cursor::new (bc); + chunk = Some (lwvm::parse_chunk (&mut rdr).unwrap ()); + + lua_args = vec! [x.to_string ()]; + } + else { + lua_args.push (x.into ()); + } + }, } } - let chunk = if let Some (script) = script { - let bytecode = lwvm::compile_bytecode_from_file (&script); - let mut rdr = std::io::Cursor::new (bytecode); - lwvm::parse_chunk (&mut rdr).unwrap () - } - else if pipe_bytecode { - let mut stdin = std::io::stdin ().lock (); - lwvm::parse_chunk (&mut stdin).unwrap () - } - else { - unimplemented!(); - }; + let chunk = chunk.unwrap (); if list_bytecode { dbg! (&chunk); } - let upvalues = lwvm::State::upvalues_from_args ([exe_name].into_iter ().chain (args)); + let upvalues = lwvm::State::upvalues_from_args (lua_args.into_iter ()); let mut vm = lwvm::State::new (chunk, upvalues); if std::env::var("LWVM_DEBUG").is_ok() { @@ -77,7 +95,7 @@ fn main () -> Result <(), lwvm::StepError> { match input.as_str ().trim_end () { "c" => in_break = false, - "q" => return Ok (()), + "q" => return Ok (vec! []), "registers" => { dbg! (&vm.registers); continue; @@ -86,8 +104,7 @@ fn main () -> Result <(), lwvm::StepError> { match vm.step ()? { None => (), Some (lwvm::StepOutput::ChunkReturned (x)) => { - dbg! (x); - return Ok (()); + return Ok (x); }, } continue; @@ -99,12 +116,9 @@ fn main () -> Result <(), lwvm::StepError> { match vm.step ()? { None => (), Some (lwvm::StepOutput::ChunkReturned (x)) => { - dbg! (x); - return Ok (()); + return Ok (x); }, } } - - dbg! (vm); - panic! ("Hit max iterations before block returned"); } + diff --git a/lunar_wave_vm/src/lib.rs b/lunar_wave_vm/src/lib.rs index 4ff2145..173ca6d 100644 --- a/lunar_wave_vm/src/lib.rs +++ b/lunar_wave_vm/src/lib.rs @@ -4,7 +4,8 @@ mod state; mod value; pub use loader::compile_bytecode_from_file as compile_bytecode_from_file; -pub use loader::compile_bytecode_from_stdin as compile_bytecode_from_stdin; +pub use loader::compile_bytecode as compile_bytecode; +pub use loader::ensure_bytecode as ensure_bytecode; pub use loader::parse_chunk as parse_chunk; pub use state::Breakpoint as Breakpoint; pub use state::State as State; diff --git a/lunar_wave_vm/src/loader.rs b/lunar_wave_vm/src/loader.rs index 0d31daa..b4d63a9 100644 --- a/lunar_wave_vm/src/loader.rs +++ b/lunar_wave_vm/src/loader.rs @@ -34,7 +34,7 @@ pub fn compile_bytecode_from_file (path: &str) -> Vec { /// /// `source` is a Vec because we move it to a worker thread -pub fn compile_bytecode_from_stdin (source: Vec ) -> Vec { +pub fn compile_bytecode (source: Vec ) -> Vec { use std::{ io::Write, process::{ @@ -64,6 +64,19 @@ pub fn compile_bytecode_from_stdin (source: Vec ) -> Vec { output.stdout.as_slice ().to_vec () } +/// Checks whether the input is already bytecode, or is possibly +/// Lua source code. If it's source code, compiles and returns bytecode. +/// If it's bytecode, just returns the input. + +pub fn ensure_bytecode (buffer: Vec ) -> Vec { + let bytecode_header = &[0x1b, 0x4c, 0x75, 0x61, 0x54, 0x00, 0x19, 0x93]; + if buffer.starts_with (bytecode_header) { + return buffer; + } + + compile_bytecode (buffer) +} + fn i_sb (buf: [u8; 4]) -> Option { let b = buf [2]; i8::try_from (i32::try_from (b).ok ()? - 127).ok () diff --git a/lunar_wave_vm/src/tests.rs b/lunar_wave_vm/src/tests.rs index 03afac3..15d65d9 100644 --- a/lunar_wave_vm/src/tests.rs +++ b/lunar_wave_vm/src/tests.rs @@ -42,7 +42,7 @@ fn run_bytecode (args: &[&str], bc: &[u8]) -> Vec { /// and returns the output fn run_source (args: &[&str], s: &str) -> Vec { - let bc = loader::compile_bytecode_from_stdin (s.as_bytes ().to_vec ()); + let bc = loader::compile_bytecode (s.as_bytes ().to_vec ()); run_bytecode (args, &bc) } @@ -128,7 +128,7 @@ fn bools () { #[test] fn closure () { let source = include_bytes! ("../test_vectors/closure.lua"); - let bytecode = &crate::loader::compile_bytecode_from_stdin (source.to_vec ()); + let bytecode = &crate::loader::compile_bytecode (source.to_vec ()); let chunk = crate::loader::parse_chunk_from_bytes (bytecode).unwrap (); assert_eq! (run_chunk (&["_exe_name"], chunk), vec! [Value::from (23i64)]); @@ -185,7 +185,7 @@ fn floats () { #[test] fn fma () { let source = include_bytes! ("../test_vectors/fma.lua"); - let bytecode = &crate::loader::compile_bytecode_from_stdin (source.to_vec ()); + let bytecode = &crate::loader::compile_bytecode (source.to_vec ()); let chunk = crate::loader::parse_chunk_from_bytes (bytecode).unwrap (); assert_eq! (chunk.blocks.len (), 5); @@ -275,7 +275,7 @@ fn is_93 () { end "#; - let bc = loader::compile_bytecode_from_stdin (src.as_bytes ().to_vec ()); + let bc = loader::compile_bytecode (src.as_bytes ().to_vec ()); let chunk = loader::parse_chunk_from_bytes (&bc).unwrap (); assert_eq! (chunk.blocks [0].instructions [3], Inst::EqK (0, 1, false)); @@ -363,7 +363,7 @@ fn tailcall () { return tonumber ("5") "#; - let bc = loader::compile_bytecode_from_stdin (src.as_bytes ().to_vec ()); + let bc = loader::compile_bytecode (src.as_bytes ().to_vec ()); let chunk = loader::parse_chunk_from_bytes (&bc).unwrap (); assert_eq! (chunk.blocks [0].instructions [3], Instruction::TailCall (0, 2, 1, false)); diff --git a/lunar_wave_vm/test_vectors/args.lua b/lunar_wave_vm/test_vectors/args.lua new file mode 100644 index 0000000..2794b10 --- /dev/null +++ b/lunar_wave_vm/test_vectors/args.lua @@ -0,0 +1,2 @@ +print (arg [0]) +print (arg [1]) diff --git a/lunar_wave_vm/tests/embedding.rs b/lunar_wave_vm/tests/embedding.rs index 5f79aad..0d77181 100644 --- a/lunar_wave_vm/tests/embedding.rs +++ b/lunar_wave_vm/tests/embedding.rs @@ -19,7 +19,7 @@ fn embedding () { 1 } - let bytecode = lwvm::compile_bytecode_from_stdin (src.to_vec ()); + let bytecode = lwvm::compile_bytecode (src.to_vec ()); let mut rdr = std::io::Cursor::new (bytecode); let chunk = lwvm::parse_chunk (&mut rdr).unwrap ();