120 lines
2.6 KiB
Rust
120 lines
2.6 KiB
Rust
// cargo run -- --script test_vectors/fizz_buzz.lua
|
|
|
|
mod instruction;
|
|
mod loader;
|
|
mod state;
|
|
mod value;
|
|
|
|
#[cfg (test)]
|
|
mod tests;
|
|
|
|
fn main () -> Result <(), state::StepError> {
|
|
use state::State;
|
|
|
|
let mut list_bytecode = false;
|
|
let mut pipe_bytecode = false;
|
|
let mut script = None;
|
|
let mut breakpoints = vec![];
|
|
|
|
let mut args = std::env::args ();
|
|
let exe_name = args.next ().unwrap ();
|
|
|
|
while let Some (arg) = args.next () {
|
|
match arg.as_str () {
|
|
"--break" => {
|
|
let s = args.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 ();
|
|
|
|
breakpoints.push (state::Breakpoint {
|
|
block_idx,
|
|
program_counter,
|
|
});
|
|
},
|
|
"--list-bytecode" => list_bytecode = true,
|
|
"--pipe-bytecode" => pipe_bytecode = true,
|
|
"--script" => script = Some (args.next ().unwrap ()),
|
|
"--" => break,
|
|
_ => panic! ("can't parse args"),
|
|
}
|
|
}
|
|
|
|
let chunk = if let Some (script) = script {
|
|
let bytecode = loader::compile_bytecode_from_file (&script);
|
|
let mut rdr = std::io::Cursor::new (bytecode);
|
|
loader::parse_chunk (&mut rdr).unwrap ()
|
|
}
|
|
else if pipe_bytecode {
|
|
let mut stdin = std::io::stdin ().lock ();
|
|
loader::parse_chunk (&mut stdin).unwrap ()
|
|
}
|
|
else {
|
|
unimplemented!();
|
|
};
|
|
|
|
if list_bytecode {
|
|
dbg! (&chunk);
|
|
}
|
|
|
|
let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args));
|
|
|
|
let mut vm = State::new (&chunk, &upvalues);
|
|
if std::env::var("LWVM_DEBUG").is_ok() {
|
|
vm.debug_print = true;
|
|
}
|
|
|
|
let max_iters = 2000;
|
|
let mut in_break = false;
|
|
let mut last_input = String::new ();
|
|
|
|
for _ in 0..max_iters {
|
|
if in_break || breakpoints.iter ().any (|bp| vm.at_breakpoint (bp)) {
|
|
in_break = true;
|
|
dbg! (&vm.stack);
|
|
|
|
let mut input = Default::default ();
|
|
std::io::stdin ().read_line (&mut input).unwrap ();
|
|
|
|
let input = if input == "" {
|
|
&last_input
|
|
}
|
|
else {
|
|
last_input = input;
|
|
&last_input
|
|
};
|
|
|
|
match input.as_str ().trim_end () {
|
|
"c" => in_break = false,
|
|
"q" => return Ok (()),
|
|
"registers" => {
|
|
dbg! (&vm.registers);
|
|
continue;
|
|
}
|
|
"s" => {
|
|
match vm.step ()? {
|
|
None => (),
|
|
Some (state::StepOutput::ChunkReturned (x)) => {
|
|
dbg! (x);
|
|
return Ok (());
|
|
},
|
|
}
|
|
continue;
|
|
},
|
|
x => { dbg! (x); },
|
|
}
|
|
}
|
|
|
|
match vm.step ()? {
|
|
None => (),
|
|
Some (state::StepOutput::ChunkReturned (x)) => {
|
|
dbg! (x);
|
|
return Ok (());
|
|
},
|
|
}
|
|
}
|
|
|
|
dbg! (vm);
|
|
panic! ("Hit max iterations before block returned");
|
|
}
|