♻️ refactor: match the Lua CLI API more closely
parent
db84365c27
commit
b8dd59cd7c
|
@ -1,20 +1,28 @@
|
||||||
// cargo run -- --script lunar_wave_vm/test_vectors/fizz_buzz.lua
|
// cargo run -- --script lunar_wave_vm/test_vectors/fizz_buzz.lua
|
||||||
|
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
use lunar_wave_vm as lwvm;
|
use lunar_wave_vm as lwvm;
|
||||||
|
|
||||||
fn main () -> Result <(), lwvm::StepError> {
|
fn main () -> Result <(), lwvm::StepError> {
|
||||||
|
let args: Vec <_> = std::env::args ().collect ();
|
||||||
|
lunar_wave (args)?;
|
||||||
|
Ok (())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lunar_wave (args: Vec <String>) -> Result <Vec <lwvm::Value>, lwvm::StepError> {
|
||||||
let mut list_bytecode = false;
|
let mut list_bytecode = false;
|
||||||
let mut pipe_bytecode = false;
|
|
||||||
let mut script = None;
|
|
||||||
let mut breakpoints = vec![];
|
let mut breakpoints = vec![];
|
||||||
|
let mut chunk = None;
|
||||||
|
let mut lua_args = vec! [];
|
||||||
|
|
||||||
let mut args = std::env::args ();
|
let mut arg_iter = args.iter ();
|
||||||
let exe_name = args.next ().unwrap ();
|
let _exe_name = arg_iter.next ().unwrap ();
|
||||||
|
|
||||||
while let Some (arg) = args.next () {
|
while let Some (arg) = arg_iter.next () {
|
||||||
match arg.as_str () {
|
match arg.as_str () {
|
||||||
"--break" => {
|
"--break" => {
|
||||||
let s = args.next ().unwrap ();
|
let s = arg_iter.next ().unwrap ();
|
||||||
let (block_idx, program_counter) = s.split_once (":").unwrap ();
|
let (block_idx, program_counter) = s.split_once (":").unwrap ();
|
||||||
let block_idx = str::parse (block_idx).unwrap ();
|
let block_idx = str::parse (block_idx).unwrap ();
|
||||||
let program_counter = str::parse (program_counter).unwrap ();
|
let program_counter = str::parse (program_counter).unwrap ();
|
||||||
|
@ -25,31 +33,41 @@ fn main () -> Result <(), lwvm::StepError> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
"--list-bytecode" => list_bytecode = true,
|
"--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,
|
"--" => 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 chunk = chunk.unwrap ();
|
||||||
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!();
|
|
||||||
};
|
|
||||||
|
|
||||||
if list_bytecode {
|
if list_bytecode {
|
||||||
dbg! (&chunk);
|
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);
|
let mut vm = lwvm::State::new (chunk, upvalues);
|
||||||
if std::env::var("LWVM_DEBUG").is_ok() {
|
if std::env::var("LWVM_DEBUG").is_ok() {
|
||||||
|
@ -77,7 +95,7 @@ fn main () -> Result <(), lwvm::StepError> {
|
||||||
|
|
||||||
match input.as_str ().trim_end () {
|
match input.as_str ().trim_end () {
|
||||||
"c" => in_break = false,
|
"c" => in_break = false,
|
||||||
"q" => return Ok (()),
|
"q" => return Ok (vec! []),
|
||||||
"registers" => {
|
"registers" => {
|
||||||
dbg! (&vm.registers);
|
dbg! (&vm.registers);
|
||||||
continue;
|
continue;
|
||||||
|
@ -86,8 +104,7 @@ fn main () -> Result <(), lwvm::StepError> {
|
||||||
match vm.step ()? {
|
match vm.step ()? {
|
||||||
None => (),
|
None => (),
|
||||||
Some (lwvm::StepOutput::ChunkReturned (x)) => {
|
Some (lwvm::StepOutput::ChunkReturned (x)) => {
|
||||||
dbg! (x);
|
return Ok (x);
|
||||||
return Ok (());
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -99,12 +116,9 @@ fn main () -> Result <(), lwvm::StepError> {
|
||||||
match vm.step ()? {
|
match vm.step ()? {
|
||||||
None => (),
|
None => (),
|
||||||
Some (lwvm::StepOutput::ChunkReturned (x)) => {
|
Some (lwvm::StepOutput::ChunkReturned (x)) => {
|
||||||
dbg! (x);
|
return Ok (x);
|
||||||
return Ok (());
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg! (vm);
|
|
||||||
panic! ("Hit max iterations before block returned");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ mod state;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
pub use loader::compile_bytecode_from_file as compile_bytecode_from_file;
|
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 loader::parse_chunk as parse_chunk;
|
||||||
pub use state::Breakpoint as Breakpoint;
|
pub use state::Breakpoint as Breakpoint;
|
||||||
pub use state::State as State;
|
pub use state::State as State;
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn compile_bytecode_from_file (path: &str) -> Vec <u8> {
|
||||||
///
|
///
|
||||||
/// `source` is a Vec because we move it to a worker thread
|
/// `source` is a Vec because we move it to a worker thread
|
||||||
|
|
||||||
pub fn compile_bytecode_from_stdin (source: Vec <u8>) -> Vec <u8> {
|
pub fn compile_bytecode (source: Vec <u8>) -> Vec <u8> {
|
||||||
use std::{
|
use std::{
|
||||||
io::Write,
|
io::Write,
|
||||||
process::{
|
process::{
|
||||||
|
@ -64,6 +64,19 @@ pub fn compile_bytecode_from_stdin (source: Vec <u8>) -> Vec <u8> {
|
||||||
output.stdout.as_slice ().to_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 <u8>) -> Vec <u8> {
|
||||||
|
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 <i8> {
|
fn i_sb (buf: [u8; 4]) -> Option <i8> {
|
||||||
let b = buf [2];
|
let b = buf [2];
|
||||||
i8::try_from (i32::try_from (b).ok ()? - 127).ok ()
|
i8::try_from (i32::try_from (b).ok ()? - 127).ok ()
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn run_bytecode (args: &[&str], bc: &[u8]) -> Vec <Value> {
|
||||||
/// and returns the output
|
/// and returns the output
|
||||||
|
|
||||||
fn run_source (args: &[&str], s: &str) -> Vec <Value> {
|
fn run_source (args: &[&str], s: &str) -> Vec <Value> {
|
||||||
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)
|
run_bytecode (args, &bc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ fn bools () {
|
||||||
#[test]
|
#[test]
|
||||||
fn closure () {
|
fn closure () {
|
||||||
let source = include_bytes! ("../test_vectors/closure.lua");
|
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 ();
|
let chunk = crate::loader::parse_chunk_from_bytes (bytecode).unwrap ();
|
||||||
|
|
||||||
assert_eq! (run_chunk (&["_exe_name"], chunk), vec! [Value::from (23i64)]);
|
assert_eq! (run_chunk (&["_exe_name"], chunk), vec! [Value::from (23i64)]);
|
||||||
|
@ -185,7 +185,7 @@ fn floats () {
|
||||||
#[test]
|
#[test]
|
||||||
fn fma () {
|
fn fma () {
|
||||||
let source = include_bytes! ("../test_vectors/fma.lua");
|
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 ();
|
let chunk = crate::loader::parse_chunk_from_bytes (bytecode).unwrap ();
|
||||||
assert_eq! (chunk.blocks.len (), 5);
|
assert_eq! (chunk.blocks.len (), 5);
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ fn is_93 () {
|
||||||
end
|
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 ();
|
let chunk = loader::parse_chunk_from_bytes (&bc).unwrap ();
|
||||||
|
|
||||||
assert_eq! (chunk.blocks [0].instructions [3], Inst::EqK (0, 1, false));
|
assert_eq! (chunk.blocks [0].instructions [3], Inst::EqK (0, 1, false));
|
||||||
|
@ -363,7 +363,7 @@ fn tailcall () {
|
||||||
return tonumber ("5")
|
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 ();
|
let chunk = loader::parse_chunk_from_bytes (&bc).unwrap ();
|
||||||
|
|
||||||
assert_eq! (chunk.blocks [0].instructions [3], Instruction::TailCall (0, 2, 1, false));
|
assert_eq! (chunk.blocks [0].instructions [3], Instruction::TailCall (0, 2, 1, false));
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
print (arg [0])
|
||||||
|
print (arg [1])
|
|
@ -19,7 +19,7 @@ fn embedding () {
|
||||||
1
|
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 mut rdr = std::io::Cursor::new (bytecode);
|
||||||
let chunk = lwvm::parse_chunk (&mut rdr).unwrap ();
|
let chunk = lwvm::parse_chunk (&mut rdr).unwrap ();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue